/**
 * Portada (home nueva) — Javier Torices
 * ------------------------------------------------------------------
 * Home de una sola página, larga y contemplativa. Este CSS SOLO se
 * carga en la portada (functions.php, guarda is_front_page()).
 *
 * Reproduce el handoff de alta fidelidad (design_handoff_home): tokens
 * de color, escala tipográfica, reveals al scroll, parallax sticky,
 * degradado de fondo Arena→Turquesa→Azul, portales y CTAs.
 *
 * Cabecera y pie NO se pintan aquí: son los globales de Elementor
 * (get_header()/get_footer() en front-page.php). Lo único propio de la
 * home sobre el header es hacerlo STICKY (bloque 2).
 *
 * NUNCA negro puro: el "negro" del proyecto es Azul Atlántico #1A2F3B.
 * Índice:
 *   1. Tokens + wrapper + fondo animado
 *   2. Header global STICKY (solo en portada)
 *   3. Hero (vídeo Vimeo + poster + play)
 *   4. Secciones, rejillas y escala tipográfica
 *   5. Reveals al scroll (gate anti-FOUC .jt-front-anim)
 *   6. Parallax interior
 *   7. El lugar (mapa + puntos)
 *   8. Obra emergente (caja de zoom)
 *   9. Cierre (portales + CTAs)
 *  10. Responsive (1200 / 980 / 680)
 *  11. prefers-reduced-motion
 * ------------------------------------------------------------------ */

/* ============================================================
   1. TOKENS + WRAPPER + FONDO ANIMADO
   ============================================================ */
.jt-front {
  --jt-arena:    #F1ECE1;
  --jt-turquesa: #3A7472;  /* verde-mar del degradado */
  --jt-azul:     #1A2F3B;  /* Azul Atlántico = "negro" */
  --jt-espuma:   #F4F7F6;
  --jt-verdemar: #3A5A65;
  --jt-cielo:    #85A8C1;  /* turquesa claro (acentos en cursiva) */
  --jt-link:     #498F8D;  /* etiquetas / enlaces sobre claro */
  --jt-easing:   cubic-bezier(.2, .7, .2, 1);

  font-family: 'Open Sans', sans-serif;
  color: var(--jt-azul);
  position: relative;
  /* `hidden` haría que overflow-y compute a `auto` → .jt-front se vuelve contenedor
     de scroll y ROMPE position:sticky de sus descendientes (El lugar reveal). `clip`
     recorta igual el desbordamiento horizontal SIN crear contenedor de scroll. */
  overflow-x: hidden;   /* fallback navegadores muy viejos */
  overflow-x: clip;
}

/* Capa de fondo a pantalla completa: el JS interpola su color con el
   progreso del scroll (Arena→Turquesa→Azul). Queda DETRÁS del contenido
   (z 1) y del header/footer globales (con fondo propio). */
#jt-bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  background: var(--jt-arena);
  pointer-events: none;
}
.jt-front__flow {
  position: relative;
  z-index: 1;
}

.jt-front a { color: inherit; text-decoration: none; }
.jt-front a:hover { color: inherit; }

/* Scroll suave (ancla a la obra emergente). Solo en portada: este CSS no
   se carga en el resto del sitio. */
html { scroll-behavior: smooth; }

/* ============================================================
   2. HEADER GLOBAL FIJO (SOLO EN PORTADA)
   ============================================================
   La cabecera es la MISMA plantilla global de Elementor que en interior;
   aquí solo la fijamos arriba. Se usa position:fixed (no sticky): el sticky
   resultaba frágil en el maquetado de Elementor y `backdrop-filter` sobre
   sticky provoca un bug de composición que desplaza/recorta la barra. Fixed
   es el enfoque del prototipo original (fixed + espaciador) y es a prueba de
   balas. Fondo Arena SÓLIDO → menú siempre legible aunque el fondo de página
   degrade a Azul. Interior no se toca (este CSS solo carga en portada).
   El espaciador #jt-headerspace (front-page.php) compensa la altura del header
   fijo para que el hero no quede tapado; su alto lo sincroniza portada.js. */
body.home .elementor-location-header,
body.home header.site-header,
body.home .ehf-header,
body.home #site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background-color: #F1ECE1;
  border-bottom: 1px solid rgba(26, 47, 59, 0.06);
}
#jt-headerspace { height: 56px; }   /* fallback; portada.js pone el alto real */

/* Respeta la barra de admin de WordPress (solo usuarios logueados). La admin
   bar es fixed a top:0 (32px; 46px en móvil ≤782px) y un header fixed la
   ignoraría, quedando por debajo y con el logo recortado. Bajando el header lo
   justo, se ve entero SIN necesidad de ocultar la admin bar. En visitantes
   (no logueados, producción) no hay clase .admin-bar → el header va a top:0. */
body.admin-bar .elementor-location-header,
body.admin-bar header.site-header,
body.admin-bar .ehf-header,
body.admin-bar #site-header { top: 32px; }
@media screen and (max-width: 782px) {
  body.admin-bar .elementor-location-header,
  body.admin-bar header.site-header,
  body.admin-bar .ehf-header,
  body.admin-bar #site-header { top: 46px; }
}

/* ============================================================
   3. HERO (Vimeo + poster + play)
   ============================================================ */
#jt-hero {
  position: relative;
  width: 100%;
  aspect-ratio: 2544 / 1088;      /* proporción nativa del vídeo */
  overflow: hidden;
  background: var(--jt-azul);
  cursor: pointer;                /* el vídeo hace play/pausa al clicar (portada.js) */
}
#jt-vimeo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  pointer-events: none;           /* el hero no es interactivo salvo el play */
}
#jt-heroposter {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 1;                     /* visible hasta que arranca el vídeo y de nuevo al terminar */
  transition: opacity .9s ease;
}
#jt-herovelo {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(26,47,59,.55) 0%,
    rgba(26,47,59,.12) 38%,
    rgba(26,47,59,.28) 70%,
    rgba(26,47,59,.28) 100%);
}
/* Intro del hero: logo + subtítulo + play. Sobre el vídeo/poster; solo el
   botón play es clicable (el resto no captura el ratón). */
