/**
 * DES Banners — Front-end Styles
 *
 * @author    David Escudero Digital Studio <soporte@davidescudero.com>
 * @copyright 2007-2026 David Escudero Digital Studio
 * @license   http://opensource.org/licenses/afl-3.0.php
 */

/* ── Item ───────────────────────────────────────────────────────────────── */
.desbanners-item {
  position: relative;
  width: 100%;
}

/* ── Slots ──────────────────────────────────────────────────────────────── */
/* El dispositivo se decide en servidor y solo se renderiza un slot,
   por lo que el slot presente siempre se muestra (sin ocultar por CSS). */
.desbanners-slot { display: block; }

/* ── Modo COVER ─────────────────────────────────────────────────────────── */
.desbanners-mode-cover {
  position: relative;
  width: 100%;
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  display: flex;
  align-items: center;
  /* min-height evita colapso si no hay height configurado */
  min-height: 8rem;
}

/* Imagen del modo cover como <img> real (descubrible para el LCP, admite
   fetchpriority/loading) en vez de background-image. Replica background-size:cover. */
.desbanners-cover-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  z-index: 0;
  pointer-events: none;
  -webkit-user-drag: none;
}

.desbanners-mode-cover .desbanners-overlay {
  position: relative;
  z-index: 1;
  width: 100%;
}

/* ── Modo CONTAIN ───────────────────────────────────────────────────────── */
.desbanners-mode-contain {
  display: grid;
  width: 100%;
}
/* Sin height configurada: el aspect-ratio del img (via width/height attrs)
   hace que el navegador reserve espacio antes de cargar la imagen → 0 CLS */
.desbanners-mode-contain .desbanners-img {
  grid-column: 1;
  grid-row: 1;
  display: block;
  width: 100%;
  max-width: 100%;
  height: auto;
}
.desbanners-mode-contain .desbanners-overlay {
  grid-column: 1;
  grid-row: 1;
  display: flex;
  align-items: center;
  width: 100%;
  z-index: 1;
}

/* Contain con altura fija: la imagen se ve ENTERA dentro del contenedor
   (puede dejar espacio a los lados/arriba según su proporción). */
.desbanners-mode-contain.desbanners-has-height .desbanners-img {
  height: 100%;
  object-fit: contain;
  object-position: center center;
}

/* ── Banner "boxed": el banner COMPLETO (imagen incluida) se limita al ancho
   del contenedor y se centra, alineado con el contenido de la página. En
   "full" ocupa el 100% (a sangre completa). ──────────────────────────────── */
.desbanners-item--boxed {
  box-sizing: border-box;
  max-width: var(--des-container-max-width, 1440px);
  margin-inline: auto;
  /* Sin padding: la imagen llena el ancho del box (máx. 1440) centrado. */
}
/* Esquinas redondeadas solo en boxed (en full el banner va a sangre completa). */
.desbanners-item--boxed img {
  border-radius: 12px;
}

/* ── Overlay: variantes de ancho ────────────────────────────────────────── */
/* Full width: el content ocupa todo el banner */
.desbanners-overlay--full {
  width: 100%;
  padding-inline: 1.5rem;
}

/* Boxed: el content está centrado con un ancho máximo */
.desbanners-overlay--boxed {
  max-width: var(--des-container-max-width, 1440px);
  width: 100%;
  margin-inline: auto;
  padding-inline: var(--des-container-padding-x, 1.5rem);
}

/* ── Content ────────────────────────────────────────────────────────────── */
.desbanners-content {
  position: relative;
  z-index: 1;
  width: 100%;
}

/* ── Slider peek/coverflow ──────────────────────────────────────────────── */
.desbanners-slider {
  /* Padding lateral del layout (desktop 30px, ≤992px 15px). */
  --desb-edge: 30px;
  /* Sigue al ancho de contenedor del tema (--des-container-max-width), para que
     el slide activo quede alineado con el resto del contenido sin tener que
     tocar aquí cada vez que cambie el layout. El 1440 es solo el respaldo por si
     el tema no define la variable. */
  --desb-max: var(--des-container-max-width, 1440px);
  /* Principal: ancho del contenedor menos el padding lateral, a ambos lados. */
  --desb-slide: min(calc(var(--desb-max) - var(--desb-edge) * 2), calc(100% - var(--desb-edge) * 2));
  --desb-side-scale: 0.86;
  --desb-gap: 20px;

  position: relative;
  /* Recortador: ancho normal (NO 100vw) para no desbordar el contenedor padre.
     El viewport interno es el que va a sangre completa, recortado aquí. */
  width: 100%;
  overflow-x: clip;
  overflow-y: visible;
  user-select: none;
  -webkit-user-select: none;
  cursor: grab;
}

.desbanners-slider.is-dragging { cursor: grabbing; }

.desbanners-slider img {
  pointer-events: none;
  -webkit-user-drag: none;
}

/* Viewport a sangre completa (ancho de pantalla) para que el vecino asome
   pegado al borde. Recortado por .desbanners-slider, así no genera scroll. */
.desbanners-viewport {
  /* Ancho del contenedor (layout, con %) — NO 100vw, para que el slide activo
     (ancho contenedor − 60px) quede centrado a 30/15px del borde de contenido,
     alineado con el resto del sitio en cualquier anchura (con o sin scrollbar). */
  width: 100%;
  margin-inline: 0;
  overflow-x: clip;
  overflow-y: visible;
}

