/* ============================================================
   Home Pro Guides — Recorrido por la casa (VIDEO snap-scroll)
   v4 — reemplaza el sistema de fotos con crossfade / la escena 3D
   exploratoria. Ahora es UN video real (Luma AI, aprobado por Luis)
   con 6 paradas fijas (timestamps). El scroll NO se mapea 1:1 al
   video: un poco de scroll/swipe dispara un salto RÁPIDO (scrub
   animado, ~450-900ms según distancia) hacia el siguiente punto,
   donde el video se congela hasta el próximo input. Ver js/scroll-tour.js.

   Estructura:
     .tour-pin              → contenedor 100vh, primer elemento de <main>
       video.tour-video      → el recorrido real
       .tour-video-frame     → wrapper con Ken Burns idle sutil (SIEMPRE
                                corriendo, independiente del snap-scroll,
                                para que el cuadro congelado nunca se
                                sienta 100% muerto)
       .tour-scrim            → degradado para legibilidad del texto
       .tour-topbar/.tour-pillnav → nav de las 6 paradas (reusado)
       .tour-content/.tour-panel  → copy por parada (reusado, 1 visible)
   ============================================================ */

.tour{ position: relative; background: var(--bg); }
.tour-pin{
  /* overflow:clip (no "hidden") a propósito: "hidden" sigue creando un
     scroll container real, así que el foco nativo del navegador al
     clickear un <button> del pill-nav (que mide 69px más ancho que
     este contenedor) le hacía scrollLeft:51 por su cuenta y desalineaba
     todo el hero horizontalmente — encontrado en vivo con
     getBoundingClientRect()/scrollLeft, no era el bug de scrollIntoView
     que ya se había arreglado antes, era este otro. "clip" no crea
     scroll container, así que ni el navegador ni ningún scrollIntoView
     lo pueden desalinear. */
  position: relative; height: 100vh; min-height: 560px; overflow: clip; cursor: grab;
  /* evita que un click-drag sobre el headline/CTA dispare selección de
     texto nativa del navegador en vez del gesto de scrub — se vio en
     vivo un intento de click-drag mientras el tour todavía cargaba
     (antes de este fix) que dejó texto seleccionado / el layout con
     pinta rara. */
  user-select: none; -webkit-user-select: none;
}
.tour-pin:active{ cursor: grabbing; }

.tour-video-frame{
  position:absolute; inset:0; overflow:hidden;
  animation: tourIdleBreath 16s ease-in-out infinite alternate;
  /* --wm-scale/--wm-ty: recorte + paneo por parada para tapar el
     watermark de Luma AI (su posición cambia de toma a toma) — ver
     WM_HIDE en js/scroll-tour.js, que setea estas variables al
     cambiar de índice. Nunca deja huecos: cover ya llena el marco,
     esto solo agrega zoom/paneo extra. */
  --wm-scale: 1.14; --wm-ty: 0%;
  /* Red de seguridad de imagen: fondo plano vía CSS background-image
     (no depende del elemento <video> ni de su atributo poster) — se ve
     reportado en vivo en mobile que a veces NI el poster carga (red
     lenta/intermitente cargando poster+video de R2 al mismo tiempo) y
     queda una pantalla en blanco/azul. Este background siempre está,
     así que si el video falla no queda nunca vacío. */
  background-image: url('../assets/images/tour-poster.jpg');
  background-size: cover; background-position: center 42%;
  /* v2: bajado de 1.28/1.08/1.05 — quedó exagerado/artificial (reportado
     en vivo comparando contra la foto real de referencia, que es vívida
     pero natural, no "sobresaturada"). Mismo filtro que .tour-video de
     abajo, para que el poster/fallback y el video real se vean igual de
     intensos entre sí, sin salto de color cuando uno reemplaza al otro. */
  filter: saturate(1.1) contrast(1.02) brightness(1.02);
}
.tour-video{
  position:absolute; inset:0; width:100%; height:100%;
  object-fit: cover; object-position: var(--tour-pos, center 42%);
  background: transparent;
  /* Mismo ajuste: vívido pero natural, no exagerado. */
  filter: saturate(1.1) contrast(1.02) brightness(1.02);
  /* Oculto hasta que el navegador tenga un frame real que mostrar
     (JS agrega .is-ready en 'loadeddata'). Algunos navegadores —
     sobre todo mobile — pintan el <video> con una superficie propia
     opaca/negra mientras está cargando activamente, ANTES de tener
     el primer frame — eso ignora background:transparent y tapa la
     imagen de fondo de .tour-video-frame de abajo. Reportado en vivo:
     "aparece la casa un instante y after pantalla azul". Con esto el
     fondo siempre se ve nítido hasta que el video realmente tiene
     algo que mostrar, y entra con fade en vez de golpe. */
  opacity: 0; transition: opacity .45s ease;
}
.tour-video.is-ready{ opacity: 1; }
@keyframes tourIdleBreath{
  0%   { transform: scale(var(--wm-scale, 1.14)) translate3d(0, var(--wm-ty, 0%), 0); }
  100% { transform: scale(calc(var(--wm-scale, 1.14) + 0.03)) translate3d(0, var(--wm-ty, 0%), 0); }
}