#jt-herointro {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 22px;
  pointer-events: none;
}
.jt-hero-logo {
  display: block;
  width: min(600px, 62vw);
  aspect-ratio: 262.31 / 33.91;    /* proporción del wordmark JAVIERTORICES.svg */
  background-color: var(--jt-espuma);
  -webkit-mask: url('../portada/JAVIERTORICES.svg') no-repeat center / contain;
          mask: url('../portada/JAVIERTORICES.svg') no-repeat center / contain;
  filter: drop-shadow(0 2px 24px rgba(26,47,59,.4));
}
.jt-hero-sub {
  margin-top: 22px;
  font-family: 'Instrument Serif', serif;
  font-weight: 400;
  font-size: 50px;
  line-height: 1.1;
  color: var(--jt-espuma);
  text-shadow: 0 2px 22px rgba(26,47,59,.5);
}
#jt-heroplay {
  margin-top: 30px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 86px; height: 86px;
  padding: 0;
  border: 1.4px solid rgba(244,247,246,.85);
  border-radius: 50%;
  background: rgba(26,47,59,.28);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  color: var(--jt-espuma);
  cursor: pointer;
  pointer-events: auto;
}
#jt-heroplay svg { display: block; margin-left: 4px; }

/* Entrada desde abajo al cargar (logo y subtítulo a 1). */
#jt-herointro .jt-hero-logo,
#jt-herointro .jt-hero-sub {
  opacity: 0;
  transform: translateY(42px);
  animation: jtHeroIn 1.1s cubic-bezier(.2, .7, .2, 1) forwards;
}
#jt-herointro .jt-hero-sub { animation-delay: .12s; }
/* El botón play NO se muestra: el vídeo arranca solo y, al terminar, ya NO reaparece
   el icono de play (petición). Solo queda disponible bajo reduced-motion (sin
   autoplay, para poder arrancar el vídeo; ver bloque 11). */
#jt-herointro #jt-heroplay {
  display: none;
  transition: background .35s ease, transform .35s ease;
}
#jt-herointro #jt-heroplay:hover { background: rgba(26,47,59,.52); transform: scale(1.06); }
@keyframes jtHeroIn     { to { opacity: 1;  transform: none; } }
@keyframes jtHeroInPlay { to { opacity: .8; transform: none; } }

/* Salida hacia arriba del rótulo (a los 3 s: portada.js añade .is-out). */
#jt-herointro.is-out .jt-hero-logo,
#jt-herointro.is-out .jt-hero-sub { animation: jtHeroOut .85s cubic-bezier(.4, 0, .2, 1) forwards; }
@keyframes jtHeroOut { from { opacity: 1; transform: none; } to { opacity: 0; transform: translateY(-54px); } }

/* Controles del vídeo — BAJO el vídeo, a la izquierda (alineados con el padding de
   sección). Aparecen con un fundido cuando el vídeo ya reproduce (.is-ready). Sobre
   fondo Arena → iconos teal de realce. El play/pausa también se hace CLICANDO en el
   propio vídeo (portada.js); estos botones son el control explícito + el mute. */
#jt-heroctrl {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 56px 0;
  position: relative;   /* ancla del indicador de scroll centrado */
  min-height: 70px;     /* que quepa el indicador de 60 px, que va en absoluto y
                           por sí solo no empuja el alto de la fila */
  /* Visibles desde que carga la página (botones + aviso), sin esperar al vídeo. */
}
/* Indicador de scroll: chevron que late suavemente bajo el vídeo. CENTRADO en la
   fila, y en posición ABSOLUTA para que centrarlo no dependa de cuánto ocupen el
   play, el mute y el aviso de sonido, que están a la izquierda y cambian de ancho
   según el idioma. Cualificado con .jt-front (0,2,0) para ganar al kit de
   Elementor, que estila los <button> (§2). */
.jt-front #jt-scrollhint {
  position: absolute;
  left: 50%;
  top: 16px;  /* medido: alinea el eje del círculo de 54 con el de los botones de 38 */
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  height: 54px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--jt-link);
  opacity: .8;
  cursor: pointer;
  transition: opacity .3s ease;
}
.jt-front #jt-scrollhint:hover { opacity: 1; }
/* El latido va en el SVG y no en el botón: el botón ya usa su transform para
   centrarse, y animar ahí lo descolocaría. */
#jt-scrollhint svg { animation: jtScrollHint 2.2s ease-in-out infinite; }
@keyframes jtScrollHint {
  0%, 100% { transform: translateY(-3px); }
  50%      { transform: translateY(3px); }
}
@media (prefers-reduced-motion: reduce) {
  #jt-scrollhint svg { animation: none; }
}
/* En pantallas estrechas NO CABE en la fila: a 375 px el aviso "Toca para activar
   el sonido" ocupa de 122 a 325 y el chevron centrado caía justo encima (medido).
   Ahí deja de estar en absoluto y baja a una línea propia, centrado. La fila se
   permite envolver solo en este tramo para no alterar el escritorio. */
