/* ============================================================
   MONTE SOLARE — hoja de estilos global

   Es el style.css del diseño original (html/css/style.css), partido en
   parciales por seccion SIN mover ninguna regla de lugar: el orden de estos
   @import es el orden de la cascada, y varias secciones dependen de el. La
   capa movil (23-mobile.css) va ultima a proposito — son pisos que tienen que
   ganarle a cualquier regla anterior por orden, a igual especificidad.

   El CSS es global y no de componente: los \3c style> de Astro agregan
   [data-astro-cid-*] y no llegan al DOM que arma o clona el JS (las lineas de
   la mascara de los titulos, la invitacion clonada de Bosque 2), ni a lo que
   entra con set:html. Las clases ya son BEM (.hero__video, .gallery__track),
   que es el alcance por convencion.
   ============================================================ *//* ============================================================
   MONTE SOLARE — sistema visual
   Base mecánica: ADN Soulspell (adn/soulspell-dna/DESIGN.md) —
   suelos que alternan, tipografía de cuatro roles, grano de papel,
   movimiento de una sola duración/propiedad.
   Paleta: marca real de Monte Solare (assets/marca.svg, etiqueta.svg).
   Instrucción del cliente: fondos SIEMPRE claros, la alternancia
   se logra con textura de papel, no con suelos oscuros.
   ============================================================ */

/* ---- fuentes ----
   Ya no hay @font-face a mano: Work Sans, Courier Prime y Providence Sans las
   declara la Fonts API de Astro (astro.config.mjs) y se sirven desde el propio
   sitio. La API les pone un nombre con hash ("Work Sans-1a2b3c"), asi que los
   tokens --f-* de abajo apuntan a sus variables (--font-*) y en el resto del
   CSS ninguna regla puede nombrar una fuente en forma literal.
   IM Fell DW Pica y Nostalgia PeachCreme se dejaron de cargar: en el diseño
   original no se renderizaban en ningun lado (--f-serif no se usa y --f-hand
   pierde siempre contra blockquote.script, ver 09-historia.css). */

:root{
  /* ---- paleta de marca (confirmada sobre la etiqueta real) ---- */
  --pine:        #0B6044;   /* verde marca — títulos, cuerpo, línea de íconos */
  --pine-deep:   #084732;   /* variante oscura, para hover/énfasis */
  --pine-soft:   #0B604414;/* pine al 8% para washes/bordes suaves */
  --pine-ink:    #0B604499;/* pine al 60% — líneas de "tinta", ficha técnica */
  --raspberry:      #DB2153; /* acento de marca — sólo detalles, nunca cuerpo de texto */
  --raspberry-deep: #A81842; /* EL magenta / borravino del proyecto — es este, no el de arriba.
                                Legible como texto (6.09:1 sobre papel). */
  --teal:  #00ADBB;  /* acento decorativo puntual — nunca texto */
  --grass: #3AAA35;  /* acento terciario — insignias, uso mínimo */
  --charcoal: #2D2A26; /* texto secundario cálido */

  /* ---- papeles — siempre claros, alternan por textura, no por valor ---- */
  --paper:       #fffefe; /* papel base */
  --paper-soft:  #EFE7D8; /* variante más clara */
  --paper-sage:  #E1E6D6; /* verde muy pastel, suave — variante craft para el momento destacado */
  --paper-deep:  #DCCFBC; /* variante más tostada, para el cierre */
  --paper-oat:   #E6DCD0; /* avena — muestreado del fondo de composition.jpg, para
                             que la composición se integre sin borde visible */
  --card:        #FBF6EC; /* superficie de tarjeta/etiqueta, casi blanco cálido */
  --night:       #171812; /* sólo para el fallback del hero — base del video, nunca un suelo de sección */

  /* ---- tipografía — cuatro roles ---- */
  /* moonblossom la sirve Adobe Fonts (kit cxp0vxa, ver el <link> en BaseLayout.astro):
     no hay @font-face propio ni archivo en assets/fonts. Detras solo quedan
     fallbacks genericos, para que si el kit no responde los titulares caigan
     en una serif del sistema y no en otra fuente de marca. */
  --f-display: "moonblossom", "Playfair Display", Georgia, serif;  /* títulos */
  --f-serif:   "IM Fell DW Pica", Georgia, serif;                    /* eyebrow + subtítulos */
  --f-body:    var(--font-work-sans);                                /* cuerpo de texto */
  --f-script:  "Caveat", cursive;                                    /* pull-quotes puntuales */
  --f-hand:    "Nostalgia PeachCreme", "Caveat", cursive;            /* ficha técnica — valores a mano */
  --f-craft:   var(--font-providence-sans);                          /* ficha técnica — etiquetas */
  --f-mono:    var(--font-courier-prime);

  --fs-hero: clamp(2.4rem, 1.175rem + 2.8vw, 4.6rem); /* 60px a 1470 */
  /* 2.8125rem = 45px, el tope. La parte variable esta calculada para aterrizar
     justo ahi a 1470px de viewport y bajar de forma pareja: ~36px a 1024 y el
     piso de 2rem (32px) en telefonos. En rem y vw, no en px fijos, para que
     acompanie tanto al viewport como al tamanio de fuente del sistema. */
  --fs-title: clamp(2rem, 0.96rem + 2.02vw, 2.8125rem);
  --fs-sub:   clamp(1.3rem, 1.15rem + .8vw, 1.9rem);
  --fs-eyebrow: .78rem;
  --fs-body: .9rem;
  --fs-script: clamp(1.8rem, 1.5rem + 1.5vw, 2.8rem);

  /* ---- movimiento ---- */
  --dur: .5s;
  --ease: cubic-bezier(.4,0,.2,1);   /* estados: hover, foco, toggles */
  /* entradas: TODO lo que aparece al cargar o al entrar en viewport comparte
     esta duracion y esta curva — la del reveal del logo del hero. Es un
     ease-out largo (arranca rapido y se asienta despacio), que es lo que la
     hace leer elegante en vez de mecanica. La --ease de arriba es casi
     simetrica: sirve para un hover, pero en una entrada se siente tosca. */
  --dur-enter:  .9s;
  /* --ease-enter es para DESPLAZAMIENTO (la mascara del titulo): un ease-out
     largo, que arranca fuerte y se asienta despacio. En un movimiento se lee
     como fisica; el ojo lo acepta. */
  --ease-enter: cubic-bezier(.16,1,.3,1);
  /* --ease-fade es para OPACIDAD, y NO puede ser la misma: con la curva de
     arriba el texto llega al 49% en el primer 10% del tiempo y al 97% en la
     mitad — o sea aparece de golpe y despues arrastra medio segundo invisible.
     El ojo lee la opacidad casi lineal, asi que una entrada suave necesita una
     curva suave: esta reparte el fundido de forma pareja (32% / 79% / 96%) y
     recien afloja al final. */
  --ease-fade:  cubic-bezier(.33,0,.2,1);

  /* ---- forma ---- */
  --r-arch: 4px 120px 4px 4px;  /* arco asimétrico — foto/tarjeta protagonista */
  --r-seal: 50%;
  --r-default: 2px;
  --r-photo:   10px;   /* esquinas de las fotos del sitio */

  /* alto real de la barra fija: marca de 44px + el padding-block de .85rem.
     Lo necesita todo lo que se abra por debajo del nav sin quedar tapado. */
  --nav-h: 72px;
  --edge: 1px solid var(--pine-soft);
  --container: 1240px;
}

/* ---- pisos de tamanio en telefono ----------------------------------------
   No son "mas grande porque si": 16px es el minimo por debajo del cual iOS
   hace zoom solo al enfocar un campo, y a 14.4px el cuerpo obliga a acercar el
   telefono a la cara. En desktop la escala chica es una decision de diseno
   —bloques cortos, mucho aire—; a 40cm de los ojos y en movimiento, no.
   Van sobre los TOKENS y no sobre cada regla, asi la escala entera sube junta
   y las proporciones entre titulo, bajada y cuerpo se mantienen. */
@media (max-width:860px){
  :root{
    --fs-body: 1rem;        /* 14.4px -> 16px */
    --fs-eyebrow: .8rem;    /* el .eyebrow le suma .1rem: queda en ~14.4px */
  }
}
*,*::before,*::after{box-sizing:border-box}
/* saca el retardo de 300ms del doble-tap sin desactivar el zoom por pellizco */
html{touch-action:manipulation}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

body{
  margin:0;
  background:var(--paper);
  color:var(--pine);
  font-family:var(--f-body);
  font-size:var(--fs-body);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}

img{max-width:100%;display:block}
/* las fotos de contenido salen en un <picture> (AVIF + WebP, ver Photo.astro):
   transparente para el layout, el <img> sigue siendo el que se acomoda */
picture{display:contents}
/* el <svg> oculto que solo define filtros (SvgFilters.astro): fuera del flujo */
.svg-defs{position:absolute;overflow:hidden}
a{color:inherit}
.wrap{max-width:var(--container);margin:0 auto;padding:0 1.5rem}

/* ---- textura craft: grano de papel, al 5%, sobre cada sección ---- */
.grain{position:relative}
.grain::before{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  opacity:.05;mix-blend-mode:multiply;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
}

section{position:relative}
section[id]{scroll-margin-top:76px}
/* Bosque 2 se pega al borde, sin ese aire. Los 76px de arriba existen
   para que una seccion no quede tapada por el nav fijo, pero aca el nav todavia
   no aparecio —sale recien en #historia— y la seccion esta hecha para tocar el
   tope: con el margen quedaba una franja del hero asomando arriba. Vale tanto
   para el ancla de la flecha como para el salto de un solo scroll, que usa
   scrollIntoView y respeta la misma propiedad. */
#bosque-2{scroll-margin-top:0}
/* Historia aterriza EXACTAMENTE en el alto del nav, no en los 76px genericos.
   Cuatro pixeles de diferencia, pero deciden: el nav se enciende cuando el
   borde superior de la seccion llega a `<= --nav-h` (ver interactions/nav-gate.ts), y con 76 el
   salto la dejaba en 76 — cuatro de mas, la condicion no se cumplia y la barra
   no aparecia al llegar.
   Atado al token y no a un numero: si cambia el alto del nav, el aterrizaje y
   el encendido siguen coincidiendo. */
#historia{scroll-margin-top:var(--nav-h)}

/* ---- suelos — todos claros, alternan por textura/temperatura ---- */
.band{padding:clamp(4.5rem,6vw + 2rem,8rem) 0}
.band--paper{background:var(--paper)}
.band--soft{background:var(--paper-soft)}
.band--sage{background:var(--paper-sage)}
.band--deep{background:var(--paper-deep)}
.band--oat{background:var(--paper-oat)}
.band > .wrap{position:relative;z-index:2}
/* secciones a pantalla completa: alto minimo de viewport y contenido
   centrado verticalmente. El padding de .band queda como piso minimo, asi
   que en viewports bajos la seccion crece en vez de apretar el contenido. */
.band--full{min-height:100vh;min-height:100svh;display:flex;align-items:center}
.band--full > .wrap{width:100%}
/* ---- roles tipográficos ---- */
/* Providence Sans (--f-craft): palo seco dibujada a mano, de ahi el aire
   manuscrito. El @font-face declara un solo corte (400), asi que este 600 lo
   sintetiza el navegador engrosando los trazos por software — queda a mitad de
   camino entre el 400 real y el 800 anterior, con menos falseo del trazo. */
.eyebrow{
  font-family:var(--f-craft);font-size:calc(var(--fs-eyebrow) + .1rem);font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--raspberry-deep); margin-top:30px;
}
.eyebrow--pine{color:var(--pine)}
h1,h2,h3{font-family:var(--f-display);font-weight:400;margin:0;color:var(--pine);text-transform:uppercase}
.display{font-size:var(--fs-hero);line-height:.94;letter-spacing:-.01em;text-transform:uppercase}
.title{font-size:var(--fs-title);line-height:1.05;letter-spacing:-.005em}
/*.sub{font-family:var(--f-hand);font-style:normal;font-weight:400;font-size:clamp(1.7rem,1.4rem + 1.1vw,2.3rem);line-height:1.3;color:#2B2B2B}*/


.sub {
    font-family: var(--f-mono);
    font-size: 18px;
    line-height: 26px;
    color: #0c6044;
    padding: 30px;
    border-top: 1px solid;
    border-bottom: 1px solid;
    text-transform: uppercase;
    margin-top: 40px;
    text-align: center;
}



