/* ============================================================
   COLEGIO JUAN XXIII — EFECTOS Y MICRO-INTERACCIONES (efectos.css)
   Cargado DESPUÉS de style.css, así que todo lo que hay acá gana por
   orden de fuente. Sólo se suma: no cambia layout ni posicionamiento
   de nada que ya exista.

   CONTRATO v1 — este archivo y efectos.js son un par. Si tocás uno,
   tocás el otro:
     · .fx-progress        ← JS crea el div en <body> y escribe
                             --fx-progress (0..1) en <html>
     · [data-fx-reveal]    ← JS agrega .fx-visible (+ --fx-delay)
     · [data-fx-tilt]      ← JS inyecta <span class="fx-spotlight">
                             como PRIMER hijo, escribe --fx-x/--fx-y
                             (px) y --fx-rx/--fx-ry (deg), y agrega
                             .fx-tilting mientras hay hover
     · .parallax-section   ← JS escribe --parallax-y (px)
     · .fx-backtop         ← JS alterna .is-visible y mueve el
                             stroke-dashoffset del anillo

   MOVIMIENTO REDUCIDO: todas las animaciones decorativas se ENCIENDEN
   dentro de prefers-reduced-motion: no-preference y se APAGAN de nuevo
   al final (bloque `reduce`). Los @keyframes viven arriba, sueltos: sólo
   se Decide dónde se usan.
   ============================================================ */


/* ============================================================
   1. BARRA DE PROGRESO DE SCROLL
   ============================================================ */

.fx-progress {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;
    background: linear-gradient(90deg, var(--accent), var(--gold), var(--accent));
    background-size: 200% 100%;
    /* La escala es lo único que lee el valor de scroll: siempre horizontal,
       0 = borde izquierdo, y al no salir de 0..1 nunca se ve el vacío. */
    transform: scaleX(var(--fx-progress, 0));
    transform-origin: left center;
    z-index: 1070;
    pointer-events: none;
    will-change: transform;
}


/* ============================================================
   2. REVEAL AL HACER SCROLL
   ============================================================ */

[data-fx-reveal] {
    opacity: 0;
    transform: translateY(26px);
    transition: opacity .7s cubic-bezier(.22, 1, .36, 1),
                transform .7s cubic-bezier(.22, 1, .36, 1);
    transition-delay: var(--fx-delay, 0s);
}

[data-fx-reveal].fx-visible {
    opacity: 1;
    transform: none;
}


/* ============================================================
   3. TILT 3D + SPOTLIGHT
   Ojo con el ORDEN: `.fx-tilting` y `.fx-visible` tienen la misma
   especificidad (0,2,0) y ambos escriben `transform`. El bloque de
   tilt va DESPUÉS del reveal a propósito: si el JS marca tilt sobre un
   elemento que también se revela, gana la rotación.
   ============================================================ */

[data-fx-tilt] {
    transform-style: preserve-3d;
    backface-visibility: hidden;
    will-change: transform;
}

/* El spotlight va al fondo (z-index 0) y todo el contenido real sube
   a z-index 1, así el brillo pasa por debajo de las fotos y los textos. */
[data-fx-tilt] > *:not(.fx-spotlight) {
    position: relative;
    z-index: 1;
}

[data-fx-tilt].fx-tilting {
    /* !important del contrato: la transición del reveal (0.7s) se
       pelearía con el seguimiento del puntero y se vería laggeado. */
    transition: transform .06s linear !important;
    transform:
        perspective(900px)
        rotateX(var(--fx-rx, 0deg))
        rotateY(var(--fx-ry, 0deg))
        scale3d(1.02, 1.02, 1.02);
}

.fx-spotlight {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    border-radius: inherit;
    opacity: 0;
    transition: opacity .3s ease;
    background: radial-gradient(360px circle at var(--fx-x, 50%) var(--fx-y, 50%), rgba(30,95,187,.22), transparent 62%);
}

[data-fx-tilt]:hover .fx-spotlight {
    opacity: 1;
}