@media (max-width: 980px) {
  #jt-heroctrl { flex-wrap: wrap; }
  .jt-front #jt-scrollhint {
    position: static;
    transform: none;
    /* Ancho fijo, NO 100%: con flex-basis al 100% el botón medía 331 px de ancho
       invisible y se comía media franja bajo el vídeo como zona de toque. Con
       38 px no cabe en la fila (el aviso ya ocupa 303 de 331) y envuelve solo;
       los márgenes automáticos lo centran en su nueva línea. */
    flex: 0 0 54px;
    margin: 6px auto 0;
  }
}
/* Aviso "toca para activar el sonido": junto a los controles, visible mientras el
   vídeo está en SILENCIO (el botón mute tiene .is-muted); se va en cuanto el usuario
   activa el sonido. Latido suave para que se note. */
.jt-hero-soundhint {
  align-self: center;
  opacity: 0;
  pointer-events: none;   /* no clicable mientras está oculto (sonido activo) */
  cursor: pointer;
  font-family: 'Open Sans', sans-serif;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--jt-link);
  white-space: nowrap;
  transition: opacity .5s ease;
}
/* Visible y PULSABLE mientras hay silencio. */
#jt-hero-mute.is-muted ~ .jt-hero-soundhint { animation: jtSoundHint 2.4s ease-in-out infinite; pointer-events: auto; }
#jt-hero-mute.is-muted ~ .jt-hero-soundhint:hover { text-decoration: underline; }
@keyframes jtSoundHint { 0%, 100% { opacity: .5; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  #jt-hero-mute.is-muted ~ .jt-hero-soundhint { animation: none; opacity: .9; }
}
/* Cualificadas con .jt-front (0,2,0) para GANAR al kit de Elementor, que estila
   los <button> (fondo verde mar, sin radio, texto blanco) con 0,1,1. */
.jt-front .jt-heroctrl-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px; height: 38px;
  padding: 0;
  border: 1px solid var(--jt-link);          /* teal de realce, a color pleno */
  border-radius: 50%;
  background: transparent;
  color: var(--jt-link);                      /* iconos a 100% de color */
  opacity: 1;
  cursor: pointer;
  transition: opacity .3s ease, background .3s ease, border-color .3s ease;
}
.jt-front .jt-heroctrl-btn:hover { background: rgba(73,143,141,.14); border-color: var(--jt-link); }
/* Alternancia de iconos (pausa/play y sonido/mute) por clase de estado. */
#jt-hero-pause .ic-play { display: none; }
#jt-hero-pause.is-paused .ic-pause { display: none; }
#jt-hero-pause.is-paused .ic-play { display: block; }
#jt-hero-mute .ic-muted { display: none; }
#jt-hero-mute.is-muted .ic-sound { display: none; }
#jt-hero-mute.is-muted .ic-muted { display: block; }

/* ============================================================
   4. SECCIONES, REJILLAS Y ESCALA TIPOGRÁFICA
   ============================================================ */
.jt-sec { position: relative; }

/* padding vertical 16vh con solape -8vh entre secciones consecutivas
   (evita pantallas vacías durante los reveals). */
/* Espaciado (ajuste con Juan): Buscamos↔Instante −30%; resto de gaps +50%.
   Gap = padding-bottom(sup) + padding-top(inf) + margin(-8vh de solape). */
.jt-sec--open {                       /* Frase apertura */
  padding: 30vh 56px 18vh;            /* bottom 26→18 (parte del −30%) */
  display: flex;
  justify-content: center;
}
.jt-block {                           /* bloques frase + imagen (El instante) */
  max-width: 1320px;
  margin: 0 auto;
  padding: 11vh 56px 28.5vh;          /* top 11 (Buscamos↔Instante); bottom 21→28.5 (otro +50%) */
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 78px;
  align-items: center;
}
.jt-block--overlap {
  margin: -8vh auto 0;
  padding: 2vh 56px 28.5vh;           /* bottom 21→28.5 → gap 15→22.5vh (otro +50%) */
  align-items: start;
}
.jt-sec--agua {
  margin-top: -8vh;
  padding: 2vh 56px 6vh;              /* agua↔emerge sin cambio esta vez */
  display: flex;
  justify-content: center;
}
.jt-sec--emerge { padding: 6vh 56px 28.5vh; }  /* bottom 21→28.5 → emerge↔cierre gap 15→22.5vh */
.jt-sec--cierre {
  margin-top: -8vh;
  padding: 2vh 56px 16vh;
  display: flex;
  justify-content: center;
}

/* Frases — Instrument Serif 400. El tamaño de ESCRITORIO se fija por bloque
   (cada frase tiene el suyo, ver tabla del README); las media queries llevan
   solo los cambios responsive. Escala por bloque (desktop → ≤980 → ≤680):
     · Apertura (.jt-h1):      68 → 74 → 48   lh 1.08
     · Agua (--agua):          58 → 60 → 40   lh 1.10
     · Cierre (--cierre):      56 → 60 → 40   lh 1.12
     · Instante/Lugar (md):    62 → 62 → 30   lh 1.05
     · Silencio/Habita (--sm): 58 → 58 → 30   lh 1.10 */
.jt-front .jt-frase-xl,
.jt-front .jt-frase-md {
  font-family: 'Instrument Serif', serif;
  font-weight: 400;
}
/* Frase apertura (H1). Compuesto para ganar a .jt-frase-xl en responsive. */
.jt-frase-xl.jt-h1 { font-size: 68px; line-height: 1.08; letter-spacing: -0.015em; }
/* Frases XL centradas (agua / cierre). */
.jt-frase-xl--agua   { font-size: 58px; line-height: 1.1;  letter-spacing: -0.01em; }
.jt-frase-xl--cierre { font-size: 56px; line-height: 1.12; letter-spacing: -0.01em; }
/* Frases MD. Cualificadas con .jt-front (0,2,0) para GANAR al kit de Elementor
   (`.elementor-kit-N h2` = 0,1,1), que si no fuerza los h2 a ~26px (gotcha
   conocido del proyecto). --sm se declara después para pisar a md cuando van
   juntas. */