.tour-scrim{
  /* v3: en vez de un degradado parejo de arriba a abajo, la oscuridad
     ahora se concentra SOLO donde vive el texto (desde ~42% hacia abajo)
     y queda en CERO en el resto del cuadro (arriba/centro) — así el video
     se ve 100% limpio donde no hay texto encima, y donde sí lo hay, tiene
     contraste real independiente de qué tan clara/oscura sea esa toma en
     particular (reportado en vivo: en la parada Cocina, con la encimera
     clara de fondo, el texto blanco quedaba ilegible con el degradado
     parejo anterior). Sumado al text-shadow reforzado de abajo. */
  position:absolute; inset:0; pointer-events:none;
  background: linear-gradient(180deg, rgba(7,27,51,0) 0%, rgba(7,27,51,0) 42%, rgba(7,27,51,.46) 72%, rgba(7,27,51,.78) 100%);
}

/* Ocultos por defecto: solo existen para el fallback reduced-motion. */
.tour-hero-static{ display:none; }
.tour-stack-photo{ display:none; }

.tour-content{ position:absolute; inset:0; pointer-events:none; z-index:3; }
.tour-panel{
  position:absolute; left:0; right:0; bottom:0;
  padding: 0 28px 108px; opacity:0; transform: translate3d(0,18px,0);
  transition: opacity 420ms var(--ease-out), transform 420ms var(--ease-out);
  pointer-events:none;
}
.tour-panel.is-focused{ opacity:1; transform: translate3d(0,0,0); pointer-events:auto; }
.tour-panel-inner{ max-width: var(--container); margin: 0 auto; }
.tour-eyebrow{
  display:inline-flex; align-items:center; gap:.6em; color: var(--gold-soft);
  font-size:12.5px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; margin-bottom:14px;
}
.tour-eyebrow::before{ content:''; width:22px; height:1px; background: var(--gold-soft); }
.tour-panel h2{
  color: var(--text); font-size: clamp(30px, 5vw, 58px); max-width: 780px; margin: 0 0 14px;
  line-height: 1.08;
  /* v2: reforzado — el blur suave solo (0.45 de opacidad) no alcanzaba
     contraste real sobre fondos claros (ej. encimera/gabinete blanco en
     la parada Cocina, reportado en vivo: texto blanco casi invisible).
     Se agrega una sombra CHICA y más opaca pegada a la letra (efecto
     "sticker", el contraste real) + la sombra grande sigue para separar
     del fondo en general. Funciona igual sobre cualquier toma, clara u
     oscura, sin depender de cuánto oscurezca el scrim en ese punto. */
  text-shadow: 0 1px 3px rgba(3,10,20,.85), 0 2px 10px rgba(3,10,20,.65), 0 8px 32px rgba(7,27,51,.5);
}
.tour-panel p{
  color: var(--text-muted); font-size: 16.5px; max-width: 480px; margin-bottom: 22px;
  text-shadow: 0 1px 3px rgba(3,10,20,.8), 0 1px 10px rgba(3,10,20,.55), 0 4px 20px rgba(7,27,51,.4);
}
.tour-panel .btn{ pointer-events:auto; }

