/**
 * ============================================================
 * VISUAL STABILITY — animacion universal de translates post-reveal
 * ============================================================
 *
 * Cuando el `visual-stability-coordinator` revela el contenido,
 * añade un frame despues la clase `vs-animar-translates` a
 * `#responsive-content`. A partir de ese momento, CUALQUIER cambio
 * de `translate` o `transform` en elementos con `data-drag-id`
 * (campos colocados, decos, bloque-wrappers) se INTERPOLA suavemente
 * en lugar de saltar de golpe.
 *
 * Cobertura de casos:
 *
 *   1. **Recalibraciones post-reveal por imagenes tardias** — los 8
 *      shifts residuales que el coordinador no puede esperar (iconos
 *      Google Maps, decos remotos) se vuelven imperceptibles al
 *      animarse en lugar de saltar 3-6px.
 *
 *   2. **Entrada al modo lapiz** — `engine.enter()` aplica shifts a
 *      bloques-wrappers; con esta transition los shifts se animan
 *      en lugar de "saltar a posicion final".
 *
 *   3. **Salida del modo lapiz** — `engine.exit()` revierte shifts;
 *      el cierre del modo es elegante en lugar de brusco.
 *
 *   4. **Edicion en vivo** — autoCalibrar dispara cuando el usuario
 *      escribe y el textarea crece; los reposicionamientos se animan.
 *
 *   5. **Cambios futuros de plantilla** — cualquier nuevo flujo que
 *      mueva un `[data-drag-id]` hereda esta transition automaticamente.
 *
 * Diseno escalable:
 *
 *   - **Universal**: aplica a TODO `[data-drag-id]` en `#responsive-content`.
 *     Cualquier plantilla (actual o futura) se beneficia sin cambios.
 *
 *   - **No fija una transition rigida**: usa las CSS variables
 *     `--ux-lapiz-duracion-larga` y `--ux-lapiz-easing` que ya existen
 *     en el sistema (definidas via `LapizBridge.php` y consumidas por
 *     el modo lapiz). Si los timings cambian en BD, esta transition
 *     hereda los nuevos valores sin tocar este archivo.
 *
 *   - **Respeta override inline**: `_aplicarShiftsInstantaneo()` del
 *     engine inserta `style.transition: none !important` en wrappers
 *     cuando NO quiere animar (reset canonico). Como inline > class
 *     specificity, esos casos siguen siendo instantaneos.
 *
 *   - **API de suspension**: `window.VisualStability.suspendAnimations()`
 *     permite a cualquier mixin futuro desactivar transitions en
 *     operaciones masivas (ver coordinator).
 *
 *   - **Accesibilidad**: respeta `prefers-reduced-motion: reduce`.
 *
 * NO se carga durante la fase pre-reveal: el coordinador garantiza que
 * el primer paint NO tiene movimiento visible (gates convergidos).
 * Sin esta clase, el primer pintado seria instantaneo de todas formas.
 */

/* ============================================================
   ELEMENTOS CUBIERTOS POR LA TRANSITION UNIVERSAL
   ------------------------------------------------------------
   Cubre `[data-drag-id]` (campos colocados, decos, items
   posicionables individuales). Mueven via `style.translate`. Casos:
   recalibraciones por imagenes tardias, edicion en vivo, cambios
   de plantilla.

   NO cubre `.bloque-wrapper[data-bloque-id]` aunque el modo lapiz
   los mueva: el sistema asume wrappers INSTANTANEOS por defecto y
   solo anima swaps individuales con `.is-animando-swap`. Si
   añadiesemos transition a los wrappers, el overlay del lapiz
   mediria posiciones intermedias durante la animacion y los marcos
   /menus quedarian fuera de su bloque (bug "posiciones del menu
   lapiz corrompidas"). El sistema YA tiene su propia animacion
   especifica donde la necesita.
   ============================================================ */
#responsive-content.vs-animar-translates [data-drag-id] {
    transition:
        translate var(--ux-lapiz-duracion-larga, 280ms) var(--ux-lapiz-easing, cubic-bezier(.32, .72, 0, 1)),
        transform var(--ux-lapiz-duracion-larga, 280ms) var(--ux-lapiz-easing, cubic-bezier(.32, .72, 0, 1));
}

/* Suspension explicita: cuando un mixin necesita aplicar shifts sin
   animar (reset masivo, restauracion de canvas, etc.) puede usar
   `window.VisualStability.suspendAnimations()` que añade esta clase
   al contenedor — desactiva transitions hasta el siguiente frame. */
#responsive-content.vs-animar-translates.vs-no-anim [data-drag-id],
#responsive-content.vs-animar-translates [data-drag-id].vs-no-anim {
    transition: none !important;
}

/* Accesibilidad: usuarios con prefers-reduced-motion no ven animaciones */
@media (prefers-reduced-motion: reduce) {
    #responsive-content.vs-animar-translates [data-drag-id] {
        transition: none;
    }
}