.script{font-family:var(--f-hand);font-size:var(--fs-script);line-height:1;color:#2B2B2B;font-weight:400}
p{
  margin:0 0 1.1em;color:#2B2B2B;font-family:var(--f-mono);font-size:var(--fs-body);
  line-height:1.6;-webkit-font-smoothing:antialiased;letter-spacing:-1px; text-align: justify;
}
.lede{
  font-family:var(--f-mono);font-weight:400;color:#2B2B2B;
  font-size:var(--fs-body);line-height:1.6;letter-spacing:-1px;
}
/* 54ch y no 62: el `ch` mide el ancho del cero, mas ancho que la letra media,
   asi que 62ch aterrizaba en ~79 caracteres reales — quince de mas. 54ch da
   ~68, dentro de la medida comoda de lectura. */
.prose{max-width:54ch}
.prose--center{margin-inline:auto;text-align:center}
/* el `p{text-align:justify}` global gana por ser una declaracion directa
   sobre el elemento (la herencia del contenedor no alcanza a pisarla) — el
   `<p class="eyebrow">` queda pegado a la izquierda en vez de centrado.
   Mismo bug que en el footer, pero acotado solo al eyebrow: el resto de
   los parrafos (.story-after, lede, etc.) tienen que seguir justificados
   como en todo el sitio, no centrados. */
.prose--center .eyebrow{text-align:center}
/* ---- links: subrayado en currentColor, vira a tinta frambuesa al hover ---- */
.lnk{
  font-family:var(--f-body);font-size:var(--fs-eyebrow);font-weight:600;text-transform:uppercase;
  letter-spacing:.22em;border-bottom:1px solid currentColor;padding-bottom:.28em;
  display:inline-flex;align-items:center;gap:.5em;color:var(--pine);text-decoration:none;
  transition:color var(--dur) var(--ease);
}
.lnk:hover,.lnk:focus-visible{color:var(--raspberry-deep)}
.lnk--raspberry{color:var(--raspberry-deep)}

/* ---- botón ---- */
.btn{
  font-family:var(--f-mono);font-size:.85rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  padding:1rem 2.1rem;border:1.5px solid var(--pine);border-radius:var(--r-default);
  background:transparent;color:var(--pine);text-decoration:none;display:inline-block;
  transition:background var(--dur) var(--ease),color var(--dur) var(--ease);
}
.btn:hover,.btn:focus-visible{background:var(--pine);color:var(--paper)}
.btn--fill{background:var(--pine);color:var(--paper)}
.btn--fill:hover{background:var(--pine-deep);color:var(--paper)}

/* ---- fade de entrada — fundido, sin cascada, sin transform ---- */
/* estado inicial; el fundido lo hace GSAP (ScrollTrigger.batch) */
.js .fade{opacity:0}
@media (prefers-reduced-motion:reduce){.fade{opacity:1;transition:none}}

/* ---- skip link: oculto hasta que recibe foco por teclado ---- */
.skip-link{
  position:absolute;left:1rem;top:-100%;z-index:60;
  font-family:var(--f-body);font-size:.78rem;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;text-decoration:none;
  background:var(--pine);color:var(--paper);padding:.85rem 1.4rem;
}
.skip-link:focus{top:1rem}
/* el skip link le pasa el foco a <main> (tabindex=-1): sin contorno sobre la
   pagina entera, el lector de pantalla ya anuncia el salto */
main[tabindex="-1"]:focus{outline:none}
/* ============================== NAV ============================== */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:40;background:var(--paper);
  border-bottom:1px solid var(--pine-soft);
  transition:opacity var(--dur) var(--ease),visibility 0s linear var(--dur);
}
/* arranca oculta y la muestra el JS (interactions/nav-gate.ts). Cuelga de .js:
   sin JS la barra queda a la vista, que es la unica forma de navegar. */
.js .nav{opacity:0;visibility:hidden}
.nav.is-visible{opacity:1;visibility:visible;transition-delay:0s,0s}
/* grid de tres columnas en vez de space-between: los flancos (1fr) valen lo
   mismo pase lo que pase, asi la fila de links queda centrada de verdad en la
   barra. Con space-between el bloque central se corria hacia el flanco mas
   angosto — la marca mide ~96px y el selector de idioma ~62px, o sea que los
   items estaban ~17px fuera de eje, y cada cambio de ancho del selector los
   movia de nuevo. */
.nav .wrap{
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
  padding-block:.85rem;
}
.nav__mark{display:flex;align-items:center;gap:.6rem;text-decoration:none}
.nav__mark img{height:44px;width:auto}

/* .78rem en vez de .72rem: dos pixeles mas de cuerpo para que el menu sostenga
   la barra sin verse timido. El padding vertical lleva el area clickeable a
   ~44px de alto sin cambiar el alto de la barra (la marca, de 44px, es la que
   la define). */
.nav__links{display:flex;gap:2.4rem;list-style:none;margin:0;padding:0}
.nav__links a,.nav__lang summary{
  font-family:var(--f-mono);font-size:.78rem;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;line-height:1.2;
  color:var(--pine);text-decoration:none;
}
.nav__links a{
  display:block;position:relative;padding:.85rem .1rem;
  transition:color var(--dur) var(--ease);
}
/* la regla del hover va en un ::after y no en border-bottom: con el padding
   grande el borde quedaria despegado del texto, y asi ademas se anima una sola
   propiedad (opacity), como el resto del sitio. */
.nav__links a::after{
  content:"";position:absolute;left:.1rem;right:.1rem;bottom:.55rem;height:1px;
  background:currentColor;opacity:0;transition:opacity var(--dur) var(--ease);
}
.nav__links a:hover,.nav__links a:focus-visible{color:var(--raspberry-deep)}
.nav__links a:hover::after,.nav__links a:focus-visible::after{opacity:1}

/* ---- selector de idioma: <details> nativo ---- */
/* el toggle, el estado abierto/cerrado y el teclado los resuelve <details>;
   el JS solo agrega cerrar con Esc y con click afuera. Muestra un solo idioma
   (el activo) y despliega los dos, cada uno escrito en su propia lengua —
   asi lo encuentra quien no lee espaniol. */
.nav__lang{position:relative;justify-self:end}
.nav__lang summary{
  display:flex;align-items:center;gap:.45rem;
  padding:.85rem .1rem;cursor:pointer;list-style:none;
  transition:color var(--dur) var(--ease);
}
.nav__lang summary::-webkit-details-marker{display:none}
.nav__lang summary:hover,.nav__lang summary:focus-visible{color:var(--raspberry-deep)}
.nav__lang summary svg{width:.85rem;height:.85rem;display:block}
.nav__lang-menu{
  position:absolute;top:100%;right:0;z-index:1;min-width:100%;
  margin:0;padding:.35rem 0;list-style:none;
  background:var(--paper);border:var(--edge);border-radius:var(--r-default);
}
.nav__lang-menu a{
  display:block;white-space:nowrap;padding:.5rem 1.1rem;
  font-family:var(--f-mono);font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--pine);text-decoration:none;opacity:.55;
  transition:opacity var(--dur) var(--ease),color var(--dur) var(--ease);
}
.nav__lang-menu a:hover,.nav__lang-menu a:focus-visible{opacity:1;color:var(--raspberry-deep)}
.nav__lang-menu a[aria-current]{opacity:1}

@media (prefers-reduced-motion:reduce){
  .nav__links a,.nav__links a::after,.nav__lang summary,.nav__lang-menu a{transition:none}
}
/* entre 861 y 1024 la barra se aprieta: el gap cede antes que el cuerpo. */
@media (max-width:1024px){.nav__links{gap:1.5rem}}
.nav__toggle{display:none;background:none;border:0;padding:.4rem;cursor:pointer}
.nav__toggle svg{display:block;width:24px;height:24px;stroke:var(--pine)}

@media (max-width:860px){
  /* aparece el boton hamburguesa: son 4 items en la fila y el .nav__links pasa
     a overlay, asi que la grilla de 3 columnas ya no aplica. */
  .nav .wrap{display:flex;justify-content:space-between}
  .nav__lang{justify-self:auto;margin-left:auto;margin-right:1rem}
  .nav__links{
    position:fixed;inset:64px 0 0 0;background:var(--paper);flex-direction:column;
    align-items:flex-start;padding:2rem 1.5rem;gap:1.6rem;transform:translateY(-8px);
    opacity:0;visibility:hidden;
    transition:opacity var(--dur) var(--ease),visibility 0s linear var(--dur);
  }
  /* En un overlay a pantalla completa el objetivo no es el texto sino la FILA:
     cada link ocupa el ancho del panel y 48px de alto. Antes median 78x19 y
     habia que apuntarle a la palabra. */
  .nav__links{gap:.25rem}
  .nav__links li{width:100%}
  .nav__links a{
    font-size:1.0625rem;
    display:flex;align-items:center;
    width:100%;min-height:48px;
  }
  .nav.is-open .nav__links{opacity:1;visibility:visible;transition-delay:0s,0s}
  .nav__toggle{display:inline-flex;align-items:center;justify-content:center;padding:0;
    width:48px;height:48px;margin-right:-.6rem}   /* el margen negativo mantiene la optica del borde */
  .nav__lang summary{min-height:44px;display:inline-flex;align-items:center}
  .nav__lang-menu a{min-height:44px;display:flex;align-items:center}
}

/* ============================== HERO — video en loop ============================== */
.hero{
  position:relative;overflow:hidden;background:var(--night);
  min-height:100vh;min-height:100dvh;
  display:flex;align-items:center;
}
.hero__bg{position:absolute;inset:0;z-index:0;opacity:.32;color:var(--card)}
.hero__bg svg{width:100%;height:100%}
.hero__video{
  position:absolute;inset:0;z-index:1;width:100%;height:100%;
  object-fit:cover;object-position:center;
}
.hero__scrim{
  position:absolute;inset:0;z-index:2;
  background:linear-gradient(180deg, rgba(12,14,9,.30) 0%, rgba(12,14,9,.42) 50%, rgba(10,12,8,.55) 100%);
}
.hero__inner{position:relative;z-index:3;width:100%}
.hero__copy{max-width:none;text-align:center}
/* el bloque no se funde: la entrada es la mascara de cada linea (GSAP). */

/* lockup: marca.svg partido en sus dos lineas para poder revelarlas por
   separado. --mark es el ancho de SOLARE (la linea ancha); el ancho de MONTE
   y el hueco salen de las proporciones reales del archivo, no a ojo.
   269px a 1470 = el mismo alto de bloque (98px) que tenia en texto. */
.hero__mark{
  --mark:clamp(190px, 6.7rem + 11vw, 300px);
  display:flex;flex-direction:column;align-items:center;
  gap:calc(var(--mark) * .02807);margin:0;
}
.hero__mark-line{display:block;overflow:hidden}
.hero__mark-line img{display:block;width:100%;height:auto}
.hero__mark-line--up{width:calc(var(--mark) * .8406)}
.hero__mark-line--down{width:var(--mark)}

/* flecha de scroll: link real a la segunda seccion, con area tactil de 44px
   aunque el trazo dibujado sea mucho mas fino. */
.hero__scroll{
  /* Abajo a la derecha, en la misma posicion y medida que la invitacion del
     intro del vino y la de Bosque 2: es el mismo gesto en las tres, y
     que aparezca siempre en el mismo rincon es lo que lo vuelve un idioma en
     vez de tres adornos.
     Antes era una flecha centrada al pie. El `translate` queda libre para el
     rebote, por eso la posicion no usa transform. */
  position:absolute;z-index:3;display:block;
  right:clamp(1.5rem,4vw,4rem);
  bottom:clamp(1.5rem,3.5vw,3rem);
  width:clamp(75px,7.3vw,107px);
}
/* oculta hasta que la timeline del hero la funde; sin JS queda a la vista */
.js .hero__scroll{opacity:0}
.hero__hint{width:100%;height:auto;display:block;overflow:visible}
/* ultima en entrar: la opacidad la pone la timeline del hero (animations/hero.ts)
   (a .5, al final de la secuencia). Aca solo queda el estado de hover, que si
   es una transicion de CSS — GSAP no toca los estados interactivos. */
.hero__scroll:hover,
.hero__scroll:focus-visible{opacity:1;transition:opacity var(--dur) var(--ease)}

@media (prefers-reduced-motion:no-preference){
  /* Rebota SOLO la flecha, no el bloque entero: el texto quieto es lo que hace
     que el movimiento se lea como una indicacion y no como que la pagina
     tiembla. Se apoya en hint-arrow-bounce, la misma que usan las otras dos
     invitaciones — el hero heredaba su propio keyframe de cuando era una
     flecha suelta centrada al pie. */
  .hero__hint .vino-intro__hint-arrow{animation:hint-arrow-bounce 3s cubic-bezier(.4,0,.2,1) infinite}
  /* la posicion inicial de las dos lineas la pone GSAP; aca solo el estado
     invisible de la linea de origen (sin JS no se oculta: nadie la fundiria). */
  .js .hero__origin{opacity:0}
}
.hero__origin{
  font-family:var(--f-craft);font-size:13px;font-weight:800;
  letter-spacing:.11em;text-transform:uppercase;color:var(--card);
  margin:29px 0 0;line-height:1;text-align: center;
}

/* variantes de tinta clara — el hero es la única sección que no es "siempre clara":
   necesita texto legible sobre video/scrim oscuro, el resto del sitio se mantiene en papel. */
.eyebrow--on-video{color:var(--card)}
.display--on-video{color:var(--card)}
.btn--on-video{border-color:var(--card);color:var(--card)}
.btn--on-video:hover,.btn--on-video:focus-visible{background:var(--card);color:var(--pine-deep)}

@media (max-width:860px){
  .hero__origin{font-size:11px;letter-spacing:.16em;margin-top:26px}
}

/* ============================== STORY (02) ============================== */
/* las ramas sangran fuera del viewport a proposito: hay que recortar el
   desborde lateral. `clip` y no `hidden` — hidden crearia un contenedor de
   scroll y romperia el position:sticky del pin. */
/* sin padding arriba: ese padding empujaba el pin —y con el las ramas— hacia
   abajo, dejando un hueco contra el borde superior de la seccion.
   `clip` en x hace que overflow-y (visible) compute tambien a clip, asi que la
   sangria de las ramas se recorta contra los bordes en vez de derramarse. */
.story{
  overflow-x:clip;padding:0;
  /* las medidas del collage viven aca arriba: la pista de scroll se calcula
     con ellas, y bajan por herencia a .story-reveal y a las columnas. */
  --colw:clamp(240px,19vw,310px);
  /* topeadas en px (valor que dan a 1280x832, el viewport de referencia de
     13.6") para que en monitores mas altos/anchos no se separen de mas;
     por debajo del tope siguen siendo vh/vw puros, sin cambio de comportamiento. */
  --gap-y:min(25vh,208px);
  --top-right:min(30vh,250px);
  --top-left:min(11vh,92px);
  /* PISTA DE SCROLL: la seccion es alta, pero lo unico que se ve es la ventana
     de 100vh de .story-reveal, trabada adentro. Lo que sobra de este alto es el
     recorrido que tienen las fotos para desplazarse dentro de la ventana.
     + 12.5vh al final: colchon extra despues de que aparece la ultima foto —
     sin eso la ventana se destraba apenas terminan de aparecer las fotos y no
     queda aire entre la ultima y el solapamiento de #historia. */
  /* + 60vh al final: el tramo en el que #historia, que arranca con un margen
     negativo permanente de ese mismo valor, sube por encima de la ventana
     todavia trabada. Reservarlo aca es lo que permite que ese margen sea fijo
     en vez de agregarse en pleno scroll. */
  min-height:calc(var(--top-right) + 2 * var(--gap-y) + 3.61 * var(--colw) + 12.5vh + 60vh);
}
/* la fibra de papel real reemplaza al grano sintetico en esta seccion: hacen
   el mismo trabajo y superpuestos ensucian. Reusa el hueco de .grain::before
   (inset:0, multiply, detras de las fotos) en vez de sumar un elemento.
   Se extiende a .story-narrative para que el relato (#historia) mantenga
   la misma textura aunque ahora sea una seccion aparte. */