.tour-topbar{
  position:absolute; top: calc(var(--header-h) + 18px); left:0; right:0; z-index: 5;
  display:flex; justify-content:center; padding: 0 20px; pointer-events:none;
}
.tour-pillnav{
  pointer-events:auto; display:flex; gap: 4px; padding: 6px; border-radius: 999px;
  background: rgba(11,15,13,0.45); backdrop-filter: blur(12px);
  border: 1px solid rgba(245,241,232,0.12);
}
.tour-pillnav button{
  border:none; background:transparent; color: var(--text-muted); cursor:pointer;
  font-size: 12.5px; font-weight:600; letter-spacing:.03em; padding: 9px 16px; border-radius: 999px;
  transition: background-color 200ms var(--ease-out), color 200ms var(--ease-out);
  white-space: nowrap;
}
.tour-pillnav button.is-active{ background: var(--gold); color:#201705; }
@media (hover:hover) and (pointer:fine){
  .tour-pillnav button:hover:not(.is-active){ color: var(--text); }
}

.tour-progress{ position:absolute; left:0; right:0; bottom:0; height:2px; background: rgba(245,241,232,0.14); z-index:5; }
.tour-progress-bar{ height:100%; width:0%; background: var(--gold); transform-origin:left; transition: width 520ms var(--ease-out); }

.tour-scroll-hint{
  position:absolute; left: 28px; bottom: 34px; z-index:5;
  background:none; border:none; color: var(--text-muted); font-size:12px; letter-spacing:.06em;
  text-transform:uppercase; font-weight:600; cursor:pointer; display:flex; align-items:center; gap:8px;
  opacity: 1; transition: opacity 300ms var(--ease-out);
}
.tour-scroll-hint .chevron{ display:inline-block; animation: tourBob 1.6s var(--ease-in-out) infinite; }
.tour.is-mid-tour .tour-scroll-hint{ opacity: 0; pointer-events:none; }
@keyframes tourBob{ 0%,100%{ transform: translateY(0);} 50%{ transform: translateY(5px);} }

@media (max-width: 720px){
  .tour-pillnav{ overflow-x:auto; max-width: 100%; -ms-overflow-style:none; scrollbar-width:none; }
  .tour-pillnav::-webkit-scrollbar{ display:none; }
  .tour-panel{ padding-bottom: 84px; }
  .tour-panel p{ font-size: 15.5px; }
}

@media (prefers-reduced-motion: reduce){
  .tour-video-frame{ animation: none !important; }
}

/* ---------------- Reduced motion: sin scroll-jacking ni video ----------------
   El motor JS nunca arranca el snap-scroll ni reproduce el video: en su lugar
   muestra un hero estático (poster) con la primera parada, y apila las 6
   paradas como bloques normales debajo — cada uno con su propia foto fija
   (frame extraído del video) para no perder la referencia visual del
   recorrido, sin ningún movimiento. */
.tour.is-reduced-motion .tour-pin{ height:auto; min-height:0; overflow:visible; }
.tour.is-reduced-motion .tour-video-frame{ display:none; }
.tour.is-reduced-motion .tour-hero-static{
  position:relative; height: 78vh; min-height:480px; background-size:cover; background-position:center 42%;
}
.tour.is-reduced-motion .tour-scrim{ position:absolute; inset:0; }
.tour.is-reduced-motion .tour-content{ position:static; }
.tour.is-reduced-motion .tour-panel{
  position:static; opacity:1 !important; transform:none !important; pointer-events:auto;
  padding: 56px 28px; background: var(--primary); border-bottom: 1px solid rgba(255,255,255,.08);
}
.tour.is-reduced-motion .tour-panel[data-stop="0"]{
  position:absolute; inset:0; display:flex; align-items:flex-end; background:none; border:none;
}
.tour.is-reduced-motion .tour-topbar{ position: static; margin: 18px 0; }
.tour.is-reduced-motion .tour-progress, .tour.is-reduced-motion .tour-scroll-hint{ display: none; }
.tour.is-reduced-motion .tour-stack-photo{
  display:block; height: 44vh; min-height: 260px; background-size: cover; background-position: center 42%;
  margin: -56px -28px 24px;
}
.tour.is-reduced-motion .tour-hero-static{ display:block; }
