@charset "UTF-8";
/**
 * css/web/carrusel.css  —  v1.0  ft 03/05/2026
 *
 * Estilos del carrusel de fotos para los slots de la web pública,
 * generado por Fotos::pintarSlotPublico() y animado por
 * cra-carrusel.js. Usa CSS variables locales:
 *
 *   --cra-carrusel-duracion   (ms)  Duración de la transición. Se setea
 *                                   inline en el div .cra-carrusel.
 *
 * Filosofía: el HTML es válido sin JS. Por defecto solo la primera
 * foto es visible (clase --activa). El JS solo cambia clases para
 * activar/desactivar slides.
 */

/* ══════════════════════════════════════════════════════════════════════════
 * CONTENEDOR
 * ══════════════════════════════════════════════════════════════════════════ */

.cra-carrusel {
    --cra-carrusel-duracion: 600ms;
    position: relative;
    width: 100%;
    height: 100%;
    /* ft-fix1 03/05/2026: si el padre tiene aspect-ratio pero no altura
     * explícita (caso .habitacion__imagen, .estancia-detalle__imagen,
     * .salon-item, etc.), el carrusel colapsaba a altura 0 porque sus
     * slides son position:absolute y no aportan altura intrínseca.
     * Heredar el aspect-ratio del padre arregla esto: el carrusel ya
     * tiene su propia caja con dimensiones. */
    aspect-ratio: inherit;
    min-height: 100%;
    overflow: hidden;
}