/* ============================================================
   4. PARALLAX
   .parallax-section::before tiene inset:-20%, o sea un colchón
   vertical de sobra: por eso un --parallax-y chico nunca destapa
   los bordes. translate3d mantiene la capa en la GPU.
   ============================================================ */

.parallax-section::before {
    transform: translate3d(0, var(--parallax-y, 0), 0);
}


/* ============================================================
   5. KEN BURNS EN EL HERO
   Sólo en el slide activo (los otros están en opacity 0, animarlos
   sería quemar GPU al pedo). alternate + 22s = respiración lenta.
   Va de 1 a 1.08: como sólo escala hacia adentro, nunca aparece un
   hueco de fondo ni hay layout shift (transform no mueve nada).
   ============================================================ */

.hero-slide.active .hero-slide-bg {
    transform-origin: center;
    /* La animación pisa el transform, así que la transición de 3s del
       zoom-por-hover de style.css queda sin efecto y no hay choque. */
    transition: none;
}


/* ============================================================
   6. BACK TO TOP CON ANILLO DE PROGRESO
   Circunferencia del anillo: 2 · PI · 20 = 125.664. El SVG va
   rotado -90deg para que el relleno arranque arriba, no a la derecha.
   ============================================================ */

.fx-backtop {
    position: fixed;
    right: 22px;
    bottom: 22px;
    width: 48px;
    height: 48px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: linear-gradient(155deg, var(--primary-light), var(--primary) 72%);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
    color: var(--white);
    cursor: pointer;
    z-index: 1070;
    box-shadow: 0 8px 22px var(--accent-glow), inset 0 0 0 1px var(--accent-soft);
    opacity: 0;
    transform: translateY(12px);
    pointer-events: none;
    transition: opacity var(--transition-fast),
                transform var(--transition-smooth),
                box-shadow var(--transition-smooth);
}

.fx-backtop.is-visible {
    opacity: 1;
    transform: none;
    pointer-events: auto;
}

/* 44px dentro de un círculo de 48px: 2px de aire por lado, así el
   anillo (r=20 + 1.5 de trazo) queda centrado exacto. */
.fx-backtop-svg {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 44px;
    height: 44px;
    transform: rotate(-90deg);
    pointer-events: none;
}

.fx-backtop-track {
    stroke: rgba(255, 255, 255, .25);
}

.fx-backtop-bar {
    stroke: var(--gold);
    stroke-linecap: round;
    stroke-dasharray: 125.664;
    stroke-dashoffset: 125.664;
    transition: stroke-dashoffset .12s linear;
}

.fx-backtop-icon {
    position: relative;
    font-size: 1.05rem;
    line-height: 1;
    color: var(--white);
}

/* Va DESPUÉS de `.is-visible` a propósito: misma especificidad, y así
   el hover puede volver a transformar sin perder contra `transform:none`. */
.fx-backtop:hover {
    color: var(--gold-light);
    transform: translateY(-3px);
    box-shadow: 0 10px 30px var(--gold-glow);
}

.fx-backtop:focus-visible {
    outline: 3px solid var(--gold);
    outline-offset: 3px;
    box-shadow: 0 0 0 5px var(--accent-soft), 0 0 26px var(--gold-glow);
}

/* Choque de esquinas: el asistente flotante (.asistente-fab, 58px,
   z-index 1060) ya ocupa EXACTAMENTE la esquina que el contrato le
   reserva a este botón. Sin esta regla los dos círculos se pisan.
   Sólo actúa en navegadores con :has(); si no la soporta, gana la
   posición del contrato. Si querés que el botón viva en otra esquina
   de verdad, hay que cambiar el contrato, no el CSS. */
body:has(> .asistente-fab) .fx-backtop {
    bottom: 92px;
}


/* ============================================================
   7. SHIMMER EN .text-gradient
   El degrade se mueve con background-position (no con transform) para
   no romper el background-clip: text. La banda dorada es angosta a
   propósito: --gold sobre --gray-100 es el punto más flojo de la
   paleta, y mantenerla chica sostiene el contraste del texto.
   ============================================================ */

