/* ============================================================
   portal-inputs-v6.css — biblioteca de campos "Compacta 3" (tarjeta con
   acento tematizado + label a la izquierda). Todo va namespaced
   bajo .piv6 para no chocar con Bootstrap ni con el resto del portal.
   El acento se tiñe con la variable global del tenant --tema-color.
   Fragmentos que lo consumen: /comun/portal-inputs-v6.html
   Comportamiento del multiselect: /js/portal-inputs-v6.js
   ============================================================ */

.piv6{
  /* Derivados del color del tenant (color-mix con soporte en navegadores actuales). */
  --piv6-tema: var(--tema-color, #0d6efd);
  --piv6-soft: color-mix(in srgb, var(--piv6-tema) 12%, #fff);
  --piv6-ring: color-mix(in srgb, var(--piv6-tema) 24%, transparent);
  --piv6-ink:  color-mix(in srgb, var(--piv6-tema) 72%, #12131a);
  /* Color de SECCIÓN (header del card = C_Soluciones.bsBg), con fallback a tema.
     El label piv6 y la barra de acento se tiñen con éste (opción B, #40). */
  --rc-sec: var(--piv6-card-head, var(--tema-color, #0d6efd));
  /* Slate FIJO (independiente del tema) para el label de campos DESHABILITADOS. */
  --piv6-disabled-lbl:#adb5bd;

  --piv6-surface:#ffffff;
  --piv6-text:#1b2432;
  --piv6-muted:#6a7383;
  --piv6-faint:#9aa2b1;
  --piv6-line:#dde2ea;
  --piv6-line-strong:#c7cede;
  --piv6-danger:#d64550;
  --piv6-danger-soft:#fdecee;

  --piv6-r-chico:8px;
  --piv6-r-mini:6px;

  --piv6-shadow-sm:0 1px 2px rgba(20,30,50,.06);
  --piv6-shadow-md:0 8px 26px -12px rgba(20,30,50,.28), 0 2px 6px rgba(20,30,50,.05);

  color:var(--piv6-text);
}
.piv6 *,.piv6 *::before,.piv6 *::after{ box-sizing:border-box; }

/* Apilado vertical de campos (equivale al card-body grid del preview). */
.piv6-stack{ display:grid; gap:.5rem; }

/* Rejilla responsive de campos: 12 columnas (como el col=N de Bootstrap / de la versión
   vieja del form). Cada celda es un <div> que hospeda un .piv6-crd. **REUTILIZABLE**: por
   defecto cada campo ocupa MEDIA fila (span 6 = col-6, comportamiento previo); para hacerlo
   proporcional al contenido, ponle al <div> del campo una clase `piv6-cN` (N=1..12), usando
   el MISMO `col=N` que tenía la versión anterior (issue #41). Ej.: teléfono/CP/RFC → `piv6-c3`
   (¼), correo/razón social → default (½), calle/direcciones → `piv6-c12` (fila completa).
   Los campos cortos NO se estiran: el resto de la fila queda en blanco. */
.piv6-grid{ display:grid; grid-template-columns:repeat(12, minmax(0, 1fr)); gap:.55rem .75rem; align-items:start; }
.piv6-grid > *{ grid-column: span 6; }                 /* default = ½ (col-6), como antes */
.piv6-grid > .piv6-c1{ grid-column: span 1; }
.piv6-grid > .piv6-c2{ grid-column: span 2; }
.piv6-grid > .piv6-c3{ grid-column: span 3; }          /* ¼ */
.piv6-grid > .piv6-c4{ grid-column: span 4; }          /* ⅓ */
.piv6-grid > .piv6-c5{ grid-column: span 5; }
.piv6-grid > .piv6-c6{ grid-column: span 6; }          /* ½ */
.piv6-grid > .piv6-c7{ grid-column: span 7; }
.piv6-grid > .piv6-c8{ grid-column: span 8; }          /* ⅔ */
.piv6-grid > .piv6-c9{ grid-column: span 9; }          /* ¾ */
.piv6-grid > .piv6-c10{ grid-column: span 10; }
.piv6-grid > .piv6-c11{ grid-column: span 11; }
.piv6-grid > .piv6-c12,
.piv6-grid > .piv6-col-full{ grid-column: 1 / -1; }    /* fila completa */
/* Utilidad: forzar que un campo ½ ARRANQUE una nueva fila del grid (para agrupar campos
   relacionados juntos, p.ej. Cta SAP + Descripción Cta SAP en la misma línea). */
.piv6-grid > .piv6-nl{ grid-column: 1 / span 6; }
/* FORMA CORTA: un campo por renglón. Criterio de Enrique (2026-08-19): en una forma de
   MENOS DE 6 INPUTS el acomodo a dos columnas la hace ver como una tira de celdas y no como
   una forma, así que ahí va uno por línea. El ancho por dato (#41) NO se pierde: el campo
   arranca en la columna 1 y conserva su `span`, con el resto de la fila en blanco.
   Se pone en el CONTENEDOR: <div class="piv6-grid piv6-grid-corta">.
   OJO al escribirlo: `grid-column: span 4` mete el span en el grid-column-START (el END queda
   en auto), así que un `grid-column-start:1` suelto NO fija el inicio: BORRA el ancho y deja
   el campo en una sola columna. Hay que redeclarar las dos puntas — `1 / span N` — una por
   ancho, como ya lo hace `.piv6-nl`. */
.piv6-grid.piv6-grid-corta > *{ grid-column: 1 / span 6; }
.piv6-grid.piv6-grid-corta > .piv6-c1{ grid-column: 1 / span 1; }
.piv6-grid.piv6-grid-corta > .piv6-c2{ grid-column: 1 / span 2; }
.piv6-grid.piv6-grid-corta > .piv6-c3{ grid-column: 1 / span 3; }
.piv6-grid.piv6-grid-corta > .piv6-c4{ grid-column: 1 / span 4; }
.piv6-grid.piv6-grid-corta > .piv6-c5{ grid-column: 1 / span 5; }
.piv6-grid.piv6-grid-corta > .piv6-c6,
.piv6-grid.piv6-grid-corta > .piv6-nl{ grid-column: 1 / span 6; }
.piv6-grid.piv6-grid-corta > .piv6-c7{ grid-column: 1 / span 7; }
.piv6-grid.piv6-grid-corta > .piv6-c8{ grid-column: 1 / span 8; }
.piv6-grid.piv6-grid-corta > .piv6-c9{ grid-column: 1 / span 9; }
.piv6-grid.piv6-grid-corta > .piv6-c10{ grid-column: 1 / span 10; }
.piv6-grid.piv6-grid-corta > .piv6-c11{ grid-column: 1 / span 11; }
.piv6-grid.piv6-grid-corta > .piv6-c12,
.piv6-grid.piv6-grid-corta > .piv6-col-full{ grid-column: 1 / -1; }
/* Campo que se PEGA al final del renglón en vez de arrancar en la columna 1: para importes,
   que se leen mejor alineados a la derecha (Enrique, 2026-08-19, sobre el Subtotal de
   oc/habilitar). Conserva su ancho, y va una regla por ancho por lo mismo que la lista de
   arriba: en el shorthand el span vive en el START, así que hay que escribir las dos puntas. */
.piv6-grid.piv6-grid-corta > .piv6-c2.piv6-fin{ grid-column: span 2 / -1; }
.piv6-grid.piv6-grid-corta > .piv6-c3.piv6-fin{ grid-column: span 3 / -1; }
.piv6-grid.piv6-grid-corta > .piv6-c4.piv6-fin{ grid-column: span 4 / -1; }
.piv6-grid.piv6-grid-corta > .piv6-c5.piv6-fin{ grid-column: span 5 / -1; }
.piv6-grid.piv6-grid-corta > .piv6-c6.piv6-fin{ grid-column: span 6 / -1; }
/* Ocupa la MITAD DERECHA de un campo de media fila (c6): arranca en la columna 4 y abarca 3,
   así que su borde derecho cuadra con el del c6 de arriba. Para el importe que va debajo de un
   dato de media fila y se lee alineado con él (Enrique, 2026-08-19, Subtotal de oc/habilitar).
   En tablet y móvil mandan los cortes de abajo, que lo llevan a fila completa. */
.piv6-grid.piv6-grid-corta > .piv6-mitad-der{ grid-column: 4 / span 3; }
/* Los dos cortes de abajo REPITEN la lista de `.piv6-cN` en vez de apoyarse en el
   `.piv6-grid > *`. No es verbosidad gratuita (issue #80): una media query NO aporta
   especificidad, así que `.piv6-grid > *` (0,1,0) pierde siempre contra el
   `.piv6-grid > .piv6-cN` (0,2,0) que declara el ancho. Escrito con el `*` solo, el ancho
   explícito ganaba también a 390px y los campos con clase nunca apilaban — no se notaba
   porque la mayoría de los campos no llevan clase y caen en el default, que sí apila.
   Al agregar una clase de ancho nueva, agrégala TAMBIÉN a estas dos listas. */

/* Tablet: no bajar de ½ fila (los ¼/⅓ se leen mal en angosto). */
@media (max-width:991.98px){
  .piv6-grid > *,
  .piv6-grid > .piv6-c1, .piv6-grid > .piv6-c2, .piv6-grid > .piv6-c3,
  .piv6-grid > .piv6-c4, .piv6-grid > .piv6-c5, .piv6-grid > .piv6-c6,
  .piv6-grid > .piv6-nl{ grid-column: span 6; }
  /* De ⅔ para arriba ya no cabe media fila: se van a fila completa. */
  .piv6-grid > .piv6-c7, .piv6-grid > .piv6-c8, .piv6-grid > .piv6-c9,
  .piv6-grid > .piv6-c10, .piv6-grid > .piv6-c11,
  .piv6-grid > .piv6-c12, .piv6-grid > .piv6-col-full{ grid-column: 1 / -1; }
  /* Forma corta en tablet: sigue siendo uno por renglón, pero ningún campo baja de ½ fila. */
  .piv6-grid.piv6-grid-corta > *,
  .piv6-grid.piv6-grid-corta > .piv6-c1, .piv6-grid.piv6-grid-corta > .piv6-c2,
  .piv6-grid.piv6-grid-corta > .piv6-c3, .piv6-grid.piv6-grid-corta > .piv6-c4,
  .piv6-grid.piv6-grid-corta > .piv6-c5, .piv6-grid.piv6-grid-corta > .piv6-c6,
  .piv6-grid.piv6-grid-corta > .piv6-nl{ grid-column: 1 / span 6; }
  .piv6-grid.piv6-grid-corta > .piv6-c7, .piv6-grid.piv6-grid-corta > .piv6-c8,
  .piv6-grid.piv6-grid-corta > .piv6-c9, .piv6-grid.piv6-grid-corta > .piv6-c10,
  .piv6-grid.piv6-grid-corta > .piv6-c11, .piv6-grid.piv6-grid-corta > .piv6-c12,
  .piv6-grid.piv6-grid-corta > .piv6-col-full{ grid-column: 1 / -1; }
}
/* Móvil: una columna. */
@media (max-width:575.98px){
  .piv6-grid > *,
  .piv6-grid > .piv6-c1, .piv6-grid > .piv6-c2, .piv6-grid > .piv6-c3,
  .piv6-grid > .piv6-c4, .piv6-grid > .piv6-c5, .piv6-grid > .piv6-c6,
  .piv6-grid > .piv6-c7, .piv6-grid > .piv6-c8, .piv6-grid > .piv6-c9,
  .piv6-grid > .piv6-c10, .piv6-grid > .piv6-c11, .piv6-grid > .piv6-c12,
  .piv6-grid > .piv6-nl, .piv6-grid > .piv6-col-full{ grid-column: 1 / -1; }
  .piv6-grid.piv6-grid-corta > *,
  .piv6-grid.piv6-grid-corta > .piv6-c1, .piv6-grid.piv6-grid-corta > .piv6-c2,
  .piv6-grid.piv6-grid-corta > .piv6-c3, .piv6-grid.piv6-grid-corta > .piv6-c4,
  .piv6-grid.piv6-grid-corta > .piv6-c5, .piv6-grid.piv6-grid-corta > .piv6-c6,
  .piv6-grid.piv6-grid-corta > .piv6-c7, .piv6-grid.piv6-grid-corta > .piv6-c8,
  .piv6-grid.piv6-grid-corta > .piv6-c9, .piv6-grid.piv6-grid-corta > .piv6-c10,
  .piv6-grid.piv6-grid-corta > .piv6-c11, .piv6-grid.piv6-grid-corta > .piv6-c12,
  .piv6-grid.piv6-grid-corta > .piv6-nl,
  .piv6-grid.piv6-grid-corta > .piv6-col-full{ grid-column: 1 / -1; }
}

/* Fila compacta (flex): agrupa campos cortos en una sola línea, p.ej. el bloque de
   identidad RFC + No. Proveedor + Razón Social en proveedor.html ("en una sola línea, son
   los que se modifican por flujo"). .piv6-col-mini = ancho fijo angosto (RFC/No.Proveedor:
   12-13 caracteres no necesitan media rejilla); .piv6-col-flex crece para llenar el resto
   de la línea (p.ej. Razón Social). */
.piv6-row-compacta{ display:flex; flex-wrap:wrap; gap:.55rem .75rem; align-items:flex-start; }
.piv6-row-compacta > .piv6-col-mini{ flex:0 0 22rem; }
.piv6-row-compacta > .piv6-col-flex{ flex:1 1 18rem; min-width:0; }
@media (max-width:575.98px){ .piv6-row-compacta > .piv6-col-mini{ flex-basis:100%; } }

/* .piv6-col-mini también se puede usar SUELTO dentro de .piv6-grid (fuera de la fila
   compacta), para un campo corto que no debe estirarse a media rejilla (1fr). */
.piv6-grid > .piv6-col-mini{ max-width:22rem; }

/* Campos NUMÉRICOS (input type=number, p.ej. "día del mes..."): la etiqueta larga necesita más
   ancho y el picker de números va angosto (no ocupa toda la línea). */
.piv6-rowin:has(input[type="number"]){ grid-template-columns:minmax(10.5rem, 13rem) 1fr; }
.piv6-rowin:has(input[type="number"]) .piv6-ctrl[type="number"]{ max-width:6.5rem; }

/* ---------- Tarjeta con barra de acento ---------- */
.piv6-crd{
  position:relative; border:1px solid var(--piv6-line);
  border-radius:var(--piv6-r-chico); background:var(--piv6-surface);
  padding:.4rem .7rem .42rem .9rem; overflow:visible;
  transition:border-color .15s ease, box-shadow .15s ease;
}
.piv6-crd::before{
  content:""; position:absolute; left:0; top:0; bottom:0; width:3px;
  background:var(--rc-sec); border-radius:var(--piv6-r-chico) 0 0 var(--piv6-r-chico);
  transition:background-color .25s ease, width .15s ease;
}
.piv6-crd:focus-within{ border-color:var(--piv6-tema); box-shadow:0 0 0 3px var(--piv6-ring); }
.piv6-crd:focus-within::before{ width:4px; }
.piv6-crd.is-error{ border-color:var(--piv6-danger); }
.piv6-crd.is-error::before{ background:var(--piv6-danger); }
/* El accent (barra izquierda) va SOLO en campos requeridos (y en error). Los OPCIONALES sin
   accent — así la barra refuerza el indicador de "obligatorio". */
.piv6-crd:not(:has(.piv6-req)):not(:has(.piv6-switch)):not(.is-error):not(:has(.piv6-ctrl:disabled)):not(:has(.piv6-ctrl[readonly]))::before{ display:none; }

/* Fila: label a la izquierda + campo. */
.piv6-rowin{ display:grid; grid-template-columns:8.5rem 1fr; align-items:center; gap:.6rem; min-height:2.3rem; }
.piv6-rowin.top{ align-items:start; }
/* Switches: la etiqueta ocupa el ancho disponible y el switch se pega a la DERECHA de su celda.
   Para acercarlo al label NO se cambia esta alineación — se hace más ANGOSTO el container del
   campo (clase piv6-c3 = ¼) en el form; así el switch a la derecha queda cerca de la etiqueta. */
.piv6-rowin:has(.piv6-switch){ grid-template-columns:1fr auto; }
.piv6-rowin:has(.piv6-switch) .piv6-field{ justify-self:end; }
/* SWITCH CON AYUDA = MISMA fila que sin ayuda + la ayuda en su PROPIO renglón (issue #92).
   Antes (issue #41) la ayuda vivía DENTRO del .piv6-field, que en la fila del switch es la
   columna `auto`: el texto de ayuda inflaba esa columna, con lo que el switch —primer hijo del
   field— se despegaba del borde derecho y quedaba flotando a media tarjeta, con la ayuda debajo
   de ÉL y no de la etiqueta; y en celdas angostas (c3/c4) además aplastaba al label hasta
   desbordarlo ENCIMA de la ayuda (las "letras encimadas"). El parche de entonces fue apilar en
   c3/c4, lo que dejó DOS acomodos distintos para el mismo control.
   Aquí se resuelve la causa en vez del síntoma: `display:contents` disuelve la caja del
   .piv6-field para que switch / ayuda / error sean ítems DIRECTOS del grid de la fila, y así la
   ayuda se puede mandar a un renglón aparte a todo el ancho. Resultado único en TODOS los anchos
   de celda (c3, c4, c6, c12…) y con o sin ayuda: etiqueta a la izquierda, switch pegado al borde
   DERECHO, ayuda y error abajo alineados con la etiqueta. */
.piv6-rowin:has(.piv6-switch):has(.piv6-hint){
  grid-template-columns:1fr auto; align-items:center; row-gap:.1rem;
}
.piv6-rowin:has(.piv6-switch):has(.piv6-hint) > .piv6-field{ display:contents; }
.piv6-rowin:has(.piv6-switch):has(.piv6-hint) > .piv6-lbl{ grid-area:1 / 1; }
.piv6-rowin:has(.piv6-switch):has(.piv6-hint) .piv6-switch{ grid-area:1 / 2; justify-self:end; }
.piv6-rowin:has(.piv6-switch):has(.piv6-hint) .piv6-hint{ grid-area:2 / 1 / auto / -1; }
.piv6-rowin:has(.piv6-switch):has(.piv6-hint) .piv6-err{ grid-area:3 / 1 / auto / -1; }
/* Con el switch en línea la etiqueta puede quedar MUY angosta (c3 = ¼ de rejilla). .piv6-lbl es
   inline-flex y sus hijos son ítems flex con min-width:auto, así que sin esto el texto no baja de
   su ancho max-content y se desborda sobre el switch. Con min-width:0 el texto envuelve por
   palabras dentro de su columna (no se parten palabras: `break-word` solo actúa si una sola
   palabra no cabe). Va acotado a las filas de switch para no mover el resto de los campos, cuya
   etiqueta vive en una columna fija de 8.5rem. */
.piv6-rowin:has(.piv6-switch) > .piv6-lbl{ min-width:0; }
.piv6-rowin:has(.piv6-switch) > .piv6-lbl > span{ min-width:0; overflow-wrap:break-word; }
.piv6-rowin.top .piv6-lbl{ margin-top:.25rem; }

/* ---------- Label (opción B, #40) ----------
   El label lleva la IDENTIDAD de sección (--rc-sec). Jerarquía por estado:
     OPCIONAL     = tinte de sección aclarado + peso 500 (tenue).
     REQUERIDO    = tinte de sección oscuro + peso 800 (:has(.piv6-req)); sin "*".
     DESHABILITADO= slate FIJO neutro (no depende del tema), gana visualmente.
   El asterisco .piv6-req queda OCULTO: es solo el marcador para :has(). */
.piv6-lbl{
  /* Base = OPCIONAL: más claro/tenue + peso menor. */
  font-size:.74rem; font-weight:500;
  color:color-mix(in srgb, var(--rc-sec) 48%, #7b8493);
  display:inline-flex; align-items:center; gap:.35rem; line-height:1.2; min-width:0;
  letter-spacing:.005em;
}
/* line-height:1 — ALINEACIÓN DEL ICONO. El glifo de bootstrap-icons no está centrado dentro de su
   caja de línea: se dibuja sobre la línea base y el sobrante del interlineado cae abajo, así que con
   el `line-height:1.2` heredado la caja mide más que la tinta (12.2px contra ~10) y el icono se ve
   ALTO respecto al texto de la etiqueta, aunque las dos cajas estén centradas al pixel -medido:
   delta 0.0- (Enrique, 2026-08-19). Con line-height:1 la caja se ciñe al glifo y quedan a la misma
   altura, sin márgenes a ojo. Va en la BASE y no sólo en la variante compacta: el desfase es del
   tipo de letra de iconos, así que aplica igual a las formas de captura. */
.piv6-lbl .bi{ color:var(--rc-sec); font-size:.85rem; flex:none; opacity:.65; line-height:1; transition:color .25s ease, opacity .15s ease; }

/* REQUERIDO: label OSCURO + NEGRITA fuerte, icono a color pleno. Salta a la vista. */
.piv6-lbl:has(.piv6-req){
  color:color-mix(in srgb, var(--rc-sec) 58%, #0b0c10);
  font-weight:800; cursor:help;
}
.piv6-lbl:has(.piv6-req) .bi{ color:color-mix(in srgb, var(--rc-sec) 58%, #0b0c10); opacity:1; }
/* El "*" ya no se pinta: el requerido se comunica por el peso/tono del label. */
.piv6-lbl .piv6-req{ display:none; }

/* DESHABILITADO (input readonly / select|switch disabled): label en slate FIJO,
   neutro (no tema), claramente "apagado". Gana a opcional y a requerido. */
.piv6-crd:has(.piv6-ctrl:disabled) .piv6-lbl,
.piv6-crd:has(.piv6-ctrl[readonly]) .piv6-lbl,
.piv6-crd:has(.piv6-switch input:disabled) .piv6-lbl{
  color:var(--piv6-disabled-lbl) !important; font-weight:600; cursor:default;
}
.piv6-crd:has(.piv6-ctrl:disabled) .piv6-lbl .bi,
.piv6-crd:has(.piv6-ctrl[readonly]) .piv6-lbl .bi,
.piv6-crd:has(.piv6-switch input:disabled) .piv6-lbl .bi{
  color:var(--piv6-disabled-lbl) !important; opacity:.9;
}
/* El accent (barra izquierda) de un campo obligatorio DESHABILITADO también va en slate,
   igual que su texto — así no queda una barra a color de tema sobre un campo apagado.
   (No aplica en error: ahí la barra es danger.) */
.piv6-crd:not(.is-error):has(.piv6-ctrl:disabled)::before,
.piv6-crd:not(.is-error):has(.piv6-ctrl[readonly])::before,
.piv6-crd:not(.is-error):has(.piv6-switch input:disabled)::before{
  background:var(--piv6-disabled-lbl);
}

/* SWITCH = valor SIEMPRE definido (on/off): no hay "opcional/null" posible, así que se trata
   como REQUERIDO — label oscuro + negrita + accent visible — aunque el fragmento no lleve
   .piv6-req. El deshabilitado (regla de arriba, con !important) sigue ganando. */
.piv6-crd:has(.piv6-switch) .piv6-lbl{
  color:color-mix(in srgb, var(--rc-sec) 58%, #0b0c10);
  font-weight:800;
}
.piv6-crd:has(.piv6-switch) .piv6-lbl .bi{
  color:color-mix(in srgb, var(--rc-sec) 58%, #0b0c10); opacity:1;
}

/* ERROR (danger) gana sobre todo lo anterior. */
.piv6-crd.is-error .piv6-lbl{ color:var(--piv6-danger) !important; }
.piv6-crd.is-error .piv6-lbl .bi{ color:var(--piv6-danger) !important; opacity:1; }

.piv6-field{ min-width:0; }

/* Control borderless dentro de la tarjeta (el foco lo marca la tarjeta). */
.piv6-ctrl{
  width:100%; font:inherit; color:var(--piv6-text);
  border:0; background:transparent; padding:.18rem 0; font-size:.9rem;
  line-height:1.35;
}
.piv6-ctrl::placeholder{ color:var(--piv6-faint); }
.piv6-ctrl:focus{ outline:none; }
.piv6 textarea.piv6-ctrl{ resize:vertical; min-height:2.6rem; }
.piv6 input[type="date"].piv6-ctrl{ accent-color:var(--piv6-tema); color-scheme:light; }
.piv6 select.piv6-ctrl{ cursor:pointer; }
.piv6 select.piv6-ctrl:disabled{ cursor:default; opacity:.75; }


/* Variante RICH-TEXT (full-width, label arriba): hospeda el editor TinyMCE a lo ancho,
   debajo del label (no la rejilla label-izquierda). */
.piv6-rich .piv6-rich-in{ display:flex; flex-direction:column; gap:.45rem; }
.piv6-rich .piv6-lbl{ margin:0; }
.piv6-rich .piv6-field{ width:100%; min-width:0; }
.piv6-rich .piv6-richarea{ min-height:6rem; } /* placeholder antes de que TinyMCE monte el editor */

/* Ayuda y error por campo. */
.piv6-hint{ display:flex; align-items:flex-start; gap:.35rem; font-size:.72rem; color:var(--piv6-muted); margin-top:.2rem; }

/* ===== Checklist de Documentación PDF (columna 25% de autorizaproveedor) =====
   Una card COMPACTA por documento, apiladas (una por línea). title=descripción del
   documento; body=nombre de archivo + vigencia + preview/descarga. Estatus por borde
   izquierdo: pendiente=ámbar, aprobado=verde. No confundir con las clases .piv6-doc* del
   widget de documentos del proveedor. */
.piv6-dcard-list{ display:flex; flex-direction:column; gap:.5rem; }
.piv6-dcard{
  border:1px solid var(--piv6-line,#dde2ea); border-left:3px solid #94a3b8;
  border-radius:var(--piv6-r-chico,8px); background:#fff; padding:.5rem .6rem;
}
/* 3 estados: SIN TOCAR (no descargado)=slate neutro; DESCARGADO sin aprobar=ámbar (acción
   pendiente); APROBADO=verde. */
.piv6-dcard.is-untouched{ border-left-color:#94a3b8; background:color-mix(in srgb,#94a3b8 5%,#fff); }
.piv6-dcard.is-pending{ border-left-color:#f0a020; background:color-mix(in srgb,#f0a020 5%,#fff); }
.piv6-dcard.is-ok{ border-left-color:#2fb344; background:color-mix(in srgb,#2fb344 4%,#fff); }
/* 4o estado, solo en flujo de pagos: evidencia MARCADA PARA ELIMINARSE. */
.piv6-dcard.is-danger{ border-left-color:#d64550; background:color-mix(in srgb,#d64550 5%,#fff); }
/* 5o estado: documento OBLIGATORIO QUE TODAVIA NO EXISTE. No es un archivo con un problema, es un
   hueco por llenar, asi que el contorno va PUNTEADO -la convencion de "aqui va algo"- y el acento
   lateral se queda solido para que la tarjeta siga alineada con las demas de la lista. Se
   distingue del ambar de .is-pending (adjunto sin aprobar) por el rojo y por el punteado. */
.piv6-dcard.is-falta{
  border-style:dashed; border-color:color-mix(in srgb,var(--piv6-danger,#d64550) 45%,#fff);
  border-left-style:solid; border-left-color:var(--piv6-danger,#d64550);
  background:color-mix(in srgb,var(--piv6-danger,#d64550) 4%,#fff);
}
.piv6-dcard.is-falta .piv6-dcard-file.is-falta{ color:var(--piv6-faint,#9aa2b1); font-style:italic; }
/* Verde EN VIVO cuando el documento queda aprobado (checkbox marcado), sin esperar recarga. */
.piv6-dcard:has(.piv6-dcard-check input[type=checkbox]:checked){ border-left-color:#2fb344 !important; background:color-mix(in srgb,#2fb344 5%,#fff) !important; }
.piv6-dcard-head{ display:flex; align-items:center; gap:.45rem; }
.piv6-dcard-check{ flex:none; }
.piv6-dcard-titulo{ font-weight:700; font-size:.82rem; color:var(--piv6-ink,#1a1f2b); line-height:1.2; min-width:0; }
.piv6-dcard-body{ margin-top:.35rem; padding-left:.1rem; }
.piv6-dcard-file{ display:flex; align-items:center; gap:.3rem; font-size:.74rem; color:var(--piv6-muted,#6a7383); min-width:0; }
.piv6-dcard-file .text-truncate{ min-width:0; }
.piv6-dcard-file .bi{ color:#c0392b; flex:none; }
.piv6-dcard-foot{ display:flex; align-items:center; gap:.4rem; margin-top:.3rem; }
.piv6-dcard-vig{ font-size:.72rem; display:inline-flex; align-items:center; gap:.25rem; }
/* KPI de documentos (por descargar / descargados / por autorizar). */
.piv6-kpi{ display:flex; gap:.4rem; margin-top:.6rem; }
.piv6-kpi-item{
  flex:1 1 0; min-width:0; text-align:center;
  border:1px solid var(--piv6-line,#dde2ea); border-radius:var(--piv6-r-chico,8px);
  background:#fff; padding:.35rem .2rem;
}
.piv6-kpi-num{ display:block; font-weight:800; font-size:1.1rem; line-height:1.1; }
.piv6-kpi-lbl{ display:block; font-size:.62rem; color:var(--piv6-muted,#6a7383); text-transform:uppercase; letter-spacing:.02em; margin-top:.1rem; }
/* "Por autorizar" GRANDE en fila propia: número prominente + estado. Verde cuando ya no falta. */
.piv6-kpi-big{ display:flex; align-items:center; justify-content:center; gap:.4rem; margin-top:.45rem; padding:.5rem .7rem; border-radius:var(--piv6-r-chico,8px); border:1px solid var(--piv6-warn,#b45309); background:color-mix(in srgb,var(--piv6-warn,#b45309) 8%,#fff); font-size:.82rem; font-weight:700; color:var(--piv6-warn-ink,#7c3d06); }
.piv6-kpi-big.is-ok{ border-color:var(--piv6-ok,#15803d); background:color-mix(in srgb,var(--piv6-ok,#15803d) 8%,#fff); color:var(--piv6-ok-ink,#12602f); }
.piv6-kpi-big .bi{ font-size:1rem; flex:none; }
.piv6-kpi-big-num{ font-size:1.4rem; font-weight:800; line-height:1; }
@media (prefers-color-scheme: dark){ .piv6-kpi-item{ background:#1c2130; border-color:#33405a; } }

.piv6-dcard-acciones{ display:flex; flex-direction:column; gap:.4rem; margin-top:.6rem; }
.piv6-dcard-acciones .piv6-btn{ justify-content:center; }

/* --- Variantes que estrenó la lista de evidencias de flujo de pagos (fpcomun::filaevidencia) --- */
/* El encabezado tiene que poder envolver: el chip de vigencia se va a la derecha con ms-auto y en
   una columna angosta necesita bajar de renglón en vez de aplastar el título. */
.piv6-dcard-head{ flex-wrap:wrap; }
/* Nota dentro de la tarjeta: observaciones del proveedor, o el aviso de "evidencia eliminada"
   (antes eran un .border.bg-body-secondary y un .alert.alert-danger, que ocupaban media fila). */
.piv6-dcard-nota{
  display:flex; align-items:flex-start; gap:.35rem;
  margin-top:.35rem; padding:.3rem .5rem;
  border-radius:var(--piv6-r-mini,6px);
  background:color-mix(in srgb,#94a3b8 12%,#fff);
  font-size:.74rem; line-height:1.35; color:var(--piv6-muted,#6a7383);
}
.piv6-dcard-nota .bi{ flex:none; margin-top:.05rem; opacity:.85; }
.piv6-dcard-nota.is-danger{
  background:color-mix(in srgb,#d64550 10%,#fff);
  color:#a3323b; font-weight:600;
}
/* (La fila de acciones de la lista de evidencias vive ahora en portal.css como .fp-lote: es
   específica de flujo de pagos, no del design system.) */
/* El toggle de aprobar (checkboxpicker) compacto y v6 dentro de la card. */
.piv6-dcard-check .btn-group{ box-shadow:none; }
.piv6-dcard-check .btn{ padding:.15rem .4rem; font-size:.8rem; line-height:1; }
/* Hint "descárgalo para aprobar" SOLO en cards sin tocar (no descargado). */
/* Hint dentro del btn-group, ANTES de descargar, con flecha -> al botón de descarga. Solo sin tocar. */
.piv6-dcard-hint{ display:none; }
/* Caja CUADRADA (estilo btn-group), fondo del tema + texto/icono blanco. La caja NO se anima:
   se anima solo el CONTENIDO interno (texto+flecha) con un bob vertical (abajo->arriba). */
@keyframes piv6-hint-pulse{ 0%{ transform:translateY(1.5px); } 50%{ transform:translateY(-1.5px); } 100%{ transform:translateY(1.5px); } }
.piv6-dcard.is-untouched .piv6-dcard-hint{
  display:inline-flex; align-items:center; font-size:.66rem; font-weight:700; white-space:nowrap; overflow:hidden;
  background:var(--piv6-tema,#6c5ce7); color:#fff; border-radius:0; padding:0 .5rem;
}
.piv6-dcard.is-untouched .piv6-dcard-hint-in{
  display:inline-flex; align-items:center; gap:.2rem;
  animation:piv6-hint-pulse 1.2s ease-in-out infinite; will-change:transform;
}
.piv6-dcard-hint-arrow{ font-size:1.05rem; line-height:1; color:#fff; }
@media (prefers-reduced-motion: reduce){ .piv6-dcard.is-untouched .piv6-dcard-hint-in{ animation:none; } }
/* Con el hint presente, la fila de acciones puede envolver en la columna angosta. */
.piv6-dcard-foot{ flex-wrap:wrap; }
/* Botón de descarga ENFATIZADO cuando el doc está sin tocar (invita a descargarlo). */
.piv6-dcard.is-untouched .piv6-dcard-dl{ background:var(--piv6-tema,#6c5ce7); color:#fff; border-color:var(--piv6-tema,#6c5ce7); }
.piv6-dcard.is-untouched .piv6-dcard-dl .bi{ font-size:1.05rem; }
@media (prefers-color-scheme: dark){
  .piv6-dcard{ background:#1c2130; border-color:#33405a; }
  .piv6-dcard.is-ok{ background:color-mix(in srgb,#2fb344 12%,#1c2130); }
  .piv6-dcard.is-pending{ background:color-mix(in srgb,#f0a020 12%,#1c2130); }
  .piv6-dcard.is-falta{
    background:color-mix(in srgb,var(--piv6-danger,#d64550) 12%,#1c2130);
    border-color:color-mix(in srgb,var(--piv6-danger,#d64550) 45%,#1c2130);
  }
  .piv6-dcard-titulo{ color:#e7ecf5; }
}
/* CAMBIO DE ESTATUS (fpcomun::cambioestatus): tarjeta con las consecuencias del cambio.
   El FONDO lo pinta el JS con el color del estatus destino (C_Estatus_FlujoPagos.color), asi que
   aqui no se declara ninguno: solo la forma, y el texto en blanco porque siempre cae sobre una
   superficie saturada. Antes era un .alert de Bootstrap con `style="color:white"` inline. */
.fp-cest{
  border-radius:var(--piv6-r-chico,8px);
  padding:.75rem .9rem; color:#fff;
  display:grid; gap:.5rem;
  box-shadow:0 2px 10px -4px rgba(20,30,50,.35);
}
.fp-cest-head{ display:flex; align-items:center; gap:.45rem; font-size:1rem; font-weight:700; line-height:1.25; }
.fp-cest-head .bi{ font-size:1.15rem; flex:none; }
.fp-cest-lista{ margin:0; padding-left:1.15rem; font-size:.84rem; line-height:1.45; }
.fp-cest-lista:empty{ display:none; }
/* Pie: confirmacion y disparador en la misma linea, el boton pegado a la derecha. */
.fp-cest-pie{
  display:flex; align-items:center; gap:.75rem; flex-wrap:wrap;
  padding-top:.5rem; border-top:1px solid rgba(255,255,255,.25);
}
.fp-cest-pie .form-check-label{ font-size:.85rem; font-weight:600; }
.fp-cest-pie .piv6-btn{ margin-left:auto; }
/* El boton deshabilitado sobre fondo de color: se atenua sin desaparecer, para que se vea que la
   accion existe y falta confirmarla (regla del repo: nunca se oculta). */
.fp-cest-pie .piv6-btn:disabled{ opacity:.5; cursor:not-allowed; }

/* ESTATUS DEL CFDI ANTE EL SAT (fpcomun::chipsat). Chip compacto para dentro de una celda de tabla:
   los tonos NO se heredan del enum del ef-sdk -que devuelve nombres sueltos de Bootstrap 3, que en
   BS5 no pintan- sino que se resuelven aqui, con la misma paleta semantica que el resto del modulo
   (verde listo / rojo problema / ambar atencion / azul en proceso). */
.fp-sat{
  display:inline-flex; align-items:center; gap:.3rem; max-width:100%;
  font-size:.74rem; font-weight:700; line-height:1.3;
  padding:.15rem .5rem; border-radius:999px; border:1px solid transparent;
}
.fp-sat > span:last-child{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.fp-sat .bi{ flex:none; font-size:.8rem; }
.fp-sat.is-ok{      color:#1a7a2e; background:#e9f7ec; border-color:#bfe6c8; }
.fp-sat.is-error{   color:var(--piv6-danger,#d64550); background:var(--piv6-danger-soft,#fdecee); border-color:color-mix(in srgb,var(--piv6-danger,#d64550) 30%,transparent); }
.fp-sat.is-alerta{  color:#8a5a00; background:color-mix(in srgb,#f0a020 12%,#fff); border-color:color-mix(in srgb,#f0a020 35%,transparent); }
.fp-sat.is-proceso{ color:#0a4fa3; background:color-mix(in srgb,#0d6efd 8%,#fff); border-color:#7ba9f0; }
@media (prefers-color-scheme: dark){
  .fp-sat.is-ok{      background:color-mix(in srgb,#2fb344 18%,#1c2130); color:#7ee2a0; border-color:#33405a; }
  .fp-sat.is-error{   background:color-mix(in srgb,var(--piv6-danger,#d64550) 18%,#1c2130); border-color:#33405a; }
  .fp-sat.is-alerta{  background:color-mix(in srgb,#f0a020 18%,#1c2130); color:#f0c078; border-color:#33405a; }
  .fp-sat.is-proceso{ background:color-mix(in srgb,#0d6efd 18%,#1c2130); color:#9dc3ff; border-color:#33405a; }
}

/* ESTATUS DEL FLUJO DE PAGOS (fpcomun::chipestatusfp). El tono lo sigue dando el enum
   C_Estatus_FlujoPagos -que NO se toca- por la variable --fp-est; la LEGIBILIDAD la calcula aquí
   el CSS: texto = 55% del tono sobre negro, fondo = 14% sobre blanco, borde = 45%. Así cualquier
   hue del enum -presente o futuro- sale legible por construcción, en vez de depender de que quien
   elija el color se acuerde de medir el contraste (con el texto blanco que tenían, DEVUELTA,
   ENREVISION y PORPAGAR NO llegan a AA).
   El 55% está MEDIDO en pantalla sobre los siete estatus, no elegido a ojo: con 62% el amarillo de
   DEVUELTA se quedaba en 4.23:1 -por debajo de AA, y el texto del chip es pequeño, así que no le
   aplica la excepción de "texto grande"-; con 55% el peor caso sube a 5.13:1 y el resto va de 6.2
   a 12.0, conservando el matiz de cada tono. */
.fp-est{
  display:inline-flex; align-items:center; gap:.3rem; max-width:100%;
  font-size:.72rem; font-weight:700; line-height:1.3; white-space:nowrap;
  padding:.12rem .5rem; border-radius:999px;
  color:color-mix(in srgb, var(--fp-est,#666) 55%, black);
  background:color-mix(in srgb, var(--fp-est,#666) 14%, white);
  border:1px solid color-mix(in srgb, var(--fp-est,#666) 45%, transparent);
}
.fp-est > span:last-child{ overflow:hidden; text-overflow:ellipsis; }
.fp-est .bi{ flex:none; font-size:.8rem; }
/* Variante ABREVIADA (celda de la tabla: icono + tres letras, el nombre completo en el tooltip y
   en la leyenda del pie). El `min-width` es lo que hace que la columna se lea como UNA pila: sin
   él cada chip mide lo que mida su abreviatura y el borde derecho queda en diente de sierra.
   Y AQUÍ NO HAY ELIPSIS: el chip completo son tres letras: recortarlas no informa de nada -"AUT"
   se leía "A…"-, solo miente. La regla general de .fp-est trunca porque ahí el texto es la
   descripción entera y sí puede ceder; con la abreviatura el que tiene que ceder es el ancho de
   la columna, que para eso está declarado. */
.fp-est-abrev{ min-width:3.35rem; justify-content:center; letter-spacing:.04em; }
.fp-est-abrev > span:last-child{ overflow:visible; text-overflow:clip; }
@media (prefers-color-scheme: dark){
  /* En oscuro se invierte la mezcla: el texto se ACLARA con blanco y el fondo se apaga sobre el
     lienzo oscuro, para no acabar con texto oscuro sobre fondo oscuro. */
  .fp-est{
    color:color-mix(in srgb, var(--fp-est,#666) 45%, white);
    background:color-mix(in srgb, var(--fp-est,#666) 26%, #1c2130);
    border-color:color-mix(in srgb, var(--fp-est,#666) 45%, #33405a);
  }
}

/* Leyenda de estatus al pie de las consultas (fpcomun::leyendaestatusfp): los MISMOS chips que
   la columna Estado, en una fila que envuelve. */
.fp-leyenda{
  display:flex; flex-wrap:wrap; align-items:center; gap:.4rem;
  margin-top:.85rem; padding:.5rem .65rem;
  border:1px solid var(--bs-border-color-translucent, rgba(0,0,0,.08));
  border-radius:var(--r-contenedor, 6px);
  background:color-mix(in srgb, var(--tema-color, #0d6efd) 3%, transparent);
}
.fp-leyenda-tit{
  display:inline-flex; align-items:center; gap:.3rem;
  font-size:.72rem; font-weight:700; text-transform:uppercase; letter-spacing:.5px;
  opacity:.7; margin-right:.25rem;
}

/* La celda del estatus no cede ancho: el chip ya es compacto y recortarlo lo deja sin texto. */
.table-ultrapro td.td-estatusfp{ overflow:visible; }

/* Bloque de faltantes dentro del panel de Documentos Adjuntos: se despega de la lista de los que
   ya estan con una linea, para que se lean como dos grupos y no como una sola lista revuelta. */
.fp-faltan{ margin-top:.75rem; padding-top:.65rem; border-top:1px dashed var(--piv6-line,#dde2ea); }
.fp-faltan .piv6-evi-lbl{ color:var(--piv6-danger,#d64550); }

/* AVISO DE ESTADO (fpcomun::aviso): un solo componente para la confirmacion de exito y para el
   aviso de "no se puede operar en este estatus".
   CALIBRACION DEL TAMANO, que se fue a los dos extremos antes de quedar aqui:
     . la version original del exito iba con font-size:2em y el UUID EN LA MISMA LINEA que el
       mensaje, asi que el identificador -36 caracteres- se llevaba el ancho y tapaba el aviso;
     . al separarlos, el mensaje se quedo en .95rem y paso lo contrario: con el mismo peso que el
       texto normal, el aviso no se percibia entre tanto panel y tarjeta.
   El reparto correcto no es "grande" o "chico", es JERARQUIA: lo que crece es la FRASE -lo primero
   que el ojo debe encontrar al aterrizar-, no el dato de apoyo. El titulo va a 1.35rem/800, bien
   por encima del 1.05rem de un encabezado de panel, que es su competencia directa.
   El COLOR sale de --avi, asi que las variantes solo redefinen esa variable y el icono.
   Los margenes son generosos a proposito: este bloque tiene que despegarse de lo que va arriba y
   abajo, no leerse como una fila mas del formulario. */
.fp-aviso{
  --avi:#2fb344; --avi-ink:#1a7a2e;
  display:flex; align-items:center; gap:.9rem;
  border:1px solid color-mix(in srgb,var(--avi) 38%,#fff);
  border-left:4px solid var(--avi);
  background:color-mix(in srgb,var(--avi) 10%,#fff);
  border-radius:var(--piv6-r-chico,8px);
  padding:.9rem 1.1rem; margin:1rem 0 1.25rem;
}
.fp-aviso.is-error{  --avi:var(--piv6-danger,#d64550); --avi-ink:#a3242f; }
.fp-aviso.is-alerta{ --avi:#f0a020; --avi-ink:#8a5a00; }
.fp-aviso-ico{ flex:none; font-size:2.9rem; line-height:1; color:var(--avi); }
.fp-aviso-cuerpo{ min-width:0; display:grid; gap:.25rem; }
/* TAMANO DEL MENSAJE: 1.8rem. Es el tercer ajuste y el bueno; queda documentado el rango para no
   volver a recorrerlo. La referencia no es "que se vea", es que GANE a lo que compite con el:
   el encabezado de un panel de la cascada mide 1.05rem y el titulo de la pagina ~1.4rem, asi que
   por debajo de eso el aviso se perdia entre paneles. A 1.8rem/800 es lo primero que se lee al
   aterrizar, que es justo su trabajo: confirmar la accion que el usuario acaba de ejecutar. */
.fp-aviso-tit{ font-size:1.8rem; font-weight:800; line-height:1.2; color:var(--avi-ink); letter-spacing:-.015em; }
.fp-aviso-dato{ display:flex; align-items:baseline; gap:.4rem; flex-wrap:wrap; min-width:0; }
.fp-aviso-lbl{
  font-size:.66rem; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
  color:var(--piv6-muted,#6a7383);
}
/* Dato de APOYO (el UUID del exito): tenue, no compite con la frase. */
.fp-aviso-val{ font-size:.75rem; color:var(--piv6-muted,#6a7383); overflow-wrap:anywhere; }
/* Dato FUERTE (el estatus del error): ahi el dato ES la informacion, asi que sube de rango --pero
   sigue por debajo de la frase, para conservar los dos niveles de lectura. */
.fp-aviso-dato.is-fuerte .fp-aviso-val{
  font-size:1.2rem; font-weight:800; color:var(--avi-ink);
}
/* En movil baja dos escalones: a 1.8rem una frase de ocho palabras se come cuatro renglones. */
@media (max-width:575.98px){
  .fp-aviso{ gap:.6rem; padding:.8rem .85rem; margin:.75rem 0 1rem; }
  .fp-aviso-ico{ font-size:2rem; }
  .fp-aviso-tit{ font-size:1.25rem; }
  .fp-aviso-dato.is-fuerte .fp-aviso-val{ font-size:1rem; }
}
@media (prefers-color-scheme: dark){
  .fp-aviso{ background:color-mix(in srgb,var(--avi) 16%,#1c2130); border-color:#33405a; }
  .fp-aviso{ --avi-ink:#e7ecf5; }
  .fp-aviso.is-exito{ --avi-ink:#7ee2a0; }
}

/* Bloque de AYUDA/instrucciones modernizado (reemplazo del viejo inputsv2::instrucciones BS3:
   panel colapsable azul + alert + slideDown). Caja suave con accent de tenant, encabezado con
   icono y cuerpo (soporta <ul>/<li> del message key). Reutilizable con class="piv6-ayuda". */
.piv6-ayuda{
  border:1px solid var(--piv6-line,#dde2ea);
  border-left:3px solid var(--tema-color,#6c5ce7);
  background:color-mix(in srgb, var(--tema-color,#6c5ce7) 5%, #fff);
  border-radius:var(--piv6-r-chico,8px);
  padding:.65rem .85rem; margin:.6rem 0 .3rem;
}
.piv6-ayuda-head{
  font-weight:700; color:var(--tema-color,#6c5ce7);
  display:flex; align-items:center; gap:.45rem; margin-bottom:.3rem; font-size:.92rem;
}
.piv6-ayuda-head .bi{ font-size:1rem; }
.piv6-ayuda-body{ font-size:.85rem; color:#3a4150; }
.piv6-ayuda-body ul{ margin:0; padding-left:1.15rem; }
.piv6-ayuda-body li{ margin:.12rem 0; }
.piv6-ayuda-body p:last-child{ margin-bottom:0; }
@media (prefers-color-scheme: dark){
  .piv6-ayuda{ background:color-mix(in srgb, var(--tema-color,#6c5ce7) 14%, #1c2130); border-color:#33405a; }
  .piv6-ayuda-body{ color:#c7cfdd; }
}
.piv6-hint .bi{ flex:none; color:var(--piv6-faint); font-size:.8rem; margin-top:.02rem; }
.piv6-err{ display:flex; align-items:center; gap:.35rem; font-size:.72rem; color:var(--piv6-danger); font-weight:600; margin-top:.25rem; }
.piv6-err .bi{ flex:none; font-size:.85rem; }
.piv6-err.alert{ background:transparent; border:0; padding:0; margin:.25rem 0 0; }

/* Rango de fechas: una sola línea [inicial] -> [final]. */
.piv6-daterange{ display:flex; flex-wrap:nowrap; align-items:center; gap:.4rem; min-width:0; width:100%; }
/* Las fechas se centran en su caja. Desde que el campo tiene ancho content-aware, la caja mide más
   que el texto (10 caracteres más la holgura), y con el texto pegado a la izquierda la flecha
   quedaba lejísimos de la primera fecha y pegada a la segunda: parecía de la segunda, no entre las
   dos (Enrique, 2026-08-19: "centra la flecha"). Centrando el contenido el separador queda a la
   misma distancia de ambas. */
.piv6-daterange .piv6-ctrl{ text-align:center; }
.piv6-daterange .piv6-ctrl{ flex:1 1 0; min-width:0; width:auto; }
.piv6-daterange .piv6-arrow{ flex:0 0 auto; display:inline-flex; align-items:center; color:var(--piv6-muted); }
.piv6-daterange .piv6-arrow .bi{ font-size:1em; }

@media (max-width:520px){
  .piv6-rowin{ grid-template-columns:1fr; gap:.15rem; }
  /* Los switches NO se apilan en móvil: el control mide ~40px y cabe siempre junto a su
     etiqueta. Apilado, el switch quedaba suelto a media pantalla y rompía la lectura
     "concepto → estado" que da el switch al borde derecho. */
  .piv6-rowin:has(.piv6-switch){ grid-template-columns:1fr auto; column-gap:.6rem; }
  .piv6-daterange{ flex-wrap:wrap; }
  .piv6-daterange .piv6-ctrl{ flex:1 1 100%; }
  .piv6-daterange .piv6-arrow{ transform:rotate(90deg); }
}

/* ============================================================
   INPUT DE ARCHIVO (upload) tematizado
   ============================================================ */
.piv6-file-wrap{ display:flex; }
/* El alto TIENE que empatar con el de los demás controles (.piv6-ctrl ≈ 21px): el selector de
   archivo es el único que mete un botón dentro de la caja, y con el padding de antes (.4rem en la
   caja + .28rem en el botón) la tarjeta salía ~12px más alta que la de al lado — se notaba al
   ponerlos en la misma fila (tipo de documento + archivo, xml + pdf). */
.piv6-file{
  display:flex; align-items:center; gap:.6rem; width:100%; min-width:0; margin:0;
  border:1px dashed var(--piv6-line-strong); border-radius:var(--piv6-r-mini);
  background:#fbfcfe; padding:.12rem .5rem; cursor:pointer;
  transition:border-color .15s ease, background .15s ease, box-shadow .15s ease;
}
.piv6-file:hover{ border-color:var(--piv6-tema); background:var(--piv6-soft); }
.piv6-file.has-file{ border-style:solid; border-color:var(--piv6-tema); }
.piv6-file-btn{
  display:inline-flex; align-items:center; gap:.35rem; flex:none;
  font-size:.82rem; font-weight:600; color:#fff; background:var(--piv6-tema);
  border-radius:var(--piv6-r-mini); padding:.16rem .5rem;
}
.piv6-file-btn .bi{ font-size:.9rem; }
.piv6-file-name{ font-size:.85rem; color:var(--piv6-muted); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }
.piv6-file.has-file .piv6-file-name{ color:var(--piv6-text); font-weight:600; }
.piv6-file-input:focus-visible + *,
.piv6-file-input:focus-visible ~ .piv6-file{ box-shadow:0 0 0 3px var(--piv6-ring); }
/* Icono del TIPO de archivo esperado, al extremo derecho del selector (lo reescribe el JS de
   fpcomun con la clase FontAwesome que trae cada tipo de documento desde Java). */
.piv6-file .piv6-file-tipo{ margin-left:auto; flex:none; color:var(--piv6-muted); font-size:1rem; line-height:1; }

/* ============================================================
   SWITCH (compacto, tematizado)
   ============================================================ */
.piv6-switch{ display:inline-flex; align-items:center; gap:.55rem; cursor:pointer; font-size:.85rem; color:var(--piv6-text); user-select:none; margin:0; }
.piv6-switch input{ position:absolute; opacity:0; width:0; height:0; }
.piv6-switch .piv6-track{
  position:relative; flex:none; width:38px; height:22px;
  background:var(--piv6-line-strong); border-radius:999px;
  transition:background-color .2s ease; box-shadow:inset 0 1px 2px rgba(0,0,0,.12);
}
.piv6-switch .piv6-thumb{
  position:absolute; top:3px; left:3px; width:16px; height:16px;
  background:#fff; border-radius:50%; box-shadow:0 1px 3px rgba(0,0,0,.28);
  transition:transform .2s cubic-bezier(.4,1.3,.6,1);
}
.piv6-switch input:checked ~ .piv6-track{ background:var(--piv6-tema); }
.piv6-switch input:checked ~ .piv6-track .piv6-thumb{ transform:translateX(16px); }
.piv6-switch input:focus-visible ~ .piv6-track{ box-shadow:0 0 0 4px var(--piv6-ring); }
.piv6-switch input:disabled ~ .piv6-track{ opacity:.55; }
.piv6-switch .piv6-switch-txt{ font-weight:600; }

/* ============================================================
   MULTISELECT (réplica del filtro Proveedor: búsqueda + TODOS +
   checkboxes + switch "Excepto", con chips en el toggle)
   ============================================================ */
.piv6-ms-wrap{ display:flex; align-items:center; gap:.55rem; flex-wrap:wrap; }
.piv6-ms-wrap > .piv6-ms{ flex:1 1 180px; min-width:0; }

.piv6-ms{ position:relative; }
.piv6-ms-toggle{
  display:flex; align-items:center; gap:.5rem; width:100%; text-align:left;
  font:inherit; color:var(--piv6-text); cursor:pointer; background:#fff;
  border:1px solid var(--piv6-line-strong); border-radius:var(--piv6-r-mini);
  padding:.32rem .55rem; min-height:3.1rem;
  transition:border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.piv6-ms-toggle:focus-visible{ outline:none; border-color:var(--piv6-tema); box-shadow:0 0 0 3px var(--piv6-ring); }
.piv6-ms.open > .piv6-ms-toggle{ border-color:var(--piv6-tema); box-shadow:0 0 0 2px var(--piv6-ring); }
.piv6-ms-chips{ display:flex; flex-wrap:wrap; gap:.25rem; flex:1 1 auto; min-width:0; align-items:center; }
.piv6-ms-ph{ color:var(--piv6-faint); font-size:.86rem; }
.piv6-ms-chip{
  display:inline-flex; align-items:center; gap:.2rem;
  background:var(--piv6-soft); color:var(--piv6-ink);
  border:1px solid color-mix(in srgb, var(--piv6-tema) 25%, transparent);
  border-radius:999px; padding:.06rem .22rem .06rem .5rem;
  font-size:.72rem; font-weight:600; max-width:100%;
}
.piv6-ms-chip .piv6-ms-chip-lbl{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:13ch; }
.piv6-ms-x{ display:inline-flex; align-items:center; justify-content:center; border:0; background:transparent; cursor:pointer; color:inherit; padding:1px; border-radius:50%; line-height:1; }
.piv6-ms-x .bi{ font-size:.7rem; }
.piv6-ms-x:hover{ background:color-mix(in srgb, var(--piv6-tema) 22%, #fff); }
.piv6-ms-chip.piv6-ms-count{ background:var(--piv6-tema); color:#fff; border-color:transparent; padding:.06rem .5rem; }
.piv6-ms-caret{ margin-left:auto; color:var(--piv6-muted); display:flex; flex:none; transition:transform .18s ease; }
.piv6-ms.open > .piv6-ms-toggle .piv6-ms-caret{ transform:rotate(180deg); }

.piv6-ms-inverted-tag{
  display:inline-flex; align-items:center; font-size:.62rem; font-weight:800;
  letter-spacing:.05em; text-transform:uppercase; color:#fff; background:var(--piv6-tema);
  border-radius:999px; padding:.06rem .42rem;
}

.piv6-ms-panel{
  position:absolute; z-index:1060; top:calc(100% + 5px); left:0; right:0;
  background:#fff; border:1px solid var(--piv6-line); border-radius:var(--piv6-r-chico);
  box-shadow:var(--piv6-shadow-md); padding:.45rem;
}
.piv6-ms-panel[hidden]{ display:none; }
.piv6-ms-search{
  display:flex; align-items:center; gap:.4rem; padding:.35rem .5rem;
  border:1px solid var(--piv6-line); border-radius:var(--piv6-r-mini); margin-bottom:.35rem;
}
.piv6-ms-search:focus-within{ border-color:var(--piv6-tema); box-shadow:0 0 0 3px var(--piv6-ring); }
.piv6-ms-search .bi{ color:var(--piv6-faint); flex:none; }
.piv6-ms-search input{ border:0; outline:none; font:inherit; font-size:.85rem; width:100%; background:transparent; color:var(--piv6-text); }
.piv6-ms-list{ max-height:200px; overflow-y:auto; overflow-x:hidden; display:flex; flex-direction:column; }
.piv6-ms-opt{ position:relative; display:flex; align-items:center; gap:.5rem; padding:.32rem .45rem; border-radius:var(--piv6-r-mini); cursor:pointer; font-size:.85rem; margin:0; }
.piv6-ms-opt:hover{ background:var(--piv6-soft); }
.piv6-ms-opt.piv6-hide{ display:none; }
.piv6-ms-opt input{ position:absolute; opacity:0; width:0; height:0; }
.piv6-ms-box{ position:relative; flex:none; width:17px; height:17px; border-radius:5px; border:1.5px solid var(--piv6-line-strong); background:#fff; display:flex; align-items:center; justify-content:center; transition:all .12s ease; }
.piv6-ms-box .bi{ font-size:.72rem; color:#fff; opacity:0; line-height:1; }
.piv6-ms-opt input:checked ~ .piv6-ms-box{ background:var(--piv6-tema); border-color:var(--piv6-tema); }
.piv6-ms-opt input:checked ~ .piv6-ms-box .bi{ opacity:1; }
.piv6-ms-opt input:indeterminate ~ .piv6-ms-box{ background:var(--piv6-tema); border-color:var(--piv6-tema); }
.piv6-ms-opt input:indeterminate ~ .piv6-ms-box::after{ content:""; width:9px; height:2px; background:#fff; border-radius:2px; position:absolute; }
.piv6-ms-opt input:focus-visible ~ .piv6-ms-box{ box-shadow:0 0 0 3px var(--piv6-ring); }
.piv6-ms-optlabel{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; flex:1 1 auto; min-width:0; display:flex; align-items:center; justify-content:space-between; gap:.5rem; }
.piv6-ms-optlabel .piv6-ms-optname{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.piv6-ms-optlabel .piv6-ms-optbadge{ flex:none; font-size:.68rem; font-weight:700; color:#fff; background:var(--piv6-tema); border-radius:999px; padding:.02rem .4rem; }
.piv6-ms-optlabel .piv6-ms-optbadge.piv6-cero{ background:var(--piv6-line-strong); color:#5b6472; }
.piv6-ms-all{ font-weight:700; }
.piv6-ms-vacio{ font-size:.8rem; color:var(--piv6-muted); text-align:center; padding:.6rem; }
.piv6-ms-divider{ height:1px; background:var(--piv6-line); margin:.3rem .2rem; }

.piv6-ms-excepto{ flex:none; display:flex; align-items:center; gap:.4rem; font-size:.74rem; color:var(--piv6-muted); cursor:pointer; user-select:none; white-space:nowrap; }

/* ============================================================
   BOTONES — mismo lenguaje, tematizados
   ============================================================ */
.piv6-btn{
  display:inline-flex; align-items:center; justify-content:center; gap:.45rem;
  font:inherit; font-weight:600; font-size:.9rem; line-height:1;
  padding:.55rem 1rem; border-radius:var(--piv6-r-chico);
  border:1.5px solid transparent; cursor:pointer; white-space:nowrap; text-decoration:none;
  transition:background-color .15s ease, border-color .15s ease, box-shadow .15s ease, transform .05s ease, color .15s ease;
}
.piv6-btn:active{ transform:translateY(1px); }
.piv6-btn:focus-visible{ outline:none; box-shadow:0 0 0 4px var(--piv6-ring); }
/* DESHABILITADO: aplica tanto al <button disabled> (:disabled) como al <a class="disabled">
   (los enlaces ignoran el atributo disabled). Se ve apagado y NO es clickeable. */
.piv6-btn:disabled, .piv6-btn.disabled{
  opacity:.5 !important; cursor:not-allowed; pointer-events:none; box-shadow:none; transform:none;
  filter:grayscale(.35);
}
.piv6-btn .bi{ font-size:1rem; }
.piv6-btn-sm{ font-size:.8rem; padding:.4rem .7rem; border-radius:var(--piv6-r-mini); }
.piv6-btn-primary{ background:var(--piv6-tema); color:#fff; }
.piv6-btn-primary:hover{ background:color-mix(in srgb, var(--piv6-tema) 88%, #000); color:#fff; }
.piv6-btn-secondary{ background:#fff; color:var(--piv6-ink); border-color:var(--piv6-line-strong); }
.piv6-btn-secondary:hover{ background:var(--piv6-soft); border-color:color-mix(in srgb, var(--piv6-tema) 40%, transparent); color:var(--piv6-ink); }
/* Verde para botones de AUTORIZACIÓN / confirmar positivo (autorizar, aprobar). Mantiene el
   tamaño piv6-btn, solo cambia el color (convención: los de autorización van en verde). */
.piv6-btn-success{ background:var(--piv6-ok,#15803d); color:#fff; }
.piv6-btn-success:hover{ background:color-mix(in srgb, var(--piv6-ok,#15803d) 85%, #000); color:#fff; }
.piv6-btn-danger{ background:var(--piv6-danger); color:#fff; }
.piv6-btn-danger:hover{ background:color-mix(in srgb, var(--piv6-danger) 88%, #000); color:#fff; }
/* Ámbar para acciones que DEVUELVEN al remitente (devolver solicitud, regresar a corrección): no
   son destructivas como rechazar (rojo) ni positivas como autorizar (verde). Ámbar-700 y no el
   ámbar-600 de las tablas porque aquí el texto va en blanco y necesita contraste AA. */
.piv6-btn-warning{ background:var(--piv6-warn,#b45309); color:#fff; }
.piv6-btn-warning:hover{ background:color-mix(in srgb, var(--piv6-warn,#b45309) 85%, #000); color:#fff; }

/* ============================================================
   CHIPS DE DESTINATARIOS (preview "Nombre <correo>")
   ============================================================ */
.piv6-badge{ background-color: var(--piv6-tema, var(--tema-color, #667085)) !important; color:#fff; }
/* Rejilla de 2 columnas consistente; cada chip llena su celda y trunca. En angosto, 1 columna. */
.piv6-dest-grid{ display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:.3rem .5rem; }
@media (max-width:575.98px){ .piv6-dest-grid{ grid-template-columns:1fr; } }
.piv6-dest-chip{
  display:flex; align-items:center; gap:.3rem; width:100%; min-width:0; max-width:100%;
  background:#eef1f6; color:#344054; border:1px solid #e2e6ee;
  border-radius:999px; font-size:.72rem; padding:.14rem .6rem; line-height:1.4;
}
.piv6-dest-chip .bi{ color:var(--piv6-tema, var(--tema-color, #667085)); font-size:.75rem; flex:none; }
.piv6-dest-chip .piv6-dest-txt{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; flex:1 1 auto; }
.piv6-dest-chip .piv6-dest-mail{ color:#6a7383; }
.piv6-dest-more{ grid-column:1 / -1; font-size:.72rem; color:#6a7383; font-weight:600; padding:.1rem .15rem 0; }
.piv6-dest-vacio{ grid-column:1 / -1; font-size:.72rem; color:var(--piv6-faint, #9aa2b1); font-style:italic; }

/* ============================================================
   PANEL DE AYUDA "info" TEMATIZADO POR SECCIÓN (recepcionescomun::panel con
   temaseccion=true). Sustituye el celeste fijo de Bootstrap por el color de
   SECCIÓN (--piv6-card-head, = el del header del card-pagina), con fallback a
   --tema-color: fondo ACLARADO + texto/icono OSCUROS (contraste) + borde sutil.
   Solo aplica donde se pide (clase .rc-panel-seccion); no toca otros panel-info.
   ============================================================ */
.rc-panel-seccion{
  --rc-sec: var(--piv6-card-head, var(--tema-color, #0d6efd));
  --rc-sec-bg:     color-mix(in srgb, var(--rc-sec) 15%, #fff);
  --rc-sec-bg-body:color-mix(in srgb, var(--rc-sec) 7%,  #fff);
  --rc-sec-ink:    color-mix(in srgb, var(--rc-sec) 72%, #12131a);
  --rc-sec-border: color-mix(in srgb, var(--rc-sec) 30%, #fff);
  /* chevron neutro (evita el azul del active-icon de BS sobre el fondo claro) */
  --bs-accordion-btn-active-icon: var(--bs-accordion-btn-icon);
}
.rc-panel-seccion .accordion-item{ border-color:var(--rc-sec-border); background-color:transparent; }
.rc-panel-seccion .accordion-button,
.rc-panel-seccion .accordion-button:not(.collapsed){
  background-color:var(--rc-sec-bg) !important;
  color:var(--rc-sec-ink) !important;     /* gana al .text-primary que agrega el fragmento */
  box-shadow:none;
}
.rc-panel-seccion .accordion-button .bi,
.rc-panel-seccion .accordion-button i{ color:var(--rc-sec-ink) !important; }
.rc-panel-seccion .accordion-button:focus{
  border-color:var(--rc-sec-border);
  box-shadow:0 0 0 .25rem color-mix(in srgb, var(--rc-sec) 22%, transparent);
}
.rc-panel-seccion .accordion-body{ background-color:var(--rc-sec-bg-body); color:#344054; }

/* ============================================================
   CARD CONTENEDOR DE PÁGINA (reemplazo del panel viejo de BS)
   Header tematizado via .card-header-tema (bg = --tema-color). Aquí solo
   añadimos el radio/sombra de la card y el layout del encabezado.
   ============================================================ */
/* Sin overflow:hidden: recortaba los popovers que se inyectan DENTRO del card —el calendario del
   datepicker, sobre todo—. El radio se mantiene redondeando el encabezado, que es el único hijo
   que llega al borde con fondo propio. */
.piv6-card-pagina{
  border:1px solid var(--piv6-line, #dde2ea);
  border-radius:12px;
  box-shadow:0 8px 26px -12px rgba(20,30,50,.28), 0 2px 6px rgba(20,30,50,.05);
}
.piv6-card-pagina > .piv6-card-pagina-head{ border-radius:12px 12px 0 0; }
.piv6-card-pagina > .piv6-card-pagina-head{
  /* Color de SECCIÓN (--piv6-card-head = C_Soluciones.bsBg del módulo de la página, el mismo del
     grupo activo del sidebar3), con fallback a --tema-color. Texto/iconos en blanco.
     REVERTIR a --tema-color: quita 'var(--piv6-card-head, ' y su ')' de la línea del background. */
  background-color: var(--piv6-card-head, var(--tema-color, var(--bs-primary, #0d6efd)));
  color:#fff;
  border-bottom:0;
  /* padding-left holgado: el rail del sidebar (esquina redondeada) se encima al inicio
     del header; así el icono siempre libra el borde. */
  padding:.85rem 1.1rem .85rem 2.2rem;
  font-size:1.05rem;
}
.piv6-card-pagina > .piv6-card-pagina-head .bi,
.piv6-card-pagina > .piv6-card-pagina-head b,
.piv6-card-pagina > .piv6-card-pagina-head a{ color:#fff; }
/* Icono decorado en círculo/badge semitransparente (estilo /proveedores/consulta). */
.piv6-card-pagina-badge{
  display:inline-flex; align-items:center; justify-content:center; flex:none;
  width:46px; height:46px; border-radius:14px;
  background:rgba(255,255,255,.22); box-shadow:0 1px 3px rgba(0,0,0,.18);
}
.piv6-card-pagina-badge .bi{ font-size:1.4rem; line-height:1; }
/* Título más grande. */
.piv6-card-pagina-titulo{ font-size:1.5rem; font-weight:700; letter-spacing:-.01em; min-width:0; margin:0; }

/* ============================================================
   BARRA DE KPIs DEL HEADER (slot `titulofrag` de card-pagina)
   Para las pantallas de UN documento: en vez del nombre de la pantalla, los datos que lo
   identifican. Cada KPI es etiqueta chica arriba + valor grande abajo, que es lo que hace que se
   lean como datos y no como una frase; en una sola línea corrida (Estatus · Fecha · Folio) el ojo
   no sabe dónde termina uno y empieza el siguiente.
   Va DENTRO del header de color, así que todo el texto es blanco: el valor a plena opacidad y la
   etiqueta al 72%, que es contraste suficiente para un rótulo de 7px y a la vez deja clara la
   jerarquía. No se usan colores propios: el color de esa franja ya significa algo (el estatus).
   El separador es un borde izquierdo translúcido en vez de un punto medio, porque sobrevive al
   salto de línea cuando la ventana es angosta.
   ============================================================ */
.piv6-card-kpis{
  display:flex; align-items:stretch; flex-wrap:wrap; gap:0;
  flex:1 1 auto; min-width:0;                 /* se queda con el ancho que dejan icono y acciones */
}
/* TODO ESTE BLOQUE VA ACOTADO A `.piv6-card-kpis` (issue #81). El nombre `.piv6-kpi` lo usan
   DOS componentes distintos del design system: éste -cada dato de la franja de color de la
   cabecera de página- y el de más arriba, el contenedor de los contadores en tarjeta
   (`.piv6-kpi` + `.piv6-kpi-item`, el del expediente de evidencias y la checklist del
   proveedor). Escrito sin acotar, éste ganaba por orden y le imponía al otro
   `flex-direction:column` -los tres contadores salían apilados en vez de en fila-,
   `padding:.1rem 1rem` -de ahí que su borde derecho no cuadrara con el del botón "Adjuntar
   Documento", que es lo que se reportó- y, peor, un `.piv6-kpi-lbl` BLANCO al 72%, que sobre la
   tarjeta blanca dejaba DOCUMENTOS / REVISADOS / FALTAN invisibles.
   La franja de cabecera siempre vive dentro de `.piv6-card-kpis`, así que acotarla ahí es
   suficiente y no toca ninguna plantilla. */
.piv6-card-kpis > .piv6-kpi{
  display:flex; flex-direction:column; justify-content:center; gap:.1rem;
  padding:.1rem 1rem; min-width:0;
  border-left:1px solid rgba(255,255,255,.28);
}
.piv6-card-kpis > .piv6-kpi:first-child{ border-left:0; padding-left:0; }
.piv6-card-kpis .piv6-kpi-lbl{
  font-size:.68rem; font-weight:700; letter-spacing:.4px; text-transform:uppercase;
  color:rgba(255,255,255,.72); white-space:nowrap; line-height:1.1;
}
.piv6-card-kpis .piv6-kpi-val{ font-size:1.12rem; font-weight:700; line-height:1.2; color:#fff; min-width:0; }
/* El proveedor es el único de largo imprevisible: es el que absorbe el espacio sobrante y el
   único que se recorta (el nombre completo queda en el title). Los demás son datos cortos y de
   ancho conocido: recortarlos sería perder el dato. */
.piv6-card-kpis .piv6-kpi-ancho{ flex:1 1 12rem; }
.piv6-card-kpis .piv6-kpi-ancho .piv6-kpi-val{ display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* El total se va a la derecha y pesa más: es la cifra por la que se abre la pantalla. */
.piv6-card-kpis .piv6-kpi-total{ margin-left:auto; align-items:flex-end; text-align:right; padding-right:0; }
.piv6-card-kpis .piv6-kpi-total .piv6-kpi-val{ font-size:1.3rem; white-space:nowrap; }
@media (max-width:767.98px){
  .piv6-card-kpis > .piv6-kpi{ padding:.1rem .6rem; }
  .piv6-card-kpis .piv6-kpi-val{ font-size:.98rem; }
  .piv6-card-kpis .piv6-kpi-total .piv6-kpi-val{ font-size:1.1rem; }
  /* En móvil el total baja de renglón: pegado a la izquierda como los demás, porque un `auto` que
     lo empuja a la derecha en una fila propia lo deja huérfano al otro extremo de la pantalla. */
  .piv6-card-kpis .piv6-kpi-total{ margin-left:0; align-items:flex-start; text-align:left; }
}
.piv6-card-pagina > .card-body{ padding:1.5rem 1.1rem 1.15rem; }

/* Botón de acciones legible sobre el fondo de sección (contorno claro tipo outline-light). */
.piv6-btn-head{
  display:inline-flex; align-items:center; gap:.4rem; white-space:nowrap; text-decoration:none;
  font-weight:600; font-size:.88rem; line-height:1; padding:.45rem .85rem;
  border-radius:var(--piv6-r-chico, 8px); border:1.5px solid rgba(255,255,255,.75);
  color:#fff; background:rgba(255,255,255,.12);
  transition:background-color .15s ease, border-color .15s ease, color .15s ease;
}
/* Hover: NO fondo blanco (dejaba texto blanco sobre blanco = invisible). Mantiene el texto
   blanco y solo intensifica el fondo translúcido, legible sobre el color de sección. */
.piv6-btn-head:hover{ background:rgba(255,255,255,.24); color:#fff; border-color:#fff; }
.piv6-btn-head:focus-visible{ outline:none; box-shadow:0 0 0 4px rgba(255,255,255,.35); }

/* CHIP DE SECCIÓN del header: dice de qué sección viene la pantalla, para que el color del
   encabezado se lea como información y no como decoración (el reporteador pinta un color distinto
   por reporte y sin esto no hay forma de saber por qué). NO es un botón -no lleva borde ni
   hover-: es una etiqueta, y por eso pesa menos que los .piv6-btn-head con los que puede convivir
   en la misma fila. */
.piv6-card-pagina-secc{
  display:inline-flex; align-items:center; gap:.55rem; white-space:nowrap;
  /* Mismo cuerpo que .piv6-card-pagina-titulo: el nombre de la sección pesa igual que el de la
     pantalla, uno a cada extremo del header. */
  font-weight:700; font-size:1.5rem; letter-spacing:-.01em; line-height:1; padding:.5rem 1.1rem;
  border-radius:999px; color:#fff; background:rgba(255,255,255,.2);
}
.piv6-card-pagina-secc .bi{ font-size:1.4rem; opacity:.95; }
@media (max-width:575.98px){ .piv6-card-pagina-secc{ display:none; } }
.piv6-btn-head .bi{ font-size:1rem; }

/* Panel de "control de cambios" (auditoriacomun) PEGADO al título del card y tematizado por
   SECCIÓN, con el mismo tratamiento suave que el header de Filtros (fondo 15% + ink 72%). */
.piv6-card-pagina > .card-body > .piv6-cc-glued{ margin:0 -1.1rem 1rem; }
.piv6-card-pagina > .card-body > .piv6-cc-glued > .card{ border:0; border-radius:0 0 12px 12px; margin:0; box-shadow:none; overflow:hidden; }
.piv6-card-pagina > .card-body > .piv6-cc-glued > .card > .card-header{
  background: color-mix(in srgb, var(--piv6-card-head, var(--tema-color, #0d6efd)) 15%, #fff);
  color: color-mix(in srgb, var(--piv6-card-head, var(--tema-color, #0d6efd)) 72%, #12131a);
  border:0; border-radius:0; padding-left:2.2rem;
}
.piv6-card-pagina > .card-body > .piv6-cc-glued > .card > .card-header a,
.piv6-card-pagina > .card-body > .piv6-cc-glued > .card > .card-header i{ color:inherit !important; }
/* Chevron: rota según el estado real del colapso (aria-expanded del trigger). El glyph server
   viene bi-chevron-up; colapsado lo apuntamos hacia abajo, expandido hacia arriba. */
.piv6-cc-glued .card-header a .bi-chevron-up,
.piv6-cc-glued .card-header a .bi-chevron-down{ transition:transform .2s ease; margin-left:auto; }
.piv6-cc-glued .card-header a[aria-expanded="false"] .bi-chevron-up,
.piv6-cc-glued .card-header a[aria-expanded="false"] .bi-chevron-down{ transform:rotate(180deg); }

@media (max-width:575.98px){
  .piv6-card-pagina > .piv6-card-pagina-head{ padding:.7rem .85rem .7rem 1.3rem; }
  .piv6-card-pagina-badge{ width:38px; height:38px; }
  .piv6-card-pagina-badge .bi{ font-size:1.15rem; }
  .piv6-card-pagina-titulo{ font-size:1.2rem; }
  .piv6-card-pagina > .card-body{ padding:.85rem; }
}

/* ============================================================
   FORMA con FOOTER STICKY (botonera pegada al fondo de la ventana)
   Patrón reutilizable de v6:
     <form class="piv6 piv6-form-page" ...>
       <div class="piv6-form-main"> ...card-pagina / campos... </div>
       <div class="piv6-form-footer">
         <div class="piv6-form-footer-in"> Regresar  Guardar </div>
       </div>
     </form>
   - Forma CORTA: el footer se ve al fondo de la ventana (min-height ~100vh en el form +
     .piv6-form-main con flex:1 que empuja el footer con margin-top:auto).
   - Forma LARGA: el footer queda pegado abajo mientras se hace scroll (position:sticky;bottom:0).
   - El footer es HERMANO del card (no va dentro de .piv6-card-pagina, que tiene overflow:hidden y
     rompería el sticky). .piv6-form-main reserva padding-bottom para que el footer no tape el
     último campo. --piv6-form-offset ≈ altura del navbar (ajustable).
   ============================================================ */
/* --piv6-themefoot-h = alto del footer FIJO del tema (comun/head::footerdesktop, .footer.fixed-bottom,
   ~15px, z-index 1030). La botonera sticky se apoya JUSTO ENCIMA de él (bottom = ese alto) con
   z-index mayor y fondo opaco, para que los botones no queden tapados/cortados por ese footer. */
/* --piv6-form-offset ≈ chrome superior. En el layout de SIDEBAR LATERAL (rail/expandido) NO hay
   navbar superior (el menú es lateral), así que el offset solo debe cubrir el footer fijo del tema
   (~15px) + un pequeño margen; de lo contrario la botonera sticky queda separada del footer de
   versión cuando la forma es corta. Los layouts con topbar pueden subir --piv6-form-offset. */
.piv6-form-page{ display:flex; flex-direction:column; min-height:calc(100dvh - var(--piv6-form-offset, 1.5rem)); --piv6-themefoot-h:15px; }
/* OJO CON EL FALLBACK: --piv6-themefoot-h sólo lo DECLARA .piv6-form-page, y hay pantallas que
   usan .piv6-form-main sin ella -las cinco del flujo de pagos (alta, revisar, autorizar, pagar,
   devrech) y la de confirmación de ingreso, que empujan el footer con .fp-page porque el <form> no
   abre la página-. Sin el fallback, var() no resuelve, el calc() entero queda INVÁLIDO y el
   navegador tira la declaración: el padding-bottom desaparecía, no se reservaba el hueco del pie y
   la botonera sticky se montaba encima del último renglón del contenido (se veía con la tabla de
   conceptos del CFDI en /flujopagos/ingresar). Las reglas de más abajo (.piv6-tab-content y la del
   card-body) ya traían el fallback; aquí faltaba. */
.piv6-form-main{ flex:1 1 auto; padding-bottom:calc(4.75rem + var(--piv6-themefoot-h, 15px)); }
.piv6-form-footer{
  position:sticky; bottom:var(--piv6-themefoot-h, 15px); z-index:1031; margin-top:auto;
  background:color-mix(in srgb, var(--piv6-tema, #0d6efd) 5%, #fff);
  border-top:1px solid var(--piv6-line, #dde2ea);
  box-shadow:0 -6px 18px -10px rgba(20,30,50,.3);
  padding:.7rem clamp(.6rem, 2vw, 1.1rem);
}
.piv6-form-footer-in{ display:flex; align-items:center; justify-content:flex-end; gap:.6rem; flex-wrap:wrap; }
/* CONVENCIÓN de footer v6: "Regresar" (boton-enlace → .piv6-btn-back) a la IZQUIERDA y los
   botones de acción a la DERECHA. El footer-in es justify-content:flex-end, así que el back-button
   se empuja solo con margin-right:auto. Aplica a TODA forma v6 que use el fragmento boton-enlace. */
.piv6-form-footer-in > .piv6-btn-back{ margin-right:auto; }
/* PASO A TRAVÉS de un envoltorio intermedio. .piv6-form-main (flex:1) y .piv6-form-footer
   (margin-top:auto) sólo empujan el pie al fondo si son HIJOS DIRECTOS del flex column que abre
   .piv6-form-page. El reporteador mete en medio un <fieldset id="filtro"> que no puede
   desaparecer -limpiaforma('#filtro') de comun/javascript.html barre los campos POR ESE
   SELECTOR-, y con él en medio la botonera se quedaba pegada bajo el card, a media página, en
   vez de irse abajo. Esta clase lo vuelve transparente al layout: sigue existiendo en el DOM
   (y con su id) pero reparte el alto como lo haría el propio form.
   Sirve para cualquier otro envoltorio que haya que conservar por un id o por el POST. */
.piv6-form-page > .piv6-form-pass{ display:contents; }
/* display:contents y NO un flex anidado: un <fieldset> con display:flex NO reparte el alto entre
   sus hijos (el contenido de un fieldset vive en una caja anónima), así que .piv6-form-main se
   quedaba en su alto natural y el pie no bajaba. Con contents el fieldset desaparece del layout y
   main/footer pasan a ser hijos directos del flex column del form, que es lo que necesitan.
   El elemento sigue en el DOM con su id, que es lo único que se tenía que conservar. */
@media (max-width:575.98px){ .piv6-form-footer-in > .piv6-btn-back{ margin-right:0; } }
/* El info de "faltantes" va DENTRO del grupo de acciones (después de "Solicitar Corrección"),
   así que Regresar conserva su margin-right:auto. Se ESTIRA al alto de los botones para verse parejo. */
/* ANCHO ELÁSTICO. El chip se lleva el hueco que queda entre los botones del pie, ni más ni menos.
   Antes tenía un max-width fijo de 26rem, puesto para que en el registro de proveedores una lista
   larguísima de documentos no empujara la botonera a TRES renglones. Aquel tope resolvía ese caso
   y estropeaba el contrario: en el modal de Adjuntar Documento el mensaje de validación se cortaba
   con puntos suspensivos MIENTRAS quedaba un hueco vacío a su derecha, porque el `ms-auto` del
   botón de acción se quedaba con todo el sobrante.
   La clave es `flex-basis:0` y no `auto`: con basis auto el item arranca del tamaño de su
   contenido, y en un contenedor con flex-wrap un texto largo provocaría el salto de línea ANTES de
   encogerse — justo las tres líneas que se querían evitar. Con basis 0 arranca en cero, crece sólo
   con el espacio libre y nunca fuerza el wrap.
   `min-width:0` en los dos niveles es lo que permite que un flex item se encoja por debajo de su
   contenido; sin eso el text-overflow:ellipsis de dentro no llega a activarse nunca. */
.piv6-footer-faltan{ display:flex; align-items:stretch; align-self:stretch; flex:1 1 0; min-width:0; }
.piv6-faltan-chip{
  display:inline-flex; align-items:center; gap:.35rem; font-size:.78rem; font-weight:600;
  padding:0 .8rem; border-radius:999px; cursor:help;
  background:color-mix(in srgb,var(--piv6-warn,#b45309) 10%,#fff); color:var(--piv6-warn-ink,#7c3d06); border:1.5px solid var(--piv6-warn,#b45309);
  /* El límite lo pone ahora el contenedor, no un número fijo: el texto se corta con puntos
     suspensivos SÓLO cuando de verdad no cabe, y el detalle completo sigue en el `title` (el chip
     es cursor:help justo por eso). El JS que lo alimenta manda además una versión corta con
     contador. */
  max-width:100%; min-width:0;
}
.piv6-faltan-chip:not(.is-info) > span:last-child{
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0;
}
.piv6-faltan-chip.is-ok{ background:color-mix(in srgb,var(--piv6-ok,#15803d) 10%,#fff); color:var(--piv6-ok-ink,#12602f); border-color:var(--piv6-ok,#15803d); cursor:default; }
/* Variante INFORMATIVA: NO es un faltante ni un error, es una nota de estado que ocupa el lugar de
   una acción que este usuario no puede ejecutar (p.ej. el alta definitiva del registro de
   proveedores, que va detrás de un sec:authorize y sin esto dejaba un HUECO en la botonera). Azul
   neutro para que no se lea como advertencia, esquina suave y white-space normal porque el texto es
   una frase, no una etiqueta, y en pantallas angostas debe poder partirse en dos renglones. */
.piv6-faltan-chip.is-info{
  background:color-mix(in srgb,#0d6efd 8%,#fff); color:#0a4fa3; border-color:#7ba9f0;
  padding:.4rem .8rem; border-radius:.75rem; text-align:left; white-space:normal;
  max-width:min(46rem,100%); font-weight:500;
}
/* Contenedor de una TABLA dentro de un card v6. NO uses .table-responsive de Bootstrap aquí:
   portal.css le mete un `min-height:375px` global (hack viejo para que quepan los dropdowns de las
   tablas), así que una tabla de dos filas deja un hueco enorme antes de lo que venga abajo. */
.piv6-tabla-wrap{ overflow-x:auto; }

/* Uso SUELTO del chip: pantallas todavía NO modernizadas (conciliasat, retenciones/fp, comisiones
   etl, citi cargar) que lo ponen encima de su botón y no dentro de la botonera sticky. Ahí no hay
   fila flex a la que estirarse, así que el chip pone su propio alto y su separación. */
.piv6-footer-faltan.piv6-faltan-suelto{ margin-bottom:.5rem; }
.piv6-faltan-suelto .piv6-faltan-chip{ padding:.4rem .8rem; }
/* …pero si ese mismo chip-estado se usa DENTRO de la botonera sticky (el caso de
   /flujopagos/alta, que necesita el chip con texto propio -qué documentos faltan- y por eso no
   puede usar chip-faltan), el margen y el padding del uso suelto lo descuadran contra los
   botones: aquí se comporta igual que chip-faltan (estirado al alto de la fila, sin margen). */
.piv6-form-footer-in > .piv6-faltan-suelto{ margin-bottom:0; }
.piv6-form-footer-in > .piv6-faltan-suelto .piv6-faltan-chip{ padding:0 .8rem; }
/* En movil el chip baja a su propio renglon a lo ancho: flex-basis:100% y no solo width, porque
   dentro de un flex el basis manda sobre el width y el 0 de arriba lo dejaria colapsado. */
@media (max-width:575.98px){ .piv6-footer-faltan{ order:99; width:100%; flex:1 1 100%; } .piv6-form-footer-in > .piv6-footer-faltan{ margin-right:0; } }

/* DATOS DE LA FACTURA en la cabecera del modal de Adjuntar Documento (columna derecha).
   La FECHA DE LA FACTURA es la que manda: es contra la que se valida el Inicio de Vigencia, asi que
   se destaca del resto -mas cuerpo y una superficie tenue- en vez de quedar como un dato mas. */
.adj-doc-clave .piv6-crd-dato{
  background:color-mix(in srgb, var(--rc-sec) 6%, #fff);
  border-color:color-mix(in srgb, var(--rc-sec) 25%, var(--piv6-line,#dde2ea));
}
/* La fecha se distingue por su SUPERFICIE (fondo y borde de acento, arriba), no por el tamaño de
   letra: el valor se queda en la escala normal de `dato` para que las dos columnas del modal se
   lean como un solo bloque. Antes iba a 1.05rem/800 y pesaba mucho más que los chips de la
   columna de al lado, con lo que el modal parecía dos componentes distintos pegados. */
@media (prefers-color-scheme: dark){
  .adj-doc-clave .piv6-crd-dato{ background:color-mix(in srgb, var(--rc-sec) 16%, #1c2130); border-color:#33405a; }
}
@media (max-width:575.98px){
  .piv6-form-main{ padding-bottom:calc(5.25rem + var(--piv6-themefoot-h)); }
  .piv6-form-footer-in > *{ flex:1 1 auto; }
  .piv6-form-footer-in .piv6-btn{ width:100%; justify-content:center; }
}

/* ============================================================
   TABS de formulario (nav-tabs BS5 nativos), tematizados con --piv6-tema.
   Para forms largos y complejos (p.ej. /proveedores/proveedor) organizados en
   secciones navegables SIN salir de un único <form> (los tab-panes ocultos
   siguen posteando sus campos: BS5 solo les pone display:none, eso no saca
   inputs del form ni afecta hidden fields). El tab ACTIVO al cargar lo decide
   el propio template server-side (#fields.hasErrors por sección), no JS, para
   que un campo inválido en un tab oculto nunca quede invisible al usuario;
   piv6-tab-error solo pinta el testigo visual en el tab que no está activo.
   Look: "folder tabs" de FuncionalMarket (ver comentario de reglas abajo).
   ============================================================ */
/* Estilo "folder tabs" (pestañas tipo carpeta) inspirado en el menutoolbar de
   FuncionalMarket: base .fm-tabs/.fm-tab (citas.css) + overrides del toolbar
   (login.css:702-720). Cada pestaña es un bloque con esquinas SUPERIORES
   redondeadas, fondo de tinte claro, icono + texto teñidos del color de la
   sección/tenant, un acento inferior siempre visible, y la pestaña ACTIVA con
   tinte más sólido + acento inferior a todo color, fundida con el panel de abajo
   (su borde inferior monta sobre la línea base del contenedor, sin línea que la
   corte). El portal solo tiene UN color por pantalla (--piv6-tema, color del
   tenant), así que todas las pestañas comparten tono y solo la activa se realza;
   para colorear por pestaña bastaría fijar --piv6-tab-c inline como hace FM. */
.piv6-tabs{
  --piv6-tab-c: var(--piv6-tema, #0d6efd);
  display:flex; flex-wrap:wrap; gap:.15rem; padding:0;
  border-bottom:2px solid color-mix(in srgb, var(--piv6-tab-c) 22%, var(--piv6-line, #dde2ea));
  margin-bottom:1rem;
}
.piv6-tabs .nav-item{ margin-bottom:-2px; } /* la pestaña activa monta sobre la línea base */
.piv6-tabs .nav-link{
  position:relative; border:0;
  border-radius:.5rem .5rem 0 0; /* esquinas superiores redondeadas = carpeta */
  color:color-mix(in srgb, var(--piv6-tab-c) 66%, var(--piv6-ink, #12131a));
  font:inherit; font-weight:600; font-size:.86rem; line-height:1.15; letter-spacing:.01em;
  padding:.5rem .95rem; display:inline-flex; align-items:center; gap:.45rem;
  background:color-mix(in srgb, var(--piv6-tab-c) 8%, transparent); /* tinte claro del folder */
  cursor:pointer;
  transition:color .15s ease, background-color .15s ease;
}
/* Acento inferior tenue del color de la sección, SIEMPRE visible (no solo hover) */
.piv6-tabs .nav-link::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:3px;
  background:color-mix(in srgb, var(--piv6-tab-c) 32%, transparent);
  transition:background-color .15s ease; pointer-events:none;
}
.piv6-tabs .nav-link .bi{ font-size:.95rem; color:var(--piv6-tab-c); transition:transform .15s ease; }
.piv6-tabs .nav-link:hover{
  color:color-mix(in srgb, var(--piv6-tab-c) 82%, var(--piv6-ink, #12131a));
  background:color-mix(in srgb, var(--piv6-tab-c) 12%, transparent);
}
.piv6-tabs .nav-link:hover::after{ background:color-mix(in srgb, var(--piv6-tab-c) 50%, transparent); }
.piv6-tabs .nav-link:focus-visible{
  outline:none; box-shadow:inset 0 0 0 2px var(--piv6-ring, rgba(13,110,253,.24));
  border-radius:.5rem .5rem 0 0;
}
/* Pestaña ACTIVA: tinte más sólido, texto/peso realzados y acento a todo color
   que se funde con el panel de abajo. */
.piv6-tabs .nav-link.active{
  color:var(--piv6-tab-c); font-weight:700;
  background:color-mix(in srgb, var(--piv6-tab-c) 15%, var(--piv6-surface, #fff));
}
.piv6-tabs .nav-link.active::after{ background:var(--piv6-tab-c); height:3px; }
.piv6-tabs .nav-link.active .bi{ transform:scale(1.06); }
/* Testigo de error de validación por sección: siempre visible y en rojo (danger),
   tanto en la pestaña activa como en las inactivas. */
.piv6-tabs .nav-link .piv6-tab-err{ color:var(--piv6-danger, #d64550); font-size:.8rem; }
@media (max-width:768px){
  .piv6-tabs{
    flex-wrap:nowrap; overflow-x:auto; overflow-y:hidden;
    scrollbar-width:thin; scrollbar-color:var(--piv6-line-strong, #c7cede) transparent;
    -webkit-overflow-scrolling:touch;
  }
  .piv6-tabs .nav-link{ white-space:nowrap; padding:.5rem .7rem; }
  .piv6-tabs::-webkit-scrollbar{ height:6px; }
  .piv6-tabs::-webkit-scrollbar-thumb{ background:var(--piv6-line-strong, #c7cede); border-radius:3px; }
  .piv6-tabs::-webkit-scrollbar-track{ background:transparent; }
}

@media (prefers-reduced-motion:reduce){ .piv6 *{ transition:none !important; } }

/* Tabs pfv6: altura mínima uniforme del contenido para que el card NO cambie de tamaño al
   alternar de pestaña (se ve del mismo alto sin importar la pestaña). Reutilizable: pon la
   clase `piv6-tab-content` en el <div class="tab-content"> de cualquier form con tabs. */
/* El tab-content SE ESTIRA a ocupar el viewport disponible (que el card llegue hasta el footer
   sticky, sin hueco entre el contenido y la botonera). Cadena flex: form-main → card → card-body
   → tab-content, todos crecen. El min-height es piso para viewports cortos. */
.piv6-tab-content{ min-height: 24rem; }
.piv6-form-main{ display:flex; flex-direction:column; }
.piv6-form-main > .piv6-card-pagina{ flex:1 1 auto; }
.piv6-card-pagina > .card-body:has(> .piv6-tab-content){ display:flex; flex-direction:column; }
.piv6-card-pagina > .card-body > .piv6-cc-glued{ flex:0 0 auto; }
.piv6-card-pagina > .card-body > .piv6-tabs{ flex:0 0 auto; }
.piv6-tab-content{ flex:1 1 auto; }
/* En forms con tabs: el padding-bottom que reserva el .piv6-form-main dejaba un HUECO entre el
   card y el footer (el footer es hermano, no encima). Se quita ese padding y se mueve DENTRO del
   tab-content, así el card llega pegado al footer y el contenido igual respira sobre la botonera. */
.piv6-form-main:has(.piv6-tab-content){ padding-bottom: 0; }
.piv6-tab-content{ padding-bottom: calc(4.75rem + var(--piv6-themefoot-h, 15px)); }

/* MISMO problema en forms SIN tabs (card-pagina simple, p.ej. proveedorescc/cambio): el card se
   estira (flex:1) pero el padding-bottom del form-main quedaba como HUECO entre el card y el footer
   sticky. Se quita ese padding y la reserva anti-footer se pasa al card-body, así el card llega
   pegado al footer y el último campo respira sobre la botonera al hacer scroll. */
.piv6-form-main:not(:has(.piv6-tab-content)):has(> .piv6-card-pagina){ padding-bottom: 0; }
.piv6-form-main:not(:has(.piv6-tab-content)) > .piv6-card-pagina{ display:flex; flex-direction:column; }
.piv6-form-main:not(:has(.piv6-tab-content)) > .piv6-card-pagina > .card-body{ flex:1 1 auto; padding-bottom: calc(3.5rem + var(--piv6-themefoot-h, 15px)); }

/* Glue del panel "Control de Cambios" al header del card: MISMA excepción que usa el panel de
   filtros (padding-top:0 del card-body cuando su primer hijo es el panel), para que el
   .piv6-cc-glued quede pegado al header morado y no cuelgue con un hueco arriba. */
.piv6-card-pagina > .card-body:has(> .piv6-cc-glued:first-child){ padding-top:0; }

/* ============================================================
   CONTENIDO del panel "Control de Cambios" (auditoriacomun :: historia).
   Timeline de revisiones legible y tematizado por SECCIÓN/tenant, compartido por
   proveedor / rol / contacto / usuario. Tokens con FALLBACK propio: el fragmento
   también se usa en pantallas sin ancestro .piv6, así que .cc-hist redefine sus
   variables desde --tema-color y degrada sin color-mix si no hay soporte.
   Cada revisión = tarjeta con acento por tipo (Alta=verde, Eliminación=rojo,
   Modificación=color de sección) + rejilla de campos "antes → después".
   Sin animaciones costosas (puede haber muchas revisiones listadas).
   ============================================================ */
.cc-hist{
  --cc-c: var(--piv6-card-head, var(--tema-color, #0d6efd));
  --cc-line: var(--piv6-line, #dde2ea);
  --cc-muted: var(--piv6-muted, #6a7383);
  --cc-faint: var(--piv6-faint, #9aa2b1);
  --cc-surface: var(--piv6-surface, #fff);
  --cc-text: var(--piv6-text, #1b2432);
  --cc-r: var(--piv6-r-chico, 8px);
  --cc-r-mini: var(--piv6-r-mini, 6px);
  /* acento por defecto (Modificación) = color de sección; success/danger lo pisan abajo */
  --cc-accent: var(--cc-c);
  --cc-accent-soft: color-mix(in srgb, var(--cc-c) 10%, var(--cc-surface));
  padding: .8rem .9rem 1rem;
  font-size: .86rem;
  line-height: 1.35;
  color: var(--cc-text);
}
.cc-hist *, .cc-hist *::before, .cc-hist *::after{ box-sizing:border-box; }

/* Acentos semánticos por tipo de revisión (Revision.getClase()). */
.cc-rev.cc-success{ --cc-accent:#1f9d57; --cc-accent-soft:#eaf7ef; }
.cc-rev.cc-danger { --cc-accent:var(--piv6-danger, #d64550); --cc-accent-soft:var(--piv6-danger-soft, #fdecee); }
.cc-rev.cc-info   { --cc-accent:var(--cc-c); --cc-accent-soft:color-mix(in srgb, var(--cc-c) 10%, var(--cc-surface)); }

/* Estado vacío */
.cc-hist-empty{
  display:flex; align-items:center; justify-content:center; gap:.5rem;
  padding:1.6rem 1rem; color:var(--cc-muted);
}
.cc-hist-empty .bi{ font-size:1.15rem; opacity:.7; }

/* Lista / timeline (una tarjeta por revisión) */
.cc-hist-list{ list-style:none; margin:0; padding:0; display:grid; gap:.55rem; }
.cc-rev{
  border:1px solid var(--cc-line);
  border-left:3px solid var(--cc-accent);
  border-radius:var(--cc-r);
  background:var(--cc-surface);
  box-shadow:var(--piv6-shadow-sm, 0 1px 2px rgba(20,30,50,.06));
  overflow:hidden;
}

/* Cabecera de la revisión: etiqueta de tipo + usuario/correo + fecha (a la derecha) */
.cc-rev-head{
  display:flex; align-items:center; flex-wrap:wrap; gap:.4rem .7rem;
  padding:.45rem .65rem;
  background:color-mix(in srgb, var(--cc-accent) 6%, var(--cc-surface));
  border-bottom:1px solid var(--cc-line);
}
.cc-tag{
  display:inline-flex; align-items:center; gap:.3rem;
  font-size:.68rem; font-weight:700; letter-spacing:.03em; text-transform:uppercase;
  color:var(--cc-accent); background:var(--cc-accent-soft);
  border:1px solid color-mix(in srgb, var(--cc-accent) 30%, transparent);
  padding:.14rem .5rem; border-radius:999px; white-space:nowrap;
}
.cc-tag .bi{ font-size:.85rem; }
.cc-user{ display:inline-flex; align-items:center; gap:.35rem; min-width:0; }
.cc-user .bi{ color:var(--cc-accent); font-size:1.05rem; flex:0 0 auto; }
.cc-user b{ font-weight:600; color:var(--cc-text); }
.cc-mail{
  color:var(--cc-muted); font-size:.78rem;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:16rem;
}
.cc-date{
  margin-left:auto; display:inline-flex; align-items:center; gap:.3rem;
  color:var(--cc-muted); font-size:.78rem; white-space:nowrap;
}
.cc-date .bi{ font-size:.85rem; }

/* Cuerpo: rejilla responsive de campos modificados */
.cc-rev-body{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(15rem, 1fr));
  gap:.4rem .55rem; padding:.55rem .65rem;
}
.cc-field{
  display:grid; gap:.2rem;
  padding:.35rem .5rem; border-radius:var(--cc-r-mini);
  background:color-mix(in srgb, var(--cc-line) 20%, transparent);
  min-width:0;
}
.cc-field-label{
  font-size:.68rem; font-weight:700; letter-spacing:.02em; text-transform:uppercase;
  color:var(--cc-muted);
}
.cc-vals{ display:flex; align-items:center; gap:.35rem; flex-wrap:wrap; min-width:0; }
.cc-val{
  display:inline-flex; align-items:center; min-height:1.4rem;
  padding:.06rem .45rem; border-radius:var(--cc-r-mini);
  font-size:.82rem; line-height:1.25; max-width:100%; overflow-wrap:anywhere;
}
.cc-val-old{ color:var(--cc-muted); background:color-mix(in srgb, var(--cc-line) 42%, transparent); }
.cc-val-new{ color:var(--cc-accent); background:var(--cc-accent-soft); font-weight:600; }
/* Un lado sin valor (alta o baja) → guion discreto en vez de hueco vacío */
.cc-val:empty::before{ content:'—'; color:var(--cc-faint); font-weight:400; }
.cc-arrow{ color:var(--cc-faint); font-size:.8rem; flex:0 0 auto; }

@media (max-width:575.98px){
  .cc-hist{ padding:.6rem .55rem .75rem; }
  .cc-date{ margin-left:0; }
  .cc-rev-body{ grid-template-columns:1fr; }
}

/* ============================================================
   TIPOS DE DOCUMENTO / EVIDENCIAS  (proveedor #tab-documentos)
   Checklist de tipos de documento del proveedor en REJILLA de TARJETAS
   compactas (hasta 4 por fila). Cada tarjeta es seleccionable (switch).
   Tematizada con --piv6-tema; el icono se tiñe por tipo de archivo.
   Markup en comun/inputs.html :: input-evidencia.
   ============================================================ */

/* Caja de ayuda: deja claro que sin selección el proveedor ve TODOS */
.piv6-doc-nota{
  display:flex; align-items:flex-start; gap:.5rem;
  background:var(--piv6-soft); color:var(--piv6-ink);
  border:1px solid var(--piv6-ring); border-radius:var(--piv6-r-chico);
  padding:.6rem .8rem; margin-bottom:.6rem;
  font-size:.84rem; line-height:1.4;
}
.piv6-doc-nota > .bi{ color:var(--piv6-tema); margin-top:.1rem; flex:none; font-size:1rem; }
.piv6-doc-nota strong{ color:var(--piv6-ink); }
.piv6-doc-nota-sub{ display:block; margin-top:.25rem; color:var(--piv6-muted); font-size:.78rem; }

/* Preview: qué verá el proveedor según la selección (sincronizado por JS mínimo) */
.piv6-doc-preview{
  display:flex; flex-wrap:wrap; align-items:center; gap:.4rem .6rem;
  background:var(--piv6-surface);
  border:1px solid var(--piv6-line-strong); border-radius:var(--piv6-r-chico);
  padding:.55rem .75rem; margin-bottom:.7rem;
}
.piv6-doc-preview.has-sel{ border-color:var(--piv6-tema); background:color-mix(in srgb, var(--piv6-tema) 4%, #fff); }
.piv6-doc-preview-hd{
  display:inline-flex; align-items:center; gap:.35rem; flex:none;
  font-weight:700; font-size:.74rem; text-transform:uppercase; letter-spacing:.03em;
  color:var(--piv6-tema);
}
.piv6-doc-preview-msg{ font-size:.82rem; color:var(--piv6-text); flex:none; }
.piv6-doc-preview.has-sel .piv6-doc-preview-msg{ font-weight:600; }
.piv6-doc-preview-chips{ display:flex; flex-wrap:wrap; gap:.3rem; min-width:0; }
.piv6-doc-preview-chip{
  display:inline-flex; align-items:center;
  background:var(--piv6-soft); color:var(--piv6-ink);
  border:1px solid color-mix(in srgb, var(--piv6-tema) 25%, transparent);
  border-radius:999px; padding:.08rem .55rem;
  font-size:.74rem; font-weight:600; max-width:16rem;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* REJILLA de tarjetas: hasta 4 por fila (breakpoints → 3 / 2 / 1) */
.piv6-doc-list{
  display:grid; gap:.6rem;
  grid-template-columns:repeat(4, minmax(0, 1fr));
}
@media (max-width:1199.98px){ .piv6-doc-list{ grid-template-columns:repeat(3, minmax(0, 1fr)); } }
@media (max-width:767.98px){ .piv6-doc-list{ grid-template-columns:repeat(2, minmax(0, 1fr)); } }
@media (max-width:479.98px){ .piv6-doc-list{ grid-template-columns:1fr; } }
/* Los <div> intermedios (th:each + th:insert) desaparecen para que la tarjeta
   sea el ítem directo del grid y todas queden a igual alto */
.piv6-doc-list > div:not(.piv6-doc-empty){ display:contents; }
.piv6-doc-list > div:not(.piv6-doc-empty) > div{ display:contents; }

/* Tarjeta = <label> compacta y vertical (toda la tarjeta alterna la selección) */
.piv6-doc{
  display:flex; flex-direction:column; gap:.35rem;
  margin:0; padding:.6rem .7rem; cursor:pointer; height:100%; min-width:0;
  background:var(--piv6-surface);
  border:1px solid var(--piv6-line); border-radius:var(--piv6-r-chico);
  box-shadow:var(--piv6-shadow-sm);
  transition:border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.piv6-doc:hover{ border-color:var(--piv6-line-strong); }
/* Estado seleccionado en vivo (sin JS) vía :has() sobre el checkbox real */
.piv6-doc:has(input[type=checkbox]:checked){
  border-color:var(--piv6-tema);
  background:color-mix(in srgb, var(--piv6-tema) 5%, #fff);
  box-shadow:0 0 0 1px var(--piv6-ring), var(--piv6-shadow-sm);
}
.piv6-doc:has(input[type=checkbox]:focus-visible){ box-shadow:0 0 0 3px var(--piv6-ring); }

/* Cabecera de la tarjeta: icono de tipo + etiqueta de tipo + switch a la derecha */
.piv6-doc-head{ display:flex; align-items:center; gap:.4rem; }
.piv6-doc-head .piv6-doc-sw{ margin-left:auto; }

/* Icono de tipo de archivo (por defecto tematizado; se colorea por tipo) */
.piv6-doc-ico{
  flex:none; width:34px; height:34px;
  display:flex; align-items:center; justify-content:center;
  border-radius:var(--piv6-r-mini); font-size:1.05rem;
  background:var(--piv6-soft); color:var(--piv6-tema);
}
.piv6-doc-ico.is-pdf{ background:#fdecec; color:#d64550; }
.piv6-doc-ico.is-excel{ background:#e7f5ec; color:#1e8e56; }
.piv6-doc-ico.is-xml{ background:#eaf1fd; color:#2b6cd6; }
.piv6-doc-ico.is-zip{ background:#fff3e0; color:#c47d18; }

.piv6-doc-body{ min-width:0; display:flex; flex-direction:column; gap:.15rem; }
.piv6-doc-titulo{
  display:flex; align-items:flex-start; gap:.3rem;
  font-weight:600; font-size:.86rem; color:var(--piv6-text); line-height:1.25;
}
.piv6-doc-titulo > span:first-child{
  min-width:0; overflow:hidden; text-overflow:ellipsis;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
}
/* Icono de ayuda por línea (tooltip nativo vía title): explica qué es el tipo
   de documento y qué significa la referencia de RFC. cursor:help para señalarlo */
.piv6-doc-info{ color:var(--piv6-faint); font-size:.78rem; cursor:help; flex:none; margin-top:.1rem; transition:color .15s ease; }
.piv6-doc-info:hover{ color:var(--piv6-tema); }

.piv6-doc-meta{
  display:flex; flex-wrap:wrap; align-items:center; gap:0 .4rem;
  font-size:.74rem; color:var(--piv6-muted); min-width:0;
}
/* «Aplica a:» = a qué emisor (RFC) corresponde este requisito */
.piv6-doc-aplica-lbl{ font-weight:600; color:var(--piv6-faint); text-transform:uppercase; letter-spacing:.03em; font-size:.64rem; flex:none; width:100%; }
.piv6-doc-rfc{ display:inline-flex; align-items:center; gap:.25rem; font-weight:600; letter-spacing:.02em; flex:none; cursor:help; }
.piv6-doc-rfc .bi{ opacity:.7; }
.piv6-doc-rs{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0; }

/* Nota por documento (comentariosProveedor de V_Evidencias), si existe */
.piv6-doc-coment{
  font-size:.73rem; color:var(--piv6-faint); line-height:1.3; margin-top:.05rem;
  overflow:hidden; text-overflow:ellipsis;
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
}

.piv6-doc-tags{ display:flex; flex-wrap:wrap; gap:.25rem; margin-top:auto; padding-top:.25rem; }
.piv6-doc-tag{
  display:inline-flex; align-items:center; gap:.25rem;
  font-size:.64rem; font-weight:700; letter-spacing:.02em; text-transform:uppercase;
  border-radius:999px; padding:.08rem .45rem; line-height:1.4;
}
.piv6-doc-tag .bi{ font-size:.7rem; }
.piv6-doc-tag.is-req{ background:var(--piv6-danger-soft); color:var(--piv6-danger); }
/* Vigencia: con vigencia = ámbar (acción/renovar) · sin vigencia = gris neutro.
   Iconos distintos (bi-calendar-check vs bi-infinity) para distinguir de un vistazo */
.piv6-doc-tag.is-vig{ background:#fff3e0; color:#b8730f; }
.piv6-doc-tag.is-novig{ background:#eef1f6; color:var(--piv6-muted); }
/* Etiqueta de tipo de archivo en la cabecera (junto al icono) */
.piv6-doc-head .piv6-doc-tag.is-tipo{ background:var(--piv6-soft); color:var(--piv6-ink); }

.piv6-doc-sw{ flex:none; }

/* Estado vacío (empresa sin tipos de documento definidos) */
.piv6-doc-empty{
  grid-column:1 / -1;
  text-align:center; padding:2rem 1rem; color:var(--piv6-faint);
  border:1px dashed var(--piv6-line-strong); border-radius:var(--piv6-r-chico);
  font-size:.86rem;
}
.piv6-doc-empty .bi{ font-size:1.6rem; display:block; margin-bottom:.4rem; opacity:.6; }

/* Hint (info) MOVIDO FUERA del .piv6-crd (issue: el hint dentro engordaba el card y desalineaba
   la fila). Ahora cuelga debajo del card, sin el borde del card, empujando su propio alto sin
   afectar la altura del campo vecino de la misma fila (align-items:start). */
.piv6-hint-out{ margin:.15rem 0 .1rem .3rem; }
/* .piv6-nl (forzar nueva fila) se declara ARRIBA, junto a las clases de ancho: como los
   cortes responsive tienen su misma especificidad (0,2,0), tiene que quedar ANTES que ellos
   o gana por orden y el campo nunca apila en móvil (issue #80). */

/* Switches junto al RFC (Expide CFDI / Requiere OC / Habilitado) en la fila compacta de identidad:
   comparten el espacio restante después del RFC (col-mini). El placeholder vacío ocupa su lugar
   cuando el tenant no usa Órdenes de Compra (Requiere OC no aplica → ¼ en blanco). */
.piv6-row-compacta > .piv6-col-sw{ flex:1 1 12rem; min-width:11rem; max-width:22rem; }
.piv6-row-compacta > .piv6-col-sw-empty{ min-width:11rem; }


/* ============================================================
   DATOS EN SOLO LECTURA (paneles de información)
   ------------------------------------------------------------
   Misma tarjeta/label de los campos capturables (.piv6-crd + .piv6-rowin + .piv6-lbl), pero con
   un VALOR estático en vez de un control. Sirve para las pantallas de revisión/consulta que hoy
   pintaban tablas grises etiqueta/valor ("Datos de la Factura", validación SAT, …).
   Fragmento: /comun/portal-inputs-v6 :: dato(titulo,valor).
   El ancho de cada dato se decide con las mismas clases piv6-cN del grid (issue #41): el ancho
   comunica la longitud del dato (RFC/fecha/monto = c3, UUID/uso CFDI = c6, …).
   ============================================================ */
.piv6-dato{
  display:block; min-width:0;
  font-size:.9rem; font-weight:650; line-height:1.3; color:var(--piv6-text);
  overflow-wrap:anywhere;
}
/* Valor ausente: guion tenue en vez de una celda vacía que se lee como "se perdió el dato". */
.piv6-dato.is-vacio{ color:var(--piv6-faint); font-weight:500; }
/* Identificadores (UUID, RFC, serie-folio, claves SAT): monoespaciado y un pelo más chico para
   que los 36 caracteres del UUID quepan sin romper la rejilla. */
.piv6-dato-mono{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
  font-size:.8rem; letter-spacing:.01em; font-weight:600;
}
/* Importes: alineados a la DERECHA dentro de su tarjeta (convención de montos) + tabular. */
.piv6-crd:has(.piv6-dato-num) .piv6-field{ text-align:right; }
.piv6-dato-num{ font-variant-numeric:tabular-nums; font-weight:700; }
/* Valores que NO deben partirse en dos renglones (fechas con hora, folios): el ancho de la
   celda alcanza, lo que sobraba era el salto de linea. */
.piv6-dato-nw{ white-space:nowrap; }

/* ------------------------------------------------------------
   Panel de datos en COLUMNA ANGOSTA (opt-in: .piv6-grid-datos en el .piv6-grid)
   ------------------------------------------------------------
   Al meter la "Ruta del Documento" al lado, los paneles de datos del flujo de pagos pasaron de
   ancho completo a col-xl-8. Ahí la tarjeta de un campo ¼ mide ~175px y, como .piv6-rowin
   reserva 8.5rem FIJOS para la etiqueta, al valor le quedaban ~30px: "Serie" partía E-19349 en
   dos renglones, el RFC salía en tres y el total en tres.
   La regla es una CONTAINER QUERY, no un media query, a propósito: lo que decide es el ancho de
   la TARJETA -que depende de si el panel va a 8/12 o a 12/12- y no el del viewport, así que el
   mismo fragmento sirve en las dos disposiciones sin parametrizarlo ni duplicarlo. Bajo 24rem la
   etiqueta se pasa ARRIBA y el valor se queda con el ancho completo de la tarjeta.
   Se declara SOLO en los grids marcados (no en .piv6-crd-dato a secas) para no cambiar de golpe
   los paneles de las pantallas que hoy se ven bien a ancho completo. */
.piv6-grid-datos > * > .piv6-crd-dato{ container-type:inline-size; container-name:piv6dato; }
/* Con la etiqueta arriba cada tarjeta ya trae su propio aire, así que el gap de .piv6-grid (.55 /
   .75rem, pensado para campos capturables) deja el panel demasiado aireado: se reduce a la MITAD.
   El padding del contenedor lo baja el fragmento cambiando p-3 por p-2. */
.piv6-grid-datos{ gap:.28rem .38rem; }
@container piv6dato (max-width: 24rem){
  .piv6-crd-dato > .piv6-rowin{
    grid-template-columns:1fr; align-items:start; gap:.05rem; min-height:0;
  }
  /* Con la etiqueta arriba, el valor ya no necesita el tirón a la derecha del importe: el número
     queda pegado al borde y se lee como si se hubiera desalineado. */
  .piv6-crd-dato:has(.piv6-dato-num) > .piv6-rowin > .piv6-field{ text-align:left; }
}
/* Apunte al margen del valor (fragmento `dato`, parámetro `extra`): la FECHA junto a quien hizo el
   movimiento. Pastilla tenue para que se lea como metadato y no compita con el nombre. */
.piv6-dato-extra{
  margin-left:.4rem; padding:.05rem .4rem; border-radius:999px;
  font-size:.68rem; font-weight:700; white-space:nowrap;
  color:var(--piv6-muted,#6a7383); background:color-mix(in srgb,var(--piv6-muted,#6a7383) 10%,#fff);
  border:1px solid color-mix(in srgb,var(--piv6-muted,#6a7383) 22%,transparent);
}
@media (prefers-color-scheme: dark){
  .piv6-dato-extra{ background:color-mix(in srgb,var(--piv6-muted,#6a7383) 22%,#1c2130); border-color:#33405a; }
}

/* Moneda del importe (antes iba en un <sup> suelto). */
.piv6-moneda{
  margin-left:.3rem; font-size:.66rem; font-weight:700; letter-spacing:.04em;
  color:var(--piv6-muted); text-transform:uppercase; white-space:nowrap;
}
/* Selects/controles "heredados" (fragmentos viejos de comun/inputs, p.ej. select-moneda) que se
   hospedan dentro de una tarjeta piv6: les damos la piel de .piv6-ctrl SIN tocar el fragmento
   compartido (que sigue sirviendo a pantallas todavía no modernizadas). */
.piv6 .piv6-field > select:not(.piv6-ctrl){
  width:100%; font:inherit; font-size:.9rem; color:var(--piv6-text);
  border:0; background:transparent; padding:.18rem 0; cursor:pointer;
}
.piv6 .piv6-field > select:not(.piv6-ctrl):focus{ outline:none; }

/* Los datos de solo lectura NO llevan la barra de acento (esa marca "obligatorio" en captura). */
.piv6-crd-dato::before{ display:none; }
.piv6-crd-dato{ background:color-mix(in srgb, var(--rc-sec) 3%, #fff); }

/* Salto de fila explícito del grid: obliga a que el SIGUIENTE campo arranque en la columna 1,
   sin ocupar una celda visible (a diferencia de un .piv6-cN vacío, que en tablet/móvil sí deja
   media fila en blanco). Sirve para separar bloques lógicos dejando el sobrante EN BLANCO. */
.piv6-grid > .piv6-salto{ grid-column:1 / -1; height:0; margin:0; padding:0; }

/* Título de sub-bloque dentro de una rejilla de datos (p.ej. "Documentos relacionados"). */
.piv6-grid > .piv6-datos-titulo{
  grid-column:1 / -1;
  display:flex; align-items:center; gap:.45rem;
  font-size:.72rem; font-weight:800; letter-spacing:.06em; text-transform:uppercase;
  color:color-mix(in srgb, var(--rc-sec) 62%, #5a6472);
  margin:.5rem 0 .05rem;
}
.piv6-grid > .piv6-datos-titulo::after{
  content:""; flex:1 1 auto; height:1px;
  background:color-mix(in srgb, var(--rc-sec) 22%, var(--piv6-line));
}
.piv6-grid > .piv6-datos-titulo .bi{ font-size:.9rem; opacity:.8; }


/* ============================================================
   CONCEPTOS DEL CFDI (fragmento /comun/infocfdi :: infocfdi)
   ------------------------------------------------------------
   Antes: una tabla BS3 con rowspan=4, clases `success`/`info` (que ya no existen en BS5) y una
   tabla anidada por clasificación. Ahora: una TARJETA por clasificación SAT (cabecera con las
   claves División/Grupo/Clase/ClaveProdServ) + la tabla de partidas, y un resumen de importes
   alineado a la derecha. Todo teñido por el color de sección (--rc-sec).
   ============================================================ */
.piv6-cfdi{ display:grid; gap:.6rem; }
.piv6-cfdi-tit{
  display:flex; align-items:center; gap:.45rem;
  font-size:.75rem; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
  color:color-mix(in srgb, var(--rc-sec) 62%, #5a6472);
}
.piv6-cfdi-tit .bi{ font-size:1rem; opacity:.85; }

.piv6-cps{
  border:1px solid var(--piv6-line); border-radius:var(--piv6-r-chico);
  background:var(--piv6-surface); overflow:hidden;
}
.piv6-cps-head{
  display:flex; flex-wrap:wrap; align-items:center; gap:.35rem .5rem;
  padding:.45rem .6rem;
  background:color-mix(in srgb, var(--rc-sec) 8%, #fff);
  border-bottom:1px solid color-mix(in srgb, var(--rc-sec) 16%, var(--piv6-line));
}
/* Clave SAT del concepto: la más importante de la cabecera. */
.piv6-cps-clave{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:.78rem; font-weight:800; letter-spacing:.02em;
  color:#fff; background:color-mix(in srgb, var(--rc-sec) 78%, #1b2432);
  border-radius:999px; padding:.1rem .5rem; white-space:nowrap;
}
.piv6-cps-desc{ font-size:.86rem; font-weight:700; color:var(--piv6-text); min-width:0; }
/* Chips de la clasificación (División / Grupo / Clase): etiqueta tenue + valor fuerte. */
.piv6-cps-chips{ display:flex; flex-wrap:wrap; gap:.3rem; margin-left:auto; }
.piv6-cps-chip{
  display:inline-flex; align-items:baseline; gap:.3rem;
  font-size:.7rem; border-radius:999px; padding:.1rem .5rem;
  background:var(--piv6-soft); color:var(--piv6-ink);
  border:1px solid color-mix(in srgb, var(--rc-sec) 18%, transparent);
  max-width:100%;
}
.piv6-cps-chip b{ font-weight:700; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.piv6-cps-chip span{ opacity:.7; font-weight:600; text-transform:uppercase; letter-spacing:.04em; font-size:.62rem; flex:none; }

/* Partidas del concepto */
.piv6-part{ width:100%; margin:0; border-collapse:collapse; font-size:.82rem; }
.piv6-part thead th{
  font-size:.66rem; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
  color:var(--piv6-muted); background:#fbfcfe;
  padding:.3rem .6rem; border-bottom:1px solid var(--piv6-line); white-space:nowrap;
}
.piv6-part td{ padding:.32rem .6rem; border-bottom:1px solid color-mix(in srgb, var(--piv6-line) 60%, #fff); vertical-align:top; }
.piv6-part tbody tr:last-child td{ border-bottom:0; }
.piv6-part .num{ text-align:right; white-space:nowrap; font-variant-numeric:tabular-nums; }
.piv6-part .uni{ white-space:nowrap; color:var(--piv6-muted); }
.piv6-part .uni b{ color:var(--piv6-ink); }
.piv6-part .des{ font-weight:600; color:var(--piv6-text); }

/* CONCEPTOS DEL CFDI: columnas ALINEADAS ENTRE GRUPOS.
   Un CFDI con varias ClaveProdServ pinta UNA TABLA POR GRUPO, y con el layout automático cada una
   repartía el ancho según su propio contenido: "Descripción" arrancaba en un punto en un bloque y
   ~60px más a la izquierda en el siguiente, así que se leían como tablas distintas en vez de como
   una sola lectura vertical.
   Con table-layout:fixed mandan los anchos declarados y no el contenido, así que todos los grupos
   quedan a plomo. Cant / Unidad de Medida / Importe van FIJAS y Descripción se queda con el
   sobrante, que es la única que de verdad necesita crecer.
   Sólo aplica a las tablas de conceptos (.piv6-cps): la de órdenes de compra
   (recepcionescomun::infooc) también es .piv6-part pero trae NUEVE columnas y con anchos fijos en
   las tres primeras quedaría rota. */
.piv6-cps .piv6-part{ table-layout:fixed; min-width:36rem; }
/* Cant: cabe "15155" y también "1.0000". Importe: el monto más el sufijo de moneda
   ($1,234,567.89 MXN) sin partirse. Unidad: clave + descripción (E48 · Unidad de servicio). */
.piv6-cps .piv6-part th:nth-child(1), .piv6-cps .piv6-part td:nth-child(1){ width:5.5rem; }
.piv6-cps .piv6-part th:nth-child(2), .piv6-cps .piv6-part td:nth-child(2){ width:13rem; }
.piv6-cps .piv6-part th:nth-child(4), .piv6-cps .piv6-part td:nth-child(4){ width:10rem; }
/* Con ancho fijo, lo que no cabe tiene que ENVOLVER en vez de desbordar la celda. La unidad pierde
   el nowrap por eso; los números lo conservan (sus columnas ya están dimensionadas para ellos). */
.piv6-cps .piv6-part .uni{ white-space:normal; overflow-wrap:anywhere; }
.piv6-cps .piv6-part .des{ overflow-wrap:anywhere; }

/* Resumen de importes (subtotal / descuento / impuestos / total) */
.piv6-tot{ margin-left:auto; width:min(26rem,100%); display:grid; gap:.1rem; }
.piv6-tot-fila{
  display:grid; grid-template-columns:1fr auto; align-items:baseline; gap:.6rem;
  padding:.22rem .6rem; font-size:.82rem; border-radius:var(--piv6-r-mini);
}
.piv6-tot-fila > span{ color:var(--piv6-muted); }
.piv6-tot-fila > b{ font-variant-numeric:tabular-nums; font-weight:700; white-space:nowrap; }
.piv6-tot-fila.is-neg > b{ color:var(--piv6-danger); }
.piv6-tot-total{
  background:color-mix(in srgb, var(--rc-sec) 10%, #fff);
  border:1px solid color-mix(in srgb, var(--rc-sec) 22%, transparent);
  font-size:.95rem; padding:.35rem .6rem; margin-top:.2rem;
}
.piv6-tot-total > span{ color:color-mix(in srgb, var(--rc-sec) 60%, #12131a); font-weight:800; text-transform:uppercase; letter-spacing:.05em; font-size:.72rem; }
.piv6-tot-total > b{ font-size:1rem; }
/* El renglón destacado puede además llevar veredicto (lo estrenó el SALDO de centro de costos:
   mientras no sea cero, el flujo de pagos no se puede enviar). */
.piv6-tot-total.is-ok{
  background:color-mix(in srgb,#2fb344 10%,#fff); border-color:color-mix(in srgb,#2fb344 30%,transparent);
}
.piv6-tot-total.is-ok > span{ color:#1a7a2e; }
.piv6-tot-total.is-ok > b{ color:#1a7a2e; }
.piv6-tot-total.is-error{
  background:var(--piv6-danger-soft,#fdecee); border-color:color-mix(in srgb,var(--piv6-danger,#d64550) 35%,transparent);
}
.piv6-tot-total.is-error > span{ color:var(--piv6-danger,#d64550); }
.piv6-tot-total.is-error > b{ color:var(--piv6-danger,#d64550); }

/* ============================================================
   CENTRO DE COSTOS (comun/centrocostos.html)
   Panel de prorrateo: captura a la izquierda, conceptos capturados y totales a la derecha.
   Reusa .piv6-crd/.piv6-grid para los campos y .piv6-tot para el resumen; aquí sólo va lo
   propio de la pantalla. El acento sale de --rc-sec (color de SECCIÓN), como el resto.
   ============================================================ */
.cc-captura{
  border:1px solid var(--piv6-line,#dde2ea); border-radius:var(--piv6-r-chico,8px);
  background:color-mix(in srgb, var(--rc-sec) 4%, #fff);
  padding:.75rem .85rem;
}
/* El botón Agregar va en su propio renglón, a la derecha (convención v6). */
.cc-agregar{ display:flex; align-items:stretch; }
/* El monto se lee como número: alineado a la derecha y con cifras de ancho fijo. Ancho mínimo
   pensado para un importe grande con separadores y dos decimales, no para el caso corto. */
.cc-monto{ text-align:right; font-variant-numeric:tabular-nums; min-width:7rem; }
/* En la columna de captura la etiqueta no necesita las 8.5rem del piv6-rowin por defecto: cada
   rem que cede es ancho para el importe. */
.cc-captura .piv6-rowin{ grid-template-columns:6.5rem 1fr; }

/* Tabla de conceptos capturados. Se queda como <table> porque el JS hace append al tbody, pero
   pierde el table-striped/bordered/condensed de BS3 y se apoya en líneas suaves. */
.cc-tabla{ margin-bottom:.5rem; }
.cc-tabla > thead > tr > th{
  border-bottom:1px solid var(--piv6-line,#dde2ea);
  font-size:.7rem; font-weight:800; text-transform:uppercase; letter-spacing:.04em;
  color:var(--piv6-muted,#6a7383); padding:.3rem .5rem;
}
.cc-tabla > tbody > tr > td{
  border-bottom:1px solid color-mix(in srgb, var(--piv6-line,#dde2ea) 60%, transparent);
  padding:.35rem .5rem; font-size:.82rem; vertical-align:middle;
}
.cc-tabla > tbody > tr:last-child > td{ border-bottom:0; }
.cc-tabla .cc-num{ text-align:right; white-space:nowrap; }
.cc-tabla .cc-monto-val{ font-variant-numeric:tabular-nums; font-weight:700; }
.cc-tabla .cc-concepto{ overflow-wrap:anywhere; }
.cc-tabla .cc-del{
  display:inline-flex; align-items:center; justify-content:center;
  width:1.7rem; height:1.7rem; padding:0; margin-right:.4rem; vertical-align:middle;
}
/* Estado vacío: sin conceptos capturados la tabla se quedaba con puros encabezados. El aviso va
   FUERA de la tabla (un ::after sobre <tbody> genera una caja que no es hija válida de una tabla
   y cada navegador la coloca a su modo) y se esconde solo en cuanto hay filas, gracias a :has().
   Así el JS que hace append no tiene que acordarse de quitarlo. */
.cc-vacio{
  padding:.5rem .6rem; margin-bottom:.5rem;
  border:1px dashed var(--piv6-line-strong,#c7cede); border-radius:var(--piv6-r-chico,8px);
  font-size:.78rem; color:var(--piv6-muted,#6a7383);
  display:flex; align-items:center; gap:.4rem;
}
.cc-tabla:has(tbody tr) + .cc-vacio{ display:none; }
.cc-tot{ margin-left:auto; }


/* ============================================================
   ADJUNTAR DOCUMENTO (fragmento /comun/fpcomun :: adjuntar)
   ------------------------------------------------------------
   Lista de documentos ya cargados / faltantes + botonera del alta de evidencias.
   ============================================================ */
.piv6-evi{ display:flex; flex-wrap:wrap; gap:.35rem; }
.piv6-evi-item{
  display:inline-flex; align-items:center; gap:.35rem;
  font-size:.78rem; font-weight:600; border-radius:999px; padding:.18rem .6rem;
  border:1px solid transparent; max-width:100%;
}
.piv6-evi-item > span:last-child{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.piv6-evi-ok{ background:#e9f7ec; color:#1a7a2e; border-color:#bfe6c8; }
.piv6-evi-falta{ background:var(--piv6-danger-soft); color:var(--piv6-danger); border-color:color-mix(in srgb,var(--piv6-danger) 30%,transparent); }
.piv6-evi-lbl{
  font-size:.7rem; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
  color:var(--piv6-muted); display:flex; align-items:center; gap:.35rem; margin-bottom:.25rem;
}
/* Giro del icono mientras sube el archivo. spin() de portal.js solo sabe de FontAwesome
   (data-icon + fa-pulse), así que los botones con icono bi usan esta clase. */
@keyframes piv6-girar{ to{ transform:rotate(360deg); } }
.piv6-spin{ display:inline-block; animation:piv6-girar .9s linear infinite; }
@media (prefers-reduced-motion:reduce){ .piv6-spin{ animation:none; } }

/* Pasos 1-2-3 del alta de documento (la duda del usuario era el ORDEN). */
.piv6-pasos{ display:flex; flex-wrap:wrap; gap:.4rem 1rem; margin:.1rem 0 .6rem; }
.piv6-paso{ display:inline-flex; align-items:center; gap:.4rem; font-size:.78rem; color:var(--piv6-muted); }
.piv6-paso b{
  flex:none; width:1.25rem; height:1.25rem; border-radius:999px;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--rc-sec); color:#fff; font-size:.7rem; font-weight:800;
}

/* ============================================================
   GUÍA DE PASOS (.piv6-guia) — el bloque "¿Cómo realizar X?" de las pantallas de flujo de
   pagos, que arma comun/inputsv2.html :: instrucciones(). Es la variante VERTICAL de
   .piv6-pasos: aquel es para pasos de dos palabras en una línea ("Elige el tipo",
   "Selecciona el archivo"); aquí cada paso es una frase completa y en horizontal no cabe.
   El acento sale del color de SECCIÓN (--rc-sec, que declara .piv6) y cae al del tenant.
   ============================================================ */
.piv6-guia{
  /* --guia tiñe los números y la separación; --guia-chip es el color del BOTÓN real que
     aparecerá al terminar, que no siempre coincide (en revisar/pagar el panel es neutro pero
     el botón es verde). */
  --guia: var(--rc-sec);
  --guia-chip:#16a34a;                /* = .piv6-btn-success */
}
.piv6-guia-warning{ --guia:#b45309; --guia-chip:#b45309; }   /* = .piv6-btn-warning */
/* Variante EN CAJA: cuando la guía no vive en su propio panel colapsable (instrucciones()) sino
   DENTRO del cuerpo de otro panel -la ayuda de /flujopagos/alta, que va arriba del formulario de
   captura-, necesita su propia superficie para no quedar flotando sobre el fondo del panel. */
.piv6-guia-caja{
  border:1px solid var(--piv6-line,#dde2ea);
  border-left:3px solid var(--guia);
  background:color-mix(in srgb, var(--guia) 5%, #fff);
  border-radius:var(--piv6-r-chico,8px);
  padding:.65rem .85rem; margin-bottom:.75rem;
  display:grid; gap:.5rem;
}
@media (prefers-color-scheme: dark){
  .piv6-guia-caja{ background:color-mix(in srgb, var(--guia) 14%, #1c2130); border-color:#33405a; }
}
.piv6-guia-danger{  --guia:var(--piv6-danger,#d64550); --guia-chip:var(--piv6-danger,#d64550); }

.piv6-guia-pasos{
  list-style:none; margin:0; padding:0;
  display:grid; gap:.55rem;
  counter-reset:piv6paso;
}
.piv6-guia-pasos > li{
  position:relative;
  display:flex; align-items:flex-start; gap:.6rem;
  font-size:.86rem; line-height:1.45;
  color:var(--piv6-text,#1b2432);
}
.piv6-guia-pasos > li::before{
  counter-increment:piv6paso;
  content:counter(piv6paso);
  flex:none; width:1.45rem; height:1.45rem; border-radius:999px;
  display:inline-flex; align-items:center; justify-content:center;
  background:var(--guia); color:#fff;
  font-size:.75rem; font-weight:800; line-height:1;
}
/* Hilo que une un paso con el siguiente: hace que se lean como una SECUENCIA y no como tres
   viñetas independientes, que es justo lo que se perdía con el <ul> del mensaje. */
.piv6-guia-pasos > li:not(:last-child)::after{
  content:"";
  position:absolute; left:.7rem; top:1.55rem; bottom:-.55rem; width:2px;
  background:color-mix(in srgb, var(--guia) 28%, transparent);
}

/* Resultado: "al completar los pasos aparecerá el botón X". */
.piv6-guia-fin{
  display:flex; align-items:center; flex-wrap:wrap; gap:.35rem .5rem;
  margin-top:.8rem; padding-top:.7rem;
  border-top:1px dashed color-mix(in srgb, var(--guia) 32%, transparent);
  font-size:.83rem; color:var(--piv6-muted,#6a7383);
}
.piv6-guia-fin-ico{ color:var(--guia-chip); font-size:1rem; }
/* Réplica del botón real (mismo icono, texto y color) para que se reconozca de un vistazo. */
.piv6-guia-chip{
  display:inline-flex; align-items:center; gap:.35rem;
  padding:.28rem .65rem; border-radius:999px;
  background:var(--guia-chip); color:#fff;
  font-size:.78rem; font-weight:700; line-height:1.2;
}
.piv6-guia-chip .bi{ font-size:.85rem; }

/* ============================================================
   docprov — expediente de DOCUMENTOS del proveedor.
   Lo consume /comun/docpendientescomun.html (lado CLIENTE: autorizar, documentos
   vigentes/vencidos y el panel "Adjuntar Archivo") bajo el contenedor .docprov-comun.
   Antes vivía como <style> inline dentro de la plantilla y con clases contextuales de
   Bootstrap 3 (verde/azul quemados). El acento se deriva del color de SECCIÓN
   (--piv6-card-head, que fija card-pagina) y cae al color del TENANT (--tema-color).
   ============================================================ */
.docprov-comun{ --docprov-acc: var(--piv6-card-head, var(--tema-color, #0d6efd)); }

/* Encabezado de sección (Por Autorizar / Vigentes / Vencidos) + su línea de ayuda. */
.docprov-comun .docprov-seccion{
  display:flex; align-items:center; gap:.4rem; flex-wrap:wrap;
  margin:1rem 0 .3rem; font-size:1rem; font-weight:800;
  color:var(--docprov-acc);
}
.docprov-comun .docprov-seccion .bi{ opacity:.85; }
.docprov-comun .docprov-ayuda{
  margin:0 0 .5rem .15rem; font-size:.8rem; color:#6a7383;
}

/* Acordeón de documentos (uno por tipo de documento). */
.docprov-comun .docprov-acc .accordion-button{ font-weight:600; }
.docprov-comun .docprov-acc .accordion-button:not(.collapsed){
  color:var(--docprov-acc);
  background:color-mix(in srgb, var(--docprov-acc) 12%, #fff);
  box-shadow:none;
}
.docprov-comun .docprov-acc .accordion-button:focus{
  box-shadow:0 0 0 .2rem color-mix(in srgb, var(--docprov-acc) 25%, transparent);
  border-color:color-mix(in srgb, var(--docprov-acc) 40%, transparent);
}
.docprov-comun .docprov-acc .accordion-button:not(.collapsed)::after{ filter:none; }

/* Chip de estado del documento (En revisión / N archivos). */
.docprov-comun .docprov-chip{
  display:inline-flex; align-items:center; gap:.3rem;
  font-size:.72rem; font-weight:700; line-height:1.4;
  padding:.15rem .55rem; border-radius:999px;
  color:var(--docprov-acc);
  background:color-mix(in srgb, var(--docprov-acc) 14%, #fff);
  border:1px solid color-mix(in srgb, var(--docprov-acc) 30%, transparent);
}
.docprov-comun .docprov-chip.is-ok{ color:#1a7a2e; background:#e9f7ec; border-color:#bfe6c8; }
.docprov-comun .docprov-chip.is-venc{
  color:#d64550; background:#fdecee; border-color:color-mix(in srgb, #d64550 30%, transparent);
}

/* Tarjeta por ARCHIVO dentro del acordeón (sustituye la tabla + .table-responsive). */
.docprov-comun .docprov-arch-body{ display:grid; gap:.4rem; padding:.6rem .75rem; }
.docprov-comun .docprov-arch{
  display:flex; flex-wrap:wrap; align-items:center; gap:.3rem .9rem;
  padding:.45rem .65rem; background:#fff;
  border:1px solid #dde2ea; border-left:3px solid #c7cede; border-radius:8px;
}
.docprov-comun .docprov-arch.is-ok{ border-left-color:#3ea55c; }
.docprov-comun .docprov-arch.is-venc{ border-left-color:#d64550; background:#fffafa; }
.docprov-comun .docprov-arch-nom{
  display:inline-flex; align-items:center; gap:.4rem; min-width:0; max-width:100%;
  font-weight:600; text-decoration:none; color:var(--docprov-acc);
}
.docprov-comun .docprov-arch-nom > span:last-child{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.docprov-comun .docprov-arch-nom:hover{ text-decoration:underline; }
.docprov-comun .docprov-meta{
  display:inline-flex; align-items:center; gap:.3rem; min-width:0;
  font-size:.78rem; color:#6a7383;
}
.docprov-comun .docprov-meta .bi{ opacity:.75; }
.docprov-comun .docprov-meta-com{ max-width:24rem; }
.docprov-comun .docprov-meta-com > span:last-child{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.docprov-comun .docprov-vig{ font-weight:700; }
.docprov-comun .docprov-arch.is-ok .docprov-vig{ color:#1a7a2e; }
.docprov-comun .docprov-arch.is-venc .docprov-vig{ color:#d64550; }

/* Acción de la tarjeta (editar / desautorizar): a la derecha de la fila. */
.docprov-comun .docprov-arch-btn{
  margin-left:auto; flex:none;
  display:inline-flex; align-items:center; justify-content:center;
  width:2.2rem; height:2.2rem; border-radius:8px; text-decoration:none;
  color:var(--docprov-acc);
  background:color-mix(in srgb, var(--docprov-acc) 8%, #fff);
  border:1px solid color-mix(in srgb, var(--docprov-acc) 30%, transparent);
  transition:background .15s ease, color .15s ease;
}
.docprov-comun .docprov-arch-btn:hover{ background:var(--docprov-acc); color:#fff; }

/* En móvil la tarjeta se apila y la acción deja de flotar a la derecha. */
@media (max-width:575.98px){
  .docprov-comun .docprov-arch{ align-items:flex-start; flex-direction:column; }
  .docprov-comun .docprov-arch-btn{ margin-left:0; }
}

/* ============================================================
   Carga masiva de pagos: bloques de código (XML del CFDI y traza del error).
   .codeXml no tenía NINGUNA regla: vivía dentro de un contenedor de 400px de alto fijo, sin
   scroll ni ajuste de línea, así que el XML se desbordaba de la tarjeta. Ahora es un bloque
   monoespaciado con tope de alto y scroll propio. Lo usan comun/masivacomun.html y las
   pantallas clientes/recepcionespagos/masiva*.
   ============================================================ */
.codeXml,
.codeTraza{
  display:block; max-height:22rem; overflow:auto;
  margin:0; padding:.6rem .75rem;
  font-family:var(--bs-font-monospace, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size:.72rem; line-height:1.45;
  white-space:pre-wrap; word-break:break-word;
  background:rgba(15,23,42,.04); color:#334155;
  border:1px solid rgba(15,23,42,.10); border-radius:8px;
}
.codeTraza code{ color:inherit; }

/* ============================================================
   Información de Órdenes de Compra (#infoOcDiv) — lo pinta comun/javascript.html :: infooc
   y aparece en recepciones/revisar y en flujopagos/alta y revisar.

   Rediseño 2026-08-16. De qué se venía:
   - Los ocho datos se pintaban como valores SUELTOS, sin etiqueta: la etiqueta existía pero
     sólo dentro del `title`, así que había que pasar el mouse por cada celda para saber qué
     era ese número. Ahora cada dato lleva su etiqueta visible, con la tipografía del propio
     design system (.piv6-lbl / .piv6-dato) para no abrir una escala nueva.
   - La fila entera iba teñida con `text-bg-${estatusColor}`. Verde y ámbar ocupaban todo el
     renglón sin decir de qué hablaban —el estado sólo se leía en una celda a la mitad— y
     encima mentían de tono: son los colores de CERRADA y ABIERTA, dos estados neutros que en
     semáforo se leen como "bien" y "cuidado". El color se concentra ahora en el chip de
     estatus, que trae icono + texto: el significado no depende del color (y así también lo
     lee quien no distingue verde de ámbar).
   - Todo iba apretado en una rejilla de 8 columnas fijas, con las celdas pegadas unas a otras.
     Ahora cada OC es una tarjeta con el ritmo de los demás bloques piv6 y los datos toman el
     ancho que pide su contenido (una fecha no mide lo que la lista de agentes).
   ============================================================ */
.oc-info{ display:flex; flex-direction:column; gap:.5rem; }

/* El borde va con --piv6-line-strong y no con --piv6-line: estas tarjetas se apilan sobre el
   gris del contenedor, y con la línea suave (#dde2ea sobre #f4f6f9) el contorno desaparecía —
   se leían como texto suelto en la página, no como tarjetas. */
.oc-oc{
  border:1px solid var(--piv6-line-strong, #c7cede);
  border-radius:var(--piv6-r-chico, 8px);
  background:var(--piv6-surface, #ffffff);
  color:var(--piv6-text, #1b2432);
  box-shadow:var(--piv6-shadow-sm, 0 1px 2px rgba(20,30,50,.06));
  overflow:hidden;
}
/* Las órdenes que NO son la de esta factura: la sección ya las rotula, esto sólo acompaña. */
.oc-oc.is-otra{ background:color-mix(in srgb, var(--piv6-line, #dde2ea) 22%, var(--piv6-surface, #ffffff)); }

/* --- Encabezado: folio, estatus e importe, que son los tres datos "ancla" de la OC --- */
.oc-cab{
  display:flex; align-items:center; gap:.6rem; flex-wrap:wrap;
  padding:.45rem .6rem;
  border-bottom:1px solid var(--piv6-line, #dde2ea);
  background:color-mix(in srgb, var(--piv6-line, #dde2ea) 45%, var(--piv6-surface, #ffffff));
}
/* Folio e importe: los dos extremos del encabezado, con la MISMA estructura etiqueta/valor que
   los datos de abajo, para que el folio tampoco dependa de que el usuario adivine qué número es.
   El folio se distingue por tamaño y peso, no por ser el único sin rotular. */
.oc-folio{ display:inline-flex; flex-direction:column; gap:.05rem; }
.oc-folio .piv6-dato{ font-size:1rem; font-weight:750; font-variant-numeric:tabular-nums; }
/* El importe se va al extremo derecho: es la cifra que se compara entre órdenes.
   Las cifras tabulares y el nowrap ya vienen de .piv6-dato-num / .piv6-dato-nw. */
.oc-imp{ margin-left:auto; display:inline-flex; flex-direction:column; gap:.05rem; align-items:flex-end; }

/* --- Chip de estatus: aquí vive el color, y nunca solo --- */
.oc-chip{
  display:inline-flex; align-items:center; gap:.3rem;
  padding:.1rem .5rem; border-radius:999px;
  font-size:.75rem; font-weight:600; white-space:nowrap;
  border:1.5px solid currentColor;
}
.oc-chip > i{ font-size:.8em; }
/* Los cuatro estatus de C_Estatus_Oc. El tono se deriva del color declarado en el enum
   (warning/success/primary/danger) para no inventar una paleta paralela. */
.oc-chip-success{ color:#1a7a2e; background:color-mix(in srgb,#2fb344 12%,#fff); }
.oc-chip-warning{ color:#8a5a00; background:color-mix(in srgb,#f0a020 12%,#fff); }
.oc-chip-primary{ color:#0a4fa3; background:color-mix(in srgb,#0d6efd 10%,#fff); }
.oc-chip-danger { color:#a52222; background:color-mix(in srgb,#dc3545 10%,#fff); }

/* --- Los datos: ancho según el contenido, no todo a fila completa ---
   Es FLEX y no grid a propósito. Con `grid auto-fit` + spans de 1/2/3 columnas los datos no
   encajaban en la retícula que el auto-fit iba calculando: quedaban huecos grandes entre
   columnas y un dato suelto se iba a un renglón para él solo. En flex cada dato pide su ancho
   base según lo que le toca —una fecha no mide lo que la lista de agentes— y los renglones se
   llenan seguidos. */
.oc-datos{
  display:flex; flex-wrap:wrap; gap:.45rem 1.25rem;
  padding:.5rem .6rem;
  align-items:flex-start;
}
/* .piv6-lbl ya es inline-flex con su gap, y .piv6-dato.is-vacio ya se pinta tenue: aquí sólo
   se apila etiqueta sobre valor y se permite partir cadenas largas (UUID, listas de agentes). */
.oc-d{ display:flex; flex-direction:column; gap:.05rem; min-width:0; }
.oc-d .piv6-dato{ overflow-wrap:anywhere; line-height:1.3; }
.oc-d-sm{ flex:0 1 auto; min-width:7rem; }   /* fechas            */
.oc-d-md{ flex:1 1 12rem; max-width:22rem; } /* comprador         */
.oc-d-lg{ flex:2 1 16rem; }                  /* agentes, concepto */

/* --- Separador de "Otras Órdenes…" --- */
.oc-sep{
  display:flex; align-items:center; gap:.4rem; flex-wrap:wrap;
  margin-top:.35rem; padding:.3rem .1rem;
  font-size:.8rem; font-weight:600;
  color:var(--piv6-muted, #6a7383);
  border-top:1px dashed var(--piv6-line, #dde2ea);
}
.oc-sep-prov{ display:inline-flex; align-items:center; gap:.3rem; font-weight:700; }

/* OSCURO. Las variables --piv6-* NO se redefinen por tema en este archivo (--piv6-surface es
   #ffffff fijo): cada componente declara su propio override con los tonos de la casa, #1c2130
   de fondo y #33405a de borde. Sin esto la tarjeta se quedaba blanca en modo oscuro. */
@media (prefers-color-scheme: dark){
  /* --piv6-text (#1b2432) se declara UNA vez en .piv6 y no se aclara por tema, porque el resto
     del design system siempre se pinta sobre --piv6-surface, que es blanco fijo. Al poner la
     tarjeta en oscuro, .piv6-dato seguía escribiendo en gris casi negro sobre #1c2130 y los
     VALORES quedaban ilegibles (las etiquetas no, porque .piv6-lbl sí tiene su propio tono).
     Se redefinen las dos variables en el ámbito de la tarjeta —no globalmente— para que todo
     lo que las consume dentro de ella se aclare solo.
     No pasaba con el diseño anterior porque las celdas usaban `text-bg-*` de Bootstrap, que
     fija fondo Y color de texto a la vez. */
  .oc-oc{
    background:#1c2130; border-color:#33405a;
    --piv6-text:#e6e9ef;
    --piv6-muted:#9aa6bd;
  }
  .oc-oc.is-otra{ background:#171b28; }
  .oc-cab{ background:#222839; border-bottom-color:#33405a; }
  .oc-sep{ border-top-color:#33405a; color:#9aa6bd; }
  .oc-chip-success{ color:#7ee2a8; background:color-mix(in srgb,#2fb344 22%,#1c2130); }
  .oc-chip-warning{ color:#fbbf24; background:color-mix(in srgb,#f0a020 22%,#1c2130); }
  .oc-chip-primary{ color:#8ab4ff; background:color-mix(in srgb,#0d6efd 22%,#1c2130); }
  .oc-chip-danger { color:#f87171; background:color-mix(in srgb,#dc3545 22%,#1c2130); }
}

/* En pantalla chica los datos bajan a dos columnas y los anchos por contenido dejan de
   aplicar: a 390px cualquier `span 3` desborda. */
@media (max-width:767.98px){
  .oc-d-sm{ flex:1 1 40%; min-width:0; }        /* las dos fechas, lado a lado */
  .oc-d-md,.oc-d-lg{ flex:1 1 100%; max-width:none; }
  .oc-imp{ margin-left:0; width:100%; }
}

/* Monto + Agregar a mitad y mitad, con el mismo alto: el botón se estira a lo que mida la caja
   del campo (.piv6-crd suma su padding al min-height de .piv6-rowin, así que un piv6-btn suelto
   siempre quedaba más bajo). El importe se alinea a la derecha para que no se lea perdido en
   medio de la caja. */
.cc-agregar{ display:flex; align-items:stretch; align-self:stretch; height:100%; }
.cc-agregar > .piv6-btn{ flex:1 1 auto; justify-content:center; height:100%; }
/* El importe pegado a SU etiqueta (alineación natural del input). A la derecha se veía encajado
   contra el filo de la caja, y como el botón Agregar arranca 9px después, el número quedaba
   aplastado entre los dos. tabular-nums para que las cifras no bailen al teclear. */
.cc-captura .cc-monto{ text-align:left; font-variant-numeric:tabular-nums; }


/* ============================================================
   ESTADO VACÍO GENÉRICO
   ------------------------------------------------------------
   Mismo tratamiento que el .cc-vacio de centro de costos, pero sin apellido de módulo: cualquier
   lista/tabla v6 que se quede sin renglones puede usarlo en vez de dejar puros encabezados.
   ============================================================ */
.piv6-vacio{
  padding:.6rem .7rem; border:1px dashed var(--piv6-line-strong,#c7cede);
  border-radius:var(--piv6-r-chico,8px); font-size:.82rem; color:var(--piv6-muted,#6a7383);
  display:flex; align-items:center; gap:.45rem;
}


/* ============================================================
   APLICACIÓN DE PAGOS POR EXCEL (.fpx-*)
   ------------------------------------------------------------
   Tabla de revisión de los renglones leídos del .xlsx
   (clientes/flujopagos/excelcomun.html :: revisar).

   POR QUÉ NO ES UNA TABLA `comun/tablas5 :: ultrapro`: ultrapro es para CONSULTAS (celdas de solo
   lectura, sticky-col, paginación, dropdown de acciones). Aquí la tabla vive DENTRO de un <form>,
   sus celdas son inputs con th:field y las filas se recolorean por estatus desde el JS conforme
   el backend va aplicando cada pago. Se queda como <table class="table"> de Bootstrap 5 —para que
   table-danger/warning/success sí pinten— con la piel del design system v6.
   ============================================================ */
.fpx-tabla > thead > tr > th{
  border-bottom:1px solid var(--piv6-line,#dde2ea);
  font-size:.7rem; font-weight:800; text-transform:uppercase; letter-spacing:.04em;
  color:var(--piv6-muted,#6a7383); padding:.35rem .5rem; white-space:nowrap;
}
.fpx-tabla > thead > tr > th .bi{ margin-right:.3rem; opacity:.75; }
.fpx-tabla > tbody > tr > td{
  padding:.3rem .5rem; vertical-align:middle; font-size:.82rem;
  border-bottom:1px solid color-mix(in srgb, var(--piv6-line,#dde2ea) 60%, transparent);
}
.fpx-tabla > tbody > tr:last-child > td{ border-bottom:0; }
/* Cada columna de dato se ciñe a su contenido; el sobrante se lo lleva la de Estado. El min-width
   NO es decorativo: sin él, cuando la tabla entra en scroll horizontal (pantalla angosta) el
   navegador aplasta esta columna a unos pocos caracteres y el mensaje de error del backend —que
   son varias líneas de HTML— estira la fila a cientos de píxeles de alto, dejando la tabla llena
   de huecos. Con el tope, el mensaje envuelve en 2-3 renglones y la fila se mantiene compacta. */
.fpx-tabla .fpx-col-estado{ width:100%; }
.fpx-tabla > thead > tr > th:last-child,
.fpx-tabla > tbody > tr > td:last-child{ min-width:17rem; }
.fpx-tabla .fpx-num{ text-align:right; }

/* Celda de captura. Los inputs de SOLO LECTURA siguen ahí (son el contrato de la forma) pero se
   leen como texto: una fila de cajas vacías se lee como "aquí se captura" y es mentira, solo la
   fecha de pago lo es. */
.fpx-campo{ display:inline-flex; align-items:baseline; max-width:100%; }
.fpx-num .fpx-campo{ justify-content:flex-end; width:100%; }
.fpx-ctrl{ font-size:.82rem; min-width:6rem; }
.fpx-num .fpx-ctrl{ text-align:right; font-variant-numeric:tabular-nums; max-width:9rem; }
.fpx-ctrl[readonly]{
  border-color:transparent; background:transparent; box-shadow:none;
  padding-left:0; padding-right:0; font-weight:600; color:var(--piv6-text,#1b2432);
}
.fpx-ctrl[readonly]:focus{ border-color:transparent; box-shadow:none; }

/* Estado del renglón: mismo lenguaje de chip que .piv6-evi-item. El JS de la pantalla cambia la
   clase de estado (is-pend -> is-ok / is-error) conforme termina cada pago. */
.fpx-msg{
  display:inline-flex; align-items:flex-start; gap:.35rem;
  font-size:.74rem; font-weight:600; border-radius:.75rem; padding:.2rem .6rem;
  border:1px solid transparent; max-width:100%;
}
/* Los mensajes de error del backend pueden traer varias líneas de HTML: el chip crece sin
   deformarse (por eso el radio suave y no la píldora completa de .piv6-evi-item). */
.fpx-msg .bi{ flex:none; margin-top:.1rem; }
.fpx-msg > span:last-child{ overflow-wrap:anywhere; }
/* "Por aplicar" es un estado NEUTRO: gris fijo, no el tinte del tenant (--piv6-soft). Teñido del
   tenant se leía como un estado semántico más (en Telemundo salía rosa, casi como el de error). */
.fpx-msg.is-pend{ background:#f1f3f7; color:var(--piv6-muted,#6a7383); border-color:var(--piv6-line,#dde2ea); }
.fpx-msg.is-warn{ background:#fff6e5; color:#8a5a00; border-color:#ffe0a3; }
.fpx-msg.is-ok{ background:#e9f7ec; color:#1a7a2e; border-color:#bfe6c8; }
.fpx-msg.is-error{
  background:var(--piv6-danger-soft,#fdecee); color:var(--piv6-danger,#d64550);
  border-color:color-mix(in srgb, var(--piv6-danger,#d64550) 30%, transparent);
}

/* Resultado del proceso (#fin). Arranca oculto (.d-none) y el JS le pone is-ok / is-error. */
.fpx-fin{
  margin-top:.75rem; padding:.6rem .8rem; font-size:.86rem;
  border:1px solid transparent; border-radius:var(--piv6-r-chico,8px);
  display:flex; align-items:center; flex-wrap:wrap; gap:.25rem;
}
.fpx-fin.is-ok{ background:#e9f7ec; color:#1a7a2e; border-color:#bfe6c8; }
.fpx-fin.is-error{
  background:var(--piv6-danger-soft,#fdecee); color:var(--piv6-danger,#d64550);
  border-color:color-mix(in srgb, var(--piv6-danger,#d64550) 30%, transparent);
}

/* ============================================================================
   .rpv — RUTA DEL DOCUMENTO / RUTA DEL REGISTRO
   Timeline vertical con bitácora (quién hizo cada paso y cuándo) que sirve a las
   DOS rutas del portal: la de flujo de pagos (10 pasos) y la del registro de
   proveedores (4 pasos). El markup lo emite `comun/rutaproceso :: ruta(tipo,datos)`,
   que entrega SÓLO el cuerpo — el marco (panel de la cascada o bloque con <h6>) lo
   pone cada pantalla.

   PALETA: la que los usuarios ya conocen, los `color` de C_Estatus_FlujoPagos
   (VALIDADA #454545 · ENREVISION #00B1D0 · PORAUTORIZAR #A327A0 · PORPAGAR #808080 ·
   PAGADA #008A00 · DEVUELTA #E3B838 · RECHAZADA #E02441). El color crudo llega por
   la variable inline --rp-est y se usa TAL CUAL donde va como relleno con texto
   blanco (igual que en las tablas de consulta, que es donde el usuario lo aprendió).
   Donde el mismo color tiene que ser TEXTO sobre fondo claro se usa --rp-est-ink,
   que es el mismo matiz mezclado hacia el negro: #00B1D0 como texto sobre blanco
   da 2.4:1 y sería ilegible. En oscuro la mezcla se voltea hacia el blanco.
   --rp-sec es el color de SECCIÓN (C_Soluciones.bsBg: flujo de pagos #16A34A,
   proveedores #9333EA) y es el que pinta los pasos YA HECHOS, para que el timeline
   no se lea como siete estados distintos.
   ========================================================================== */
.rpv{
  --rp-sec: var(--piv6-card-head, var(--tema-color, #0d6efd));
  --rp-est: var(--rp-sec);
  --rp-est-ink: color-mix(in srgb, var(--rp-est) 74%, #12131a);
  --rp-pend:#c7cede;
  --rp-tuyo:#15803d;  --rp-tuyo-bg:color-mix(in srgb,#2fb344 10%,#fff);  --rp-tuyo-bd:#2fb344;
  --rp-ajeno:#0a4fa3; --rp-ajeno-bg:color-mix(in srgb,#0d6efd 8%,#fff);  --rp-ajeno-bd:#7ba9f0;
  --rp-bloq:#8a5a00;  --rp-bloq-bg:color-mix(in srgb,#f0a020 10%,#fff);  --rp-bloq-bd:#f0a020;
  --rp-desv:#7a5300;  --rp-desv-bg:color-mix(in srgb,#E3B838 16%,#fff);  --rp-desv-bd:#E3B838;
  --rp-rech:#a01b2c;  --rp-rech-bg:color-mix(in srgb,#E02441 10%,#fff);  --rp-rech-bd:#E02441;
  --rp-prov:#7028c4;  --rp-prov-bg:color-mix(in srgb,#9333EA 10%,#fff);  --rp-prov-bd:#c4a1f5;
  font-size:1rem; color:var(--piv6-text,#1b2432);
  padding:.85rem .9rem 1rem;
}
.rpv *,.rpv *::before,.rpv *::after{ box-sizing:border-box; }

/* --- 1. resumen: "Paso N de M" + pastilla de estatus + barra de progreso --- */
.rpv-resumen{ display:flex; align-items:center; gap:.5rem; flex-wrap:wrap;
  font-size:.78rem; font-weight:700; color:var(--piv6-muted,#6a7383); margin-bottom:.3rem; }
.rpv-est{ display:inline-flex; align-items:center; gap:.25rem; padding:.12rem .5rem;
  border-radius:999px; font-weight:800; font-size:.72rem; color:#fff; background:var(--rp-est); }
.rpv-track{ display:flex; gap:3px; margin-bottom:.65rem; }
.rpv-seg{ height:5px; flex:1 1 0; border-radius:3px; background:var(--rp-pend); }
.rpv-seg.is-hecho{ background:var(--rp-sec); }
.rpv-seg.is-actual{ background:var(--rp-est);
  box-shadow:0 0 0 2px color-mix(in srgb,var(--rp-est) 25%,transparent); }
.rpv-seg.is-noaplica{ background:repeating-linear-gradient(90deg,var(--rp-pend) 0 3px,transparent 3px 6px); }
.rpv-seg.is-desvio{ flex:0 0 8px; background:var(--rp-desv-bd); }
.rpv-seg.is-rechazo{ flex:0 0 8px; background:var(--rp-rech-bd); }

/* --- 2. renglón de TURNO (2ª persona): contesta "¿tengo que hacer algo?" ---
   Va ARRIBA del timeline a propósito: el timeline contesta "¿dónde va?" y ése es
   el dato secundario. Sin este renglón el usuario tiene que deducir su turno del
   último nodo, que es justo el error que originó el reporte de soporte. */
.rpv-turno{ display:flex; align-items:flex-start; gap:.45rem; padding:.5rem .6rem; margin-bottom:.75rem;
  border-radius:var(--piv6-r-mini,6px); font-size:.84rem; line-height:1.35; border:1px solid; }
.rpv-turno .rpv-tico{ flex:none; font-size:1.05rem; margin-top:.02rem; }
.rpv-turno b{ font-weight:800; }
.rpv-turno.is-tuyo     { background:var(--rp-tuyo-bg);  color:var(--rp-tuyo);  border-color:var(--rp-tuyo-bd); }
.rpv-turno.is-ajeno    { background:var(--rp-ajeno-bg); color:var(--rp-ajeno); border-color:var(--rp-ajeno-bd); }
.rpv-turno.is-bloqueado{ background:var(--rp-bloq-bg);  color:var(--rp-bloq);  border-color:var(--rp-bloq-bd); }
.rpv-turno.is-fin      { background:var(--rp-tuyo-bg);  color:var(--rp-tuyo);  border-color:var(--rp-tuyo-bd); }
.rpv-turno.is-prov     { background:var(--rp-prov-bg);  color:var(--rp-prov);  border-color:var(--rp-prov-bd); }
.rpv-turno.is-desvio   { background:var(--rp-desv-bg);  color:var(--rp-desv);  border-color:var(--rp-desv-bd); }
.rpv-turno.is-rechazo  { background:var(--rp-rech-bg);  color:var(--rp-rech);  border-color:var(--rp-rech-bd); }

/* --- 3. timeline --- */
.rpv-paso{ display:grid; grid-template-columns:24px minmax(0,1fr); gap:.55rem;
  position:relative; padding-bottom:.65rem; }
.rpv-paso:last-child{ padding-bottom:0; }
.rpv-rail{ position:relative; display:flex; justify-content:center; }
.rpv-paso:not(:last-child) .rpv-rail::after{ content:""; position:absolute; top:24px; bottom:-.65rem;
  width:2px; background:var(--rp-pend); }
.rpv-paso.is-hecho:not(:last-child) .rpv-rail::after{ background:var(--rp-sec); }
.rpv-paso.is-desvio:not(:last-child) .rpv-rail::after{ background:var(--rp-desv-bd); }
.rpv-paso.is-noaplica:not(:last-child) .rpv-rail::after{
  background:repeating-linear-gradient(180deg,var(--rp-pend) 0 4px,transparent 4px 8px); }

.rpv-nodo{ position:relative; z-index:1; width:22px; height:22px; border-radius:50%; background:#fff;
  border:2px solid var(--rp-pend); color:#8b93a3;
  display:inline-flex; align-items:center; justify-content:center; font-size:.8rem; }
.rpv-paso.is-hecho .rpv-nodo{ background:var(--rp-sec); border-color:var(--rp-sec); color:#fff; }
.rpv-paso.is-actual .rpv-nodo{ border-color:var(--rp-est); color:var(--rp-est-ink);
  border-width:2.5px; box-shadow:0 0 0 3.5px color-mix(in srgb,var(--rp-est) 20%,transparent); }
.rpv-paso.is-noaplica .rpv-nodo{ border-style:dashed; background:#f4f6fa; }
.rpv-paso.is-desvio .rpv-nodo{ background:var(--rp-desv-bd); border-color:var(--rp-desv-bd); color:#4a3400; }
.rpv-paso.is-rechazo .rpv-nodo{ background:var(--rp-rech-bd); border-color:var(--rp-rech-bd); color:#fff; }
/* Candado sobre el nodo ACTUAL cuando la acción no es de este usuario: es la señal
   que explica el hueco de la botonera antes de leer una sola palabra. */
.rpv-lock{ position:absolute; z-index:2; right:-4px; bottom:-3px; width:13px; height:13px; border-radius:50%;
  background:var(--rp-ajeno); color:#fff; font-size:.5rem; display:inline-flex;
  align-items:center; justify-content:center; border:1.5px solid #fff; }
.rpv-paso.es-prov .rpv-lock{ background:var(--rp-prov); }

.rpv-titulo{ font-size:.88rem; font-weight:700; line-height:1.25;
  display:flex; align-items:center; gap:.3rem; flex-wrap:wrap; min-height:22px; }
.rpv-paso.is-pendiente .rpv-titulo{ font-weight:600; color:var(--piv6-muted,#6a7383); }
.rpv-paso.is-noaplica  .rpv-titulo{ font-weight:500; color:var(--piv6-faint,#9aa2b1); }
.rpv-paso.is-actual    .rpv-titulo{ font-weight:800; }
.rpv-glifo{ opacity:.5; font-size:.92em; }
.rpv-meta{ font-size:.76rem; color:var(--piv6-muted,#6a7383); margin-top:.08rem;
  display:flex; align-items:center; gap:.25rem; flex-wrap:wrap; line-height:1.3; }
.rpv-meta .bi{ font-size:.8rem; opacity:.75; }
.rpv-meta .sep{ opacity:.4; }

.rpv-tag{ display:inline-flex; align-items:center; gap:.2rem; font-size:.66rem; font-weight:700;
  padding:.08rem .4rem; border-radius:999px; white-space:nowrap;
  background:color-mix(in srgb,var(--rp-sec) 14%,#fff);
  color:color-mix(in srgb,var(--rp-sec) 78%,#12131a);
  border:1px solid color-mix(in srgb,var(--rp-sec) 30%,#fff); }
.rpv-tag.is-prov{ background:var(--rp-prov-bg); color:var(--rp-prov); border-color:var(--rp-prov-bd); }
.rpv-tag.is-na{ background:#f1f3f7; color:#8b93a3; border-color:#dde2ea; }
.rpv-tag.is-tu{ background:var(--rp-tuyo-bg); color:var(--rp-tuyo); border-color:var(--rp-tuyo-bd); }
.rpv-tag.is-alerta{ background:var(--rp-bloq-bg); color:var(--rp-bloq); border-color:var(--rp-bloq-bd); }
/* DOS actores en un solo chip ("lo puede hacer el proveedor o el interno"): degradado suave del
   color de proveedor al neutro de la sección, para que se lea como una sola etiqueta con dos
   caras y no como dos chips pegados. El separador va tenue. */
.rpv-tag.is-ambos{
  background:linear-gradient(90deg, var(--rp-prov-bg) 0%, color-mix(in srgb,var(--rp-sec) 14%,#fff) 100%);
  border-color:color-mix(in srgb,var(--rp-prov-bd) 60%, var(--rp-sec) 40%);
  gap:.25rem;
}
.rpv-tag.is-ambos .rpv-tago{ opacity:.45; font-weight:600; }

/* SUB-PASO anidado dentro de un nodo (Autorización de Documentación dentro de Revisión de
   Evidencias). Sangrado y en cuerpo chico: se lee como un detalle DEL paso, no como un paso.
   Pendiente = círculo hueco tenue; hecho = palomita en el verde de "listo" del design system. */
.rpv-sub{
  display:flex; align-items:flex-start; gap:.3rem; margin-top:.2rem; margin-left:.1rem;
  font-size:.72rem; line-height:1.35; color:var(--piv6-muted,#6a7383);
}
.rpv-sub .bi{ flex:none; margin-top:.1rem; font-size:.8rem; opacity:.55; }
.rpv-sub b{ font-weight:700; color:var(--piv6-muted,#6a7383); }
.rpv-sub .sep{ opacity:.4; margin:0 .1rem; }
.rpv-sub.is-ok .bi{ color:#2fb344; opacity:1; }
.rpv-sub.is-ok b{ color:#1a7a2e; }

/* Hint de PERMISO. El nombre que se escribe es el del MÓDULO tal cual aparece en la
   pantalla de alta de rol (clientes/roles/rol.html) más el nivel Alta/Consulta/
   Administración: eso es literalmente lo que el usuario tiene que pedirle a su
   administrador. NUNCA el nombre del ROLE_* ni el puesto de la empresa.
   Dos pesos a propósito: renglón tenue en los pasos PENDIENTES (dato de referencia)
   y caja punteada en el paso ACTUAL (ahí sí es accionable). Con un solo peso, cinco
   cajas apiladas se comen el panel. */
.rpv-perm{ display:flex; align-items:flex-start; gap:.28rem; margin-top:.14rem;
  font-size:.71rem; line-height:1.3; color:var(--piv6-faint,#9aa2b1); }
.rpv-perm .bi{ flex:none; margin-top:.1rem; opacity:.7; }
.rpv-perm b{ font-weight:600; color:var(--piv6-muted,#6a7383); }
.rpv-perm .niv{ font-weight:700; }
.rpv-perm.es-actual{ color:var(--piv6-muted,#6a7383); margin-top:.25rem;
  padding:.22rem .45rem; border-radius:var(--piv6-r-mini,6px);
  background:#f4f6fa; border:1px dashed var(--piv6-line-strong,#c7cede); }
.rpv-perm.es-actual b{ font-weight:700; color:var(--rp-est-ink); }

.rpv-caja{ margin-top:.3rem; padding:.4rem .55rem; border-radius:var(--piv6-r-mini,6px);
  font-size:.79rem; line-height:1.35; display:flex; gap:.35rem; align-items:flex-start; border:1px solid; }
.rpv-caja .bi{ flex:none; margin-top:.1rem; }
.rpv-caja.is-tuyo     { background:var(--rp-tuyo-bg);  border-color:var(--rp-tuyo-bd);  color:var(--rp-tuyo);  font-weight:600; }
.rpv-caja.is-ajeno    { background:var(--rp-ajeno-bg); border-color:var(--rp-ajeno-bd); color:var(--rp-ajeno); }
.rpv-caja.is-bloqueado{ background:var(--rp-bloq-bg);  border-color:var(--rp-bloq-bd);  color:var(--rp-bloq);  font-weight:600; }
.rpv-caja.is-prov     { background:var(--rp-prov-bg);  border-color:var(--rp-prov-bd);  color:var(--rp-prov); }
.rpv-caja.is-desvio   { background:var(--rp-desv-bg);  border-color:var(--rp-desv-bd);  color:var(--rp-desv); }
.rpv-caja.is-rechazo  { background:var(--rp-rech-bg);  border-color:var(--rp-rech-bd);  color:var(--rp-rech); }
.rpv-caja .m{ display:block; font-weight:800; }
.rpv-caja .d{ display:block; font-weight:400; margin-top:.1rem; }
.rpv-nota{ font-size:.74rem; color:var(--piv6-faint,#9aa2b1); margin-top:.12rem; line-height:1.35; }

/* Icono externo del sprite local (static/imagenes/rutaproceso.svg, inline en el
   fragmento). Se normaliza a las métricas de un glifo bi-* para que no baile. */
.rp-ico{ width:1em; height:1em; fill:currentColor; vertical-align:-.125em; flex:none; }

/* Encabezado propio, para el sitio donde la ruta NO cuelga de un panel de la cascada
   (registro de proveedores, columna de Documentación PDF). */
.rpv-h6{ font-weight:700; margin:1rem 0 .5rem; font-size:1rem;
  display:flex; align-items:center; gap:.4rem; color:var(--tema-color); }
/* Ahí no hay accordion-item que dé la caja; el padding ya lo pone .rpv, así que esto sólo
   aporta el borde y el fondo para que el bloque se lea como una tarjeta. */
.rpv-suelta{ border:1px solid var(--piv6-line,#dde2ea);
  border-radius:var(--piv6-r-chico,8px); background:#fff; }

/* Ruta puesta a lo ANCHO de la página, no en la columna de 4/12 donde se diseñó (centro de
   costos: ahí no hay panel hermano de "Información de la Factura" que la acompañe). El
   timeline es una lista vertical de renglones cortos, así que a 1400px cada paso queda
   flotando en un desierto y el ojo pierde el hilo del rail. Se le pone tope de medida —el
   mismo ancho que ya tiene en la columna estrecha— y se deja alineada a la izquierda, que es
   donde vive el rail. */
.rpv-cap .rpv{ max-width:46rem; }

@media (prefers-color-scheme: dark){
  .rpv{
    --rp-est-ink: color-mix(in srgb, var(--rp-est) 58%, #ffffff);
    --rp-pend:#3a445c;
    --rp-tuyo:#7fe0a0;  --rp-tuyo-bg:color-mix(in srgb,#2fb344 22%,#1c2130);  --rp-tuyo-bd:#2f8f4a;
    --rp-ajeno:#a8caff; --rp-ajeno-bg:color-mix(in srgb,#0d6efd 22%,#1c2130); --rp-ajeno-bd:#3f6db8;
    --rp-bloq:#f5cf85;  --rp-bloq-bg:color-mix(in srgb,#f0a020 22%,#1c2130);  --rp-bloq-bd:#9c7020;
    --rp-desv:#f5cf85;  --rp-desv-bg:color-mix(in srgb,#E3B838 20%,#1c2130);  --rp-desv-bd:#b08b25;
    --rp-rech:#ffa8b3;  --rp-rech-bg:color-mix(in srgb,#E02441 22%,#1c2130);  --rp-rech-bd:#a3202f;
    --rp-prov:#d7b6ff;  --rp-prov-bg:color-mix(in srgb,#9333EA 24%,#1c2130);  --rp-prov-bd:#7440b8;
  }
  .rpv-nodo{ background:#1c2130; color:#98a2b5; }
  .rpv-paso.is-noaplica .rpv-nodo{ background:#242b3d; }
  .rpv-paso.is-desvio .rpv-nodo{ color:#2a1f00; }
  .rpv-lock{ border-color:#1c2130; }
  .rpv-tag{ background:color-mix(in srgb,var(--rp-sec) 30%,#1c2130); color:#e7ecf5; border-color:#43506c; }
  .rpv-tag.is-na{ background:#242b3d; color:#8b93a3; border-color:#33405a; }
  .rpv-perm{ color:#8d99ad; }
  .rpv-perm b{ color:#c3cddd; }
  /* .es-actual vuelve a declarar background: hay que re-declararlo aquí o la caja del
     paso actual sale BLANCA sobre el panel oscuro. */
  .rpv-perm.es-actual{ background:#242b3d; border-color:#43506c; color:#a7b2c6; }
  .rpv-seg{ background:#3a445c; }
  .rpv-h6{ color:#c9a6ff; }
  .rpv-suelta{ background:#1c2130; border-color:#33405a; }
}

/* Separador "o bien" entre los dos selects EXCLUYENTES del cambio de propietario: el flujo pasa a
   un usuario interno O a un contacto del proveedor, nunca a los dos. La marca tiene que leerse como
   disyuntiva, no como un paso mas de la lista. */
.piv6-cu-o{
  font-size:.72rem; font-weight:800; letter-spacing:.06em; text-transform:uppercase;
  color:var(--piv6-faint,#9aa2b1); display:flex; align-items:center; justify-content:center; gap:.35rem;
}
.piv6-cu-o::before,.piv6-cu-o::after{ content:""; flex:1 1 0; height:1px; background:var(--piv6-line,#dde2ea); }

/* VARIANTE DISCRETA del aviso (fpcomun::aviso con inline=true).
   El aviso base esta dimensionado como HERO: es el unico contenido de una pantalla de resultado, y
   por eso el titulo va a 1.8rem/800 con el icono a 2.9rem. Metido como nota dentro de una forma
   -"no se puede cambiar hasta que haya pago", "no hay director asignado"- ese tamano compite con
   el titulo de la pagina y descuadra el panel que lo contiene.
   Aqui solo cambia la ESCALA: color, icono, semantica y estructura son los mismos, para que se
   siga leyendo como el mismo componente y no como un bloque aparte. */
.fp-aviso.is-inline{ gap:.6rem; padding:.6rem .8rem; margin:.5rem 0 .25rem; }
.fp-aviso.is-inline .fp-aviso-ico{ font-size:1.35rem; }
.fp-aviso.is-inline .fp-aviso-tit{ font-size:.95rem; font-weight:700; letter-spacing:0; line-height:1.35; }
.fp-aviso.is-inline .fp-aviso-dato.is-fuerte .fp-aviso-val{ font-size:.9rem; }
@media (max-width:575.98px){
  .fp-aviso.is-inline{ padding:.55rem .7rem; }
  .fp-aviso.is-inline .fp-aviso-ico{ font-size:1.15rem; }
  .fp-aviso.is-inline .fp-aviso-tit{ font-size:.9rem; }
}

/* ============================================================================================
   COMPONENTE DE ACCIONES v6 — botonera + panel de estado (Enrique, 2026-08-19)
   Las dos piezas son UNA sola unidad de diseño: abajo la botonera, encima el panel que dice qué
   falta para poder ejecutar la acción primaria (fragmentos panel-estado / chip-faltan /
   chip-estado de comun/portal-inputs-v6.html, alimentados por marcaSubmit/marcaFaltantes de
   /js/portal-inputs-v6.js).

   POR QUÉ ESTE BLOQUE VA AL FINAL DEL ARCHIVO: son reglas nuevas que se apoyan en las de arriba
   (.piv6-form-footer, .piv6-faltan-chip) y deben ganarles por orden, no por especificidad
   inflada. Nada de lo de arriba se reordenó.

   TOKENS SEMÁNTICOS. El chip venía con #f0a020 / #2fb344 escritos a mano; ahora los dos estados
   -aviso y éxito- salen de variables, así que el día que cambie la paleta se cambia aquí. NO son
   colores de marca (esos siguen saliendo de --tema-color / --piv6-card-head): son señales de
   estado, y por eso son fijas y no dependen del tenant. El verde bajó de #16a34a a #15803d
   porque el anterior daba 3.1:1 con texto blanco y no cumplía AA.
   ============================================================================================ */
.piv6{
  --piv6-warn:#b45309;     /* ámbar de "falta algo" — 5.9:1 con blanco */
  --piv6-warn-ink:#7c3d06; /* texto ámbar sobre superficie clara — 8.2:1 */
  --piv6-warn-surf:#fff8ed;
  --piv6-ok:#15803d;       /* verde de "listo" — 4.9:1 con blanco */
  --piv6-ok-ink:#12602f;
  --piv6-ok-surf:#f1fbf4;
  --piv6-dang-ink:#a3242f;
  --piv6-acc-min:10.5rem;  /* ancho mínimo común de los botones del pie */

  /* COLOR DE LA ACCIÓN NEUTRA DEL PIE (Enrique, 2026-08-20). El botón que ejecuta la acción de la
     pantalla -Guardar, Generar, Procesar, Timbrar- debe HACER JUEGO CON EL ENCABEZADO del
     card-pagina, o sea salir del color de SECCIÓN y no del color del tenant. Sin esto, en sadasi
     el encabezado quedaba azul marino y el botón naranja, en la misma pantalla.

     POR QUÉ HIZO FALTA UNA VARIABLE NUEVA Y NO BASTÓ --piv6-card-head: esa la fija `card-pagina`
     INLINE en el <div class="piv6-card-pagina">, y el pie sticky es HERMANO de .piv6-form-main —
     vive FUERA del card, porque .piv6-card-pagina tiene overflow:hidden y ahí dentro un
     position:sticky no tiene dónde pegarse—, así que la variable nunca le llegaba y el botón caía
     al fallback del tenant. Las custom properties heredan hacia abajo, no hacia los lados.

     CÓMO LLEGA AHORA: `card-pagina` publica el color A NIVEL DE PÁGINA con un <style> resuelto en
     el servidor (:root{--piv6-sec-pagina:…}), que es el MISMO truco que fpcomun::titulo ya usaba
     con --piv6-card-head. Server-side y no por JS a propósito: así no hay parpadeo de color al
     cargar (el pie ya está pintado del color correcto en el primer frame).

     POR QUÉ UN NOMBRE PROPIO Y NO REUSAR --piv6-card-head EN :root: --rc-sec (el color de los
     labels y de la barra de acento de TODOS los campos piv6) se computa arriba, en .piv6, donde
     --piv6-card-head hoy no existe y por eso cae al tenant. Publicar --piv6-card-head en :root le
     habría cambiado el color a los labels de las ~110 pantallas migradas de un solo golpe. Con un
     nombre propio el cambio queda acotado exactamente al botón que se pidió.

     CADENA DE FALLBACK, en este orden y por este motivo:
       1) --piv6-sec-pagina  → lo publica card-pagina con el `colorseccion` de la pantalla.
       2) --piv6-card-head   → lo publican en :root las pantallas de flujo de pagos vía
                               fpcomun::titulo, que no usan card-pagina.
       3) --piv6-tema        → el color del tenant, o sea EXACTAMENTE como se veía antes. Las
                               pantallas que no declaran color de sección no cambian nada.

     SEMÁNTICA INTACTA: esto es sólo para la acción NEUTRA. success (autorizar / confirmar
     positivo), danger (destructivo / cancelar) y warning (devolver al remitente) conservan su
     color semántico fijo — son señales de estado, no de marca ni de sección (ver los tokens de
     arriba). */
  --piv6-accion: var(--piv6-sec-pagina, var(--piv6-card-head, var(--piv6-tema)));
}

/* ---------------------------------------------------------------------------------------------
   1. BOTONERA. Todos los botones del pie con la MISMA FORMA y el MISMO ANCHO (regla de Enrique):
   la fila se lee como una serie de piezas idénticas y sólo el color, el icono y la etiqueta las
   distinguen. El ancho lo fija --piv6-acc-w, que calcula el JS midiendo el botón más largo (las
   etiquetas vienen de i18n y en inglés crecen); mientras el JS no corre, el min-width común ya
   los deja casi parejos. Nunca se encogen: si no caben, envuelven conservando el ancho.
   --------------------------------------------------------------------------------------------- */
.piv6-form-footer-in{ row-gap:.5rem; }
.piv6-form-footer-in > .piv6-btn{
  min-width:var(--piv6-acc-w, var(--piv6-acc-min));
  justify-content:center; text-align:center; white-space:nowrap;
  padding:.5rem 1rem; border-width:1.5px; border-style:solid; border-color:transparent;
  border-radius:var(--piv6-r-chico,8px); font-weight:600; flex:0 0 auto;
}
/* JERARQUÍA. Con una acción primaria presente (verde o del tema), las destructivas y las
   secundarias bajan de peso: pasan de relleno sólido a superficie tenue con borde y texto del
   color semántico. No pierden legibilidad -al contrario: el texto sube de ~3.6:1 (blanco sobre el
   sólido) a 7:1+-, pero dejan de competir con la acción que el usuario viene a hacer. Si en el pie
   NO hay primaria (pantallas donde Rechazar ES la acción), el :has() no aplica y el botón conserva
   su relleno sólido de siempre. */
.piv6-form-footer-in:has(.piv6-btn-success, .piv6-btn-primary) > .piv6-btn-danger{
  background:color-mix(in srgb, var(--piv6-danger) 8%, #fff); color:var(--piv6-dang-ink);
  border-color:color-mix(in srgb, var(--piv6-danger) 45%, transparent);
}
.piv6-form-footer-in:has(.piv6-btn-success, .piv6-btn-primary) > .piv6-btn-danger:hover{
  background:color-mix(in srgb, var(--piv6-danger) 16%, #fff); border-color:var(--piv6-danger); color:var(--piv6-dang-ink);
}
.piv6-form-footer-in:has(.piv6-btn-success, .piv6-btn-primary) > .piv6-btn-warning{
  background:color-mix(in srgb, var(--piv6-warn) 8%, #fff); color:var(--piv6-warn-ink);
  border-color:color-mix(in srgb, var(--piv6-warn) 45%, transparent);
}
.piv6-form-footer-in:has(.piv6-btn-success, .piv6-btn-primary) > .piv6-btn-warning:hover{
  background:color-mix(in srgb, var(--piv6-warn) 16%, #fff); border-color:var(--piv6-warn); color:var(--piv6-warn-ink);
}
/* Regresar: el más ligero de la fila, pero con el mismo tamaño y forma que los demás. */
.piv6-form-footer-in > .piv6-btn-back{
  background:transparent; border-color:color-mix(in srgb, var(--piv6-tema) 22%, transparent); color:var(--piv6-ink);
}
.piv6-form-footer-in > .piv6-btn-back:hover{ background:var(--piv6-soft); border-color:color-mix(in srgb, var(--piv6-tema) 45%, transparent); }
/* Primaria: la única con relleno sólido y una sombra de su propio color que la levanta del pie. */
.piv6-form-footer-in > .piv6-btn-success,
.piv6-form-footer-in > .piv6-btn-primary{ font-weight:700; box-shadow:0 6px 16px -9px color-mix(in srgb, currentColor 0%, #0b1220); }
.piv6-form-footer-in > .piv6-btn-success:not(:disabled){ box-shadow:0 6px 16px -9px color-mix(in srgb, var(--piv6-ok) 90%, #000); }
.piv6-form-footer-in > .piv6-btn-primary:not(:disabled){ box-shadow:0 6px 16px -9px color-mix(in srgb, var(--piv6-accion) 90%, #000); }
/* El relleno de la primaria sale de --piv6-accion (color de SECCIÓN, ver el token allá arriba) y
   no de --piv6-tema: el botón y el encabezado de la página son el mismo color. Va por DESCENDENTE
   y no por hijo directo -a diferencia de las reglas de forma de arriba- porque hay pies que meten
   un div envoltorio (el que el JS esconde) y el COLOR no se puede perder por eso; la forma sí se
   asume ya resuelta. Gana a .piv6-btn-primary (0,1,0) por especificidad, y a las reglas de
   :disabled de aquí abajo las pierde a propósito: un botón bloqueado no lleva color de sección. */
.piv6-form-footer .piv6-btn-primary{ background:var(--piv6-accion); color:#fff; }
.piv6-form-footer .piv6-btn-primary:hover{ background:color-mix(in srgb, var(--piv6-accion) 88%, #000); color:#fff; }
/* CONTRASTE: por qué el texto se queda en blanco y no se deriva. La paleta de sección YA garantiza
   la legibilidad en el origen -la regla 2 de C_Soluciones.bsBg exige >= 4.5:1 contra blanco- y los
   13 colores la cumplen. Medido sobre los hexadecimales de hoy: el peor caso es Recepción #1274DE
   con 4.59:1, luego Conciliación SAT #D52093 con 4.71, Flujo de Pagos #9451D6 con 4.76 y Reportes
   #0B7F76 con 4.87; el mejor es Administración de Usuarios #0E1058 con 17.0:1. Ninguno es claro,
   así que blanco es correcto en los 13 y el botón se lee igual que el encabezado.
   NO se puso un contrast-color() ni un tope de luminosidad "por si acaso", y conviene saber por
   qué: (a) un tope fijo en OKLCH no sirve, porque la L que hace falta para AA depende del tono
   -0.548 en el cian contra 0.598 en el magenta-, así que cualquier tope que salve al cian oscurece
   de más a cuatro secciones que ya cumplen y las despega del encabezado; y (b) contrast-color()
   decide por empate y en Recepción el empate es de 4.590 (blanco) contra 4.576 (negro): el mismo
   botón podría salir con texto blanco en un navegador y negro en otro. Un design system no puede
   depender de eso.
   TRIPWIRE: los ÚNICOS hexadecimales del portal que no llegan a 4.5:1 son dos estatus de flujo de
   pagos -En Revisión #00B1D0 con 2.56:1 y Devuelta #D97706 con 3.19:1-, que pueden entrar como
   color de sección por la excepción de C_Modulos.getColorSeccion(). Hoy NO alcanzan ningún pie:
   las seis pantallas de flujo de pagos declaran el violeta del GRUPO (#9451D6) y además su acción
   primaria es verde (success). Si alguna vez una pantalla de esos módulos estrena un pie con
   .piv6-btn-primary, el botón saldrá ilegible y hay que arreglarlo en el ORIGEN -esos dos hex ya
   incumplen la regla 2 también en el encabezado-, no parchando aquí. */

/* DESHABILITADO: bloqueado, no muerto (a Enrique le gustó este borde, se conserva tal cual).
   El opacity:.5 de antes hundía el texto por debajo de AA y el botón se leía como decorado. Aquí
   el botón conserva su tamaño, el texto queda legible en el ámbar de "falta algo" y el borde
   punteado dice "esto se va a activar", no "esto no existe". El contador que le inyecta el JS
   (.piv6-btn-n) repite cuántos datos lo están bloqueando, que es justo lo que el panel enumera. */
.piv6-form-footer-in > .piv6-btn:disabled,
.piv6-form-footer-in > .piv6-btn.disabled{
  background:var(--piv6-surface); color:var(--piv6-warn-ink);
  border:1.5px dashed color-mix(in srgb, var(--piv6-warn) 60%, transparent);
  box-shadow:none; opacity:1; cursor:not-allowed;
}
.piv6-form-footer-in > .piv6-btn:disabled .bi,
.piv6-form-footer-in > .piv6-btn.disabled .bi{ opacity:.75; }
.piv6-btn-n{
  display:inline-flex; align-items:center; justify-content:center; min-width:1.5em; height:1.5em; padding:0 .35em;
  border-radius:999px; background:var(--piv6-warn); color:#fff; font-size:.72rem; font-weight:800;
  font-variant-numeric:tabular-nums; line-height:1;
}
.piv6-form-footer-in > .piv6-btn:not(:disabled):not(.disabled) .piv6-btn-n{ display:none; }

/* ---------------------------------------------------------------------------------------------
   2. PANEL DE ESTADO. Dentro de una botonera sticky FLOTA encima de ella (absolute + bottom:100%),
   que es la razón de ser del rediseño: el panel puede crecer de 1 a 6 chips sin empujar los
   botones ni moverlos de sitio. El contenedor de referencia es .piv6-form-footer, que ya es
   position:sticky (un sticky es un elemento posicionado, así que sirve de ancla sin tocarlo).
   --------------------------------------------------------------------------------------------- */
.piv6-form-footer{ /* el panel flotante se ancla aquí; sin overflow para no recortarlo */ }
.piv6-form-footer-in > .piv6-est{
  position:absolute; left:0; right:0; bottom:100%;
  display:flex; align-items:center; gap:.55rem; flex:0 0 auto; width:auto; min-width:0;
  padding:.4rem clamp(.6rem,2vw,1.1rem); min-height:2.6rem;
  background:color-mix(in srgb, var(--piv6-warn) 10%, var(--piv6-surface));
  border-top:1px solid color-mix(in srgb, var(--piv6-warn) 40%, transparent);
  box-shadow:0 -10px 22px -18px rgba(20,30,50,.65);
  max-height:40vh; overflow:auto; overscroll-behavior:contain;
  transition:background .2s ease, border-color .2s ease;
}
.piv6-form-footer-in > .piv6-est.is-ok{
  background:color-mix(in srgb, var(--piv6-ok) 10%, var(--piv6-surface));
  border-top-color:color-mix(in srgb, var(--piv6-ok) 40%, transparent);
}
/* BANDA INTEGRADA: degradación de la barra flotante para donde el overlay no cabe -dentro de un
   modal se recortaría contra .modal-content, y en el uso suelto no hay pie al que colgarse-. Misma
   pieza, mismo JS: sólo deja de flotar y se coloca en el flujo, con alto reservado para que pasar
   de "faltan 3" a "listo" no mueva nada. Es el DEFAULT de cualquier panel: el overlay sólo lo gana
   -por especificidad, no por orden- el que vive dentro de .piv6-form-footer-in y no está en un
   modal. Con clase='piv6-est-banda' se fuerza a mano. */
.piv6-est,
.piv6-est.piv6-est-banda,
.modal .piv6-form-footer-in > .piv6-est{
  position:static; display:flex; align-items:center; gap:.5rem; flex-wrap:wrap;
  width:100%; flex:1 1 100%; min-height:2.4rem; max-height:none; overflow:visible;
  padding:.35rem .6rem; border-radius:var(--piv6-r-chico,8px);
  background:color-mix(in srgb, var(--piv6-warn) 8%, var(--piv6-surface));
  border:1px solid color-mix(in srgb, var(--piv6-warn) 35%, transparent);
}
.piv6-est.is-ok,
.piv6-est.piv6-est-banda.is-ok,
.modal .piv6-form-footer-in > .piv6-est.is-ok{
  background:color-mix(in srgb, var(--piv6-ok) 8%, var(--piv6-surface));
  border-color:color-mix(in srgb, var(--piv6-ok) 35%, transparent);
}

/* KPI: contador + etiqueta, y a la vez el disparador de colapsar/expandir el detalle (la
   preferencia se recuerda en localStorage). Ancho fijo del número con tabular-nums para que pasar
   de 9 a 10 no mueva la etiqueta. */
.piv6-est-kpi{
  flex:none; display:inline-flex; align-items:center; gap:.4rem; cursor:pointer;
  font:inherit; font-size:.72rem; font-weight:700; text-transform:uppercase; letter-spacing:.03em;
  color:var(--piv6-warn-ink); background:transparent; border:0; padding:.15rem .3rem; border-radius:999px;
}
.piv6-est-kpi:hover{ background:color-mix(in srgb, var(--piv6-warn) 14%, transparent); }
.piv6-est-kpi:focus-visible{ outline:2px solid var(--piv6-warn); outline-offset:1px; }
.piv6-est-kpi:disabled{ cursor:default; }
.piv6-est-kpi .piv6-est-n{
  display:inline-flex; align-items:center; justify-content:center; min-width:1.7em; height:1.7em; padding:0 .35em;
  border-radius:999px; background:var(--piv6-warn); color:#fff; font-size:.88rem; font-weight:800;
  font-variant-numeric:tabular-nums; line-height:1;
}
.piv6-est-kpi .piv6-faltan-ico{ font-size:.95rem; }
.piv6-est-cv{ font-size:.7rem; opacity:.7; transition:transform .18s ease; }
.piv6-est.is-colapsado .piv6-est-cv{ transform:rotate(-90deg); }
.piv6-est.is-colapsado .piv6-est-lista{ display:none; }
/* Un solo motivo: el chip ya lo dice todo, el número sobra (el KPI se queda como disparador). */
.piv6-est.piv6-est-uno .piv6-est-n{ display:none; }
.piv6-est.is-ok .piv6-est-kpi{ color:var(--piv6-ok-ink); }
.piv6-est.is-ok .piv6-est-n{ background:var(--piv6-ok); }
.piv6-est.is-ok:not(.is-aviso) .piv6-est-cv{ display:none; }

/* Lista de chips: uno por motivo. En cuanto no caben, scroll horizontal PROPIO -nunca del body-. */
.piv6-est-lista{ display:flex; align-items:center; gap:.35rem; min-width:0; flex:1 1 auto;
  flex-wrap:wrap; padding:.1rem; }
.piv6-form-footer-in > .piv6-est .piv6-est-lista{ flex-wrap:nowrap; overflow-x:auto; overscroll-behavior-x:contain; scrollbar-width:thin; }
/* El chip: hereda del .piv6-faltan-chip de siempre (mismo aspecto para quien no migre) y suma el
   color de SECCIÓN cuando el motivo sabe a qué campo pertenece —--piv6-est-c lo pone el JS
   leyendo el acento del panel donde vive el campo—, más el cursor de "esto te lleva ahí". */
.piv6-est .piv6-faltan-chip{
  --piv6-est-c:var(--piv6-warn);
  background:color-mix(in srgb, var(--piv6-est-c) 8%, var(--piv6-surface));
  border-color:color-mix(in srgb, var(--piv6-est-c) 55%, transparent);
  color:var(--piv6-warn-ink); padding:.24rem .7rem; cursor:default; max-width:none;
}
.piv6-est .piv6-faltan-chip.piv6-est-ir{ cursor:pointer; }
.piv6-est .piv6-faltan-chip.piv6-est-ir:hover,
.piv6-est .piv6-faltan-chip:focus-visible{
  background:color-mix(in srgb, var(--piv6-est-c) 16%, var(--piv6-surface));
  border-color:var(--piv6-est-c); outline:none; box-shadow:0 0 0 3px color-mix(in srgb, var(--piv6-est-c) 22%, transparent);
}
.piv6-est-chip-ico{ color:var(--piv6-est-c); opacity:.9; }
/* Nivel RECOMENDADO (la columna admite nulos): avisa, no bloquea, y se ve claramente más tenue
   que un bloqueante para que el usuario distinga "no puedo enviar" de "te falta capturar esto". */
.piv6-est .piv6-faltan-chip.piv6-est-aviso{
  --piv6-est-c:var(--piv6-line-strong);
  color:var(--piv6-muted); font-weight:500; border-style:dashed;
}
.piv6-est .piv6-faltan-chip.piv6-est-aviso .piv6-est-chip-ico{ color:var(--piv6-muted); }
/* El chip base del fragmento se recicla; cuando el JS no lo usa (todo listo y sin avisos) se oculta
   con [hidden], que en un flex hay que forzar. */
.piv6-est .piv6-faltan-chip[hidden]{ display:none; }

/* ÉXITO: mensaje afirmativo propio, no el chip de error repintado de verde. Ocupa el mismo alto
   que el estado de faltantes (min-height del panel), así que la transición no brinca. */
.piv6-est-ok{ display:flex; align-items:center; gap:.5rem; min-width:0; font-size:.84rem; font-weight:700; color:var(--piv6-ok-ink); }
.piv6-est-ok[hidden]{ display:none; }
.piv6-est-ok > .bi{ font-size:1.15rem; color:var(--piv6-ok); flex:none; }
.piv6-est-ok small{ font-weight:500; color:var(--piv6-muted); }
@media (max-width:767.98px){ .piv6-est-ok small{ display:none; } }

/* Destello del campo al que lleva un chip: el usuario tiene que ver DÓNDE aterrizó. */
.piv6-destacado{ animation:piv6-destello 1.5s ease; }
@keyframes piv6-destello{
  0%,100%{ box-shadow:0 0 0 0 transparent; }
  15%,60%{ box-shadow:0 0 0 4px color-mix(in srgb, var(--piv6-warn) 45%, transparent); }
}

/* Móvil: el panel sigue flotando (no empuja), los chips hacen scroll horizontal propio y la
   botonera apila a todo lo ancho con la ACCIÓN PRIMARIA bajo el pulgar y Regresar al final. */
@media (max-width:575.98px){
  .piv6-form-footer-in > .piv6-btn{ width:100%; min-width:0; flex:1 1 100%; }
  .piv6-form-footer-in > .piv6-btn-back{ order:99; margin-right:0; }
  .piv6-form-footer-in > .piv6-est{ padding:.35rem .6rem; }
  .piv6-est-kpi{ font-size:.68rem; }
  .piv6-est .piv6-faltan-chip{ font-size:.74rem; }
}
@media (prefers-reduced-motion:reduce){
  .piv6-form-footer-in > .piv6-est,.piv6-est-cv{ transition:none; }
  .piv6-destacado{ animation:none; outline:3px solid var(--piv6-warn); outline-offset:2px; }
}

/* Oscuro: los tokens se recalibran (las mismas señales, subidas de luminancia para leerse sobre
   superficie oscura) y todo lo de arriba sigue derivando de ellos. */
@media (prefers-color-scheme: dark){
  .piv6{
    --piv6-warn:#e08a2e; --piv6-warn-ink:#f6c98a; --piv6-warn-surf:#2a2418;
    --piv6-ok:#2f9e56;   --piv6-ok-ink:#8fe0ab;   --piv6-ok-surf:#16261c;
    --piv6-dang-ink:#f4a7ad;
  }
  .piv6-form-footer-in > .piv6-est{ background:color-mix(in srgb, var(--piv6-warn) 16%, #1c2130); }
  .piv6-form-footer-in > .piv6-est.is-ok{ background:color-mix(in srgb, var(--piv6-ok) 16%, #1c2130); }
  .piv6-est.piv6-est-banda,.piv6-est.piv6-faltan-suelto,.modal .piv6-form-footer-in > .piv6-est{ background:color-mix(in srgb, var(--piv6-warn) 14%, #1c2130); }
  .piv6-est .piv6-faltan-chip{ background:color-mix(in srgb, var(--piv6-est-c) 18%, #1c2130); color:var(--piv6-warn-ink); }
  .piv6-est .piv6-faltan-chip.piv6-est-aviso{ color:#9aa6bd; }
  .piv6-form-footer-in > .piv6-btn:disabled,
  .piv6-form-footer-in > .piv6-btn.disabled{ background:#1c2130; color:var(--piv6-warn-ink); }
  .piv6-form-footer-in:has(.piv6-btn-success, .piv6-btn-primary) > .piv6-btn-danger{ background:color-mix(in srgb, var(--piv6-danger) 18%, #1c2130); color:var(--piv6-dang-ink); }
  .piv6-form-footer-in:has(.piv6-btn-success, .piv6-btn-primary) > .piv6-btn-warning{ background:color-mix(in srgb, var(--piv6-warn) 18%, #1c2130); color:var(--piv6-warn-ink); }
  .piv6-form-footer-in > .piv6-btn-back{ color:#cfe0f5; }
}

/* ---------------------------------------------------------------------------------------------
   PIE DE FORMA: UNA PIEZA DE DOS RENGLONES (Enrique, 2026-08-19)
   Sustituye al panel FLOTANTE del bloque anterior. El overlay resolvía que los botones no se
   movieran, pero a cambio TAPABA la página: medido en /flujopagos/revisar/57, debajo del panel
   quedaba un `.piv6-rowin` -un campo del formulario- sin forma de leerlo ni de picarlo. Y al estar
   fuera del flujo se quedaba en 360px de ancho mientras sobraban 1000px a la derecha, así que los
   motivos salían truncados ("Falta capturar: D…"), que es justo lo que el rediseño quería evitar.

   Ahora el pie es una sola pieza: BANDA DE ESTADO arriba y BOTONES abajo. La banda va en el flujo
   (nada tapa), ocupa todo el ancho del pie (los motivos se leen completos) y tiene ALTO FIJO
   reservado, así que pasar de 6 motivos a 0 sólo cambia color y contenido: ni reflow ni salto, que
   era la razón de ser del overlay. Los chips no envuelven: la lista lleva su propio scroll
   horizontal.
   --------------------------------------------------------------------------------------------- */
.piv6-form-footer-in > .piv6-est{
  position:static;            /* en el flujo: deja de tapar el contenido de la página */
  order:-1;                   /* primer renglón, pase lo que pase el orden del DOM */
  flex:1 1 100%; width:100%; max-width:none;
  height:2.75rem; min-height:2.75rem; max-height:2.75rem;  /* alto RESERVADO: sin salto */
  overflow:hidden;            /* el scroll lo lleva la lista de chips, no la banda */
  border-top:0;
  border-radius:var(--piv6-r-chico,8px);
  box-shadow:none;
}
/* La lista se lleva el ancho sobrante y se desplaza sola cuando no caben los chips. */
.piv6-form-footer-in > .piv6-est .piv6-est-lista{
  flex:1 1 auto; min-width:0;
  flex-wrap:nowrap; overflow-x:auto; overscroll-behavior-x:contain; scrollbar-width:thin;
}
/* Con el alto fijo, el chip no debe crecer ni encogerse de alto. */
.piv6-form-footer-in > .piv6-est .piv6-faltan-chip{ flex:0 0 auto; }

/* --- Ajustes del pie de dos renglones (Enrique, 2026-08-19) -----------------------------------
   1. La banda va SIN BORDE: es una franja del propio pie, no una tarjeta aparte.
   2. Un motivo pendiente NUNCA se pinta de verde. `--piv6-est-c` lo asigna el JS con el color de
      la SECCIÓN donde vive el campo, así que "Faltan 1 de 4 documentos por revisar" heredaba el
      acento verde del panel de Documentos Adjuntos — y en este portal el verde significa
      aprobado/sí, justo lo contrario de lo que dice el chip. Dentro de la banda el color lo manda
      el ESTADO (ámbar de advertencia), no la sección. Los chips quedan blancos con borde fino,
      como en la propuesta.
   3. Los avisos (`piv6-est-aviso`, la columna admite nulos) conservan su gris punteado: son los
      únicos que no bloquean y deben seguir distinguiéndose de un pendiente real.
   --------------------------------------------------------------------------------------------- */
.piv6-form-footer-in > .piv6-est{ border:0; }
.piv6-form-footer-in > .piv6-est .piv6-faltan-chip:not(.piv6-est-aviso){
  --piv6-est-c:var(--piv6-warn) !important;
  background:var(--piv6-surface);
  border:1px solid color-mix(in srgb, var(--piv6-warn) 32%, transparent);
  color:var(--piv6-warn-ink);
}
.piv6-form-footer-in > .piv6-est .piv6-faltan-chip:not(.piv6-est-aviso) .piv6-est-chip-ico{
  color:var(--piv6-warn);
}

/* Estado de ÉXITO sin repetirse (Enrique, 2026-08-19): el KPI de la izquierda ya dice "LISTO" con
   su paloma, así que el mensaje decía lo mismo tres veces y con dos iconos —"LISTO" + "Listo para
   enviar a autorización" + "Revisado y completo"—. Se queda sólo lo que aporta información nueva:
   cuál es el siguiente paso. En el estado de faltantes el paralelo se mantiene ("6 PENDIENTES" +
   los motivos). */
.piv6-form-footer-in > .piv6-est.is-ok .piv6-est-ok > .bi,
.piv6-form-footer-in > .piv6-est.is-ok .piv6-est-ok small{ display:none; }

/* Estilo del mock C (Enrique, 2026-08-19): los chips y el KPI CONSERVAN su icono -se probó
   quitarlos y Enrique los prefiere con icono-. Lo que sí cambia respecto al diseño original está
   en los bloques de arriba: banda a todo el ancho sin borde, chips ámbar en vez del color de
   sección, y éxito sin repetir la palabra "listo". */

/* Chip CUMPLIDO: el requisito que ya se satisfizo. Aparece sólo en el estado de éxito, cuando el
   panel repinta en verde todo lo que estuvo pendiente (ver la memoria de requisitos en
   portal-inputs-v6.js). Aquí el verde SÍ corresponde: significa aprobado/hecho, que es justo lo
   que dice el chip -al revés del caso que se corrigió arriba, donde un PENDIENTE heredaba el verde
   de la sección-. */
.piv6-form-footer-in > .piv6-est .piv6-faltan-chip.piv6-est-hecho{
  --piv6-est-c:var(--piv6-ok) !important;
  background:color-mix(in srgb, var(--piv6-ok) 10%, var(--piv6-surface));
  border:1px solid color-mix(in srgb, var(--piv6-ok) 45%, transparent);
  color:var(--piv6-ok-ink);
}
.piv6-form-footer-in > .piv6-est .piv6-faltan-chip.piv6-est-hecho .piv6-est-chip-ico{ color:var(--piv6-ok); }

/* Primera fila del pie: CUADRADA, A SANGRE Y SEPARADA POR UN BORDE (Enrique, 2026-08-19).
   La banda es la cabecera del pie, no una tarjeta dentro de él: por eso pierde el redondeo y el
   aire lateral -sale con margen negativo hasta los bordes del contenedor, compensando el padding
   de .piv6-form-footer- y se separa de los botones con una línea, en vez de con un hueco.
   El borde sigue el estado: ámbar cuando falta algo, verde cuando ya está listo. */
.piv6-form-footer-in > .piv6-est{
  border-radius:0;
  margin:-.7rem calc(-1 * clamp(.6rem, 2vw, 1.1rem)) .55rem;
  padding:.4rem clamp(.6rem, 2vw, 1.1rem);
  width:auto;
  border-bottom:1px solid color-mix(in srgb, var(--piv6-warn) 38%, transparent);
}
.piv6-form-footer-in > .piv6-est.is-ok{
  border-bottom-color:color-mix(in srgb, var(--piv6-ok) 38%, transparent);
}

/* Botonera en BLANCO (Enrique, 2026-08-19): la banda de estado va tintada -ámbar o verde- y la
   fila de botones tenía un tinte propio, así que las dos franjas competían. Con la botonera en
   blanco el color queda reservado al ESTADO y la separación entre ambas se lee sola. */
.piv6-form-footer{ background:var(--piv6-surface, #fff); }

/* Y borde ARRIBA también en la banda (Enrique, 2026-08-19): con la botonera en blanco, la franja
   de estado queda enmarcada arriba y abajo, así se separa tanto del contenido de la página como de
   los botones. Sigue el estado, igual que el de abajo. */
.piv6-form-footer-in > .piv6-est{
  border-top:1px solid color-mix(in srgb, var(--piv6-warn) 38%, transparent);
}
.piv6-form-footer-in > .piv6-est.is-ok{
  border-top-color:color-mix(in srgb, var(--piv6-ok) 38%, transparent);
}

/* El CONTADOR en estado listo (Enrique, 2026-08-19): `.piv6-est-n` es la burbuja del número de
   pendientes; al completarse el JS le vacía el texto y quedaba un círculo verde relleno sin nada
   dentro ni significado. Se retira: la paloma de la izquierda ya marca el estado y la etiqueta
   dice LISTO. La burbuja vuelve en cuanto haya pendientes que contar. */
.piv6-form-footer-in > .piv6-est.is-ok .piv6-est-kpi .piv6-est-n{ display:none; }

/* El mensaje de éxito SIEMPRE a la derecha (Enrique, 2026-08-19). Antes su posición dependía del
   azar: con chips verdes la lista (flex:1) lo empujaba al extremo, pero al abrir la pantalla ya
   completa no hay chips que mostrar, la lista va oculta y el mensaje quedaba pegado al KPI. Con el
   margen automático el sitio es el mismo en los dos casos. */
.piv6-form-footer-in > .piv6-est .piv6-est-ok{ margin-left:auto; }

/* El chip de AVISO tampoco hereda el color de la sección (Enrique, 2026-08-19). Su regla ya pedía
   gris (`--piv6-est-c:var(--piv6-line-strong)`), pero el JS escribe `--piv6-est-c` INLINE con el
   acento del panel donde vive el campo, y una variable inline le gana a la regla: por eso "Falta
   elegir: Clave del Concepto" salía verde con borde punteado. Mismo criterio que el bloqueante:
   dentro de la banda el color lo manda el ESTADO, no la sección. */
.piv6-form-footer-in > .piv6-est .piv6-faltan-chip.piv6-est-aviso{
  --piv6-est-c:var(--piv6-line-strong) !important;
  background:var(--piv6-surface);
  border-color:var(--piv6-line-strong);
  color:var(--piv6-muted);
}
.piv6-form-footer-in > .piv6-est .piv6-faltan-chip.piv6-est-aviso .piv6-est-chip-ico{
  color:var(--piv6-muted);
}

/* La banda NO envuelve (Enrique, 2026-08-19): hereda `flex-wrap:wrap` de la banda integrada, así
   que con muchos chips la lista se iba a un SEGUNDO renglón y el alto fijo de la franja la
   recortaba — los motivos existían en el DOM pero no se veían. En una sola línea: el KPI manda su
   ancho y la lista se lleva el resto, desplazándose sola cuando no caben (ya es nowrap + scroll-x). */
.piv6-form-footer-in > .piv6-est{ flex-wrap:nowrap; }
.piv6-form-footer-in > .piv6-est > .piv6-est-kpi{ flex:none; }
.piv6-form-footer-in > .piv6-est .piv6-est-lista{ min-width:0; }

/* Icono de alerta al tamaño del contador: es la marca de estado de la banda y quedaba diminuto
   junto a la burbuja del número. */
.piv6-form-footer-in > .piv6-est .piv6-est-kpi > .piv6-faltan-ico{ font-size:1.35rem; line-height:1; }

/* SELECTOR DE ARCHIVO: mismo alto que el resto de los controles y a todo lo ancho de su celda
   (Enrique, 2026-08-19). Su fila usa `.piv6-rowin.top` -pensada para textarea y richtext, donde la
   etiqueta debe alinearse arriba-, y con un control de UNA línea eso dejaba la caja pegada al
   borde superior, más corta que la tarjeta y con el hueco debajo. En la fila del archivo la
   alineación vuelve a ser centrada, el campo ocupa el alto completo y el label pierde el
   desplazamiento que compensaba el caso del textarea. */
.piv6-rowin.top:has(.piv6-file-wrap){ align-items:stretch; }
.piv6-rowin.top:has(.piv6-file-wrap) > .piv6-lbl{ margin-top:0; align-self:center; }
.piv6-rowin.top:has(.piv6-file-wrap) > .piv6-field{ display:flex; }
.piv6-rowin.top .piv6-file-wrap{ flex:1 1 auto; min-width:0; }
.piv6-rowin.top .piv6-file{ min-height:100%; }

/* ==============================================================================================
   PANTALLA DE ESPERA v6 (.piv6-espera-*) — fragmento comun/portal-espera-v6 :: espera
   ----------------------------------------------------------------------------------------------
   Sustituye a la capa paralela `lf-moderno` (/css/moderno/reporteador-moderno.css), que vivía
   fuera del design system y sólo servía a estas pantallas. De aquella se conserva lo que valía la
   pena -el orbe con anillo, el count-up del contador y el respeto a prefers-reduced-motion /
   forced-colors- y se tira lo demás: los gradientes verdes a mano, los botones propios
   (lf-gen-btn) y los grises escritos en hexadecimal.

   TEMATIZACIÓN: --pe-sec sale del color de SECCIÓN del card que la hospeda
   (--piv6-card-head, que fija `card-pagina` en el elemento .piv6-card-pagina) y cae a --tema-color.
   Se declara aquí y no se usa --rc-sec porque ésa se computa allá arriba, en .piv6, donde
   --piv6-card-head todavía no existe -mismo motivo por el que el resto de las reglas de dentro del
   card repiten el var() completo-.
   Las señales de ESTADO (verde de éxito, ámbar de error) NO se tiñen con el tenant: son los tokens
   semánticos --piv6-ok / --piv6-warn, que ya se recalibran solos en oscuro.
   ============================================================================================== */
.piv6-espera{
  --pe-sec: var(--piv6-card-head, var(--tema-color, #0d6efd));
  --pe-ok:  var(--piv6-ok, #15803d);
  --pe-warn:var(--piv6-warn, #b45309);   /* ámbar: sólo la nota de "se truncó la exportación" */
  --pe-err: var(--piv6-danger, #d64550); /* rojo: la exportación FALLÓ, que no es una advertencia */
  --pe-line:var(--piv6-line, #dde2ea);
  --pe-est: var(--pe-sec);              /* color del estado en curso; lo cambia [data-estado] */
}
.piv6-espera[data-estado="success"]{ --pe-est: var(--pe-ok); }
.piv6-espera[data-estado="error"]{   --pe-est: var(--pe-err); }
.piv6-espera[data-estado="empty"]{   --pe-est: var(--piv6-muted, #6a7383); }

/* ---- HERO: orbe + mensaje + barra ------------------------------------------------------------ */
.piv6-espera-hero{
  display:flex; align-items:center; justify-content:center; flex-wrap:wrap;
  gap:1.5rem; padding:.5rem 0 .25rem;
}
.piv6-espera-orb{
  position:relative; flex:none;
  width:7rem; height:7rem; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:color-mix(in srgb, var(--pe-est) 10%, #fff);
  box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--pe-est) 16%, transparent);
  transition:background .25s ease;
}
.piv6-espera-ring{
  position:absolute; inset:0; border-radius:50%;
  border:.26rem solid color-mix(in srgb, var(--pe-est) 18%, transparent);
}
/* Sólo mientras trabaja: el anillo gira con un cuarto encendido y el icono respira. En cualquier
   estado terminal se queda quieto (es la señal de que ya no hay nada esperando). */
.piv6-espera[data-estado="loading"] .piv6-espera-ring{
  border-top-color:var(--pe-est);
  animation:piv6-espera-giro 1s linear infinite;
}
.piv6-espera-orb-ico{
  position:relative; line-height:1; font-size:2.9rem;
  color:color-mix(in srgb, var(--pe-est) 82%, #0b0c10);
}
.piv6-espera[data-estado="loading"] .piv6-espera-orb-ico{ animation:piv6-espera-latido 1.4s ease-in-out infinite; }
.piv6-espera:not([data-estado="loading"]) .piv6-espera-orb-ico{ animation:piv6-espera-pop .45s ease-out both; }

.piv6-espera-hero-txt{ flex:1 1 22rem; min-width:0; max-width:34rem; }
.piv6-espera-msg{
  margin:0 0 .7rem; min-height:1.4em;
  font-size:1.08rem; font-weight:700; line-height:1.35;
  color:var(--piv6-text, #1b2432);
}
.piv6-espera-barra{
  height:.5rem; border-radius:999px; overflow:hidden;
  background:color-mix(in srgb, var(--pe-est) 12%, var(--pe-line));
}
.piv6-espera-barra-fill{
  display:block; width:0; height:100%; border-radius:999px;
  background:var(--pe-est);
  transition:width .45s cubic-bezier(.22,.9,.32,1);
}
.piv6-espera-conteo{
  margin:.4rem 0 0; font-size:.78rem; font-weight:600; letter-spacing:.2px;
  color:var(--piv6-muted, #6a7383);
}

/* DESENLACE QUE NO ES ÉXITO: fuera la barra y el contador de pasos. Los dos son indicadores de
   PROGRESO y aquí ya no hay progreso que indicar: dejar "Paso 2 de 3" con la barra a medias hace
   creer que la pantalla sigue trabajando cuando en realidad ya terminó. En éxito sí se quedan
   (100% y "Paso N de N"), que es la confirmación de que se recorrió todo. */
.piv6-espera[data-estado="error"] .piv6-espera-barra,
.piv6-espera[data-estado="error"] .piv6-espera-conteo,
.piv6-espera[data-estado="empty"] .piv6-espera-barra,
.piv6-espera[data-estado="empty"] .piv6-espera-conteo{ display:none; }

/* La ayuda del "sin resultados" sólo se ve en ese desenlace. En un error no aplica -no es cosa de
   los filtros- y mientras corre estorbaría. */
.piv6-espera-ayuda{ display:none; }
.piv6-espera[data-estado="empty"] .piv6-espera-ayuda{
  display:block; margin:.35rem 0 0; font-size:.92rem; line-height:1.4;
  color:var(--piv6-muted, #6a7383);
}

/* ---- STEPPER ---------------------------------------------------------------------------------
   Los escalones son los pasos REALES del enum. Los cumplidos llevan palomita, el actual va
   encendido y los pendientes apagados. El conector es un ::before de cada paso (menos el primero)
   que se pinta del color de éxito cuando el paso ya se cumplió: la línea "se llena" hacia la
   derecha conforme avanza. */
.piv6-espera-pasos{
  display:flex; list-style:none; margin:1.9rem 0 0; padding:0;
}
.piv6-espera-paso{
  position:relative; flex:1 1 0; min-width:0;
  display:flex; flex-direction:column; align-items:center; gap:.45rem; text-align:center;
}
.piv6-espera-paso:not(:first-child)::before{
  content:""; position:absolute; z-index:0;
  top:1.15rem; right:50%; width:100%; height:2px;
  background:var(--pe-line);
  transition:background .3s ease;
}
.piv6-espera-paso.is-hecho::before,
.piv6-espera-paso.is-actual::before{ background:var(--pe-ok); }
.piv6-espera-paso-bullet{
  position:relative; z-index:1;
  width:2.3rem; height:2.3rem; border-radius:50%;
  display:inline-flex; align-items:center; justify-content:center;
  font-size:1rem; line-height:1;
  background:var(--piv6-surface, #fff);
  border:2px solid var(--pe-line);
  color:var(--piv6-faint, #9aa2b1);
  transition:background .25s ease, border-color .25s ease, color .25s ease, box-shadow .25s ease;
}
.piv6-espera-paso-ok{ display:none; }
.piv6-espera-paso-x{ display:none; }

/* PASO DONDE SE DETUVO. Las dos formas de no terminar tienen que verse DISTINTO, porque significan
   cosas distintas para quien pidió el reporte:
     . ERROR = algo falló y hay que reintentar o avisar -> escalón en rojo, con una X en lugar de su
       icono, y el conector que llega hasta él también en rojo: se ve en qué paso tronó.
     . SIN RESULTADOS = todo funcionó, simplemente no había nada que exportar -> escalón en gris con
       el borde punteado. Ni rojo ni X: no hay nada que arreglar, sólo que ampliar el filtro.
   Sin esta distinción los dos desenlaces se veían igual (un escalón apagado) y el usuario no podía
   saber si el reporte falló o si su búsqueda no encontró nada. */
.piv6-espera[data-estado="error"] .piv6-espera-paso.is-detenido .piv6-espera-paso-ico{ display:none; }
.piv6-espera[data-estado="error"] .piv6-espera-paso.is-detenido .piv6-espera-paso-x{ display:inline-block; }
.piv6-espera[data-estado="error"] .piv6-espera-paso.is-detenido .piv6-espera-paso-bullet{
  background:var(--pe-err); border-color:var(--pe-err); color:#fff;
}
.piv6-espera[data-estado="error"] .piv6-espera-paso.is-detenido::before{ background:var(--pe-err); }
.piv6-espera[data-estado="empty"] .piv6-espera-paso.is-detenido .piv6-espera-paso-bullet{
  background:var(--piv6-surface, #fff); border-style:dashed;
  border-color:var(--piv6-faint, #9aa2b1); color:var(--piv6-muted, #6a7383);
}
.piv6-espera-paso.is-hecho .piv6-espera-paso-ico{ display:none; }
.piv6-espera-paso.is-hecho .piv6-espera-paso-ok{ display:inline-block; }
.piv6-espera-paso.is-hecho .piv6-espera-paso-bullet{
  background:var(--pe-ok); border-color:var(--pe-ok); color:#fff;
}
.piv6-espera-paso.is-actual .piv6-espera-paso-bullet{
  background:var(--pe-est); border-color:var(--pe-est); color:#fff;
  box-shadow:0 0 0 .32rem color-mix(in srgb, var(--pe-est) 18%, transparent);
}
.piv6-espera[data-estado="loading"] .piv6-espera-paso.is-actual .piv6-espera-paso-bullet{
  animation:piv6-espera-halo 1.6s ease-out infinite;
}
.piv6-espera-paso-etq{
  font-size:.78rem; font-weight:600; line-height:1.25;
  color:var(--piv6-faint, #9aa2b1);
  padding:0 .25rem;
  transition:color .25s ease;
}
.piv6-espera-paso.is-hecho .piv6-espera-paso-etq{ color:var(--piv6-muted, #6a7383); }
.piv6-espera-paso.is-actual .piv6-espera-paso-etq{
  color:color-mix(in srgb, var(--pe-est) 62%, #0b0c10); font-weight:700;
}

/* ---- CONTADOR DE REGISTROS (sólo el reporteador manda `registros`) ---------------------------- */
.piv6-espera-contador{ margin:2rem auto .25rem; text-align:center; }
.piv6-espera-contador.is-visible{ animation:piv6-espera-entra .5s ease-out both; }
.piv6-espera-contador-big{
  display:flex; align-items:baseline; justify-content:center; flex-wrap:wrap; gap:.4rem;
}
/* Tinta neutra a propósito: el verde es del botón de descarga (la acción), y dos verdes grandes
   compitiendo en la misma pantalla se anulan. */
.piv6-espera-contador-num{
  font-size:3.4rem; font-weight:800; line-height:1; letter-spacing:-.02em;
  color:var(--piv6-text, #1b2432); font-variant-numeric:tabular-nums;
}
.piv6-espera-contador-etq{ font-size:1.05rem; font-weight:600; color:var(--piv6-muted, #6a7383); }
.piv6-espera-contador-nota{
  display:flex; align-items:flex-start; justify-content:center; gap:.35rem;
  margin:.55rem auto 0; max-width:22rem;
  font-size:.8rem; font-weight:600; line-height:1.35; color:var(--piv6-warn-ink, #7c3d06);
}
.piv6-espera-contador-nota .bi{ color:var(--pe-warn); margin-top:.05rem; }

/* Nombre del archivo generado: nota discreta, no compite con el botón del pie. */
.piv6-espera-archivo{
  display:flex; align-items:center; justify-content:center; gap:.4rem;
  margin:.9rem 0 0; font-size:.85rem; font-weight:600; color:var(--piv6-muted, #6a7383);
  word-break:break-all;
}
.piv6-espera-archivo .bi{ color:var(--pe-ok); flex:none; }

/* Utilidad "sólo lector de pantalla" (el count-up es aria-hidden y se anuncia una vez el total). */
.piv6-espera-sr{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}

/* ---- TARJETA DE FILTROS DE LA CONSULTA -------------------------------------------------------
   Mismo tratamiento que el header de "Filtros" del resto de pfv6 (fondo de sección al 15%, tinta
   al 72%) y, dentro, los datos con el componente `dato` en la rejilla de 12. */
/* Los fallbacks de --pe-sec/--pe-line NO son adorno: esta misma caja se usa ahora en la pantalla de
   SELECCIÓN de filtros del reporteador, que no tiene el envoltorio .piv6-espera donde esas dos
   variables se declaran. Con el fallback la caja se ve idéntica en las dos pantallas, que es
   justo lo que se pidió (Enrique, 2026-08-19). */
.piv6-espera-filtros{
  /* 88rem y no 52: con menos, el valor de un multiselect con varios estatus -"Validada, En
     Revisión, Por Autorizar, Tesorería, Pagada", los cinco de flujo de pagos- se partía en dos
     renglones y la tarjeta se leía peor que el propio filtro (Enrique, 2026-08-19). A este ancho la
     mitad de la rejilla alcanza para esa cadena, que es de las más largas que produce el resumen.
     Se quitó el tope: la tarjeta ocupa el ancho del contenido, igual que los campos de arriba, y
     así el valor cabe en un renglón en cualquier pantalla. */
  /* col-6 con offset 3 por lado: la tarjeta ocupa la mitad central del ancho del contenido
     (Enrique, 2026-08-19). Dentro, la rejilla de 12 deja cada filtro en col-6, o sea dos por
     renglón, que es el default de .piv6-grid. */
  margin:1.9rem auto 0; max-width:none; width:50%;
  border:1px solid var(--pe-line, var(--piv6-line, #dde2ea)); border-radius:12px; overflow:hidden;
  background:var(--piv6-surface, #fff);
}
/* En pantallas chicas la mitad central no alcanza para nada: la tarjeta pasa a ancho completo y sus
   filtros se apilan (de eso ya se encarga la rejilla). Es la razón de haberlo resuelto con
   porcentaje y no con un ancho fijo. */
@media (max-width:991.98px){ .piv6-espera-filtros{ width:100%; } }
.piv6-espera-filtros-head{
  display:flex; align-items:center; gap:.45rem;
  padding:.5rem .85rem; font-size:.82rem; font-weight:700;
  letter-spacing:.3px; text-transform:uppercase;
  background:color-mix(in srgb, var(--pe-sec, var(--rc-sec)) 15%, #fff);
  color:color-mix(in srgb, var(--pe-sec, var(--rc-sec)) 72%, #12131a);
}
.piv6-espera-filtros > .piv6-grid{ padding:.7rem .75rem; }

/* ---- Móvil: el stepper se vuelve vertical (4 etiquetas en fila no caben) ---------------------- */
@media (max-width:575.98px){
  .piv6-espera-orb{ width:5.5rem; height:5.5rem; }
  .piv6-espera-orb-ico{ font-size:2.3rem; }
  .piv6-espera-hero-txt{ flex:1 1 100%; text-align:center; }
  .piv6-espera-contador-num{ font-size:2.9rem; }
  .piv6-espera-pasos{ flex-direction:column; gap:.85rem; }
  .piv6-espera-paso{ flex:none; flex-direction:row; align-items:center; gap:.7rem; text-align:left; }
  .piv6-espera-paso:not(:first-child)::before{
    top:auto; bottom:100%; right:auto; left:1.15rem;
    width:2px; height:.85rem;
  }
  .piv6-espera-paso-etq{ padding:0; }
}

/* ---- Movimiento reducido: sin giro, sin latido, sin entradas ---------------------------------- */
@media (prefers-reduced-motion: reduce){
  .piv6-espera-ring,
  .piv6-espera-orb-ico,
  .piv6-espera-paso.is-actual .piv6-espera-paso-bullet,
  .piv6-espera-contador.is-visible{ animation:none !important; }
  .piv6-espera-barra-fill{ transition:none; }
}

/* ---- Alto contraste: los estados no pueden depender sólo del color -----------------------------
   En forced-colors el sistema reescribe fondos y bordes, así que el escalón cumplido se distingue
   además por la palomita (que ya está en el marcado) y el actual por un contorno propio. */
@media (forced-colors: active){
  .piv6-espera-barra{ border:1px solid CanvasText; }
  .piv6-espera-barra-fill{ background:Highlight; forced-color-adjust:none; }
  .piv6-espera-paso.is-actual .piv6-espera-paso-bullet{ outline:2px solid Highlight; outline-offset:2px; }
}

/* ---- Oscuro: superficies propias; los tokens de estado ya se recalibran arriba ----------------- */
@media (prefers-color-scheme: dark){
  /* --piv6-danger no se recalibra en oscuro (es el rojo de los bordes de campo con error, que
     ahí sí funciona); como aquí tiñe una superficie y un icono grandes, se sube de luminancia. */
  .piv6-espera{ --pe-line:#33405a; --pe-err:#e8646f; }
  .piv6-espera-orb{ background:color-mix(in srgb, var(--pe-est) 18%, #1c2130); }
  .piv6-espera-orb-ico{ color:color-mix(in srgb, var(--pe-est) 70%, #ffffff); }
  .piv6-espera-msg{ color:#e6ebf5; }
  .piv6-espera-paso-bullet{ background:#1c2130; }
  .piv6-espera-contador-num{ color:#e6ebf5; }
  .piv6-espera-contador-nota{ color:var(--piv6-warn-ink, #f6c98a); }
  .piv6-espera-filtros{ background:#1c2130; }
  .piv6-espera-filtros-head{
    background:color-mix(in srgb, var(--pe-sec) 22%, #1c2130);
    color:color-mix(in srgb, var(--pe-sec) 35%, #ffffff);
  }
}

@keyframes piv6-espera-giro{ to{ transform:rotate(360deg); } }
@keyframes piv6-espera-latido{
  0%,100%{ transform:scale(1); opacity:.92; }
  50%{ transform:scale(1.07); opacity:1; }
}
@keyframes piv6-espera-pop{
  0%{ transform:scale(.65); opacity:0; }
  60%{ transform:scale(1.08); opacity:1; }
  100%{ transform:scale(1); }
}
@keyframes piv6-espera-halo{
  0%{   box-shadow:0 0 0 .32rem color-mix(in srgb, var(--pe-est) 26%, transparent); }
  70%{  box-shadow:0 0 0 .85rem color-mix(in srgb, var(--pe-est) 0%, transparent); }
  100%{ box-shadow:0 0 0 .32rem color-mix(in srgb, var(--pe-est) 0%, transparent); }
}
@keyframes piv6-espera-entra{
  from{ opacity:0; transform:translateY(.7rem) scale(.96); }
  to{   opacity:1; transform:none; }
}


/* ============================================================================================
   ANCHO CONTENT-AWARE — el ancho de un campo lo manda la LONGITUD DEL DATO
   (generalización del criterio del issue #41, que hasta ahora sólo vivía en la rejilla de 12
   con las clases piv6-cN: aquéllas dimensionan la CELDA, esto dimensiona el CONTROL).

   POR QUÉ. Un RFC son 13 caracteres, una fecha dd/mm/aaaa son 10, un UUID 36. Estirarlos a todo
   lo ancho de la celda no aporta nada y hace que la pantalla se lea como una sábana de cajas
   iguales cuando los datos no lo son (Enrique, 2026-08-19: "el ancho de cada input debe salir de
   la longitud del dato").

   CÓMO SE USA (una sola variable, sin números mágicos por campo):
     --piv6-ch = nº de CARACTERES que puede tener el dato. Se declara sobre el propio control o
                 sobre su .piv6-crd (se hereda, así los DOS inputs de un rango lo toman de una).
     Tres caminos, en este orden:
       1. El fragmento lo sabe por definición (p.ej. filtro-rango: una fecha son 10) y lo emite.
       2. El caller lo pasa: los fragmentos aceptan `ch` (y `maxlength`, que además emite el
          atributo HTML real y de paso sirve de `ch` por defecto).
       3. AUTOMÁTICO: /js/portal-inputs-v6.js copia el `maxLength` del <input> a --piv6-ch.
          Por eso NO hay que tocar este CSS al agregar un campo: basta con que el control declare
          su maxlength, que es lo mismo que ya declaran las entidades con @Size/length.

   ANCHO = min(100%, ch caracteres + holgura). El `width:100%` de .piv6-ctrl sigue mandando
   cuando la celda es más angosta (móvil, columna chica): el campo ENCOGE, no se desborda.
   La holgura (--piv6-ch-holgura) cubre el padding y el afford del control (caret, calendario)
   y da el margen para que un dato de longitud exacta no se vea apretado; se sube en los
   controles que dibujan algo dentro (select nativo, input type=date).

   SIN --piv6-ch EL CAMPO QUEDA ELÁSTICO (default 999ch = sin tope), que es el comportamiento
   de siempre: las plantillas que no declaran nada no cambian. Para APAGARLO en un campo
   concreto que sí declara maxlength, ponle --piv6-ch:999 en su tarjeta.

   NO aplica a <textarea>: ahí el texto envuelve, así que la longitud máxima no dice nada del
   ancho (un textarea de 400 caracteres no mide 400 caracteres de ancho).
   ============================================================================================ */
.piv6{ --piv6-ch-holgura:1.5rem; }

.piv6 input.piv6-ctrl,
.piv6 select.piv6-ctrl,
.piv6 .piv6-ms-toggle{
  max-width:calc(var(--piv6-ch, 999) * 1ch + var(--piv6-ch-holgura, 1.5rem));
}
/* El widget nativo dibuja calendario/flecha DENTRO de la caja: más holgura que un texto pelón. */
.piv6 input[type="date"].piv6-ctrl{ --piv6-ch-holgura:3.2rem; }
.piv6 select.piv6-ctrl{ --piv6-ch-holgura:2.6rem; }


/* ============================================================================================
   VARIANTE COMPACTA DE LA TARJETA — .piv6-crd-cmp

   MISMA tarjeta que la de las formas de captura: mismo borde, mismo radio, mismo anillo de foco
   (:focus-within), mismo control borderless (.piv6-ctrl) y misma tipografía de etiqueta. Sólo
   cambia la DENSIDAD: menos padding, columna de etiqueta más angosta y etiqueta recortada a dos
   renglones.

   PARA QUÉ. Los paneles de filtros de las consultas comparten pantalla con la tabla: si la
   tarjeta creciera de alto, la tabla se iría abajo del pliegue. Con esta variante un filtro mide
   lo mismo (o menos) que el campo etiqueta-arriba que tenían antes.

   DIFERENCIAS DELIBERADAS respecto de la tarjeta de captura:
     · SIN barra de acento: la barra marca "obligatorio" y ningún filtro lo es.
     · Etiqueta siempre en tono/peso de campo OPCIONAL, incluso cuando la tarjeta hospeda un
       switch o el switch "Excepto" del multiselect (en captura eso significa "valor siempre
       definido" = requerido; en un filtro no significa nada).
     · El multiselect y el segmentado pierden su borde propio: el borde lo pone la tarjeta,
       igual que se lo pone a un <input>. Es lo que elimina el "borde dentro de borde".
   ============================================================================================ */
.piv6-crd-cmp{ padding:.28rem .55rem .3rem .7rem; }

/* ---- ANCHO CONTENT-AWARE **DE LA TARJETA** ----------------------------------------------------
   La caja que el usuario VE es la tarjeta, no el <input>: desde que el control es borderless, el
   borde, el fondo y el anillo de foco los pinta el .piv6-crd. Topar solo el input dejaba la
   tarjeta midiendo la pista completa y el campo se seguia viendo igual de largo (medido en
   /reporteador/flowserveingresosegresos: input de Serie 80px dentro de una tarjeta de 514px).
   Asi que el tope va a la TARJETA y el input queda topado de rebote.

   POR QUE AQUI Y NO EN LA TARJETA DE CAPTURA: en las formas el ancho de la caja ya lo declara la
   rejilla de 12 con piv6-cN (issue #41). En los filtros la rejilla es `auto-fit` y nadie declara
   el ancho de la celda, asi que lo declara la propia tarjeta y el sobrante de la pista queda en
   blanco a la derecha.

   ANCHO DE TARJETA = (ch caracteres + holgura) x nº de controles + separadores + CROMO
   donde CROMO es lo que ocupa la tarjeta al margen del dato: columna de etiqueta (7.5rem) + gap
   (.5rem) + paddings (1.25rem) + bordes. Los tres sumandos variables son:
     --piv6-ch-holgura : depende del CONTROL (un select dibuja su chevron dentro, un date su
                         calendario, el multiselect su caret) - de ahi los :has() de abajo.
     --piv6-ch-factor  : cuantos controles van lado a lado en la celda (el rango lleva DOS).
     --piv6-ch-extra   : lo que va ENTRE esos controles (la flecha del rango y sus dos gaps).
   Sin --piv6-ch (999 por defecto) el calculo se dispara a miles de px, o sea: sin tope. */
.piv6-crd-cmp{
  --piv6-crd-cromo:9.4rem;   /* etiqueta 7.5 + gap .5 + paddings 1.25 + bordes */
  --piv6-ch-factor:1;
  --piv6-ch-extra:0rem;
  max-width:calc((var(--piv6-ch, 999) * 1ch + var(--piv6-ch-holgura, 1.5rem)) * var(--piv6-ch-factor)
                 + var(--piv6-ch-extra) + var(--piv6-crd-cromo));
}
/* Holgura por TIPO DE CONTROL: se declara en la tarjeta (que es quien calcula su ancho) y se
   hereda al control, asi los dos topes salen del mismo numero y no se pueden desincronizar. */
.piv6-crd-cmp:has(select.piv6-ctrl){ --piv6-ch-holgura:2.6rem; }
.piv6-crd-cmp:has(input[type="date"].piv6-ctrl){ --piv6-ch-holgura:3.2rem; }
.piv6-crd-cmp:has(.piv6-ms){ --piv6-ch-holgura:2rem; }
/* RANGO DE FECHAS: dentro de la celda van DOS inputs de 10 caracteres mas la flecha. Con la
   holgura de un campo simple la tarjeta saldria a la mitad y los dos inputs se aplastarian. */
.piv6-crd-cmp:has(.piv6-daterange){ --piv6-ch-factor:2; --piv6-ch-extra:1.8rem; }
/* Ningún filtro es obligatorio: sin barra de acento (ni siquiera la que la tarjeta de captura
   enciende para switches y campos deshabilitados). */
.piv6-crd-cmp::before{ display:none !important; }

/* Columna de etiqueta más angosta que en captura (8.5rem): en una rejilla de filtros la celda
   mide ~300px y con 8.5rem no quedaba control. Los títulos de filtro son más largos que los de
   un formulario ("Rfc del Receptor"), así que la etiqueta ENVUELVE hasta dos renglones y a
   partir de ahí recorta con puntos suspensivos; el texto completo queda en el `title`. */
.piv6-crd-cmp .piv6-rowin{ grid-template-columns:7.5rem 1fr; gap:.5rem; min-height:2.1rem; }
/* Icono CENTRADO con el texto (Enrique, 2026-08-19: "alinea el icono en medio"). Estaba en
   flex-start por el recorte a dos renglones, pero la enorme mayoría de las etiquetas son de UNA
   línea y ahí el glifo quedaba más alto que el texto y se leía desalineado. */
.piv6-crd-cmp .piv6-lbl{ align-items:center; }
/* :not(.bi) para no enganchar los <span class="bi"> del icono ni el candado de un filtro fijo:
   el que se recorta es el TEXTO del título. */
.piv6-crd-cmp .piv6-lbl > span:not(.bi){
  display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
  overflow:hidden; overflow-wrap:anywhere; min-width:0;
}
/* La caja del icono ya queda centrada con la del texto (medido: delta 0.0), pero el GLIFO no está
   centrado DENTRO de su caja: bootstrap-icons dibuja sobre la línea base y con `line-height:1.2`
   heredado la caja mide 12.2px para una tinta que ocupa ~10, así que el sobrante cae abajo y el
   dibujo se ve alto. Con line-height:1 la caja se ciñe al glifo y la corrección deja de depender
   de un margen a ojo. */
.piv6-crd-cmp .piv6-lbl .bi{ margin-top:0; }

/* La etiqueta NO se pone en negrita por hospedar un switch (regla de la tarjeta de captura:
   "switch = valor siempre definido = requerido"). En un filtro no hay obligatorios. */
.piv6-crd-cmp:has(.piv6-switch) .piv6-lbl,
.piv6-crd-cmp:has(.piv6-ms) .piv6-lbl{
  color:color-mix(in srgb, var(--rc-sec) 48%, #7b8493); font-weight:500;
}
.piv6-crd-cmp:has(.piv6-switch) .piv6-lbl .bi,
.piv6-crd-cmp:has(.piv6-ms) .piv6-lbl .bi{ color:var(--rc-sec); opacity:.65; }

/* MULTISELECT DENTRO DE LA TARJETA. En las formas de captura el multiselect vive suelto (con su
   propia etiqueta arriba) y por eso trae borde, radio y min-height propios. Dentro de la tarjeta
   eso sería un borde dentro de otro: aquí se comporta como un .piv6-ctrl más y el borde y el
   anillo de foco los pone la tarjeta.
   OJO con la fila: la regla de captura `.piv6-rowin:has(.piv6-switch)` (etiqueta 1fr + control
   pegado a la derecha) también engancharía aquí, porque el switch "Excepto" del multiselect
   lleva la clase .piv6-switch. Se re-declara la rejilla normal para que no pase. */
.piv6-crd-cmp .piv6-rowin:has(.piv6-ms){ grid-template-columns:7.5rem 1fr; }
/* Ídem con la regla de captura para inputs numéricos, que ensancha la columna de etiqueta a
   10.5-13rem: en una celda de filtro de 300px eso dejaría al control sin espacio. El ancho corto
   del propio input numérico (max-width:6.5rem, también de la biblioteca) sí se conserva: es el
   mismo criterio content-aware. */
.piv6-crd-cmp .piv6-rowin:has(input[type="number"]){ grid-template-columns:7.5rem 1fr; }
.piv6-crd-cmp .piv6-rowin:has(.piv6-ms) > .piv6-field{ justify-self:stretch; }
.piv6-crd-cmp .piv6-ms-toggle{
  border:0; background:transparent; border-radius:0; box-shadow:none;
  padding:.1rem 0; min-height:1.7rem; gap:.35rem;
}
.piv6-crd-cmp .piv6-ms.open > .piv6-ms-toggle,
.piv6-crd-cmp .piv6-ms-toggle:focus-visible{ border-color:transparent; box-shadow:none; }
.piv6-crd-cmp .piv6-ms-wrap{ gap:.4rem; }
/* El desplegable del multiselect se sale de la tarjeta (position:absolute). Mientras está
   abierto, la tarjeta se levanta sobre sus hermanas para que la de al lado no lo tape. */
.piv6-crd-cmp:has(.piv6-ms.open){ position:relative; z-index:1060; }

/* Rango de fechas: los dos controles se reparten el ancho (flex:1 1 0) pero el max-width
   content-aware (--piv6-ch:10 que emite el fragmento) los topa en el ancho de un dd/mm/aaaa;
   el sobrante de la celda queda en blanco a la derecha. En celda angosta el flex-shrink los
   encoge, que es justo lo que se quiere. */
.piv6-crd-cmp .piv6-daterange{ justify-content:flex-start; }

/* MÓVIL: la tarjeta compacta apila etiqueta y control igual que la de captura. La regla de arriba
   (.piv6-crd-cmp .piv6-rowin, columna de 7.5rem) es más específica que el @media de .piv6-rowin y
   se lo comería, así que aquí se repite para la variante. */
@media (max-width:520px){
  .piv6-crd-cmp .piv6-rowin,
  .piv6-crd-cmp .piv6-rowin:has(.piv6-ms){ grid-template-columns:1fr; gap:.15rem; }
  .piv6-crd-cmp .piv6-rowin:has(.piv6-switch){ grid-template-columns:1fr auto; column-gap:.6rem; }
  /* Con la etiqueta ARRIBA el "cromo" ya no es una columna de 7.5rem, asi que el calculo del
     ancho de tarjeta deja de valer: se quita el tope y las tarjetas vuelven a ocupar el ancho de
     la pantalla (una tarjeta de 250px bajo otra de ancho completo se lee como maquetacion rota).
     El tope del INPUT si se queda: dentro de la tarjeta el dato corto sigue midiendo lo suyo. */
  .piv6-crd-cmp{ max-width:none; }
}


/* ============================================================
   MODAL pfv6 — chrome tematizado para los diálogos que abre una pantalla piv6.
   Nació con el "Enviar por correo" de la pantalla de espera (#115). Hasta ahora cada modal del
   portal se armaba a mano sobre Bootstrap crudo (uno con .bg-warning, otro con .sb3-modal-header
   —que vive en sidebar3.css y sólo se carga en los tenants del sidebar nuevo—), así que ninguno
   se parecía al siguiente. Aquí sólo se viste el chrome de Bootstrap; los campos de adentro son
   los .piv6-crd de siempre.

   OJO: la clase .piv6 va EN EL PROPIO .modal. Bootstrap 5 NO mueve el diálogo al <body>, pero el
   modal tampoco puede colgar del card (.piv6-card-pagina tiene overflow:hidden): sin un ancestro
   .piv6 no resuelven --piv6-tema ni --rc-sec y los botones salen del color equivocado.
   ============================================================ */
.piv6-modal .modal-content{ border:1px solid var(--piv6-line); border-radius:14px; overflow:hidden; box-shadow:var(--piv6-shadow-md); }
/* La cabecera sale del COLOR DE SECCIÓN (--piv6-accion) y no del tenant, por el mismo motivo que
   la acción del pie: el modal lo abre UNA pantalla y tiene que hablar de la sección de esa
   pantalla. Ver el token --piv6-accion allá arriba. */
.piv6-modal .modal-header{ background:var(--piv6-accion); color:#fff; border-bottom:0; padding:.8rem 1.05rem; }
.piv6-modal .modal-header .modal-title{ font-size:1rem; font-weight:700; display:flex; align-items:center; gap:.5rem; }
.piv6-modal .modal-header .btn-close{ filter:invert(1) grayscale(1) brightness(2); opacity:.9; }
.piv6-modal .modal-body{ padding:1rem 1.05rem; background:var(--piv6-surface); }
.piv6-modal .modal-footer{ background:#f7f8fa; border-top:1px solid var(--piv6-line); padding:.7rem 1.05rem; gap:.6rem; }
/* Mismo reparto que el pie de las formas (.piv6-form-footer-in): el secundario se despega a la
   izquierda y la acción primaria queda a la derecha. */
.piv6-modal .modal-footer > .piv6-btn-back{ margin-right:auto; }

/* Línea de retroalimentación del diálogo (éxito / error / aviso). Arranca oculta: la clase de
   estado es la que la muestra, para que el hueco no exista mientras no hay nada que decir. */
.piv6-modal-msg{ display:none; align-items:flex-start; gap:.45rem; margin:.75rem 0 0; padding:.55rem .7rem;
  border-radius:var(--piv6-r-chico); font-size:.85rem; line-height:1.45; }
.piv6-modal-msg .bi{ flex:0 0 auto; margin-top:.08rem; }
.piv6-modal-msg.is-ok{ display:flex; background:#eaf7ef; color:#15803d; }
.piv6-modal-msg.is-error{ display:flex; background:var(--piv6-danger-soft); color:var(--piv6-danger); }
.piv6-modal-msg.is-info{ display:flex; background:var(--piv6-soft); color:var(--piv6-ink); }

@media (prefers-color-scheme: dark){
  .piv6-modal .modal-content{ border-color:#33405a; }
  .piv6-modal .modal-body{ background:#1c2130; }
  .piv6-modal .modal-footer{ background:#161a26; border-top-color:#33405a; }
  .piv6-modal-msg.is-ok{ background:color-mix(in srgb, #15803d 22%, #1c2130); color:#7fd6a0; }
  .piv6-modal-msg.is-error{ background:color-mix(in srgb, var(--piv6-danger) 22%, #1c2130); color:#e8646f; }
}

/* ============================================================
   COLOR DE LOS MODALES — que la cabecera y la acción del diálogo salgan del MISMO ORIGEN que la
   página que lo abre (Enrique, 2026-08-20; misma queja que la del pie: en sadasi el modal de
   Nueva Partida salía con cabecera azul pálido de Bootstrap y botón Guardar naranja del tenant,
   con el encabezado de la página en azul marino de Facturación).

   Todo cuelga de --piv6-accion, el token que declara el bloque del componente de acciones:
   color de SECCIÓN de la página, con el color del tenant como último escalón. Aquí se RE-DECLARA
   sobre .modal con la cadena completa porque un diálogo puede vivir FUERA de cualquier .piv6
   -los de comun/dialogos.html no llevan la clase- y ahí --piv6-tema no existe: sin este escalón
   extra el var() quedaba sin resolver y el botón se habría quedado SIN fondo, no del color viejo.
   Dentro de un .piv6 el valor que produce es idéntico, así que re-declararlo no cambia nada.

   Va TODO por clase, a propósito: así aplica también a los diálogos de comun/dialogos.html sin
   editar ese archivo (lo está consolidando otro agente) y a los que salgan de esa consolidación.
   ============================================================ */
.modal{ --piv6-accion: var(--piv6-sec-pagina, var(--piv6-card-head, var(--piv6-tema, var(--tema-color, #0d6efd)))); }

/* 1. CABECERAS LEGADAS. Doce diálogos de comun/dialogos.html -más los que aún no migran- traen
   `bg-primary-subtle text-primary-emphasis`, o sea el azul genérico de Bootstrap: el mismo en
   todos los tenants y en todas las secciones, sin relación con la pantalla. Se re-tiñen desde
   --piv6-accion CONSERVANDO el tratamiento tenue (no se convierten en banda sólida): una cabecera
   de diálogo no debe competir con el encabezado de la página, y así el cambio es sólo de color y
   no de jerarquía, que es lo que permite aplicarlo a ciegas sobre diálogos ajenos.
   Los porcentajes son los mismos ya validados en esta hoja para superficie y tinta de sección
   (--rc-sec-bg 15% y --rc-sec-ink 72%), no números nuevos. Medidos sobre los 13 colores de
   sección: el peor par es Recepción con 5.70:1 y el resto va de 5.85 a 12.8, o sea que la
   cabecera tenue tiene MÁS margen que la sólida del pie (4.59 en el mismo peor caso).
   El !important es obligado y no descuido: `bg-primary-subtle` y `text-primary-emphasis` son
   utilidades de Bootstrap y las utilidades traen su propio !important en el markup. */
.modal-header.bg-primary-subtle{
  background-color:color-mix(in srgb, var(--piv6-accion) 15%, #fff) !important;
  border-bottom:1px solid color-mix(in srgb, var(--piv6-accion) 30%, #fff);
}
.modal-header.bg-primary-subtle.text-primary-emphasis{
  color:color-mix(in srgb, var(--piv6-accion) 72%, #12131a) !important;
}

/* 2. ACCIÓN DEL DIÁLOGO. El primario del pie de CUALQUIER modal (lleve o no .piv6-modal) toma el
   color de sección, igual que el primario del pie de la forma. La SEMÁNTICA no se toca: success
   sigue siendo autorizar/confirmar positivo, danger destructivo -un modal de confirmación de
   borrado sigue en rojo- y warning devolver al remitente. */
.modal-footer .piv6-btn-primary{ background:var(--piv6-accion); color:#fff; }
.modal-footer .piv6-btn-primary:hover{ background:color-mix(in srgb, var(--piv6-accion) 88%, #000); color:#fff; }

@media (prefers-color-scheme: dark){
  /* En oscuro la mezcla se hace contra el lienzo de la casa, no contra blanco (mismo criterio que
     el resto de los componentes de esta hoja). */
  .modal-header.bg-primary-subtle{
    background-color:color-mix(in srgb, var(--piv6-accion) 22%, #1c2130) !important;
    border-bottom-color:#33405a;
  }
  .modal-header.bg-primary-subtle.text-primary-emphasis{
    color:color-mix(in srgb, var(--piv6-accion) 35%, #e9edf5) !important;
  }
}