.jt-front .jt-frase-md     { font-size: 62px; line-height: 1.05; }
.jt-front .jt-frase-md--sm { font-size: 58px; line-height: 1.1; }
.jt-i { font-style: italic; color: var(--jt-cielo); }

.jt-copy {
  margin-top: 30px;
  max-width: 460px;
  font-size: 19px;
  font-weight: 300;
  line-height: 1.85;
  text-wrap: pretty;
}
.jt-label {
  display: inline-block;
  margin-top: 32px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--jt-link);
}
.jt-label--light { color: var(--jt-espuma); }
/* CTA del mapa ("Pulsa sobre los puntos…"): sigue AL FONDO en vez de llevar un
   color fijo. El bloque "El lugar" mide 200vh y su texto queda anclado mientras
   el fondo viaja de gris claro a turquesa, así que ningún color fijo aguanta todo
   el recorrido: medido con la fórmula de portada.js, el blanco arranca en 1,53 de
   contraste (invisible) y el azul termina en 2,71. La variable --jt-auto-color la
   publica portada.js en cada scroll con el mismo cálculo de luminancia que ya usa
   para el texto general → oscuro sobre fondo claro, espuma (blanco) sobre fondo
   oscuro. Siempre por encima de 5 de contraste. El valor de reserva mantiene el
   teal de siempre si el JS no llega a correr. */
/* Subrayado blanco que late para resaltar la instrucción, con el MISMO ritmo
   (2,4 s) que el pulso de los puntos del mapa: los dos elementos respiran a la
   vez y se leen como parte del mismo gesto. El desfase de .4s evita que
   parpadeen exactamente al unísono. Se usa el mismo espuma literal
   rgba(244,247,246,…) que ya emplea jtDotPulse.

   Es DECORACIÓN, no contenido: el texto lo sigue llevando --jt-auto-color, que
   es quien garantiza el contraste sobre un fondo que cambia.

   ⚠️ Se anima text-decoration-color, NO un ::after con opacidad. Un ::after de
   ancho completo parece equivalente y NO lo es: a 360 px de ventana este texto
   PARTE EN DOS LÍNEAS (medido) y la barra quedaba suelta bajo la segunda,
   sobresaliendo por la derecha. text-decoration sigue a cada línea sola, y su
   color sí es animable por separado del color del texto. */
.jt-front .jt-lugar-textcol .jt-label {
  color: var(--jt-auto-color, var(--jt-link));
  text-decoration: underline;
  text-decoration-thickness: 1.5px;
  text-underline-offset: 7px;
  text-decoration-color: rgba(244, 247, 246, .2);
  animation: jtSubrayadoPulso 2.4s ease-in-out .4s infinite;
}
@keyframes jtSubrayadoPulso {
  0%, 100% { text-decoration-color: rgba(244, 247, 246, .2); }
  50%      { text-decoration-color: rgba(244, 247, 246, 1); }
}
@media (prefers-reduced-motion: reduce) {
  .jt-front .jt-lugar-textcol .jt-label {
    animation: none;
    text-decoration-color: rgba(244, 247, 246, .85);
  }
}
.jt-label--cielo { color: var(--jt-cielo); }

.jt-block__media {
  position: relative;
  align-self: start;
  display: block;
  overflow: hidden;
  height: 78vh;
}
.jt-block__media--ratio {
  height: auto;
  aspect-ratio: 5 / 4;
  background: rgba(26,47,59,.12);
}
.jt-blockimg { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Nav-link estilo (por si se codifica algún enlace inline con subrayado) */
.jt-navlink { position: relative; }
.jt-navlink::after {
  content: "";
  position: absolute;
  left: 0; right: 100%; bottom: -4px;
  height: 1px;
  background: currentColor;
  transition: right .35s ease;
}
.jt-navlink:hover::after { right: 0; }

/* ============================================================
   5. REVEALS AL SCROLL — dos modos (portada.js fija ?fx=calm|silk)
   ============================================================
   Gate anti-FOUC: .jt-front-anim en <html>. Sin el gate (JS caído /
   reduced-motion) TODO queda visible y estático — nunca hay contenido
   invisible por culpa del JS.

   CALM (por defecto): fundido de entrada suave, UNA vez (clase .jt-in del
   IntersectionObserver), sin salir volando y sin re-animar. */
.jt-front-anim.jt-fx-calm [data-reveal] {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity .95s ease-out,
              transform 1.1s cubic-bezier(.2, .7, .2, 1);
  will-change: opacity, transform;
}
.jt-front-anim.jt-fx-calm [data-reveal].jt-fade { transform: none; }
.jt-front-anim.jt-fx-calm [data-reveal].jt-in { opacity: 1; transform: none; }

/* SILK: la opacidad/posición las controla portada.js ligadas al scroll →
   sin transición para que vaya pegado al scroll (sedoso y reversible). */
.jt-front-anim.jt-fx-silk [data-reveal] {
  opacity: 0;
  transition: none;
  will-change: opacity, transform;
}

/* ============================================================
   6. PARALLAX INTERIOR
   ============================================================ */
[data-pxi] {
  position: absolute;
  left: 0; right: 0;
  top: -50%;
  height: 200%;
  display: block;
  will-change: transform;
}

/* ============================================================
   7. EL LUGAR (mapa + puntos)
   ============================================================ */
.jt-mapa-wrap {
  position: relative;
  width: 100%;
  max-width: 520px;
  margin-left: auto;
}
.jt-mapa-wrap img { width: 100%; display: block; opacity: .75; }
.jt-dot {
  position: absolute;
  transform: translate(-50%, -50%);
  display: block;
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--jt-espuma);
  box-shadow: 0 0 0 5px rgba(244,247,246,.28);
  transition: transform .4s var(--jt-easing);
}
.jt-dot:hover { transform: translate(-50%, -50%) scale(1.45); }
/* Los nombres de los lugares se ven DESDE EL PRINCIPIO (Mayte, 20 ago 2026). Antes
   nacían a 0 y solo aparecían al pasar el ratón, que en táctil no existe: en móvil
   no se leía ningún nombre nunca. Se conservan las reglas de hover y de foco por si
   alguna variante vuelve a ocultarlos. */
