/* ═══════════════════════════════════════
   ▓ COMPONENTE · Progress — gemelo vanilla ▓
   v1.3 · 2026-10-29. Ficha: `design-system/COMPONENTE_PROGRESS.md`

   El avance de algo cuyo final SE CONOCE. Dos formas de la misma pieza:
     · BARRA  — el riel fino de una transferencia (subir/bajar un archivo).
     · ANILLO — la espera con final conocido que vive DENTRO de un renglón (Ricardo, 15-ago),
                donde una barra no cabe: la cuenta atrás de un código, por ejemplo.

   ⛔ NO CONFUNDIR CON EL SPINNER. El Spinner es «proceso SIN forma conocida»; éste es su
   contrario exacto. Comparten grosor (2px), color (`currentColor`) y la ausencia de riel de
   fondo — el hueco ES lo que falta — precisamente para que se lean como la misma familia.

   REQUISITOS DEL ANFITRIÓN:
     1. Los tokens del canon (`colors_and_type.css`).
     2. `box-sizing: border-box`.
   ═══════════════════════════════════════ */

/* ── FORMA BARRA ─────────────────────────────────────────────────────────── */
.exds-progress {
  height: 3px;                                  /* el peso viene del GROSOR, no del color */
  border-radius: var(--radius-pill, 999px);
  background: var(--color-border-subtle, #E5E7EB);
  overflow: hidden;
}
.exds-progress-fill {
  height: 100%;
  border-radius: var(--radius-pill, 999px);
  background: var(--color-action-ink, #21272C);
  transition: width var(--motion-base, 250ms) var(--ease-default, cubic-bezier(.32,.72,0,1));
}

/* ── MODO «POR PASOS» (Ricardo, 2026-10-29) ─────────────────────────────────
   Ancho = --avance (0..1) del carril. Lo fija progress.js. data-fase="paso": completa el paso en
   700 ms (--ease-settle, excepción aprobada al techo de 400 ms); data-fase="espera": avance lento
   hacia 90 % del tramo siguiente, indicador de espera, nunca retrocede. */
.exds-progress[data-pasos] .exds-progress-fill {
  width: calc(var(--avance, 0) * 100%);
  transition: width var(--motion-progreso-paso, 700ms) var(--ease-settle, cubic-bezier(.22,1,.36,1));
}
.exds-progress[data-pasos][data-fase="espera"] .exds-progress-fill {
  transition: width var(--motion-progreso-espera, 22s) var(--ease-progreso-espera, cubic-bezier(.1,.55,.3,1));
}

/* ── RÓTULO OPCIONAL DEL PASO (Ricardo, 2026-10-29) ─────────────────────────
   DECISION-FUENTE: Ricardo, 2026-10-29 — «si abro excepcion y la quiero en el canon, como un opcional de la barra de progreso.»
   Sólo existe si el contenedor `.exds-progress-wrap` lleva `data-rotulo`. Fila encima del riel:
   izquierda = el texto del paso en curso, derecha = el % que sigue al relleno (lo escribe progress.js).
   El texto del paso cambia con el gesto «text-states-swap» = papel 6 con salida (COMPONENTE_MOVIMIENTO.md,
   «Las DOS mitades del papel 6»): el viejo SUBE y se desenfoca en --motion-fast, el nuevo ENTRA desde
   abajo en --motion-base, --ease-default en las dos mitades. Mismos valores que `.cz-np-swap` de NumberPop
   (10 px + 2 px de desenfoque); aquí con @keyframes en vez de transición, porque el rótulo se reconstruye
   en cada cambio. EXCEPCIÓN ACOTADA al «sólo capa expresiva de cliente» de NumberPop: vale únicamente
   para este rótulo (aunque lo cambie el sistema y viva en el backoffice). El % NO lleva gesto. */
.exds-progress-rotulo {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-3, 12px); margin-bottom: var(--space-2, 8px);
  font: var(--fw-regular, 400) var(--fs-body-sm, 13px) var(--font-sans, Inter, sans-serif);
  color: var(--fg2, #4B5563);
}
.exds-progress-rotulo-paso { position: relative; min-width: 0; white-space: nowrap; }
.exds-progress-rotulo-pct { flex: none; color: var(--fg3, #5C6B7A); font-variant-numeric: tabular-nums; }
.exds-progress-rotulo-cambio { position: relative; display: inline-block; }
/* EL FANTASMA · `content: attr()` para que el texto viejo NO exista como nodo (no cuenta en textContent
   ni lo lee el lector de pantalla): el elemento dice la verdad desde el primer cuadro. */
.exds-progress-rotulo-cambio.is-cambia::before {
  content: attr(data-fantasma);
  position: absolute; inset: 0;
  white-space: nowrap; pointer-events: none;
  animation: exds-progress-rotulo-fuga var(--motion-fast, 120ms) var(--ease-default, cubic-bezier(.32,.72,0,1)) both;
}
.exds-progress-rotulo-cambio.is-cambia .exds-progress-rotulo-nuevo {
  display: inline-block;
  animation: exds-progress-rotulo-entra var(--motion-base, 250ms) var(--ease-default, cubic-bezier(.32,.72,0,1)) var(--motion-fast, 120ms) both;
}
@keyframes exds-progress-rotulo-fuga {
  from { transform: translateY(0);     filter: blur(0);   opacity: 1; }
  to   { transform: translateY(-10px); filter: blur(2px); opacity: 0; }
}
@keyframes exds-progress-rotulo-entra {
  from { transform: translateY(10px); filter: blur(2px); opacity: 0; }
  to   { transform: translateY(0);    filter: blur(0);   opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .exds-progress-rotulo-cambio.is-cambia::before { content: none; animation: none !important; }
  .exds-progress-rotulo-cambio.is-cambia .exds-progress-rotulo-nuevo { animation: none !important; }
}

/* ── FORMA ANILLO ────────────────────────────────────────────────────────── */
.exds-prog-anillo {
  display: inline-block;
  flex: none;                    /* sin esto se encoge en una fila flex y deja de ser redondo */
  width: var(--anillo-size, 16px);
  height: var(--anillo-size, 16px);
  border-radius: 999px;

  /* El arco: `--v` es lo que QUEDA (100 → lleno · 0 → vacío).
     ⛔ ES UN NÚMERO, NO UN PORCENTAJE, y se homologa a PRODUCCIÓN el 2026-08-22.
     El gemelo escribía `var(--v, 100%)` y el cotizador público —que es la fuente de la
     verdad de esta pieza— escribe `calc(var(--v, 100) * 1%)`. **Dos convenciones para la
     misma variable**: quien montara el gemelo pasando `70` vería el anillo vacío, y quien
     copiara de producción pasando `70%` lo vería roto. Ninguna de las dos falla ruidosamente.
     *Una variable con dos convenciones no es un detalle de sintaxis: es una pieza que sólo
     funciona si adivinas de dónde la copiaron.* Gana producción, que es lo que ya opera. */
  background: conic-gradient(currentColor calc(var(--v, 100) * 1%), transparent 0);

  /* ⛔ `closest-side` NO ES OPCIONAL, y aquí está la trampa que duplica el grosor.
     El tamaño por defecto de un `radial-gradient` es `farthest-corner`, así que un `50%`
     mide hasta la ESQUINA (la media diagonal), no hasta el borde. Medido contando píxeles
     sobre el render a 200px: la versión sin `closest-side` daba **59px donde pedía 30**.
     Lo cazó Ricardo A OJO —«se consume más grueso que gira»— antes que ningún gate.
     Con `closest-side` el radio es la mitad del ANCHO y los 2px son 2px. */
  -webkit-mask: radial-gradient(circle closest-side, transparent calc(100% - 2px), #000 0);
          mask: radial-gradient(circle closest-side, transparent calc(100% - 2px), #000 0);

  transition: background var(--motion-base, 250ms) var(--ease-default, cubic-bezier(.32,.72,0,1));
}

/* ⛔ NO SE APAGA CON «REDUCIR MOVIMIENTO»: cambia de paso.
   El Spinner se detiene porque su giro es DECORACIÓN. Este arco es EL DATO — apagarlo sería
   borrar información. Se retira la transición y el valor salta de segundo en segundo. */
@media (prefers-reduced-motion: reduce) {
  .exds-prog-anillo { transition: none !important; }
  .exds-progress-fill { transition: none !important; }
}

/* ── LOS 5 TOKENS QUE CONSUME ───────────────────────────────────────────────
   --radius-pill · --color-border-subtle · --color-action-ink · --motion-base · --ease-default
   El anillo además NO trae color: hereda por `currentColor` del renglón donde vive. */