.desbanners-track {
  display: flex;
  align-items: center;
  gap: var(--desb-gap);
  cursor: grab;
  touch-action: pan-y;
  /* Oculto hasta que el JS centra el slide activo: así no se ve el estado
     inicial "pegado a la izquierda" ni el salto al centro (CLS). El espacio
     queda reservado (solo opacity), así que no hay desplazamiento de layout.
     La animación es una RED DE SEGURIDAD: si el JS no llega a ejecutarse,
     el track se revela igualmente a los 1.2s. */
  opacity: 0;
  animation: desbTrackReveal 0s linear 1.2s forwards;
}
.desbanners-slider.is-ready .desbanners-track {
  opacity: 1;
  animation: none;
}
@keyframes desbTrackReveal { to { opacity: 1; } }

.desbanners-slide {
  flex: 0 0 var(--desb-slide);
  min-width: 0;
  transform: scale(var(--desb-side-scale));
  opacity: 0.55;
  cursor: pointer;
  transition: transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.45s ease;
}

/* El vecino se escala anclado hacia el activo (queda pegado, gap constante). */
.desbanners-slide--prev { transform-origin: right center; }
.desbanners-slide--next { transform-origin: left center; }

.desbanners-slide--active {
  transform: scale(1);
  opacity: 1;
  cursor: default;
  position: relative;
  z-index: 2;
}

/* Durante el "snap" del bucle infinito: sin transiciones ni en el track ni en
   los slides, para que el reposicionamiento al índice equivalente sea instantáneo
   e invisible (si no, el cambio de slide activo animaría la escala/opacidad y se
   vería un parpadeo al volver al primero). */
.desbanners-slider.is-snapping .desbanners-track,
.desbanners-slider.is-snapping .desbanners-slide {
  transition: none !important;
}

/* ── Un solo banner: sin carrusel, ancho normal ─────────────────────────── */
.desbanners-slider--single,
.desbanners-slider--single .desbanners-viewport {
  width: 100%;
  margin: 0;
  overflow: visible;
}
.desbanners-slider--single .desbanners-slide {
  flex-basis: 100%;
  transform: none;
  opacity: 1;
  cursor: default;
}

/* ── Responsive ─────────────────────────────────────────────────────────── */
@media (max-width: 992px) {
  /* Padding lateral 15px; con varios slides el principal no ocupa el 100%
     para que asome el siguiente. Gap menor y más contraste de escala. */
  .desbanners-slider {
    --desb-edge: 15px;
    --desb-slide: 80%;
    --desb-gap: 14px;
    --desb-side-scale: 0.82;
  }
  .desbanners-slide:not(.desbanners-slide--active) { opacity: 0.45; }
}

@media (max-width: 576px) {
  .desbanners-slider { --desb-side-scale: 0.8; }
}

/* ── Flechas ────────────────────────────────────────────────────────────── */
.desbanners-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 20;
  background: rgba(0, 0, 0, 0.35);
  color: #fff;
  border: none;
  width: 4.4rem;
  height: 4.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 2.8rem;
  line-height: 1;
  cursor: pointer;
  transition: background 0.2s ease;
  padding: 0;
}
.desbanners-arrow:hover  { background: rgba(0, 0, 0, 0.65); }
.desbanners-arrow--prev  { left: 0; }
.desbanners-arrow--next  { right: 0; }

/* ── Dots ───────────────────────────────────────────────────────────────── */
.desbanners-dots {
  position: absolute;
  bottom: 1.6rem;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 0.8rem;
  z-index: 20;
}
.desbanners-dot {
  width: 1rem;
  height: 1rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.5);
  border: 2px solid rgba(255, 255, 255, 0.7);
  cursor: pointer;
  padding: 0;
  transition: background 0.2s ease, transform 0.2s ease;
}
.desbanners-dot--active,
.desbanners-dot:hover {
  background: #fff;
  transform: scale(1.25);
}

/* ── Enlace dinámico del banner (stretched link) ─────────────────────────── */
.desbanners-link {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: block;
  /* Sin texto visible: es una capa clicable sobre el banner. */
  font-size: 0;
  text-indent: -9999px;
}
.desbanners-item--linked { cursor: pointer; }
/* Los CTAs/enlaces del contenido del banner quedan por encima del stretched
   link para seguir siendo clicables. */
.desbanners-overlay { position: relative; z-index: 2; }
.desbanners-content a,
.desbanners-content button { position: relative; z-index: 3; }

/* ==========================================================================
   Modo SPLIT — imagen a un lado, contenido al otro
   --------------------------------------------------------------------------
   A diferencia de cover/contain, aqui el contenido NO se superpone a la
   imagen: van en dos columnas. Pensado para la cabecera de home y categoria,
   con el formulario de presupuesto en la columna derecha.
   ========================================================================== */
.desbanners-mode-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 350px);
  align-items: center;
  gap: 0;
}

.desbanners-mode-split .desbanners-split__media { min-width: 0; }

.desbanners-mode-split .desbanners-img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: contain;
}

/* Con altura fija definida en el banner, la imagen se recorta en lugar de
   estirar la fila. */
.desbanners-mode-split.desbanners-has-height .desbanners-img {
  height: 100%;
  object-fit: cover;
}

.desbanners-mode-split .desbanners-split__aside {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* El formulario lo inyecta el hook displayProposalForm: aqui solo se le da
   sitio, los estilos son los suyos. */
.desbanners-mode-split .desbanners-proposal {width: 100%;height: 100%;}

/* Movil: se apilan, imagen arriba y contenido debajo. */
@media (max-width: 992px) {
  .desbanners-mode-split {
    grid-template-columns: 1fr;
    gap: 24px;
  }
  .desbanners-mode-split.desbanners-has-height .desbanners-img {
    height: auto;
    object-fit: contain;
  }
}