.jt-dot span { transition: opacity .35s ease; opacity: 1; }
.jt-dot:hover span { opacity: 1 !important; }

/* Punto del mapa como BOTÓN interactivo + etiqueta del lugar (aparece al hover
   o al enfocar con teclado). */
.jt-front .jt-dot--btn {   /* .jt-front (0,2,0) gana al kit de Elementor (0,1,1) */
  width: 12px; height: 12px;
  min-width: 0; min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 50%;                  /* redondo (el kit lo cuadraba) */
  background: var(--jt-espuma);
  cursor: pointer;
  -webkit-appearance: none;
          appearance: none;
}
/* Cartel del lugar: Instrument Serif cursiva, altas y bajas, blanco, sin fondo,
   sutil (una sombra leve para que se lea sobre el mapa). */
.jt-dot-label {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 8px);
  transform: translateX(-50%);
  white-space: nowrap;
  font-family: 'Instrument Serif', serif;
  font-style: italic;
  font-weight: 400;
  font-size: 16px;                     /* nombres de lugar (−25%) */
  line-height: 1;
  letter-spacing: 0;
  text-transform: none;
  color: var(--jt-espuma);
  text-shadow: 0 1px 10px rgba(26, 47, 59, .6), 0 0 2px rgba(26, 47, 59, .5);
  pointer-events: none;
}
.jt-dot--btn:focus-visible { outline: 2px solid var(--jt-cielo); outline-offset: 4px; }
.jt-dot--btn:focus-visible .jt-dot-label { opacity: 1 !important; }

/* Pulso sutil de los puntos del mapa (petición de Javier): un anillo que se
   expande y se desvanece en bucle, escalonado entre puntos para que no latan a la
   vez. Va en un ::after para no tocar el box-shadow estático del punto. */