.story.grain::before,
.story-narrative.grain::before{
  background-image:url("/_astro/fondo-hoja-papel.E3xv_2px.webp");
  background-size:620px;
  opacity:.45;
}
/* la ramita no es cuadrada (89.59 x 111.07): el alto va en auto para no
   achatarla. fill:currentColor porque al inlinear el SVG se le quito el color
   fijo que traia el archivo. */
.story__mark{width:68px;height:auto;color:var(--pine);fill:currentColor;margin-inline:auto}
/* la bajada de Bosque 2, centrada y partida en dos renglones */
.story-2__copy .eyebrow{justify-content:center;display:flex;flex-wrap:wrap;text-align:center}
.story-narrative blockquote{margin:1.8rem 0;font-family:var(--f-hand);font-size:var(--fs-script);color:#2B2B2B;line-height:1.15}
.story-after{margin-top:clamp(3rem,6vw,5rem)}
/* ---- BOSQUE 2: la misma escena en una composicion armada ---- */
/* Mismo fondo y mismas ramas que #bosque; lo que cambia es el escenario: en
   vez de dos columnas que atraviesan la ventana, cinco fotos con posicion
   propia y el titulo en el hueco del medio.
   Pista mucho mas corta que la de #bosque (2.6 pantallas contra ~5): la
   composicion no la atraviesa, apenas deriva. Una pantalla de recorrido mas
   los 60vh que #historia se come al superponerse.
   Sube 60vh y se apoya sobre el final de #bosque con el mismo mecanismo (y el
   mismo z-index) que usa #historia unas lineas mas abajo: esa reserva ya esta
   pedida en la pista de #bosque, y sin aprovecharla quedaba media pantalla de
   scroll pinneado sin que pase nada. */
.story-2{
  /* Sin las 60vh de reserva: existian para que #historia se montara ENCIMA
     mientras la ventana seguia trabada. Ahora la empuja, asi que la pista
     termina donde termina su contenido y la ventana se suelta ahi. */
  min-height:200vh;
  position:relative;z-index:5;
  /* Sin margin-top negativo ni sombra: los -60vh y la sombra existian para
     montarse sobre la cola de Story Reveal 1, que hoy esta oculta. Contra el
     hero no hay nada que solapar y la sombra se leeria como una costura.
     Los 60vh del min-height SI se quedan: son los que se lleva #historia
     subiendo por encima de esta seccion. */
}
/* El escenario ocupa la ventana entera: los margenes del original (~6% a cada
   lado) se aplican contra la PANTALLA, no contra una caja centrada mas chica.
   Por eso las posiciones van en % del viewport y no de un lienzo fijo: en una
   pantalla ancha las piezas se separan, que es lo que se quiere de un collage.
   Los TAMANIOS en cambio salen de min(svh, vw): la referencia mide 1405x1058,
   asi que cada pieza lleva su ancho expresado contra las dos dimensiones y
   manda la que aprieta. Solo con vw se pasarian de alto en pantallas bajas;
   solo con svh se saldrian de cuadro en pantallas altas y angostas. */
.compo{position:absolute;inset:0;z-index:1;pointer-events:none}
.compo__item{
  position:absolute;margin:0;
  will-change:transform;
}
.compo__photo{
  width:100%;height:auto;display:block;
  /* drop-shadow y no box-shadow: son recortes de borde irregular con aire
     transparente alrededor, asi que la sombra tiene que seguir el canal alfa
     y no la caja del <img> — con box-shadow saldria un rectangulo flotando
     alrededor de cada foto. */
  filter:drop-shadow(0 5px 12px rgba(45,42,38,.22));
}
/* Los iconos van SVG inline y no <img> porque el trazo se dibuja de verdad, y
   para eso hay que poder tocar los <path> desde afuera.
   Como se dibuja algo que en el archivo es un contorno RELLENO y no una linea
   con stroke: el mismo path sirve de recorte, y adentro se anima una copia
   stroke-only bien gruesa que recorre ese contorno. El grosor tapa el ancho
   del garabato y el recorte se come lo que sobra, asi que lo que se ve es el
   dibujo apareciendo a lo largo de su propio trazo.
   pathLength="1" (en el HTML) normaliza cada path: dasharray y dashoffset van
   de 0 a 1 sin medir nada, y no hace falta DrawSVGPlugin. */
.compo__icon{
  position:absolute;height:auto;display:block;overflow:visible;
}
.compo__icon-line{
  fill:none;stroke:#fff;
  stroke-width:11;stroke-linecap:round;stroke-linejoin:round;
  /* MEDIO contorno y no entero. El path es el borde del garabato: va por un
     lado del trazo hasta la punta y vuelve por el otro. Con la mitad ya se
     recorrio el dibujo de punta a punta —y el grosor tapa el ancho— asi que
     animar el contorno completo hacia que todo apareciera en el primer 30% y
     despues no pasara nada.
     El hueco mas largo que el trazo (1.6 contra 0.5) para que en el arranque
     el dash quede ENTERO fuera del path: si el extremo cae sobre el punto
     cero, el linecap redondo dibuja un puntito antes de empezar. */
  stroke-dasharray:0.5 1.6;
}
/* El dibujo de verdad, encima del trazo. Existe porque medio contorno no
   alcanza a cubrir las formas mas gordas del garabato (al zorro le faltaba una
   oreja y parte de la cabeza): el trazo hace el gesto de dibujar y este cierra
   el dibujo al final, asi el estado final es exactamente el archivo. */
.compo__icon-fill{fill:#fff}
/* El estado sin dibujar solo existe donde hay algo que lo dibuje: con .js y de
   861 para arriba. Sin JS, o en movil (donde el bloque de GSAP no corre), los
   iconos arrancan y se quedan completos. */
@media (min-width:861px){
  /* Las piezas arrancan invisibles. Sin esto se ven enteras desde que el
     navegador pinta el HTML hasta que GSAP les pone su estado inicial: un
     parpadeo en el que la composicion aparece armada y despues se desarma
     para animarse. Mismo criterio que .js .fade en el resto del sitio — lo
     esconde el CSS, lo enciende GSAP.
     Solo de 861 para arriba: abajo el bloque de GSAP no corre y nadie las
     encenderia. */
  .js .compo__item{opacity:0}
  .js .compo__icon-line{stroke-dashoffset:0.56}
  .js .compo__icon-fill{opacity:0}
}

/* Posiciones (en % de la ventana) y tamanios (contra las dos dimensiones),
   leidos de la composicion de referencia. La inclinacion de cada foto viene
   dentro del PNG, no se agrega aca. */
.compo__item--1{left:7.3%;top:10.8%;width:min(50.8svh,38.2vw)}   /* bosque */
.compo__item--2{left:62.1%;top:5.6%;width:min(42.9svh,32.3vw)}   /* olivo a contraluz */
.compo__item--3{left:5.6%;top:58.5%;width:min(33.1svh,24.9vw)}   /* la ruina */
.compo__item--4{left:39.9%;top:72.8%;width:min(28.2svh,21.2vw)}  /* martin pescador */
.compo__item--5{left:63.6%;top:45.1%;width:min(47.3svh,35.6vw)}  /* el zorro */

/* Cada icono en % de SU foto: la pareja escala y se mueve junta. */
.compo__item--1 .compo__icon{left:39.9%;top:28.7%;width:28.5%}
.compo__item--2 .compo__icon{left:12.1%;top:47.3%;width:32.4%}   /* aceitunita: mas chica que la uvita que estaba */
.compo__item--3 .compo__icon{left:72.6%;top:13.3%;width:46.9%}
.compo__item--4 .compo__icon{left:52.7%;top:11.5%;width:58.7%}
.compo__item--5 .compo__icon{left:60.6%;top:10.1%;width:36.0%}

/* El texto por encima de la composicion. La altura la da el margin-top de
   .story-reveal__pin-inner (15rem), compartido con #bosque.
   Mas angosto y un punto mas chico que el titulo de arriba: el hueco entre la
   ruina y el zorro mide lo que mide, y a la medida original la segunda linea
   se le montaba al papel del zorro. */
.story-2 .story-reveal__pin-inner{z-index:3;max-width:32rem}
.story-2 .story-reveal__pin-inner .title{font-size:clamp(1.7rem, 0.9rem + 1.55vw, 2.35rem)}
/* Pantallas grandes (27" -> viewport de ~2560x1330): el margin-top plano de 12rem
   lo deja en el cuarto de arriba de la ventana. En un laptop de 13.6" ese mismo
   offset cae en el hueco de la composicion, por eso solo se corrige desde aca.
   Centrado en la ventana de 100vh: top/bottom 0 + margin auto + height:fit-content
   (sin transform, y sin flex: como item flex la ramita pierde el espacio de linea
   que la separa del titulo). animations/bosque2.ts mide copy.offsetTop, asi que el
   momento en que el martin pescador alcanza el texto se recalcula solo. */
@media (min-width:2000px) and (min-height:1100px){
  .story-2 .story-reveal__pin-inner{top:0;bottom:0;margin:auto;height:fit-content}
}

/* Multiplicadores del recorrido. Van mucho mas juntos que los de #bosque
   (0.88 a 1.24): alla las fotos van en columnas y separarse es el efecto, aca
   la composicion esta dibujada y una dispersion grande la desarma. Con scrub
   el tween es reversible: subiendo el scroll cada una vuelve a su velocidad. */
.compo__item--1{--speed:1.14}
.compo__item--2{--speed:0.88}
.compo__item--3{--speed:1.22}
.compo__item--4{--speed:0.80}
.compo__item--5{--speed:1.02}

@media (max-width:860px){
  /* Sin ventana trabada no hay composicion posible a escala legible, asi que
     las piezas pasan a una grilla. Y el orden se invierte respecto del DOM:
     primero el texto, despues las fotos. En el desktop el texto vive en el
     hueco del medio y el orden interno da igual; apilado no — el titulo tiene
     que abrir la seccion, no aparecer despues de cuatro fotos.
     Cada icono sigue anclado a su foto, asi que no hay nada que recolocar. */
  .story-2{margin-top:0;min-height:0;box-shadow:none}
  .story-2 .story-reveal{display:flex;flex-direction:column}
  .story-2 .story-reveal__pin-inner{order:1}
  .compo{order:2}

  /* La pieza del bosque no entra en telefono. Es la mas grande y a todo el
     ancho comia una pantalla entera antes de que se viera ninguna otra; sin
     ella las cuatro restantes arman una grilla 2x2 que se lee de un vistazo.
     display:none y no una grilla distinta: asi tampoco se descarga. */
  .compo__item--1{display:none}

  .compo{
    position:static;
    display:grid;grid-template-columns:1fr 1fr;gap:.6rem;align-items:center;
    padding:0 1.5rem 2rem;
  }
  .compo__item{position:relative;left:auto;top:auto;width:auto}
}

/* #historia se superpone al final de #bosque con un margen negativo FIJO.
   Antes ese margen lo agregaba y lo quitaba el JS al llegar la ultima foto,
   con una compensacion FLIP para disimular el salto y un refresh de
   ScrollTrigger detras. Todo eso existia para que el solapamiento no empezara
   demasiado pronto — pero cambia el alto del documento en pleno scroll, que es
   justo lo que rompe la simetria al subir: el contenido se corre debajo del
   dedo y la ventana no vuelve a trabarse donde corresponde.
   Ahora la pista reserva esos 60vh por adelantado (ver .story), asi el margen
   puede ser permanente: el momento en que #historia empieza a tapar es el
   mismo, pero el layout no se mueve nunca. Bajando y subiendo se comporta
   igual, y sobran el FLIP, el refresh y la clase que los disparaba.
   z-index:5 la deja por delante de la ventana, que usa 2. */
/* Historia EMPUJA, no tapa. Antes subia 60vh por encima de la ventana todavia
   trabada, con una sombra que vendia esa capa de arriba. Ahora llega por el
   flujo normal: su borde superior toca el inferior del verde y lo saca de
   cuadro empujandolo. Sin margen negativo no hay nada que montar, y sin capa
   la sombra no tiene que sugerir profundidad — sugeriria una mentira.
   El z-index se queda: la ventana de arriba es sticky y crea contexto propio,
   asi que sin el 5 el verde le pasaria por encima en el ultimo tramo. */
.story-narrative{
  position:relative;z-index:5;overflow:hidden;
}
@media (max-width:860px){
  .story-narrative{margin-top:0;border-radius:0;box-shadow:none}
}


blockquote.script {
    font-family: var(--f-mono);
    font-size: 18px;
    color: #0c6044;
    padding: 30px;
    border-top: 1px solid;
    border-bottom: 1px solid;
    text-transform: uppercase;
}



.story-banner{
  margin:clamp(3rem,6vw,5rem) auto 0;border:1px solid var(--pine-soft);
  /* sin overflow:hidden: el vector de abajo sobresale del marco (gaviotas por
     arriba, planta por abajo). La foto ya se recorta sola con su border-radius. */
  position:relative;box-shadow:0 20px 32px rgba(45,42,38,.16);
}
/* VECTOR DE HISTORIA: linea de la loma + gaviotas + planta, en blanco, pisando la
   foto. El PNG (vector-historia-22, 1259x760) esta compuesto contra la foto, asi que
   va en % de la caja de la foto —no en px— y escala con ella: corrido -3.39% a la
   izquierda y -14.80% arriba, ancho 99.46% (cada px del PNG = 0.079% de la foto).
   Medido sobre la captura del diseno (ajuste por minimos cuadrados, error < 1px).
   Solo con la foto apaisada: de 860 para abajo el banner pasa a cuadrado (ver mas
   abajo) y el dibujo ya no calza con el recorte. */
.story-banner::after{
  content:"";position:absolute;left:-3.39%;top:-14.8%;width:99.46%;
  aspect-ratio:1259/760;pointer-events:none;
  background:url("/_astro/vector-historia-22.D3hM3IIl.webp") no-repeat 0 0/100% 100%;
}
.story-banner img{width:100%;height:auto;aspect-ratio:1920/805;object-fit:cover;display:block;border-radius:var(--r-photo)}
/* mismo fade que las fotos del bloque, con un respiro antes de arrancar */
.js .story-banner{opacity:0}
@media (prefers-reduced-motion:reduce){.story-banner{opacity:1;transition:none}}
/* ---- la ventana sticky de Bosque 2: fondo con ramas + composicion + texto.
   Era el bloque de scroll de "Story Reveal 1" (dos columnas de fotos que
   subian); de aquel quedo la ventana y sus capas, que Bosque 2 reusa. ---- */
/* LA VENTANA: alto fijo de 100vh, trabada contra el tope del viewport durante
   todo el largo de .story (la pista). overflow:hidden la vuelve un recorte
   real — lo unico que se mueve adentro es la composicion de fotos. */
.story-reveal{
  position:sticky;top:0;
  height:100vh;max-height:100vh;
  overflow:hidden;
  /* z-index propio y no `auto`: position:sticky SI crea contexto de
     apilamiento, asi que el z-index:3 del pin queda encerrado adentro y ya no
     compite a nivel de seccion. Sin esto la textura de papel (.grain::before,
     z-index:1) pinta ENCIMA de las fotos. Con 2 queda por arriba de la
     textura y por debajo de #historia (5), que es el orden original. */
  z-index:2;
}
/* --- las tres capas de la ventana --- */
/* 1 · fondo: las ramas. Quietas, ancladas a los bordes de la ventana. */
.story-reveal__bg{position:absolute;inset:0;z-index:0;pointer-events:none}
/* ramas: cada racimo es su propio archivo, recortado por su bbox, para poder
   escalarlo por separado y anclarlo sangrando fuera del borde. Se dimensionan
   por alto (vh) porque el pin mide 100vh: asi la mancha ocupa siempre la misma
   proporcion de la pantalla, que es lo que define el encuadre. */
.story-reveal__branches{
  position:absolute;z-index:0;pointer-events:none;
  background-repeat:no-repeat;background-size:contain;
  opacity:.55;
}
.story-reveal__branches--tr{
  top:0;right:-3vw;height:70vh;aspect-ratio:.708;
  background-image:url("/_astro/ramas-tr.D1Mrk2K7.webp");background-position:top right;
  filter:opacity(0.4);
}
.story-reveal__branches--bl{
  bottom:-3vh;left:-1vw;height:52vh;aspect-ratio:.487;
  background-image:url("/_astro/ramas-bl.vR1nG52-.webp");background-position:bottom left;
  filter:opacity(0.4);
}
.story-reveal__pin-inner{
  /* posicion fija, sin scroll ni parallax: lo unico que se mueve durante
     el scroll son las fotos, este bloque queda quieto en todas las
     resoluciones — un margin-top plano no necesita ningun tope. */
  /* 3 · texto, la capa de arriba. Antes lo centraba el flex de .__pin (que ya
     no existe): ahora se posiciona solo — left/right 0 + margin auto. */
  position:absolute;top:0;left:0;right:0;z-index:2;
  margin:12rem auto 0;
  max-width:44rem;text-align:center;padding:0 1.5rem;pointer-events:auto;
}
/* sin fade de salida: el bloque se queda entero hasta que el sticky se
   destraba contra el final de .story-reveal, y ahi lo tapa #historia subiendo
   por su margen negativo (z-index:5, por delante de la ventana que usa 2). */
.story-reveal__pin-inner .title{margin-top:10px}   /* la ramita, bien pegada al titulo */
.story-reveal__pin-inner .eyebrow{margin-top:1.4rem;justify-content:center}

@media (max-width:860px){
  .story{min-height:0;padding-bottom:clamp(4.5rem,6vw + 2rem,8rem)}
  .story-reveal{position:static;height:auto;max-height:none;overflow:visible}
  .story-reveal__bg{display:none}
  .story-reveal__pin-inner{position:static;margin:0 auto;padding:0 1.5rem 2.4rem}
  /* las ramas dejan de ser marco de pantalla y pasan a acento de esquina:
     con el pin estatico se anclan al bloque entero y a 70/88vh lo tapaban. */
  .story-reveal__branches{opacity:.4}
  .story-reveal__branches--tr{top:-2vh;right:-6vw;height:26vh}
  .story-reveal__branches--bl{bottom:-2vh;left:-6vw;height:22vh}
}

/* ============================== TERRITORIO (03) ============================== */
.territory{overflow:hidden}
.territory .wrap{
  /* mismo gap que Expansion: las dos secciones son la misma construccion
     espejada (foto contra el gap de un lado, medida de lectura del otro), y
     con dos valores distintos la separacion imagen/texto no coincidia. */
  display:grid;grid-template-columns:1fr 1fr;gap:clamp(2.5rem,6vw,5rem);align-items:stretch;
  --measure:420px;
}
/* espejo de la seccion Expansion: ahi la foto va a la izquierda y el texto a
   la derecha; aca al reves. Misma cuenta, cambiada de lado — calc(100% - measure)
   es lo que le sobra a la columna despues de la medida de lectura, y es lo que
   hay que meterle a cada extremo para que las dos separaciones den iguales.
   El % se resuelve contra el area de grilla, o sea contra la columna. */
.territory__col{max-width:var(--measure);margin-left:max(0px, calc(100% - var(--measure)))}
.territory__col .lede{margin-top:1.6rem}
.territory__foto{
  margin:0;max-width:400px;justify-self:end;
  margin-right:max(0px, calc(100% - var(--measure)));
}
.territory__foto img{width:100%;height:auto;display:block}
@media (max-width:860px){
  .territory .wrap{grid-template-columns:1fr}
  .territory__foto{order:-1;margin-inline:auto}
  /* en una sola columna no hay con que emparejar el alto: vuelve a mandar el
     ancho, que es lo que limita en movil. */
  .territory-2 .territory__foto--still{aspect-ratio:auto;max-width:340px}
  .territory-2 .territory__foto--still img{width:100%;height:auto}
}

/* El collage viene sobre fondo blanco y multiply lo vuelve transparente: las
   fotos, los papeles rasgados y los dibujos quedan impresos sobre la avena de
   la seccion, sin recorte ni mascara. El brillo compensa lo que multiplicar
   por el avena (E6DCD0, ~88%) le come a la imagen.
   El z-index:auto del .wrap NO es cosmetico: `.band > .wrap` trae z-index:2, o
   sea contexto de apilado, y el blend solo se mezcla con lo que se pinta
   adentro. Sin eso el papel del collage vuelve a salir en blanco.
   Pintarle el fondo al wrap —el truco de Expansion— aca no sirve: ese wrap es
   de ancho completo y este mide 1240px, asi que el fondo taparia el grano de
   papel solo en esa franja y quedaria un rectangulo mas limpio en el medio de
   la seccion. Soltando el contexto, el blend llega al fondo de la SECCION.
   Lo unico que cambia es que el grano (.grain::before, z-index:1) pasa a
   pintarse encima del contenido en vez de abajo: es un 5% de ruido en multiply
   pensado justamente para ir sobre la seccion. */
.territory-2 .wrap{z-index:auto}
.territory-2 .territory__foto--still{
  mix-blend-mode:multiply;
  filter:brightness(1.08) saturate(1.03);
  /* La caja es la MISMA que la de la composicion de Expansion 2 (697x897 y el
     mismo tope de ancho), asi que las dos se dibujan a la misma altura en
     cualquier viewport: las dos secciones tienen grillas identicas.
     La imagen no se recorta ni se deforma para entrar — llena el alto de la
     caja y, siendo su proporcion un 3% mas ancha (1122x1402 contra 697x897),
     asoma ese 3% a la derecha, sobre el margen que deja el contenedor. */
  grid-column:2;justify-self:start;margin-right:0;
  /* el minimo automatico de una pista fr es el min-content del item, y adentro
     hay una imagen con width:auto: sin este 0 la columna se estira al ancho
     nativo del archivo y se come la del texto. */
  min-width:0;
  width:100%;max-width:697px;
  aspect-ratio:697/897;
}
.territory-2 .territory__foto--still img{height:100%;width:auto;max-width:none}
/* en movil la grilla es de una columna: la foto vuelve al flujo normal */
@media (max-width:860px){
  .territory__foto{display:block}
}
/* ============================== GALERIA (reutilizable) ============================== */
/* slider con scroll-snap nativo: swipe/scroll funciona sin JS. El JS (ver
   interactions/gallery.ts) solo suma flechas + puntos y sincroniza cual esta a la vista. */
.gallery{position:relative}
.gallery__track{
  display:flex;overflow-x:auto;scroll-snap-type:x mandatory;
  border-radius:var(--r-photo);
  scrollbar-width:none;-ms-overflow-style:none;
}
.gallery__track::-webkit-scrollbar{display:none}
.gallery__slide{flex:0 0 100%;scroll-snap-align:start;aspect-ratio:3/4}
.gallery .gallery__slide img{width:100%;height:100%;object-fit:cover;display:block}
/* fila de controles debajo de la foto: estatica, siempre visible, en verde de
   acento. Hoy solo la usa el slider del lightbox — territorio y expansion van
   sin flechas. */
.gallery__controls{
  display:flex;justify-content:center;align-items:center;gap:2rem;
  margin-top:.9rem;
}
.gallery__arrow{
  position:static;
  width:4rem;height:4rem;display:flex;align-items:center;justify-content:center;
  background:none;border:0;color:var(--grass);cursor:pointer;padding:0;
  transition:color var(--dur) var(--ease),transform var(--dur) var(--ease);
}
.gallery__arrow:hover{color:var(--pine-deep);transform:scale(1.15)}
.gallery__arrow svg{width:2.2rem;height:auto;display:block}
.gallery__arrow--prev svg{transform:rotate(90deg)}
.gallery__arrow--next svg{transform:rotate(-90deg)}
@media (prefers-reduced-motion:reduce){
  .gallery__track{scroll-behavior:auto}
  .gallery__arrow{transition:none}
}
/* ============================== VINO INTRO (03c) ============================== */
/* Video a sangre, pantalla completa. Lo pinea ScrollTrigger y el scroll lo va
   avanzando cuadro a cuadro; despues suben tres planos fijos. Ver animations/vino-intro.ts.
   Sin .grain: la textura de papel no tiene sentido sobre un video, y su
   ::before en multiply lo apagaria. */
.vino-intro{
  position:relative;overflow:hidden;background:var(--night);
  min-height:100vh;min-height:100dvh;
  padding:0;
}
.vino-intro__video{
  position:absolute;inset:0;z-index:1;width:100%;height:100%;
  object-fit:cover;object-position:center;
}
/* el remate: mismo encuadre que el ultimo cuadro del video, pero retocado y con
   mas resolucion. Arranca invisible y lo funde el scroll. */
.vino-intro__still{
  position:absolute;inset:0;z-index:2;width:100%;height:100%;
  object-fit:cover;object-position:center;
  opacity:0;will-change:opacity;
}
/* los planos que suben. Comparten caja y encuadre con el video y con la beauty
   para que el apilado sea exacto. El desplazamiento lo escribe GSAP (nunca el
   CSS: el transform computado vuelve en pixeles y no round-trip-ea con
   yPercent). Sin z-index propio: van todos en 2 y el orden del DOM apila. */
.vino-intro__slide{
  position:absolute;inset:0;z-index:2;width:100%;height:100%;
  object-fit:cover;object-position:center;
  will-change:transform;
}
.vino-intro__scrim{
  position:absolute;inset:0;z-index:3;
  background:linear-gradient(180deg, rgba(12,14,9,.22) 0%, rgba(12,14,9,.10) 45%, rgba(10,12,8,.30) 100%);
}
/* CTA abajo a la izquierda, a la misma linea de base que la invitacion a
   scrollear de la derecha: nunca coexisten, pero compartir la base hace que el
   segundo se lea como el relevo del primero.
   Arranca con visibility:hidden y no solo opacity:0 — un link invisible pero
   presente se puede clickear y recibe foco. GSAP lo enciende con autoAlpha. */
.vino-intro__cta{
  position:absolute;z-index:5;
  left:clamp(1.5rem,4vw,4rem);
  bottom:clamp(1.5rem,3.5vw,3rem);
  opacity:0;visibility:hidden;
  display:flex;flex-direction:column;align-items:flex-start;gap:.85rem;
}
/* el nombre del vino en la display del sitio, apilado en tres lineas. */
.vino-intro__cta-title{
  margin:0;
  font-family:var(--f-display);font-size:1rem;font-weight:400;
  line-height:1.15;letter-spacing:.06em;text-transform:uppercase;color:var(--card);
}
.vino-intro__cta-title span{color:var(--raspberry-deep)}
/* texto subrayado en vez de boton con recuadro: sobre el video un rectangulo
   competia con los planos. Peso 400 real — Courier Prime solo trae 400 y 700,
   asi que un 600 lo sintetizaba el navegador. El aire lo da el tracking. */
.vino-intro__cta-link{
  font-family:var(--f-mono);font-size:.66rem;font-weight:400;
  letter-spacing:.2em;text-transform:uppercase;color:var(--card);
  text-decoration:underline;text-underline-offset:.55em;text-decoration-thickness:.5px;
  opacity:.85;
  transition:opacity var(--dur) var(--ease);
}
.vino-intro__cta-link:hover,.vino-intro__cta-link:focus-visible{opacity:1}
/* invitacion a scrollear, abajo a la derecha. Por encima del scrim, que esta
   justamente para que se lea sobre el video. */
.vino-intro__hint{
  position:absolute;z-index:4;
  right:clamp(1.5rem,4vw,4rem);
  bottom:clamp(1.5rem,3.5vw,3rem);
  width:clamp(75px,7.3vw,107px);height:auto;display:block;
  pointer-events:none;overflow:visible;
}
.vino-intro__hint-txt{font-family:var(--f-mono);font-size:2.8px;fill:var(--card)}
.vino-intro__hint-arrow{fill:var(--card)}
/* Mismo ritmo que la flecha del hero, con keyframe propio: adentro de un SVG
   las unidades son las del viewBox (12.97 de alto aca), asi que los 10px del
   hero sacarian la flecha del cuadro. 1.5 unidades son los mismos ~7px.
   Anima `translate` y no `transform`: GSAP escribe transform en el <svg>. */
@keyframes hint-arrow-bounce{
  0%,70%,100%{translate:0 0}
  78%{translate:0 1.5px}
  86%{translate:0 0}
  92%{translate:0 .6px}
  97%{translate:0 0}
}
@media (prefers-reduced-motion:no-preference){
  .vino-intro__hint-arrow{animation:hint-arrow-bounce 3s cubic-bezier(.4,0,.2,1) infinite}
}
/* ====================== COSECHA (04) — FICHA DENTRO DEL VIDEO ====================== */
/* La ficha dejo de ser un modal: es una capa mas de .vino-intro, y el mismo
   scroll que avanza el video la trae. Entra deslizando desde la izquierda
   cuando el video llega al ultimo cuadro y despues los planos que suben la
   tapan — por eso comparte z-index con ellos y va antes en el DOM.
   El scrim (z-3) queda por encima de todo esto, asi que la timeline lo apaga
   mientras la ficha esta a la vista: un degradado oscuro sobre papel la
   ensuciaria, y con la ficha tapando la pantalla no hay nada que oscurecer. */
.vino-intro__ficha{
  position:absolute;inset:0;z-index:2;
  display:flex;align-items:center;overflow:hidden;
  /* el nav es fixed con z-index:40: se le suma su alto al padding superior
     para que el titulo no le quede debajo. */
  padding:calc(var(--nav-h) + clamp(2rem,4vw,3.5rem)) clamp(1.25rem,3vw,2.5rem) clamp(1.5rem,3vw,3rem);
  background:var(--paper);color:var(--pine);
}
/* El desplazamiento lo escribe GSAP y nunca el CSS (el transform computado
   vuelve en pixeles y no round-trip-ea con yPercent), pero entre que parsea el
   HTML y arranca la timeline la ficha taparia el video en blanco: la opacidad
   la tapa mientras tanto, y GSAP la enciende ya corrida fuera de cuadro.
   Solo de 861 para arriba: abajo no hay pin ni timeline que la encienda. */
@media (min-width:861px){ .js .vino-intro__ficha{opacity:0} }
/* la ficha entra completa en un viewport de 760px de alto; abajo de eso se
   recorta contra overflow:hidden. Se le saca el aire, que es lo unico que
   sobra: la grilla no tiene de donde ceder. */
@media (min-width:861px) and (max-height:720px){
  .vino-intro__ficha{
    padding-top:calc(var(--nav-h) + .75rem);
    padding-bottom:.75rem;
  }
}
.vino-intro__ficha > .wrap{width:100%}

/* Sin JS no hay pin ni timeline: la seccion vuelve a ser alto natural y la
   ficha se lee como un bloque mas, debajo del video. Lo mismo en movil, donde
   toda la secuencia de scroll esta desactivada (ver animations/vino-intro.ts: DESKTOP). */
@media (max-width:860px){
  .vino-intro{height:auto}
  .vino-intro__video,
  .vino-intro__still,
  .vino-intro__slide,
  .vino-intro__scrim{height:100vh;height:100svh;bottom:auto}
  .vino-intro__ficha{position:relative;inset:auto;margin-top:100vh;margin-top:100svh}
}
html:not(.js) .vino-intro{overflow:visible;height:auto}
html:not(.js) .vino-intro__video,
html:not(.js) .vino-intro__still,
html:not(.js) .vino-intro__slide,
html:not(.js) .vino-intro__scrim{height:100vh;height:100svh;bottom:auto}
html:not(.js) .vino-intro__ficha{position:relative;inset:auto;margin-top:100vh;margin-top:100svh}

/* grilla editorial con reglas — botella grande a la izquierda (ocupa toda la
   columna), texto arriba a la derecha, ficha tecnica debajo del texto. */
.harvest__texture{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:url("/_astro/textura-paper.CmZDEQGl.webp") center/cover no-repeat;
  mix-blend-mode:multiply;opacity:.4;
}
.harvest-grid{
  position:relative;display:grid;
  grid-template-columns:1fr 1.15fr;
  grid-template-areas:
    "photo text"
    "photo data";
}
.harvest-grid::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  border:1.4px solid var(--pine-ink);mix-blend-mode:multiply;filter:url(#stampRough);
}
.harvest-grid__photo{
  grid-area:photo;position:relative;display:flex;align-items:center;justify-content:center;
  padding:clamp(1rem,1.6vw,1.4rem);
}
/* la regla que separa la botella del texto */
.harvest-grid__photo::after{
  content:"";position:absolute;top:0;right:0;bottom:0;width:1.4px;
  background:var(--pine-ink);mix-blend-mode:multiply;filter:url(#stampRough);
}
.harvest-grid__text{
  grid-area:text;padding:clamp(1rem,1.6vw,1.4rem);border-bottom:1px solid var(--pine-ink);
  mix-blend-mode:multiply;filter:url(#stampRough);
  position:relative;
}
/* la medida de lectura, igual que en territorio y expansion. Va sobre los hijos
   y no sobre la celda porque la celda tiene que seguir ocupando su columna
   entera: es el hueco que sobra a la derecha el que le da lugar al sello. */
.harvest-grid__text .title,
.harvest-grid__text .lede{max-width:420px}
.harvest-grid__text .lede{margin-top:1rem}
/* sello en la esquina superior derecha del bloque, arriba de la ficha tecnica
   (que es el grid-area de abajo). Ya no centrado contra todo el alto del
   bloque: con los 4 parrafos que agrego el texto eso lo mandaba a la mitad
   de la bajada — anclado arriba queda a la altura del titulo, como el resto
   del sitio espera de un sello. */
.harvest-grid__text .harvest__stamp{
  position:absolute;z-index:2;pointer-events:none;
  top:clamp(.5rem,2vw,1.2rem);right:clamp(.5rem,2vw,1.2rem);
  width:clamp(76px,8vw,104px);height:auto;display:block;
  mix-blend-mode:multiply;
}
/* "La primera expresion" en una sola linea, achicada para entrar comoda sin
   toparse con el sello — que ahora vive en este mismo bloque, arriba a la
   derecha. Clamp mas chico que el de --fs-title: a los 861px del breakpoint
   angosto el sello deja poco margen a la derecha. */
@media (min-width:861px){
  #cosecha .harvest-grid__text .title{
    max-width:480px;white-space:nowrap;
    font-size:clamp(1.55rem, 0.75rem + 1.55vw, 2.3rem);
  }
}
.harvest-grid__data{grid-area:data;display:flex;align-items:stretch}
.harvest-grid__data .ficha{flex:1}

/* la botella: copia fotografica pegada sobre la ficha. z-index:2 para quedar
   sobre el borde estampado de la grilla, que si no la taparia.
   320 y no 360: la celda de la foto es la que define el alto de TODA la grilla
   (las filas de texto se estiran para acompaniarla), asi que bajar la botella
   achica el rectangulo y de paso se lleva el aire muerto bajo el parrafo. */
.wine-print{
  position:relative;z-index:2;margin:0;
  width:min(320px,70vw);aspect-ratio:.573;
  padding:12px 24px 40px;
  display:flex;align-items:center;justify-content:center;
}
/* la sombra la pone el filtro, no viene quemada en el archivo — y tanto la
   foto vieja como la nueva "ajustada" llegan con la botella pegada al borde
   derecho e inferior del PNG (sin margen transparente ahi), asi que el
   colchon para que el filtro no se corte contra el overflow:hidden del panel
   (#cosecha es un .vino-intro__ficha) tiene que salir de este padding, no de
   la imagen. 40px abajo por el offset-y de 16px + blur de 20px del filtro. */
.wine-print__img{
  width:auto;height:100%;max-width:100%;display:block;
  filter:drop-shadow(0 16px 20px rgba(60,54,44,.20));
}

@media (max-width:860px){
  .harvest-grid{grid-template-columns:1fr;grid-template-areas:"photo" "text" "data"}
  /* apilado: la regla pasa de vertical (al costado) a horizontal (abajo) */
  .harvest-grid__photo::after{top:auto;left:0;right:0;bottom:0;width:auto;height:1.4px}
}


/* ficha tecnica — efecto sello lineal, ficha de producto con reglas */
/* sello de goma: sin relleno, tinta al 60-85%, apenas desplazada por un filtro
   de rugosidad — la ficha se comporta como una marca estampada sobre el papel,
   no como una tarjeta con fondo propio. */
.ficha{
  margin-top:2.2rem;background:transparent;border:1.4px solid var(--pine-ink);
  mix-blend-mode:multiply;filter:url(#stampRough);
}
.ficha--embedded{margin-top:0;border:0;width:100%}
.ficha__row{border-bottom:1px solid var(--pine-ink);padding:.6rem 1.1rem}
.ficha__row:last-child{border-bottom:0}
.ficha__row--split{display:grid;grid-template-columns:1fr 1fr;padding:0}
.ficha__row--split .ficha__cell{padding:.6rem 1.1rem}
.ficha__row--split .ficha__cell:first-child{border-right:1px solid var(--pine-ink)}
/* --split-3: mismo mecanismo que --split pero a tres columnas, para datos
   cortos (grado, pH, acidez) que no justifican una fila cada uno. */
.ficha__row--split-3{display:grid;grid-template-columns:1fr 1fr 1fr;padding:0}
.ficha__row--split-3 .ficha__cell{padding:.6rem 1.1rem}
.ficha__row--split-3 .ficha__cell:not(:last-child){border-right:1px solid var(--pine-ink)}
.ficha__cell{display:flex;flex-direction:column;gap:.2rem}
/* --3-1: la fila del nombre no se parte por la mitad como el resto. "Santonovo
   di Sopra" necesita el ancho; la aniada son cuatro cifras y con un cuarto le
   sobra. */
.ficha__row--3-1{grid-template-columns:3fr 1fr}
.ficha__label{display:block;font-family:var(--f-mono);font-size:.68rem;font-weight:600;letter-spacing:.36em;text-transform:uppercase;color:var(--pine);margin-bottom:.25rem}
.ficha__value{font-family:var(--f-craft);font-size:1.15rem;font-weight:400;text-transform:uppercase;color:#2B2B2B;letter-spacing:.01em}
.ficha__value--lg{font-size:1.35rem}
.ficha__value--small{font-family:var(--f-craft);font-size:.78rem;font-weight:400;letter-spacing:.08em;text-transform:uppercase;color:var(--pine)}
.ficha__value b{color:var(--raspberry);font-weight:400}
/* menos aire que el resto de las filas: son dos lineas de texto chico y con el
   padding general quedaba una franja demasiado alta al pie de la ficha. */
.ficha__row--foot{text-align:center;padding-block:.45rem}
.ficha__row--foot .ficha__value--small{line-height:1.4}

@media (max-width:640px){
  .ficha__row--split,
  .ficha__row--split-3,
  .ficha__row--3-1{grid-template-columns:1fr}
  .ficha__row--split .ficha__cell:first-child{border-right:0;border-bottom:1px solid var(--pine-soft)}
  .ficha__row--split-3 .ficha__cell:not(:last-child){border-right:0;border-bottom:1px solid var(--pine-soft)}
}

/* ============================== EXPANSION (05) ============================== */
.expansion .wrap{
  display:grid;grid-template-columns:1fr 1fr;gap:clamp(2.5rem,6vw,5rem);align-items:stretch;
  /* medida de lectura de la columna de texto. Vive en una variable porque el
     margen de la foto se calcula CONTRA ella: si cambia una, la otra sigue. */
  --measure:420px;
}
/* el margen izquierdo iguala las dos separaciones: la del borde izquierdo del
   viewport a la foto, y la del texto al borde derecho.
   Por que calc(100% - measure): el % de un margen se resuelve contra el ancho
   del area de grilla, o sea contra la columna. El texto termina a C+gap+measure
   del borde interno izquierdo y le sobran C-measure hasta el derecho — ese
   mismo valor es el que hay que meterle a la foto.
   max(0px,...) porque abajo de ~1100px la cuenta da negativo. */
/* no crece con la grilla: se queda en la medida de lectura fija. */
.expansion__col{grid-column:2;max-width:var(--measure)}
.expansion__col .title{margin-top:1rem}
.expansion__col .lede{margin-top:1.6rem}

/* --- fotos de Territorio y Expansion a la altura de su columna de texto --- */
/* .sub es el ultimo elemento de las dos columnas, asi que "alto de la columna"
   equivale a "hasta el borde inferior de .sub".
   SIN height:100% en la figura, a proposito: en un grid item una altura
   explicita CANCELA el align-items:stretch (stretch solo actua si el tamanio
   transversal es auto), y ese 100% se resolveria contra una fila de alto auto
   — o sea contra nada, y el track colapsaba.
   El alto se lo da el stretch de la fila; adentro lo reparte flex, que si deja
   una altura definida contra la cual el 100% del slide resuelve bien. */
.territory__foto{display:flex;flex-direction:column;align-self:stretch}
/* --still: una imagen sola en vez del slider. No se estira a la altura de la
   columna: es una composicion armada, deformarla la rompe. */
.territory__foto--still{display:block;align-self:center}
.territory__foto--still img{width:100%;height:auto;display:block;border-radius:var(--r-photo)}

/* ---- Expansion 2: texto a la izquierda, composicion a la derecha ---- */
/* Misma construccion que Territorio y Estate, con los mismos tokens (el gap y
   la medida de lectura ya vienen de .expansion .wrap): el texto termina contra
   el gap y la composicion arranca del otro lado.
   El z-index:auto del .wrap NO es cosmetico: `.band > .wrap` trae z-index:2, o
   sea contexto de apilado, y el multiply de abajo solo se mezcla con lo que se
   pinta adentro. Sin eso el papel del collage vuelve a salir en blanco.
   Pintarle el fondo al wrap no sirve: mide 1240px y el grano de papel se veria
   solo afuera, marcando un rectangulo en el medio de la seccion. Soltando el
   contexto, el blend llega al fondo de la SECCION, que es de ancho completo —
   a cambio el grano (.grain::before, z-index:1) se pinta encima del contenido
   en vez de abajo, que es un 5% de ruido en multiply pensado para eso. */
/* La composicion entra desplazandose de costado (ver animations/expansion.ts), asi que
   arranca fuera de cuadro: sin este recorte son 35px de scroll horizontal en
   telefono — el defecto que mas ensucia una web en movil. */
.expansion-2{overflow-x:clip}
/* unico hijo directo de la seccion: .band--full pone la seccion en flex y
   sin este contenedor las DOS filas (.wrap de arriba + .enologo) quedarian
   una al lado de la otra en vez de apiladas — el flex-row las trataria como
   dos items en la misma fila. Adentro, las dos .wrap vuelven al flujo de
   bloque normal (una debajo de otra) y cada una arma su propia grilla de
   2 columnas por separado. width:100% porque es este div, y no las .wrap
   de adentro, el que ahora recibe el ancho completo que .band--full > .wrap
   le daria a una fila unica. */
.expansion-2__rows{width:100%}
.expansion-2 .wrap{align-items:center;z-index:auto}
.expansion-2 .expansion__col{
  grid-column:1;
  margin-left:max(0px, calc(100% - var(--measure)));
}
/* El papel del collage es blanco y multiply lo vuelve transparente sobre el
   sage: las fotos quedan impresas sobre el mismo papel de la seccion, sin
   recorte ni mascara. El brillo compensa lo que multiplicar por el verde
   (E1E6D6, ~88%) le come a las fotos. */
.expansion__collage{
  margin:0;
  /* el minimo automatico de una pista fr es el min-content del item, y con una
     imagen adentro eso es su ancho NATIVO: sin este 0 la grilla se pasa del
     viewport en cuanto la columna es mas angosta que la foto. */
  min-width:0;
  mix-blend-mode:multiply;
  filter:brightness(1.06) saturate(1.04);
}
.expansion__collage img{width:100%;height:auto;display:block}
/* arranca contra el gap y no crece mas alla de su ancho nativo: escalarla por
   encima de 697px solo la ablanda. */
.expansion__collage--right{grid-column:2;justify-self:start;width:100%;max-width:697px}

@media (max-width:860px){
  .expansion .wrap{grid-template-columns:1fr}
  .expansion__col,
  .expansion__collage{grid-column:auto}   /* si no, crearian una segunda columna */
  .expansion-2 .expansion__col{margin-left:0}
  /* stretch y no center: con center (o con width auto) la figura se dimensiona
     a max-content, o sea al ancho nativo de la foto. */
  .expansion__collage{justify-self:stretch;width:auto;max-width:340px;margin-inline:auto}
  /* en movil la foto vuelve al flujo normal (le gana al display:flex de
     arriba, que no es por breakpoint) */
  .territory__foto{display:block}
}

/* ============================== DIPTICO (05c) ============================== */
/* Base: los dos planos apilados en el flujo, a sangre y con su proporcion
   nativa (1672x941), sin recorte. Es lo que se ve en movil, sin JS y con
   movimiento reducido — o sea siempre que no haya scroll que los apile. */
.diptych{position:relative;padding:0;overflow:hidden}
.diptych__slide{width:100%;height:auto;display:block;aspect-ratio:1672/941;object-fit:cover}

/* Con JS, en desktop y con movimiento normal: la seccion pasa a ser una
   ventana de una pantalla y los dos planos comparten caja, uno encima del
   otro. El desplazamiento lo escribe GSAP (ver animations/diptych.ts); aca solo se
   arma el apilado. Sin .js la regla no aplica y el segundo plano no puede
   quedar tapando al primero para siempre. */
/* De 861 para arriba el diptico NO es un carrusel: los dos planos se apilan y
   el scroll los va tapando (ver animations/diptych.ts). El track se vuelve transparente
   con display:contents para que las reglas de posicion sigan aplicando sobre
   los <img> como si fueran hijos directos, y los puntos se esconden. */
@media (min-width:861px){
  .diptych .gallery__track{display:contents}
  .diptych .gallery__dots{display:none}
}

@media (min-width:861px) and (prefers-reduced-motion:no-preference){
  .js .diptych{height:100vh;height:100svh}
  .js .diptych__slide{
    position:absolute;inset:0;
    width:100%;height:100%;aspect-ratio:auto;
    object-position:center;will-change:transform;
  }
}

/* ============================== ESTATE (06) ============================== */
/* Misma construccion que Territorio: texto a la izquierda contra el gap,
   composicion a la derecha del otro lado. Los mismos tokens (gap y medida de
   lectura) para que la separacion imagen/texto sea la misma en las tres
   secciones que comparten esta grilla. */
.estate{position:relative}
.estate .wrap{
  display:grid;grid-template-columns:1fr 1fr;gap:clamp(2.5rem,6vw,5rem);align-items:center;
  position:relative;z-index:2;
  --measure:420px;
}
.estate__col{
  max-width:var(--measure);
  margin-left:max(0px, calc(100% - var(--measure)));
}
.estate__col .eyebrow{margin-top:1rem}
.estate__col .lede{margin-top:1.8rem}
.estate__col .btn{margin-top:2.2rem}
/* centrado bajo el cierre (.sub). Como bloque, su margen colapsa con el del .sub
   en vez de sumarse: por eso el margin-top ya trae los 19.8px (1.1em de 18px)
   que antes se apilaban, y el hueco vertical queda igual. En movil (<=860px)
   manda la regla de .btn de ese bloque. */
@media (min-width:861px){
  .estate__col .btn{display:block;width:fit-content;margin:calc(2.2rem + 19.8px) auto 0}
}

/* Arranca contra el gap, igual que el texto del otro lado. Mas ancha que las
   fotos de Territorio y Expansion (480 contra 400) porque es cuadrada: al
   mismo ancho se veria mas chica que ellas, no igual. */
.estate__foto{margin:0;max-width:480px;justify-self:start}
.estate__foto img{width:100%;height:auto;display:block}

@media (max-width:860px){
  .estate .wrap{grid-template-columns:1fr;gap:2.4rem}
  /* se queda con la medida de lectura, como Territorio y Expansion en movil:
     a 860px de ancho una linea a todo lo largo pasa los 90 caracteres. */
  .estate__col{margin-left:0}
  .estate__foto{max-width:340px;justify-self:center}
}

/* ============================== ENOLOGO (05b-ii) ============================== */
/* Segunda fila de Expansion 2, no seccion aparte: el .wrap ya hereda
   display:grid + grid-template-columns + gap + --measure de ".expansion .wrap"
   (selector generico, cualquier .wrap adentro de .expansion) y align-items:
   center de ".expansion-2 .wrap" — no hace falta repetirlos aca, solo el
   espacio contra la fila de arriba y las dos columnas propias.
   Espejada contra esa fila de arriba: alla el texto va contra el gap
   izquierdo y la composicion contra el derecho; aca la foto va contra el
   izquierdo y el texto contra el derecho. Por eso foto == misma cuenta que
   .expansion__foto (margin-left empuja la caja contra el borde derecho de
   la columna 1) y texto == misma cuenta que .expansion__col original
   (grid-column:2, sin margen: el max-width ya la deja pegada al borde
   izquierdo de la columna 2, o sea contra el mismo gap del otro lado). */
.enologo{margin-top:clamp(3rem,6vw,5rem)}
/* OCULTA a pedido: la fila del enologo no se muestra por ahora. El HTML sigue
   en Expansion2.astro (no se borro): para volver a mostrarla alcanza con borrar esta
   regla. Es display:none y no el atributo hidden porque ".expansion .wrap" le
   fija display:grid y le ganaria al hidden; con tres clases tampoco depende
   del orden en el archivo. */
.expansion-2 .wrap.enologo{display:none}
.enologo__col{grid-column:2;max-width:var(--measure)}
.enologo__col .title{margin-top:1rem}
.enologo__col .lede{margin-top:1.6rem}
/* collage (foto + inset de las botas sobre la loma, papel rasgado y cinta
   ya dibujados adentro del archivo), no una foto suelta: mismo tratamiento
   que .expansion__collage — multiply para que el papel blanco del archivo
   se sume al de la seccion, y el mismo brightness/saturate para compensar
   lo que el verde sage le come al multiplicar. Sin aspect-ratio ni
   object-fit: es una composicion armada, recortarla la rompe — se muestra
   entera, a su proporcion nativa (1002x1448). position:relative porque el
   epigrafe de abajo cuelga de esta figura. */
.enologo__foto{
  grid-column:1;margin:0;max-width:460px;min-width:0;position:relative;
  margin-left:max(0px, calc(100% - var(--measure)));
  mix-blend-mode:multiply;filter:brightness(1.06) saturate(1.04);
}
/* combinador > y no descendiente: adentro de esta figura hay OTRO <img>, el
   sello — sin el > esta regla (mas especifica que la de .enologo__stamp, por
   ser clase+etiqueta) lo estiraria a todo el ancho de la figura. */
.enologo__foto > picture > img{width:100%;height:auto;display:block}
/* el sello (copilla.svg, ya coloreado pino en el archivo): mismo gesto que
   los iconos de Bosque 2 estampados sobre sus fotos, aca estatico y sin la
   animacion de trazo (no hay scroll pineado en esta seccion que la sostenga).
   right negativo lo saca del lado derecho de la figura, asomando afuera del
   borde de la foto en vez de pisarlo hacia adentro; height fijo en px (y no
   solo el 17% de ancho) porque a este tamano el alto es lo que importa
   mantener estable entre las tres columnas de --measure distintas. */
.enologo__stamp{
  position:absolute;z-index:1;right:-22%;top:65%;translate:0 -50%;
  width:17%;height:auto;pointer-events:none;
  height:120px !important;
}
/* el epigrafe va escrito DIRECTO sobre el papel en blanco que esta version
   de la composicion deja al pie (de ~72% a ~94% del alto) — no es un trozo
   de papel aparte pegado despues, es texto sobre el mismo papel de la foto.
   Firma en miniatura: mismo par titulo+bajada que .enologo__col de al lado
   (nombre en la display, rol en la craft), solo que mas chico para entrar
   en el hueco de la foto — no una tercera tipografia nueva. */
.enologo__epigraph{
  position:absolute;left:10%;right:10%;top:70%;bottom:5%;z-index:1;
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:.3rem;text-align:center;
}
.enologo__epigraph-name{
  font-family:var(--f-display);font-weight:400;text-transform:uppercase;
  color:var(--pine);letter-spacing:-.005em;line-height:1.05;
  font-size:33px;
}
.enologo__epigraph-role{
  font-family:var(--f-craft);font-weight:600;text-transform:uppercase;
  color:var(--raspberry-deep);letter-spacing:.12em;
  font-size:clamp(.68rem, .62rem + .16vw, .78rem);
}
/* el reflow de movil (una columna, foto entre el eyebrow y el cuerpo, misma
   canaleta de 20px) se resuelve junto con Territorio/Expansion/Estate en el
   bloque compartido @media(max-width:860px) mas abajo — es la misma
   construccion (columna de texto + una sola foto) y separarla duplicaria las
   mismas siete reglas. El epigrafe en movil se resuelve ahi mismo. */
/* ============================== CIERRE (07) ============================== */
.closing{text-align:center;overflow:hidden}
/* El fondo pasa a ser un video. El degradado se separa en su propia capa: en
   un background podia apilarse sobre la imagen, sobre un <video> no. Mismos
   valores que tenia, asi el texto claro se lee igual que antes. */
.closing__video{
  position:absolute;inset:0;z-index:0;pointer-events:none;
  width:100%;height:100%;object-fit:cover;object-position:center;display:block;
}
.closing__scrim{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg, rgba(15,16,11,.42) 0%, rgba(13,14,10,.58) 55%, rgba(9,10,7,.76) 100%);
}
/* el contenido, por encima de las dos capas */
.closing .wrap{position:relative;z-index:2}
.closing .display{margin-bottom:1.2rem}
/* el titular del cierre va mas chico que el --fs-hero de .display */
.closing__copy .display{font-size:clamp(1.8rem,1.5rem + 1.8vw,3rem)}
.closing__copy .eyebrow{justify-content:center;display:flex}
.closing__actions{display:flex;justify-content:center;gap:1.2rem;margin-top:2.6rem;flex-wrap:wrap}
/* ====================== SECUENCIA DE ENTRADA (.reveal-seq) ====================== */
/* La misma mascara del logo del hero, generalizada a todos los bloques de
   texto del sitio. El orden dentro de cada bloque es siempre el mismo:
     1. el titulo entra con mascara — una linea sube, la siguiente baja
     2. el eyebrow funde a .95s, cuando la mascara ya termino
     3. el cuerpo de texto (y botones) funde a 1.15s
   Las lineas del titulo las arma animations/reveal-seq.ts partiendo por <br>: son 7 titulos con
   saltos distintos, y hacerlo a mano en el HTML era mas markup y mas
   posibilidades de romper algo que diez lineas de JS.
   Todo cuelga de .js en <html> (lo pone el script inline del <head>): sin JS nada se
   oculta y el texto se lee igual. */
.mask-reveal{display:block}
/* cada linea es una ventana con overflow:hidden y adentro un span que desliza.
   El padding-block es por el recorte: .display va con line-height:.94 y .title
   con 1.05, muy ajustados, y sin ese aire la mascara comeria colas y acentos
   (la Q de "QUE", la E de "RECIEN"). El margin-block negativo lo devuelve, asi
   el interlineado no cambia. Por eso el translate es 120% y no el 101% del
   hero: la caja recortada es mas alta que el texto y con 101% asomaria. */
.mask-reveal__line{display:block;overflow:hidden;padding-block:.12em;margin-block:-.12em}
.mask-reveal__line > span{display:block}

/* Lo unico que declara el CSS es que los bloques arrancan invisibles. La
   posicion fuera de cuadro de cada linea y toda la animacion las escribe GSAP
   (animations/reveal-seq.ts) — un solo duenio por propiedad.
   Cuelga de .js, que esta en <html> desde el primer cuadro: sin JS no se oculta nada y el
   sitio se lee igual. */
.js .reveal-seq > *{opacity:0}
/* ============================== FOOTER ============================== */
.site-footer{position:relative;overflow:hidden;background:var(--paper-deep)}
.site-footer small{font-size:.75rem;color:var(--charcoal);letter-spacing:.02em}

.site-footer__grid{
  display:grid;grid-template-columns:1fr auto 1fr;align-items:center;
  padding:clamp(3rem,6vw,5rem) 0;gap:clamp(1.5rem,4vw,3rem);
}
.site-footer__col{position:relative;z-index:2;padding:0 clamp(1rem,3vw,2.4rem)}
.site-footer__nav{
  border-right:1px solid var(--pine-soft);
  display:flex;flex-direction:column;align-items:flex-start;gap:.95rem;
}
/* misma mono que el menu de arriba (Courier Prime): heredaban --f-body y
   quedaban en Work Sans. El tracking sube a .2em como en .nav__links — una
   mono en caja alta necesita mas aire que una sans para respirar igual. */
.site-footer__nav a{
  font-family:var(--f-mono);
  font-size:.76rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  text-decoration:none;color:var(--pine);transition:color var(--dur) var(--ease);
}
.site-footer__nav a:hover,.site-footer__nav a:focus-visible{color:var(--raspberry-deep)}

.site-footer__seal{
  border-right:1px solid var(--pine-soft);
  display:flex;flex-direction:column;align-items:center;gap:1rem;text-align:center;
}
/* el iso de cuore reemplaza al sello dibujado con SVG (aros + tipografia
   circular + marca al centro). Ya es un lockup cerrado en si mismo, asi que no
   necesita contenedor posicionado ni nada superpuesto encima. */
.seal-mark{width:150px;color:var(--pine)}
.seal-mark__iso{width:100%;height:auto;display:block}
.site-footer__info{text-align:right;display:flex;flex-direction:column;align-items:flex-end;gap:.45rem}
/* el `p{text-align:justify}` global gana por ser una declaracion directa
   sobre el elemento (la herencia del contenedor no alcanza a pisarla), asi
   que si esta linea llega a envolver, la segunda queda pegada a la
   izquierda: se fija aca mismo, sobre el parrafo, no solo en el contenedor. */
.site-footer__info p{margin:0;font-size:.84rem;line-height:1.5;color:var(--charcoal);text-align:right}
.site-footer__info a{color:inherit;text-decoration:none;transition:color var(--dur) var(--ease)}
.site-footer__info a:hover,.site-footer__info a:focus-visible{color:var(--raspberry-deep)}

.site-footer__bottom{border-top:1px solid var(--pine-soft);padding:1.2rem 0;text-align:center}
/* misma mono que los links de arriba. Peso 400 y no 600: es una linea legal,
   tiene que estar disponible sin pedir atencion — y de paso el 600 en Courier
   Prime lo sintetiza el navegador (la hoja trae 400 y 700). */
.site-footer__bottom small{
  font-family:var(--f-mono);font-size:.7rem;font-weight:400;
  letter-spacing:.12em;text-transform:uppercase;color:var(--charcoal);
}

@media (max-width:760px){
  .site-footer__grid{grid-template-columns:1fr}
  .site-footer__nav{border-right:0;border-bottom:1px solid var(--pine-soft);align-items:center;text-align:center;padding-bottom:2rem}
  .site-footer__seal{border-right:0;border-bottom:1px solid var(--pine-soft);padding-bottom:2rem}
  .site-footer__info{align-items:center;text-align:center}
  .site-footer__info p{text-align:center}
}

/* ============================== deco line-art ============================== */
.deco{color:var(--pine);opacity:.9}
.deco--ghost{opacity:.14}

::selection{background:var(--pine);color:var(--paper)}

/* ==================== CAPA MOVIL — LEGIBILIDAD Y DEDO ====================
   Va al final a proposito: son pisos, no variantes de diseno, y tienen que
   ganarle a cualquier regla anterior sin ir a pelear especificidad seccion por
   seccion. Todo lo de aca responde a dos cosas medidas en un telefono real de
   375px: texto por debajo de 16px y objetivos tactiles de 19px de alto. */
@media (max-width:860px){

  /* --- texto --- 16px es el minimo real en telefono, no una preferencia.
     El tracking negativo se va: -1px sobre una mono a 16px cierra las letras
     justo cuando mas separadas tienen que estar. Y el texto justificado abre
     rios blancos en una columna de 45 caracteres — en movil se alinea a la
     izquierda, que es lo unico que funciona a esa medida. */
  p, .lede{
    font-size:1rem;
    letter-spacing:normal;
    text-align:left;
  }

  /* --- objetivos tactiles ---
     La regla es 44px de alto minimo. Estos links median 17 a 19: el texto era
     el objetivo, y hay que apuntarle a la palabra. Ahora la fila entera es
     tocable, que ademas es lo que la gente ya intenta. */
  .site-footer__nav{gap:0}
  .site-footer__nav a{
    display:flex;align-items:center;justify-content:center;
    min-height:44px;width:100%;
    font-size:.82rem;
  }
  .site-footer a[href^="mailto"]{
    display:inline-flex;align-items:center;min-height:44px;
  }
  /* el CTA sobre el video: era 110x17 */
  .vino-intro__cta-link{
    display:inline-flex;align-items:center;justify-content:center;min-height:44px;
    font-size:.78rem;                 /* .66rem daba 10.6px: ilegible */
    text-underline-offset:.35em;
  }
  /* justify-content y no text-align: al volverlos flex para darles los 48px de
     alto, el texto dejo de responder a text-align — en un contenedor flex el
     eje horizontal lo gobierna justify-content. En el footer eso rompio un
     centrado que el diseno ya tenia. */
  .btn{
    min-height:48px;display:inline-flex;align-items:center;justify-content:center;
    font-size:.9rem;
  }

  /* --- anchos: el texto lo mas cerca del borde que se pueda ---
     Canaleta de 20px en vez de 24. En un telefono de 375 esos 8px que se
     recuperan son medida de lectura, no aire: la columna pasa de 327 a 335.
     Se toca el padding y no el max-width de cada bloque porque la canaleta es
     UNA decision, y repetida en cada seccion se desincroniza sola. */
  .wrap,
  .compo,
  .story-reveal__pin-inner{padding-inline:20px}

  /* --- orden de lectura en telefono: titulo, bajada, IMAGEN, texto ---
     En desktop el texto es un bloque al lado de la foto y el orden interno da
     igual. Apilado no: el titulo tiene que abrir, la bajada situar, y la foto
     entrar ANTES del cuerpo — si va al final, el lector se come cinco parrafos
     sin haber visto de que le hablan.
     display:contents disuelve la caja de la columna y sube sus hijos a la
     grilla, que es lo unico que permite meter la foto entre el eyebrow y el
     cuerpo sin tocar el HTML. Efecto lateral bienvenido: al desaparecer la
     caja tambien desaparecen su max-width y sus margenes de escritorio, que
     eran los que dejaban la columna corrida a un lado. */
  .territory .wrap,
  .expansion-2 .wrap,
  .estate .wrap,
  .enologo{grid-template-columns:1fr}

  .territory__col,
  .expansion__col,
  .estate__col,
  .enologo__col{display:contents}

  .territory__col > *,
  .expansion__col > *,
  .estate__col > *,
  .enologo__col > *{order:4}
  .territory__col > .title,
  .expansion__col > .title,
  .estate__col > .title,
  .enologo__col > .title{order:1}
  .territory__col > .eyebrow,
  .expansion__col > .eyebrow,
  .estate__col > .eyebrow,
  .enologo__col > .eyebrow{order:2}
  /* grid-column:auto es obligatorio: las reglas de escritorio las mandan a la
     columna 2, y en una grilla de una sola columna eso CREA una segunda
     columna implicita — era lo que dejaba el texto de Territorio en 165px. */
  .territory-2 .territory__foto--still,
  .expansion__collage,
  .estate__foto,
  .enologo__foto{order:3;grid-column:auto}
  /* el epigrafe ya no necesita entrar aca: vive DENTRO de .enologo__foto
     (superpuesto sobre su propio papel), asi que viaja con la foto sin
     ningun ajuste de grilla propio. */

  /* --- una sola canaleta: 20px, para todo ---
     Las fotos iban a sangre y el texto con margen. Ahora comparten borde: nada
     queda ni mas ni menos separado del filo del telefono.
     Se anulan los anchos y margenes de escritorio de cada figura, que es lo que
     las sacaba de la columna. */
  .territory-2 .territory__foto--still,
  .expansion__collage,
  .estate__foto,
  .enologo__foto,
  .story-banner{
    width:auto;
    max-width:none;
    margin-inline:0;
    aspect-ratio:auto;
  }
  .territory-2 .territory__foto--still img,
  .expansion__collage img,
  .estate__foto img,
  .story-banner img{width:100%;height:auto}
  /* combinador > : sin el, esta regla (misma especificidad que
     .enologo__stamp, y mas tardia en el archivo) le pisaria el 17% de ancho
     al sello y lo estiraria a toda la foto. */
  .enologo__foto > picture > img{width:100%;height:auto}

  /* --- el diptico, como carrusel ---
     Apilados quedaban dos bandas de 189px, demasiado chicas para dos planos
     que son el respiro de la pagina. Con el mismo componente que Vino Intro se
     arrastran a pantalla completa. */
  .diptych{padding-inline:0;height:100svh}
  .diptych .gallery__track{height:100%}
  .diptych .gallery__slide{aspect-ratio:auto;height:100%;width:100%;object-fit:cover}
  .diptych .gallery__dots{
    position:absolute;left:0;right:0;bottom:1.5rem;z-index:4;
    display:flex;justify-content:center;gap:.5rem;
  }

  /* el footer usaba una canaleta propia (16px a 375) */
  .site-footer__col{padding-inline:20px}

  /* Los dos ultimos que se salian de la canaleta: el bloque de texto de Story
     Reveal 2 arrancaba a 46px y la botella de la ficha a 56, cada uno por un
     tope de ancho heredado del escritorio. Se sueltan y quedan al ras de los
     20 como todo lo demas. */
  .story-2 .story-reveal__pin-inner{max-width:none;margin-inline:0;padding-inline:20px}
  /* width:100% y no auto: la botella es item de un contenedor flex, y ahi
     `auto` significa fit-content — se encogia al ancho de la imagen y quedaba
     centrada a 40px del borde en vez de a 20. */
  .wine-print{max-width:none;margin-inline:0;width:100%}

  /* Sin la caja de la columna, cada hijo se estira a la grilla. En telefono es
     justo lo que se quiere (335px, contra los bordes); de 641 para arriba la
     medida de lectura vuelve a topear y el bloque se centra. */
  @media (min-width:641px){
    .territory__col > *,
    .expansion__col > *,
    .estate__col > *,
    .enologo__col > *{max-width:var(--measure);margin-inline:auto;width:100%}
  }

  /* --- ficha tecnica: una sola canaleta ---
     Tenia 40px de margen contra los 20 del resto de la pagina: 20 del panel
     mas 20 del .wrap de adentro, sumados. Y el texto agregaba otros 16 con su
     padding propio, asi que el titulo arrancaba 56px adentro mientras el resto
     del sitio arranca a 20. Se apoya en una sola: la del .wrap.
     El padding vertical del panel se queda — ese si hace falta, es lo que la
     despega del nav fijo. */
  .vino-intro__ficha{padding-inline:0}
  /* El titulo y la bajada se alinean con el TEXTO de las filas de la ficha, no
     con su caja: las filas llevan 1.1rem de padding propio, asi que su texto
     arranca 17.6px mas adentro. Sin esto el bloque de arriba quedaba pegado al
     borde y la tabla de abajo con aire — dos margenes distintos en la misma
     columna. Se copia el mismo valor para que la linea vertical sea una sola. */
  .harvest-grid__text{padding-inline:1.1rem}
  .harvest-grid__photo,
  .harvest-grid__data{padding-inline:0}

  /* El sello estaba absoluto contra el hueco que sobra a la derecha del texto.
     En una columna sin hueco no hay donde apoyarlo: caia encima de la bajada.
     Vuelve al flujo y abre el bloque, que es su otro lugar natural — un sello
     arriba del titulo se lee como lo que es. */
  .harvest-grid__text .harvest__stamp{
    position:static;translate:none;
    width:76px;margin:0 0 1.2rem;
  }
  /* sin hueco a la derecha, la medida de lectura la pone la columna */
  .harvest-grid__text .title,
  .harvest-grid__text .lede{max-width:none}

  /* --- Vino Intro en telefono: carrusel en vez de video ---
     El video avanza cuadro a cuadro con el scroll, y esa secuencia solo corre
     de 861 para arriba (mm.add(DESKTOP)). En telefono quedaba su poster fijo,
     que no cuenta nada. Se reemplaza por dos planos que se arrastran con el
     dedo — un gesto que en un telefono es mas natural que el scroll pineado. */
  /* La invitacion a scrollear no va en telefono: ahi el gesto es obvio —el
     pulgar ya esta sobre el vidrio— y no hay salto de seccion que anunciar,
     porque el retencion del hero es de escritorio. Ademas libera el rincon
     inferior, que en vertical es el mas peleado. */
  .hero__scroll{display:none}

  /* El banner de Historia pasa de apaisado (1920x805, casi 2.4:1) a 3:2. A todo el
     ancho de un telefono el formato original daba una banda de ~140px.
     object-fit recorta por los costados: la ventana va del 33% al 96% del ancho
     de la foto (object-position 90%). Conserva el pico de la loma, las gaviotas, el
     estanque, la ruina y la planta; se pierde el campo arado de la izquierda. */
  .story-banner img{aspect-ratio:3/2;object-position:90% 50%}
  /* El vector se vuelve a calzar contra ese recorte. La caja ahora es la ventana
     33%-96% de la foto, asi que lo que estaba en % del ancho se estira por 1/0.629:
     left = (-3.39% - 33.4%) / 0.629 = -58.50%, width = 99.47% / 0.629 = 158.16%.
     El alto no cambia (la caja sigue midiendo el alto entero de la foto), asi que
     top queda igual. overflow-x:clip corta el tramo de linea que cae a la
     izquierda del recorte y deja pasar lo que sobresale por arriba (gaviotas) y
     por abajo (planta). */
  .story-banner{overflow-x:clip}
  .story-banner::after{left:-58.5%;width:158.16%}

  .vino-intro__video{display:none}
  /* Sin el video, ese margen dejaba 812px de negro.
     El margin-top:100svh de la ficha existia para despejar el video, que iba
     absoluto y no ocupaba lugar en el flujo. Ahora el que ocupa esa pantalla es
     el carrusel, que SI esta en el flujo: el margen pasaba a sumarse en vez de
     reservar, y quedaba una seccion vacia entera entre Territorio y la ficha.
     Y el orden se fuerza porque en el HTML el carrusel va despues de la ficha
     —esta insertado donde vivian los planos del escritorio— pero en telefono
     tiene que abrir la seccion. */
  .vino-intro{display:flex;flex-direction:column}
  .vino-intro__swiper{order:1}
  .vino-intro__ficha{order:2;margin-top:0}
  .vino-intro__swiper{
    position:relative;z-index:1;margin:0;
    width:100%;height:100svh;
  }
  .vino-intro__swiper .gallery__track{height:100%}
  .vino-intro__swiper .gallery__slide{aspect-ratio:auto;height:100%}
  .vino-intro__swiper img{width:100%;height:100%;object-fit:cover;display:block}
  /* La botella esta al 65% del ancho de la foto. Con cover en un contenedor
     vertical el recorte se centra y la dejaba cortada contra el borde derecho:
     de los 1672px originales solo entran ~430 y el centro cae en la vid, no en
     la botella. Corriendo el encuadre al 70% la botella queda entera y
     centrada, y el tronco viejo la sigue acompaniando por la derecha. */
  .vino-intro__swiper .gallery__slide:first-child img{object-position:70% center}
  /* El segundo plano tiene la etiqueta centrada en el 55% del ancho. Con el
     recorte al 50% quedaba cortada por la derecha, justo sobre "SANTONOVO DI
     SOPRA". La etiqueta mide mas que la franja visible, asi que no entra
     entera: el 57% la centra y deja "MONTE SOLARE" completo, que es lo que
     tiene que leerse. */
  .vino-intro__swiper .gallery__slide:nth-child(2) img{object-position:57% center}
  /* los puntos, sobre la foto y por encima del scrim */
  .vino-intro__swiper .gallery__dots{
    position:absolute;left:0;right:0;bottom:1.5rem;z-index:4;
    display:flex;justify-content:center;gap:.5rem;
  }

  /* --- lo que ya no aplica en telefono ---
     La beauty y los planos existen para la secuencia de scroll de escritorio:
     los apila GSAP y los va destapando el pin. En telefono ese bloque no corre
     (es mm.add(DESKTOP)), asi que nadie los coloca fuera de cuadro y quedaban
     los tres al 100% en z-index 2, encima del video — lo que se veia al llegar
     no era el poster del video sino slide-monte02.
     Se ocultan en vez de reposicionarse: sin la secuencia no cuentan nada, y
     asi ademas no se descargan. */
  .vino-intro__still,
  .vino-intro__slide{display:none}

  /* --- mono chica: nada por debajo de 12px --- */
  .site-footer small,
  .vino-intro__cta-title,
  .ficha__label{font-size:.75rem}
}


/* ==================== PULIDO MOBILE ====================
   Ajustes de diagramacion en telefono sobre la capa de arriba. Mismo
   enfoque (apilado, un fundido por bloque, sin pins ni videos pesados): solo
   ritmo, encuadres y un CTA que caia donde no iba. El escritorio no se toca. */
@media (max-width:860px){

  /* --- ritmo vertical de las secciones apiladas ---
     Territorio, Expansion 2, Estate (y la fila del enologo) reordenan sus
     piezas en una grilla de una columna (display:contents, ver arriba). La
     grilla conservaba el gap de escritorio —40px como minimo— y lo sumaba
     entre CADA pieza, encima de sus propios margenes: 70px entre el titulo y
     la bajada, 58 entre parrafos, casi 100 antes de la cita. La pagina se
     leia deshilachada.
     Se anula el gap y se usa el ritmo de Historia, que va en flujo normal y
     ya estaba bien: ~30px del titulo a la bajada, 48 a la foto, 48 al texto,
     y entre parrafos su propio margen. */
  .territory .wrap,
  .expansion-2 .wrap,
  .estate .wrap,
  .enologo{row-gap:0}
  .territory__col > .eyebrow,
  .expansion__col > .eyebrow,
  .estate__col > .eyebrow,
  .enologo__col > .eyebrow{margin-top:1.9rem}
  /* 2rem: el eyebrow ya trae 1rem de margen abajo, y juntos dan los 48 */
  .territory-2 .territory__foto--still,
  .expansion__collage,
  .estate__foto,
  .enologo__foto{margin-top:2rem}
  .territory__col > .lede,
  .expansion__col > .lede,
  .estate__col > .lede,
  .enologo__col > .lede{margin-top:3rem}
  /* la cita con sus dos reglas: un respiro mas que entre parrafos, no el
     doble de una pantalla */
  .territory__col > .sub,
  .expansion__col > .sub,
  .estate__col > .sub,
  .enologo__col > .sub{margin-top:1.5rem}
  .estate__col > .sub{margin-bottom:0}
  .estate__col > .btn{margin-top:2rem}

  /* --- el CTA del vino, sobre el carrusel ---
     En escritorio va abajo a la izquierda de los planos. En telefono la ficha
     sigue al carrusel dentro de la misma seccion, y anclado al pie de la
     seccion el CTA caia encima de la ultima fila de la ficha, medio
     transparente. Se lo ancla al pie de la PRIMERA pantalla —la del
     carrusel—, a la altura de los puntos: el nombre del vino sobre la foto de
     la botella, como en escritorio sobre los planos. */
  .vino-intro__cta{top:calc(100svh - 1.5rem);bottom:auto;transform:translateY(-100%)}

  /* --- encuadre del diptico ---
     Igual que en el carrusel del vino: cover en una caja vertical deja ver
     ~26% del ancho de la foto. En el segundo plano la botella esta al 65% del
     ancho, y con el recorte centrado quedaba cortada contra el borde derecho;
     al 71% queda entera y centrada. El primero ya tiene la botella al medio. */
  .diptych picture:nth-child(2) > .gallery__slide{object-position:71% center}
}
/* La invitacion a seguir bajando, clonada en Bosque 2 (ver animations/bosque2.ts).
   Hereda posicion y tamanio de .vino-intro__hint; lo unico que cambia es el
   color: alla va sobre un video oscuro y aca sobre el verde claro, donde el
   --card seria invisible. */
.story-2__hint .vino-intro__hint-txt,
.story-2__hint .vino-intro__hint-arrow{fill:var(--pine)}
.story-2__hint{opacity:0}
/* El carrusel de Vino Intro es exclusivo de telefono: arriba de 860 manda el
   video que avanza con el scroll. */
@media (min-width:861px){ .vino-intro__swiper{display:none} }
/* ============================== 404 ============================== */
/* La pagina no encontrada: la marca y los tres idiomas apilados, centrados
   en el papel. Solo la usa src/pages/404.astro. */
.not-found{min-height:100vh;min-height:100svh;display:flex;align-items:center}
.not-found__body{display:flex;flex-direction:column;align-items:center;gap:2.6rem;text-align:center;padding-block:4rem}
.not-found__mark{width:150px;height:auto}
.not-found__block{display:flex;flex-direction:column;align-items:center;gap:.9rem;max-width:32rem}
.not-found__block p{text-align:center;margin:0}
/* ============================================================
   VERIFICACION DE EDAD (AgeGate.astro)
   Una tarjeta de papel sobre el hero oscurecido, con el video corriendo
   detras. Los mismos materiales que el resto del sitio: papel --card con
   grano, la marca, titulo en la display, cuerpo en Work Sans, el boton de
   siempre y los idiomas como en el menu del nav.
   ============================================================ */

/* El <dialog> es la capa entera: cubre la pantalla y oscurece lo de atras. No
   se usa ::backdrop porque el dialogo arranca NO modal (viene abierto en el
   HTML) y los no modales no tienen backdrop: asi se ve igual antes y despues
   de que el JS lo pase a modal. Por lo mismo se pisan todos los estilos de
   dialogo del navegador (margen, borde, topes de ancho y alto).
   El z-index cuenta solo mientras no es modal (sin JS, o hasta que arranca el
   bundle): tiene que quedar sobre el nav (40) y el skip link (60). Ya modal,
   va en la capa superior y el z-index no importa. */
.age-gate{
  position:fixed;inset:0;z-index:100;
  width:100%;height:100%;max-width:none;max-height:none;
  margin:0;padding:1rem;border:0;
  display:grid;place-items:center;overflow:auto;
  /* --night al 62%: deja ver el video sin competir con la tarjeta. El blur
     es poco a proposito: separa los planos, no borra el sitio. */
  background:color-mix(in srgb,var(--night) 62%,transparent);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
  color:var(--pine);
  transition:opacity var(--dur) var(--ease);
}
/* display:grid de arriba le ganaria al display:none del navegador */
.age-gate:not([open]){display:none}
.age-gate::backdrop{background:transparent}
/* el foco inicial va al cartel entero (ver interactions/age-gate.ts): un
   contorno alrededor de toda la pantalla no señala nada */
.age-gate:focus{outline:none}
/* ya acepto en otra visita: ni un cuadro (la clase la pone el <head>) */
.edad-ok .age-gate{display:none}
/* la salida: un fundido. Es opacidad, asi que va igual con movimiento
   reducido (ver la regla 3 de scripts/animations/index.ts) */
.age-gate.is-leaving{opacity:0}

/* Mientras esta abierto la pagina no scrollea: debajo no hay nada que hacer
   todavia, y el hero espera al cartel para abrir su secuencia. Con :has y no
   con una clase que ponga el JS, para que sin JS tambien se libere al
   cerrarlo. */
html:not(.edad-ok):has(.age-gate[open]){overflow:hidden}

.age-gate__card{
  width:min(100%,25rem);
  padding:2.25rem 2.5rem 2.5rem;
  background:var(--card);border-radius:var(--r-default);
  text-align:center;
  box-shadow:0 30px 80px rgb(0 0 0 / .35);
}

/* idiomas: los codigos del menu del nav, en Courier, con el actual encendido
   en el magenta del proyecto */
.age-gate__langs{
  display:flex;justify-content:center;align-items:center;
  margin:0 0 1.6rem;padding:0;list-style:none;
}
.age-gate__langs li{display:flex;align-items:center}
.age-gate__langs li + li::before{
  content:"";width:1px;height:.85em;background:var(--pine);opacity:.3;
}
.age-gate__langs a{
  display:block;padding:.55rem .8rem;
  font-family:var(--f-mono);font-size:.72rem;letter-spacing:.14em;text-transform:uppercase;
  color:var(--pine);text-decoration:none;opacity:.55;
  transition:opacity var(--dur) var(--ease),color var(--dur) var(--ease);
}
.age-gate__langs a:hover,.age-gate__langs a:focus-visible{opacity:1;color:var(--raspberry-deep)}
.age-gate__langs a[aria-current]{opacity:1;color:var(--raspberry-deep)}

.age-gate__logo{width:9.5rem;height:auto;margin:0 auto 1.9rem}
.age-gate__title{font-size:1.6rem;line-height:1.05;letter-spacing:-.005em}
/* la voz de los parrafos del sitio (Courier, ver 03-type.css), pero centrada:
   el `p` global justifica, y en una columna de 320px eso abre huecos */
.age-gate__text{margin:1rem 0 2rem;text-align:center}
.age-gate__enter{width:100%;cursor:pointer}
/* el .btn--fill ya esta pintado como su propio foco: sin un contorno, con
   teclado no se veria donde esta el foco */
.age-gate__enter:focus-visible{outline:1.5px solid var(--pine);outline-offset:3px}

@media (max-width:860px){
  .age-gate__card{padding:2rem 1.5rem 2.25rem}
}