.cra-carrusel:focus { outline: none; }
.cra-carrusel:focus-visible {
    outline: 2px solid var(--color-accent, #b89968);
    outline-offset: 2px;
}

/* ══════════════════════════════════════════════════════════════════════════
 * PISTA Y SLIDES
 * ══════════════════════════════════════════════════════════════════════════ */

.cra-carrusel__pista {
    position: relative;
    width: 100%;
    height: 100%;
}

.cra-carrusel__slide {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    pointer-events: none;
    /* Transición por defecto = fade. Las otras se sobrescriben más abajo. */
    transition: opacity var(--cra-carrusel-duracion) ease-in-out;
}

.cra-carrusel__slide picture,
.cra-carrusel__slide img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Slide activa */
.cra-carrusel__slide--activa {
    opacity: 1;
    pointer-events: auto;
    z-index: 2;
}

/* Estado degradado SIN JS: si el JS no arranca, los demás slides
 * tienen opacity:0 absoluto, así que la primera (única con --activa)
 * queda visible. El usuario ve "una foto fija" — es el fallback OK. */


/* ══════════════════════════════════════════════════════════════════════════
 * TRANSICIÓN: FADE  (default)
 * ══════════════════════════════════════════════════════════════════════════ */

.cra-carrusel--fade .cra-carrusel__slide {
    transition: opacity var(--cra-carrusel-duracion) ease-in-out;
}


/* ══════════════════════════════════════════════════════════════════════════
 * TRANSICIÓN: SLIDE (con dirección)
 *
 * El JS añade la clase cra-carrusel--dir-next o --dir-prev al root
 * según hacia dónde se navega. La activa siempre entra desde el lado
 * "lógico" de su dirección.
 * ══════════════════════════════════════════════════════════════════════════ */

.cra-carrusel--slide .cra-carrusel__slide {
    transition:
        transform var(--cra-carrusel-duracion) cubic-bezier(0.4, 0.0, 0.2, 1),
        opacity 200ms linear;
    transform: translateX(0);
    opacity: 0;
}

/* ft-fix1 03/05/2026: la slide activa SIEMPRE debe ser visible en estado
 * de reposo (sin clase --dir-next/--dir-prev), no solo durante la animación.
 * Antes esto faltaba y los carruseles SIN autoplay quedaban invisibles
 * hasta que el usuario clicara una flecha (porque la animación
 * craSlideInFromRight nunca se disparaba al cargar).
 *
 * Esta regla aplica a la activa cuando NO hay clase direccional, y se
 * sobrescribe limpiamente por las animaciones cuando sí la hay. */
.cra-carrusel--slide .cra-carrusel__slide--activa {
    transform: translateX(0);
    opacity: 1;
    z-index: 2;
}

/* En slide, las inactivas están a 100% en X (fuera) */
.cra-carrusel--slide .cra-carrusel__slide:not(.cra-carrusel__slide--activa):not(.cra-carrusel__slide--saliendo) {
    /* Por defecto detrás de la siguiente, sin movimiento */
    transform: translateX(100%);
    transition: none;  /* salto instantáneo cuando preparamos la próxima */
}

/* Dir next: la activa llega desde la derecha, la saliendo se va a la izquierda */
.cra-carrusel--slide.cra-carrusel--dir-next .cra-carrusel__slide--activa {
    transform: translateX(0);
    opacity: 1;
    animation: craSlideInFromRight var(--cra-carrusel-duracion) cubic-bezier(0.4, 0.0, 0.2, 1) both;
}
.cra-carrusel--slide.cra-carrusel--dir-next .cra-carrusel__slide--saliendo {
    animation: craSlideOutToLeft var(--cra-carrusel-duracion) cubic-bezier(0.4, 0.0, 0.2, 1) both;
}

/* Dir prev: invertido */
.cra-carrusel--slide.cra-carrusel--dir-prev .cra-carrusel__slide--activa {
    transform: translateX(0);
    opacity: 1;
    animation: craSlideInFromLeft var(--cra-carrusel-duracion) cubic-bezier(0.4, 0.0, 0.2, 1) both;
}
.cra-carrusel--slide.cra-carrusel--dir-prev .cra-carrusel__slide--saliendo {
    animation: craSlideOutToRight var(--cra-carrusel-duracion) cubic-bezier(0.4, 0.0, 0.2, 1) both;
}

@keyframes craSlideInFromRight {
    from { transform: translateX(100%); opacity: 0.3; }
    to   { transform: translateX(0);    opacity: 1; }
}
@keyframes craSlideOutToLeft {
    from { transform: translateX(0);     opacity: 1; }
    to   { transform: translateX(-100%); opacity: 0.3; }
}
@keyframes craSlideInFromLeft {
    from { transform: translateX(-100%); opacity: 0.3; }
    to   { transform: translateX(0);     opacity: 1; }
}
@keyframes craSlideOutToRight {
    from { transform: translateX(0);    opacity: 1; }
    to   { transform: translateX(100%); opacity: 0.3; }
}

/* En slide, las salientes deben mantener pointer-events:none pero z-index alto */
.cra-carrusel--slide .cra-carrusel__slide--saliendo {
    z-index: 1;
    opacity: 1;
    pointer-events: none;
}


/* ══════════════════════════════════════════════════════════════════════════
 * TRANSICIÓN: ZOOM (escala suave)
 * ══════════════════════════════════════════════════════════════════════════ */

.cra-carrusel--zoom .cra-carrusel__slide {
    transition:
        opacity var(--cra-carrusel-duracion) ease-in-out,
        transform var(--cra-carrusel-duracion) ease-in-out;
    transform: scale(1.06);
    opacity: 0;
}
.cra-carrusel--zoom .cra-carrusel__slide--activa {
    transform: scale(1);
    opacity: 1;
}
.cra-carrusel--zoom .cra-carrusel__slide--saliendo {
    transform: scale(0.96);
    opacity: 0;
}


/* ══════════════════════════════════════════════════════════════════════════
 * TRANSICIÓN: NINGUNA (cambio instantáneo)
 * ══════════════════════════════════════════════════════════════════════════ */

.cra-carrusel--ninguna .cra-carrusel__slide {
    transition: none;
}


/* ══════════════════════════════════════════════════════════════════════════
 * FLECHAS PREV/NEXT
 * ══════════════════════════════════════════════════════════════════════════ */

.cra-carrusel__flecha {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 38px;
    height: 38px;
    border: none;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.45);
    color: #fff;
    font-size: 22px;
    line-height: 1;
    font-weight: 400;
    cursor: pointer;
    z-index: 10;
    opacity: 0;
    transition: opacity 200ms ease, background 200ms ease, transform 200ms ease;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 0 3px 0;  /* compensar baseline del carácter ‹ › */
}
.cra-carrusel:hover .cra-carrusel__flecha,
.cra-carrusel:focus-within .cra-carrusel__flecha {
    opacity: 1;
}
.cra-carrusel__flecha:hover {
    background: rgba(0, 0, 0, 0.65);
    transform: translateY(-50%) scale(1.05);
}
.cra-carrusel__flecha:focus-visible {
    opacity: 1;
    outline: 2px solid var(--color-accent, #b89968);
    outline-offset: 2px;
}
.cra-carrusel__flecha--prev { left: 12px; padding-right: 4px; }
.cra-carrusel__flecha--next { right: 12px; padding-left: 4px; }

/* En móvil siempre visibles (no hay hover) */
@media (max-width: 768px) {
    .cra-carrusel__flecha {
        opacity: 0.85;
        width: 34px;
        height: 34px;
        font-size: 20px;
    }
}


/* ══════════════════════════════════════════════════════════════════════════
 * INDICADORES (PUNTOS)
 * ══════════════════════════════════════════════════════════════════════════ */

.cra-carrusel__indicadores {
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 6px;
    z-index: 10;
    padding: 4px 10px;
    background: rgba(0, 0, 0, 0.25);
    border-radius: 999px;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

.cra-carrusel__punto {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    border: none;
    background: rgba(255, 255, 255, 0.5);
    padding: 0;
    cursor: pointer;
    transition: background 200ms ease, transform 200ms ease;
}
.cra-carrusel__punto:hover {
    background: rgba(255, 255, 255, 0.85);
    transform: scale(1.15);
}
.cra-carrusel__punto--activo {
    background: #fff;
    transform: scale(1.25);
}
.cra-carrusel__punto:focus-visible {
    outline: 2px solid var(--color-accent, #b89968);
    outline-offset: 2px;
}

/* Si solo hay 1 slide (caso raro pero posible), ocultar todo control */
.cra-carrusel:not(:has(.cra-carrusel__slide:nth-child(2))) .cra-carrusel__flecha,
.cra-carrusel:not(:has(.cra-carrusel__slide:nth-child(2))) .cra-carrusel__indicadores {
    display: none;
}


/* ══════════════════════════════════════════════════════════════════════════
 * MODO ADMIN
 * ══════════════════════════════════════════════════════════════════════════
 * En modo edición, las flechas/indicadores podrían interferir con el
 * editor inline. Se mantienen visibles pero con menos prominencia. El
 * JS ya pausa el autoplay cuando hay .cra-admin-mode.
 */
html.cra-admin-mode .cra-carrusel__flecha,
html.cra-admin-mode .cra-carrusel__indicadores {
    opacity: 0.4;
}


/* ══════════════════════════════════════════════════════════════════════════
 * TRANSICIONES OVERLAY  (jc 09/05/2026)
 * ══════════════════════════════════════════════════════════════════════════
 * Persiana y Cubo 3D no animan los slides en sí (la arquitectura de N
 * slides paralelos no encaja). El JS monta una capa overlay temporal
 * sobre la pista, anima, y al terminar el cambio de slide ocurre tapado
 * por la animación. La capa se elimina del DOM al terminar.
 */
.cra-carrusel__overlay {
    position: absolute;
    inset: 0;
    z-index: 20;
    pointer-events: none;
    overflow: hidden;
}

/* ── PERSIANA (5 franjas horizontales que voltean) ─────────────── */
.cra-carrusel__overlay--persiana {
    display: grid;
    grid-template-rows: repeat(5, 1fr);
}
.cra-carrusel__persiana-franja {
    position: relative;
    overflow: hidden;
    transform-style: preserve-3d;
    perspective: 1000px;
}
.cra-carrusel__persiana-franja-inner {
    position: absolute;
    left: 0;
    right: 0;
    height: 500%;          /* la imagen completa, 5x el alto del franja */
    background-size: 100% 100%;
    transform: rotateX(-90deg);
    transform-origin: center top;
    transition: transform var(--cra-carrusel-duracion, 600ms) cubic-bezier(0.4, 0, 0.2, 1);
    backface-visibility: hidden;
}
.cra-carrusel__persiana-franja:nth-child(1) .cra-carrusel__persiana-franja-inner { top: 0; }
.cra-carrusel__persiana-franja:nth-child(2) .cra-carrusel__persiana-franja-inner { top: -100%; }
.cra-carrusel__persiana-franja:nth-child(3) .cra-carrusel__persiana-franja-inner { top: -200%; }
.cra-carrusel__persiana-franja:nth-child(4) .cra-carrusel__persiana-franja-inner { top: -300%; }
.cra-carrusel__persiana-franja:nth-child(5) .cra-carrusel__persiana-franja-inner { top: -400%; }
/* Cuando se dispara, las 5 franjas giran a 0deg con desfase escalonado */
.cra-carrusel__overlay--persiana.is-animando .cra-carrusel__persiana-franja-inner {
    transform: rotateX(0deg);
}
.cra-carrusel__overlay--persiana.is-animando .cra-carrusel__persiana-franja:nth-child(1) .cra-carrusel__persiana-franja-inner { transition-delay: 0ms; }
.cra-carrusel__overlay--persiana.is-animando .cra-carrusel__persiana-franja:nth-child(2) .cra-carrusel__persiana-franja-inner { transition-delay: 60ms; }
.cra-carrusel__overlay--persiana.is-animando .cra-carrusel__persiana-franja:nth-child(3) .cra-carrusel__persiana-franja-inner { transition-delay: 120ms; }
.cra-carrusel__overlay--persiana.is-animando .cra-carrusel__persiana-franja:nth-child(4) .cra-carrusel__persiana-franja-inner { transition-delay: 180ms; }
.cra-carrusel__overlay--persiana.is-animando .cra-carrusel__persiana-franja:nth-child(5) .cra-carrusel__persiana-franja-inner { transition-delay: 240ms; }

/* ── CUBO 3D (gira sobre el eje vertical) ─────────────────────── */
/* La distancia del cubo (--cra-carrusel-cubo-z) la fija el JS midiendo
   el ancho real del carrusel. Default 400px por si el JS no llega. */
.cra-carrusel__overlay--cubo {
    perspective: 1200px;
}
.cra-carrusel__cubo-stage {
    position: absolute;
    inset: 0;
    transform-style: preserve-3d;
    transition: transform var(--cra-carrusel-duracion, 600ms) cubic-bezier(0.6, 0, 0.4, 1);
    transform: translateZ(calc(var(--cra-carrusel-cubo-z, 400px) * -1)) rotateY(0deg);
}
.cra-carrusel__cubo-cara {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    backface-visibility: hidden;
}
.cra-carrusel__cubo-cara--a {
    transform: translateZ(var(--cra-carrusel-cubo-z, 400px));
}
.cra-carrusel__cubo-cara--b {
    transform: rotateY(90deg) translateZ(var(--cra-carrusel-cubo-z, 400px));
}
.cra-carrusel__overlay--cubo.is-animando .cra-carrusel__cubo-stage {
    transform: translateZ(calc(var(--cra-carrusel-cubo-z, 400px) * -1)) rotateY(-90deg);
}

/* ── IRIS CIRCULAR (jd 09/05/2026) ─────────────────────────────
   La nueva imagen aparece como un círculo que crece desde el centro
   hasta cubrir todo. Se usa clip-path:circle() animado. */
.cra-carrusel__overlay--iris {
    /* sin reglas extra a nivel overlay */
}
.cra-carrusel__iris-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    clip-path: circle(0% at 50% 50%);
    transition: clip-path var(--cra-carrusel-duracion, 600ms) ease-out;
}
.cra-carrusel__overlay--iris.is-animando .cra-carrusel__iris-img {
    /* 75% es suficiente para cubrir un rectángulo desde el centro
       (la diagonal mide ~71% del lado mayor; 75% lo sobrecubre con
       margen de seguridad). */
    clip-path: circle(75% at 50% 50%);
}

/* ── CORTINA DESDE EL CENTRO (jd 09/05/2026) ──────────────────
   La nueva imagen aparece como una franja vertical que se ensancha
   desde el centro hacia los lados. clip-path:inset(). */
.cra-carrusel__cortina-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    clip-path: inset(0 50% 0 50%);
    transition: clip-path var(--cra-carrusel-duracion, 600ms) cubic-bezier(0.4, 0, 0.2, 1);
}
.cra-carrusel__overlay--cortina.is-animando .cra-carrusel__cortina-img {
    clip-path: inset(0 0 0 0);
}

/* ── MOSAICO ONDULADO (jd 09/05/2026) ─────────────────────────
   Grid de 8x5 celdas, cada una mostrando una porción de la nueva
   imagen mediante background-position calculado. Las celdas
   aparecen con delay escalonado siguiendo una onda diagonal.
   El JS asigna transition-delay y transition-duration inline. */
.cra-carrusel__mosaico-celda {
    background-repeat: no-repeat;
    transform: scale(0.3);
    opacity: 0;
    transition-property: transform, opacity;
    transition-timing-function: ease-out;
    /* duration y delay los pone el JS inline */
}
.cra-carrusel__overlay--mosaico.is-animando .cra-carrusel__mosaico-celda {
    transform: scale(1);
    opacity: 1;
}

/* ── ZOOM (jj 09/05/2026) ──────────────────────────────────────
   La vieja se aleja (scale 1 → 0.7) con fade-out, la nueva se
   acerca (scale 1.3 → 1) con fade-in. Cross-zoom. */
.cra-carrusel__overlay--zoom {
    overflow: hidden;
}
.cra-carrusel__zoom-sale,
.cra-carrusel__zoom-entra {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform var(--cra-carrusel-duracion, 600ms) ease-in-out,
                opacity   var(--cra-carrusel-duracion, 600ms) ease-in-out;
}
.cra-carrusel__zoom-sale  { transform: scale(1);   opacity: 1; }
.cra-carrusel__zoom-entra { transform: scale(1.3); opacity: 0; }
.cra-carrusel__overlay--zoom.is-animando .cra-carrusel__zoom-sale  { transform: scale(0.7); opacity: 0; }
.cra-carrusel__overlay--zoom.is-animando .cra-carrusel__zoom-entra { transform: scale(1);   opacity: 1; }


/* ══════════════════════════════════════════════════════════════════════════
 * REDUCCIÓN DE MOVIMIENTO
 * ══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
    .cra-carrusel__slide,
    .cra-carrusel--slide .cra-carrusel__slide,
    .cra-carrusel--zoom .cra-carrusel__slide {
        transition-duration: 80ms !important;
        animation-duration: 80ms !important;
    }
}


/* ══════════════════════════════════════════════════════════════════════════
 * KEN BURNS  (jb 09/05/2026)
 * ══════════════════════════════════════════════════════════════════════════
 * Capa de movimiento sutil sobre el slide activo. Solo se aplica cuando
 * el root del carrusel tiene la clase .is-kenburns (la añade Fotos.php
 * cuando kenburns_activo=1 y la transición no es slide).
 *
 * La animación dura todo el intervalo del autoplay para que termine
 * justo cuando entra el siguiente slide.
 *
 * Variables:
 *   --cra-carrusel-intervalo  duración (ms) — la fija Fotos.php
 *   --cra-carrusel-kb-zoom    factor de escala final (1.06 = +6%)
 *
 * No se aplica con transición SLIDE (los dos usan transform y chocan).
 * El JS reinicia la animación al cambiar de slide activo (animation:none
 * + reflow + animation:'').
 */
.cra-carrusel.is-kenburns:not(.cra-carrusel--slide) .cra-carrusel__slide--activa img {
    animation: cra-carrusel-kenburns var(--cra-carrusel-intervalo, 5000ms) ease-out both;
    transform-origin: center center;
}
@keyframes cra-carrusel-kenburns {
    from { transform: scale(1) translate(0, 0); }
    to   { transform: scale(var(--cra-carrusel-kb-zoom, 1.06)) translate(-2%, -1.5%); }
}

/* En reducir-movimiento, anular Ken Burns (la regla de arriba ya pone
   animation-duration:80ms, lo desactivamos del todo aquí). */
@media (prefers-reduced-motion: reduce) {
    .cra-carrusel.is-kenburns .cra-carrusel__slide--activa img {
        animation: none !important;
        transform: none !important;
    }
}