.jt-front .jt-dot--btn::after {
  content: "";
  position: absolute;
  left: 50%; top: 50%;
  width: 100%; height: 100%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  box-shadow: 0 0 0 0 rgba(244, 247, 246, .5);
  animation: jtDotPulse 2.4s ease-out infinite;
  pointer-events: none;
}
.jt-front .jt-dot--btn:nth-of-type(2)::after { animation-delay: .8s; }
.jt-front .jt-dot--btn:nth-of-type(3)::after { animation-delay: 1.6s; }
@keyframes jtDotPulse {
  0%   { box-shadow: 0 0 0 0 rgba(244, 247, 246, .5); }
  70%  { box-shadow: 0 0 0 16px rgba(244, 247, 246, 0); }
  100% { box-shadow: 0 0 0 0 rgba(244, 247, 246, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .jt-front .jt-dot--btn::after { animation: none; }
}

/* --- Panel del mapa (obra del lugar pulsado) — lightbox --- */
html.jt-modal-open { overflow: hidden; }
.jt-mapa-panel {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4vh 4vw;                    /* marco de reserva: respira */
  background: rgba(26, 47, 59, .55);   /* Azul Atlántico con transparencia */
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .4s ease, visibility .4s ease;   /* apertura fundida */
}
.jt-mapa-panel.is-open { opacity: 1; visibility: visible; pointer-events: auto; }
.jt-mapa-panel-inner {
  position: relative;
  width: min(1240px, 100%);            /* lo más grande posible */
  max-height: 92vh;
  overflow: hidden;
  background: var(--jt-espuma);
  transform: scale(.985);
  transition: transform .4s ease;
}
.jt-mapa-panel.is-open .jt-mapa-panel-inner { transform: none; }
/* Cerrar: mismo patrón que el visor de la ficha (.jt-zoomer-close) — círculo
   oscuro translúcido con la × tipográfica; visible sobre la obra clara Y sobre
   el vídeo. !important en el fondo porque el kit de Elementor no rellena el
   <button> (misma nota que en la ficha). */
.jt-front .jt-mapa-cerrar {
  position: absolute;
  top: 16px; right: 16px;
  z-index: 4;
  width: 44px; height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid rgba(244, 247, 246, .35);
  border-radius: 50%;
  background: rgba(26, 47, 59, .55) !important;
  color: var(--jt-espuma);
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.jt-front .jt-mapa-cerrar:hover { background: rgba(26, 47, 59, .8) !important; }
.jt-mapa-obra { display: grid; grid-template-columns: 1.05fr 1fr; }
.jt-mapa-obra[hidden] { display: none; }
/* La obra se ve ENTERA con blanco (espuma del panel) alrededor: paspartú. */
.jt-mapa-obra-img {
  width: 100%;
  height: 100%;
  max-height: 92vh;
  object-fit: contain;
  padding: 42px;
  box-sizing: border-box;
  display: block;
}
.jt-mapa-obra-body {
  padding: 44px 40px;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.jt-mapa-obra-lugar {
  font-family: 'Open Sans', sans-serif;
  font-size: 11px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  color: var(--jt-link);
}
.jt-front .jt-mapa-obra-titulo {
  font-family: 'Instrument Serif', serif;
  font-weight: 400;
  font-size: 38px;
  line-height: 1.1;
  color: var(--jt-azul);
  margin-top: 10px;
}
.jt-mapa-obra-meta {
  margin-top: 12px;
  font-family: 'Open Sans', sans-serif;
  font-size: 16px; font-weight: 300; line-height: 1.6;
  color: var(--jt-azul);
}
.jt-mapa-obra-ctas { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }
.jt-front .jt-mapa-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 46px;
  padding: 0 22px;
  border: 1px solid var(--jt-azul);
  border-radius: 999px;
  background: transparent;
  color: var(--jt-azul);
  font-family: 'Open Sans', sans-serif;
  font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  cursor: pointer;
  transition: background .3s ease, color .3s ease, border-color .3s ease;
}
.jt-front .jt-mapa-btn:hover { background: var(--jt-azul); color: var(--jt-espuma); }
.jt-front .jt-mapa-btn--solid { background: var(--jt-verdemar); border-color: var(--jt-verdemar); color: var(--jt-espuma); }
.jt-front .jt-mapa-btn--solid:hover { background: var(--jt-azul); border-color: var(--jt-azul); }
.jt-mapa-video { position: absolute; inset: 0; z-index: 2; background: #000; }
.jt-mapa-video[hidden] { display: none; }
.jt-mapa-video-frame { position: absolute; inset: 0; }
.jt-mapa-video-frame iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

@media (max-width: 680px) {
  .jt-mapa-obra { grid-template-columns: 1fr; }
  .jt-mapa-obra-img { max-height: 46vh; padding: 22px; }
  .jt-mapa-obra-body { padding: 26px 22px; }
  .jt-front .jt-mapa-obra-titulo { font-size: 30px; }
}

/* ============================================================
   8. OBRA EMERGENTE (caja de zoom)
   ============================================================ */
.jt-zoombox {
  position: relative;
  height: 84vh;
  overflow: hidden;
  background: rgba(26,47,59,.35);
  touch-action: pan-y;               /* a escala 1: el swipe hace scroll de página */
}
.jt-zoombox.is-zoomed { touch-action: none; }
.jt-zoombox.is-grabbing { cursor: grabbing; }
.jt-zoomimg {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transform-origin: center;
  will-change: transform;
  transition: transform .16s ease-out;   /* seguimiento suave del ratón / zoom */
  -webkit-user-select: none; user-select: none;
  -webkit-user-drag: none;
}
.jt-zoombox.is-grabbing .jt-zoomimg { transition: none; }   /* inmediato al arrastrar/pellizcar */

/* Pista de uso: BANDA a todo el ancho del cuadro, pegada abajo, en UNA sola línea
   (nowrap; en móvil se partía feo). Fondo negro 30% para que el texto blanco se lea.
   Se desvanece al acercar. */
.jt-zoom-hint {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 2;
  pointer-events: none;
  white-space: nowrap;
  overflow: hidden;
  text-align: center;
  padding: 9px 10px;
  background: rgba(0, 0, 0, 0.3);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  color: var(--jt-espuma);
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  line-height: 1;   /* propia: la heredada (~30px) inflaba la banda */
  opacity: 1;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
  transition: opacity .4s ease;
}
.jt-zoombox.is-zoomed .jt-zoom-hint { opacity: 0; }
.jt-emerge-cap {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 20px;
  margin-top: 26px;
}
/* El pie de móvil (Atlántico 19:09) solo aparece en ≤680 (ver responsive). */
.jt-emerge-cap--movil { display: none; }
/* Título de la obra emergente (era "Bajo la superficie" 30px → "Atlántico
   17:46" al 50% = 15px, enlazado). Cualificado con .jt-front para ganar al
   color de enlace del kit de Elementor. */
.jt-front .jt-emerge-title {
  font-family: 'Instrument Serif', serif;
  font-size: 15px;
  line-height: 1.1;
  color: var(--jt-espuma);
  transition: color .3s ease;
}
.jt-front .jt-emerge-title:hover { color: var(--jt-cielo); }

/* ============================================================
   9. CIERRE (portales + CTAs)
   ============================================================ */
.jt-cierre { max-width: 1080px; text-align: center; }
.jt-portales {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 22px;
  margin-top: 76px;
}
.jt-portal {
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: 3 / 5;
  background: rgba(244,247,246,.06);
}
.jt-portal img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  opacity: .88;
  transition: transform 1.2s var(--jt-easing), opacity .6s ease;
}
.jt-portal:hover img { transform: scale(1.06); opacity: 1; }

/* Entrada de los portales: de abajo arriba, ESCALONADA (async), y todos
   terminan a la MISMA altura (sin desalineación de oleaje). Se dispara al
   entrar en viewport (portada.js añade .is-in). El scale de hover va en la
   img interior, así que no choca con este transform del contenedor. */
@keyframes jtPortalIn {
  from { opacity: 0; transform: translateY(60px); }
  to   { opacity: 1; transform: none; }
}
.jt-front-anim .jt-portal { opacity: 0; }
.jt-front-anim .jt-portales.is-in .jt-portal { animation: jtPortalIn .9s cubic-bezier(.2, .7, .2, 1) both; }
.jt-front-anim .jt-portales.is-in .jt-portal:nth-child(2) { animation-delay: .14s; }
.jt-front-anim .jt-portales.is-in .jt-portal:nth-child(3) { animation-delay: .28s; }
.jt-front-anim .jt-portales.is-in .jt-portal:nth-child(4) { animation-delay: .42s; }
/* El cierre admite hasta 8 obras (dos filas de cuatro) desde los campos de la
   home; estos retardos solo entran en juego a partir de la quinta pieza. */
.jt-front-anim .jt-portales.is-in .jt-portal:nth-child(5) { animation-delay: .56s; }
.jt-front-anim .jt-portales.is-in .jt-portal:nth-child(6) { animation-delay: .70s; }
.jt-front-anim .jt-portales.is-in .jt-portal:nth-child(7) { animation-delay: .84s; }
.jt-front-anim .jt-portales.is-in .jt-portal:nth-child(8) { animation-delay: .98s; }

.jt-ctas {
  display: flex;
  justify-content: center;
  gap: 16px;
  margin-top: 82px;
}
.jt-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 280px; height: 56px;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  transition: background .4s ease, color .4s ease, border-color .4s ease;
}
.jt-cta:hover {
  background: var(--jt-link);
  border-color: var(--jt-link);
  color: var(--jt-espuma);
}

/* Entrada de los botones de abajo (CTAs): fundido de abajo arriba, escalonado.
   Se dispara al entrar en viewport (portada.js añade .is-in a .jt-ctas). */
@keyframes jtCtaIn {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: none; }
}
.jt-front-anim .jt-cta { opacity: 0; }
.jt-front-anim .jt-ctas.is-in .jt-cta { animation: jtCtaIn .8s cubic-bezier(.2, .7, .2, 1) both; }
.jt-front-anim .jt-ctas.is-in .jt-cta:nth-child(2) { animation-delay: .16s; }

/* ============================================================
   10. RESPONSIVE
   ============================================================ */
@media (max-width: 980px) {
  .jt-block { grid-template-columns: 1fr; gap: 34px; }
  /* "El instante": en móvil/tablet (1 columna) la imagen NO se ancla. El
     `position:sticky` inline (efecto de escritorio, 2 columnas) hacía que la imagen
     se quedara fija y el texto pasara por encima. Se deja `relative` (mantiene el
     parallax) para que baje con el texto, como antes. !important gana al estilo inline. */
  .jt-front [data-screen-label="El instante"] .jt-block__media {
    position: relative !important;
    top: auto !important;
  }
  /* Solo la apertura crece; agua/cierre a 60; las frase-md NO cambian (62/58). */
  .jt-frase-xl.jt-h1 { font-size: 74px; }
  .jt-frase-xl--agua,
  .jt-frase-xl--cierre { font-size: 60px; }
  .jt-hero-sub { font-size: 40px; }
  .jt-hero-logo { width: min(520px, 66vw); }
  #jt-heroctrl { padding-left: 40px; padding-right: 40px; }
  .jt-sec--open,
  .jt-block,
  .jt-block--overlap,
  .jt-sec--agua,
  .jt-sec--emerge,
  .jt-sec--cierre { padding-left: 40px; padding-right: 40px; }
}

@media (max-width: 680px) {
  .jt-sec--open,
  .jt-block,
  .jt-block--overlap,
  .jt-sec--agua,
  .jt-sec--emerge,
  .jt-sec--cierre { padding-left: 22px; padding-right: 22px; }
  .jt-frase-xl.jt-h1 { font-size: 48px; }
  /* Igualadas a "El instante" (48px): "…lo que el agua esconde" y "Mis obras
     son portales…". */
  .jt-frase-xl--agua,
  .jt-frase-xl--cierre { font-size: 48px; line-height: 1.1; }
  /* Igualadas a "Buscamos en el horizonte" (.jt-h1 = 48px) por petición: El
     instante, El lugar, "Todo lo que pinto…", "Mi pintura…". */
  .jt-front .jt-frase-md, .jt-front .jt-frase-md--sm { font-size: 48px; line-height: 1.1; }

  /* Hero recortado a alto útil (evita bandas) */
  #jt-hero { aspect-ratio: auto; height: 58vh; }
  #jt-vimeo {
    width: auto; height: 100%;
    aspect-ratio: 2544 / 1088;
    left: 50%; right: auto;
    transform: translateX(-50%);
    min-width: 100%;
  }
  #jt-heroplay { width: 64px; height: 64px; margin-top: 22px; }
  .jt-hero-sub { font-size: 26px; margin-top: 16px; }
  .jt-hero-logo { width: 76vw; }
  #jt-heroctrl { padding-left: 22px; padding-right: 22px; }

  /* Espacios verticales comprimidos, sin solapes negativos */
  .jt-sec--open   { padding-top: 13vh; padding-bottom: 9vh; }
  .jt-block--overlap,
  .jt-sec--agua,
  .jt-sec--emerge,
  .jt-sec--cierre { margin-top: 0; }
  [data-screen-label="El instante"] { padding-top: 6vh; padding-bottom: 8vh; }
  [data-screen-label="El lugar"],
  [data-screen-label="Frase silencio"],
  [data-screen-label="Frase habita"] { padding-top: 12vh; padding-bottom: 8vh; }
  [data-screen-label="Frase agua"]   { padding-top: 14vh; padding-bottom: 2vh; }
  [data-screen-label="Obra emergente"] { padding-top: 12vh; padding-bottom: 9vh; }
  [data-screen-label="Cierre"]       { padding-top: 12vh; padding-bottom: 11vh; }

  .jt-block { gap: 26px; }
  .jt-block__media { height: 46vh; }
  .jt-block__media--ratio { height: auto; width: 100%; aspect-ratio: 5 / 4; }
  /* "El instante": imagen un 25% más alta (46vh → 57.5vh) por petición. */
  [data-screen-label="El instante"] .jt-block__media { height: 57.5vh; }

  /* "Mi pintura no imita": primero texto, luego imagen */
  [data-screen-label="Frase habita"] { display: flex; flex-direction: column; }
  [data-screen-label="Frase habita"] .jt-block__media {
    order: 2;
    align-self: stretch;
    width: 100%;
    flex: 0 0 auto;
    height: 46vh;
  }

  /* Zoom en móvil: obra CUADRADA (Atlántico 19:09, servida por <picture>) en un
     recuadro CUADRADO → se ve ENTERA de un vistazo, sin recorte. Doble toque /
     pellizco acercan para el detalle. Proporción exacta de la imagen (4581×4515). */
  .jt-zoombox { height: auto; aspect-ratio: 4581 / 4515; }
  /* Pie de foto: en móvil, el de "Atlántico 19:09". */
  .jt-emerge-cap--escritorio { display: none; }
  .jt-emerge-cap--movil { display: flex; }

  .jt-portales { grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 52px; }

  .jt-ctas { flex-direction: column; align-items: stretch; }
  .jt-ctas a { width: 100%; }
}