.text-gradient {
    background-image: linear-gradient(100deg, var(--accent) 0%, var(--gold) 40%, var(--accent) 68%);
    background-size: 220% 100%;
    background-repeat: no-repeat;
}


/* ============================================================
   8. PULIDO EXTRA (sólo con movimiento habilitado)
   ============================================================ */

@media (prefers-reduced-motion: no-preference) {

    /* El brillo del degradé de la barra de progreso se desliza solo. */
    .fx-progress {
        animation: fxGradientSlide 6s linear infinite;
    }

    .text-gradient {
        animation: fxGradientShift 7s ease-in-out infinite;
    }

    /* Ken Burns. Se declara acá y no arriba para que el `reduce` de más
       abajo pueda apagarlo sin tener que pelear contra `transition:none`. */
    .hero-slide.active .hero-slide-bg {
        animation: fxKenBurns 22s ease-in-out infinite alternate;
    }

    /* Sombra más rica en hover: sólo box-shadow, la caja no se mueve,
       así que no toca el layout de ninguna tarjeta. */
    .card:hover,
    [data-fx-tilt]:hover {
        box-shadow: 0 16px 34px var(--accent-glow), 0 0 26px var(--gold-glow);
    }

    [data-fx-tilt].fx-tilting {
        box-shadow: 0 18px 40px var(--accent-glow), 0 0 0 1px var(--accent-soft);
    }

    /* El subrayado del título late en el sitio: se anima el degradé, no
       el width, así el `:hover { width: 100px }` de style.css sigue. */
    .section-title::after {
        background-size: 200% 100%;
        animation: fxUnderlinePulse 5s ease-in-out infinite;
    }

    .btn-accent:hover {
        box-shadow: 0 10px 34px var(--accent-glow), 0 0 48px var(--gold-glow);
    }
}


/* ============================================================
   9. KEYFRAMES
   ============================================================ */

@keyframes fxGradientSlide {
    from { background-position: 0% 0; }
    to   { background-position: 200% 0; }
}

@keyframes fxGradientShift {
    0%   { background-position: 0% 50%; }
    50%  { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}

@keyframes fxKenBurns {
    from { transform: scale(1); }
    to   { transform: scale(1.08); }
}

@keyframes fxUnderlinePulse {
    0%, 100% { background-position: 0% 50%; }
    50%      { background-position: 100% 50%; }
}


/* ============================================================
   10. PREFERS-REDUCED-MOTION: APAGADO TOTAL
   Lo que se conserva: la barra de progreso y el estado visible del
   back-to-top (son información, no decoración). Lo que se elimina:
   todo desplazamiento, escala, rotación y fade.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {

    /* Degradé fijo: sin brillo, sin Ken Burns, sin shimmer. */
    .fx-progress,
    .text-gradient,
    .section-title::after {
        animation: none;
        background-position: 0% 50%;
    }

    .hero-slide.active .hero-slide-bg {
        animation: none;
    }

    /* El reveal tiene que verse SÍ O SÍ: si quedara en opacity 0 el
       contenido desaparecería y no hay animación que lo rescate. */
    [data-fx-reveal],
    [data-fx-reveal].fx-visible {
        opacity: 1;
        transform: none;
        transition: none;
        transition-delay: 0s;
    }

    /* !important acá sí hace falta: hay que ganarle a la regla
       `.fx-tilting` de más arriba, que también lo usa. */
    [data-fx-tilt],
    [data-fx-tilt].fx-tilting {
        transform: none;
        transition: none !important;
        transform-style: flat;
        backface-visibility: visible;
        will-change: auto;
    }

    /* El spotlight se deja, pero sin fade: es una pista de hover útil,
       no movimiento. */
    .fx-spotlight {
        transition: none;
    }

    .parallax-section::before {
        transform: none;
    }

    .fx-backtop,
    .fx-backtop-bar {
        transition: none;
    }

    .fx-backtop:hover {
        transform: none;
    }

    .btn-accent:hover {
        box-shadow: 0 4px 12px var(--accent-glow);
    }
}