/* Feedback de ACCIÓN en botones y enlaces-botón — global del panel.
   Ver `m3-acciones.js`, que es quien pone/quita `.is-loading` y `[disabled]`.

   Por qué existe (2026-07-26): el shell M3 no definía `:active` ni `[disabled]` ni ripple. Los
   ~20 `:disabled="guardando"` repartidos en 14 templates NO producían ningún cambio visual, así
   que pulsar un botón se sentía igual que no pulsarlo y la gente hacía doble clic. La única señal
   del repo vivía suelta en `validaciones.html` con un comentario que ya lo decía: "para que se
   note que se pulsó — antes solo quedaba deshabilitado, sin señal". Aquí se generaliza.

   BUG CAZADO EL MISMO DÍA: este archivo animaba con `m3Spin` pero los `@keyframes` vivían en el
   `<style>` inline de `app_layout_m3.html`. Login/recuperar (base.html) y TODO el portal del
   cliente (portal_base.html) cargan ESTE css pero NO ese shell → ahí el icono simplemente no
   giraba. Una animación con nombre inexistente no falla ni avisa: se ignora. Por eso los
   `@keyframes` viven ahora AQUÍ, junto a su único uso, y el shell ya no los declara. */

@keyframes m3Spin { to { transform: rotate(360deg); } }

/* ── 1. Se pulsó: hundido inmediato (la señal que faltaba) ───────────────────────────────── */
.m3-btn,
.btn,                    /* portal de clientes (sistema de clases propio) */
.cor-addrow,
button.m3t-touch {
  transition: filter .12s, background .12s, transform .06s ease-out, opacity .12s;
  -webkit-tap-highlight-color: transparent;   /* en móvil el flash gris tapaba el hundido */
}

.m3-btn:active:not([disabled]),
.btn:active:not([disabled]),
.cor-addrow:active:not([disabled]) {
  transform: scale(.97);
  filter: brightness(.94);
}

/* Foco visible por teclado (accesibilidad): antes no había ninguno propio. */
.m3-btn:focus-visible,
.btn:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* ── 2. Deshabilitado: la regla que NO existía en el shell ───────────────────────────────── */
.m3-btn[disabled],
.m3-btn:disabled,
.btn[disabled],
.btn:disabled,
.cor-addrow[disabled],
button[disabled].m3t-touch {
  opacity: .5;
  cursor: not-allowed;
  filter: none;
  transform: none;
  pointer-events: none;   /* mata el segundo clic incluso si el handler tardara en montar */
}

/* ── 3. Trabajando: el icono gira y el cursor lo dice ────────────────────────────────────── */
.m3-btn.is-loading,
.btn.is-loading,
a.is-loading {
  opacity: .85;
  cursor: progress;
  pointer-events: none;
}

.m3-btn.is-loading .ms,
.btn.is-loading .ms {
  animation: m3Spin .8s linear infinite;
}

/* Un botón sin icono igual necesita señal: se le inyecta un spinner. */
.m3-btn.is-loading:not(:has(.ms))::before,
.btn.is-loading:not(:has(.ms))::before {
  content: "";
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2.2px solid color-mix(in srgb, currentColor 30%, transparent);
  border-top-color: currentColor;
  animation: m3Spin .8s linear infinite;
  flex: none;
}

/* ── Spinner REUTILIZABLE ─────────────────────────────────────────────────────────────────────
   Hasta 2026-07-27 cada pantalla se hacía el suyo: `rp-spin` (radiografía y conciliación ADD),
   `ht-spin` (hoja de trabajo) y `fis-spin` (fiscal), con sus propios `@keyframes` duplicando el
   `m3Spin` que ya vivía aquí. Erick lo pidió unificado, y §14 de la skill lo exige: antes de
   crear un componente "parecido a" otro, se usa el que ya existe.

   Dos sabores, el mismo lenguaje visual que los botones `is-loading`:
     · `.m3-spin`     — hace girar lo que sea (típico: un icono `.ms` con `progress_activity`).
     · `.m3-spinner`  — el anillo, para cuando no hay icono que girar.
   Ambos respetan `prefers-reduced-motion`: quien pidió menos animación ve el indicador quieto,
   no un elemento dando vueltas. */
.m3-spin {
  animation: m3Spin .8s linear infinite;
}

.m3-spinner {
  display: inline-block;
  width: 15px;
  height: 15px;
  flex: none;
  border-radius: 50%;
  border: 2.2px solid color-mix(in srgb, currentColor 30%, transparent);
  border-top-color: currentColor;
  animation: m3Spin .8s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .m3-spin, .m3-spinner { animation-duration: 0s; }
}

/* Enlaces que disparan trabajo en el servidor (exports, descargas): mismo lenguaje visual. */
a.m3-btn.is-loading { opacity: .7; }

/* ── 4. Variante `.m3-btn-text`: se usa 14 veces y NUNCA se definió ──────────────────────── */
.m3-btn-text {
  background: none;
  color: var(--primary);
  border-color: transparent;
  padding: 8px 12px;
}

.m3-btn-text:hover:not([disabled]) {
  background: color-mix(in srgb, var(--primary) 8%, transparent);
}

/* ── 5. Respeta a quien pidió menos movimiento ───────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .m3-btn, .btn, .cor-addrow { transition: none; }
  .m3-btn:active:not([disabled]),
  .btn:active:not([disabled]),
  .cor-addrow:active:not([disabled]) { transform: none; filter: brightness(.9); }
  .m3-btn.is-loading .ms,
  .btn.is-loading .ms,
  .m3-btn.is-loading::before,
  .btn.is-loading::before { animation-duration: 2s; }
}