/* ============================================================
   11. prefers-reduced-motion — todo visible y estático
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .jt-front-anim [data-reveal] {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .jt-portal img,
  .jt-zoomimg,
  #jt-heroplay { transition: none !important; }
  /* Intro del hero estático (sin entrada/salida animada). Bajo reduced-motion NO
     hay autoplay → el vídeo espera al clic, así que el play SÍ se ve desde el inicio
     (aquí no aplica lo de "solo al terminar"). */
  #jt-herointro .jt-hero-logo,
  #jt-herointro .jt-hero-sub { animation: none !important; opacity: 1 !important; transform: none !important; }
  #jt-herointro #jt-heroplay { display: inline-flex !important; animation: none !important; opacity: .8 !important; transform: none !important; }
  html { scroll-behavior: auto !important; }
}

/* ============================================================
   12. VARIANTE HERO PARALLAX  (?hero=parallax)
   ============================================================
   Segunda opción de home (interruptor por URL, recordado en localStorage, igual
   patrón que ?fx). El vídeo del hero queda FIJO en la primera pantalla y el
   contenido (.jt-front__scroll) sube por encima OCULTÁNDOLO, en vez de subir todo
   junto. TODO va bajo .jt-front.jt-hero-parallax → la home normal NO se toca.
   El degradado de fondo, que en la home normal es una capa fija (#jt-bg), pasa aquí
   al contenido que sube (portada.js anima el backgroundColor de .jt-front__scroll).
   ⚠️ Requiere prueba en iPhone real (fixed + vídeo puede dar tirones en iOS). */
.jt-front.jt-hero-parallax #jt-bg { display: none; }

/* El vídeo queda FIJO pero conserva su MISMA banda (aspect-ratio normal → NO gana
   altura; los controles siguen DEBAJO, no encima). portada.js le fija el `top` = alto
   de la cabecera para que la banda quede bajo el header, como en la home normal. */
.jt-front.jt-hero-parallax #jt-hero {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 0;
}
/* Capa de contenido (con los controles como primer hijo) que SUBE y tapa el vídeo.
   Arranca justo bajo la banda del vídeo: alto de la banda = 100vw × 1088/2544 =
   42.77vw. Opaca (el JS anima su backgroundColor con el degradado). */
.jt-front.jt-hero-parallax .jt-front__scroll {
  position: relative;
  z-index: 1;
  /* alto banda = 42.77vw; −12px de solape para que la barra de scroll (incluida en
     vw pero no en el ancho real) no deje una fina línea entre banda y contenido. */
  margin-top: calc(42.77vw - 12px);
  min-height: 100vh;
  background: var(--jt-arena);
}
@media (max-width: 680px) {
  /* En móvil la banda del hero es 58vh (regla normal ≤680): el contenido arranca ahí. */
  .jt-front.jt-hero-parallax .jt-front__scroll { margin-top: 58vh; }
}

/* El vídeo fijo (position:fixed) flota sobre el flujo normal; sin esto se vería por
   ENCIMA del pie global de Elementor. Le damos al pie un contexto de apilamiento por
   encima. La clase jt-hero-parallax se pone también en <body> (portada.js) para poder
   alcanzar el pie, que está FUERA de .jt-front. Solo en la home (este CSS solo se
   encola en la portada) y solo en modo parallax. */
body.jt-hero-parallax .elementor-location-footer,
body.jt-hero-parallax footer.site-footer,
body.jt-hero-parallax .ehf-footer,
body.jt-hero-parallax #colophon {
  position: relative;
  z-index: 10;
}

/* ============================================================
   13. "EL LUGAR" — variante REVEAL  (?lugar=reveal)  [OPCIÓN B, en pruebas]
   ============================================================
   La sección se hace ALTA y una CAJA INTERNA (.jt-lugar-inner) de 100vh se ANCLA
   (position:sticky) durante el recorrido; los lugares aparecen uno a uno (portada.js
   pone .is-revealed por progreso). Todo bajo .jt-front.jt-lugar-reveal → la home
   normal NO se toca. Solo ≥981px (en móvil, mapa normal). sticky es amable con iOS. */

/* En modo NORMAL el envoltorio es transparente al layout: la sección sigue siendo
   el grid de 2 columnas (texto | mapa) exactamente como antes. */
.jt-lugar-inner { display: contents; }

@media (min-width: 981px) {
  /* La sección deja de ser el grid y se hace alta (pista de scroll). */
  .jt-front.jt-lugar-reveal [data-screen-label="El lugar"] {
    display: block;
    min-height: 200vh;
  }
  /* La caja interna toma el grid y se ANCLA a 100vh mientras dura la sección. */
  .jt-front.jt-lugar-reveal .jt-lugar-inner {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 78px;
    align-items: center;
    position: sticky;
    top: 0;
    min-height: 100vh;
  }
  /* Puntos: ocultos hasta que el scroll los revela; entran con un pop suave. */
  .jt-front.jt-lugar-reveal .jt-dot--btn {
    opacity: 0;
    transform: translate(-50%, -50%) scale(.35);
    transition: opacity .7s ease, transform .7s var(--jt-easing);
  }
  .jt-front.jt-lugar-reveal .jt-dot--btn.is-revealed {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }
  /* La etiqueta del lugar acompaña al punto ya revelado (además del hover). */
  .jt-front.jt-lugar-reveal .jt-dot--btn.is-revealed .jt-dot-label { opacity: 1; }
}
