/* ============================================================
   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:.9375rem;
    display:flex;align-items:center;
    width:100%;min-height:48px;
  }
  /* Los links arrancaban pegados arriba y dejaban mas de la mitad del panel
     vacia. Se centran en vertical (justify-content, porque el panel es una
     columna flex) con el padding de abajo mas grande que el de arriba: el pie
     del telefono lo come la barra del navegador, y con el centro matematico
     los links se leian caidos. Quedan alineados a la izquierda, como el resto
     del sitio. 15px y no 17: con el tracking de .2em, 17px hacia palabras como
     TERRITORIO ocupar media pantalla; la fila sigue midiendo 48px, asi que el
     area tactil no cambia. */
  .nav__links{justify-content:center;padding:2rem 1.5rem 5rem}
  /* La raya del hover era un ::after de left a right del <a>, y en el overlay el
     <a> ocupa todo el ancho del panel: la raya cruzaba la pantalla entera. Ahora
     el link mide lo que su texto (fit-content, con el mismo .1rem de aire del
     escritorio) y la raya es un subrayado propio de cada item. Aparece solo con
     el rollover (y con el foco de teclado), como en escritorio: la regla de
     hover de arriba ya la enciende, aca no se toca su opacity. Sigue siendo el
     ::after de opacity, no un border. La fila mantiene los 48px de alto; la raya
     sube de .55rem a .85rem para quedar pegada al texto y no flotando a un
     tercio de fila de distancia. */
  .nav__links a{width:fit-content;padding-inline:.1rem}
  .nav__links a::after{bottom:.85rem}
  .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 ============================== */
/* svh y no dvh. El alto DINAMICO cambia cada vez que la barra del navegador
   del telefono se esconde (al bajar) o vuelve (al subir): el hero crecia o se
   achicaba unos 56px y todo lo de abajo se corria — los "saltitos" de
   Android, en cualquier punto de la pagina. svh es el alto con la barra a la
   vista y no cambia nunca; con la barra escondida asoma abajo una franja de
   la seccion siguiente, que es mucho mejor que una pagina que se mueve sola.
   Va para todos y no solo en la capa movil: en escritorio no hay barra que
   aparezca y dvh y svh miden lo mismo, y una tablet apaisada (>860px) tiene
   la misma barra que el telefono. 100vh queda de respaldo para navegadores
   sin svh. */
.hero{
  position:relative;overflow:hidden;background:var(--night);
  min-height:100vh;min-height:100svh;
  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.
   svh y no dvh, por lo mismo que el hero (06-hero.css): el alto dinamico se
   mueve con la barra del navegador del telefono y corre todo lo que viene
   abajo. Aca ademas la seccion va pineada: un alto que cambia en medio del
   pin descalza el espaciador que ScrollTrigger midio para ella. */
.vino-intro{
  position:relative;overflow:hidden;background:var(--night);
  min-height:100vh;min-height:100svh;
  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}
  /* Los dos collages verticales (Territorio y Estate) miden 0x0 hasta que su foto
     lazy termina de cargar y despues saltan 437px de alto. La figura es item de
     una grilla con el justify-self de escritorio (start / center): se ajusta a
     su contenido, y el contenido es un <img> sin cargar con width:100%, que no
     aporta ancho — asi que la figura nace de ancho 0 y la foto, de alto 0. Todo
     lo que esta debajo se corre ese tanto al cargar, y un ancla del menu
     (#cosecha) calculada antes del salto —en una primera visita, sin las fotos
     de arriba cargadas— aterrizaba 437px corta. Se les da el ancho de la columna
     desde el principio (justify-self:stretch) y la proporcion de sus atributos
     (1122x1402) para que el alto salga de ahi: el lugar queda reservado desde el
     primer cuadro y el resultado final es el mismo que ya se veia. */
  .territory-2 .territory__foto--still,
  .estate__foto{justify-self:stretch;width:100%}
  .territory-2 .territory__foto--still img,
  .estate__foto img{aspect-ratio:1122/1402}
  /* El collage de Expansion 2 (la mitad derecha del original, ver
     Expansion2.astro) viene con su contenido cargado a la derecha: las fotos
     ocupan del 23% al 98% del ancho de la imagen y a la izquierda quedan solo
     los trazos de la ilustracion, tenues. En un telefono eso daba ~100px de
     margen a la izquierda y ~28 a la derecha (la composicion corrida 37px del
     centro). Se corre la imagen a la izquierda y se agranda un 10% para que las
     fotos queden centradas y un poco mas cerca de los bordes: ancho 110% y
     margen izquierdo -16.6% (los dos en % del ancho de la figura, asi vale igual
     a 360 que a 600px). Cuenta: el centro de las fotos esta al 60.6% de la
     imagen; con 110% de ancho, -16.6% + 60.6% x 110% = 50.0% — el centro de la
     figura. Solo se pierde el tramo izquierdo de los trazos, que queda contra el
     filo de la pantalla; a la derecha la imagen termina a 93.4% de la figura. */
  .expansion__collage--right img{width:110%;max-width:none;margin-left:-16.6%}
  /* 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 de ARRIBA se saca: en escritorio la ficha es un panel fijo
     (pineado) y esos ~100px la despegan del nav; en telefono es un bloque mas
     del flujo, y ese padding dejaba un hueco vacio entre el nav y el titulo al
     saltar desde el menu (#cosecha). Sin el, y con el scroll-margin-top de 76px
     que ya tiene toda section[id] (la altura real del nav: --nav-h dice 72 y con
     el filete mide 76), el ancla deja el borde superior de la grilla — o sea la
     regla y el titulo "La prima espressione" — justo bajo el nav. */
  .vino-intro__ficha{padding-inline:0;padding-top: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__photo,
  .harvest-grid__data{padding-inline:0}

  /* Orden en telefono: titulo (con el sello a la derecha), la botella, y recien
     despues la bajada y los parrafos. En el HTML el titulo vive DENTRO de
     .harvest-grid__text, junto con el texto, y la grilla apilada ("photo"
     "text" "data") solo puede poner el bloque entero antes o despues de la
     botella — nunca el titulo arriba y el resto abajo. Partir el bloque en dos
     en el markup rompia el escritorio (ahi es una sola celda) y la paridad con
     ../html, asi que en telefono la caja desaparece (display:contents) y sus
     hijos pasan a ser items de la grilla, ordenados con `order`: titulo -1,
     botella 0 (el default), bajada y parrafos 1, ficha 2. Con `order` y no con
     una area por hijo para que un parrafo mas o menos en un diccionario no
     rompa la grilla.
     Orden visual y de lectura difieren (la botella va antes en el DOM): no hay
     nada enfocable entre ellos, y la botella ya abria el bloque antes de esto. */
  /* minmax(0,1fr) y no 1fr: la caja de la botella toma su ancho de la proporcion
     (alto x .573) y a 360px pedia 364 — una `1fr` suelta crece hasta el minimo
     de su contenido y empujaba toda la grilla por encima del ancho de la
     pantalla. Con minimo 0 la columna es la pantalla y la botella se acomoda. */
  .harvest-grid{grid-template-areas:none;grid-template-columns:minmax(0,1fr)}
  .harvest-grid__photo,
  .harvest-grid__data{grid-area:auto}
  .harvest-grid__data{order:2}
  .harvest-grid__text{display:contents}
  /* sin caja, el padding, el borde y el efecto de sello de .harvest-grid__text
     (14-cosecha.css) ya no se aplican: cada hijo carga con lo suyo. */
  .harvest-grid__text > *{
    order:1;padding-inline:1.1rem;
    mix-blend-mode:multiply;filter:url(#stampRough);
  }
  /* El sello va a la derecha del titulo, en su misma fila. Sigue absoluto como
     en escritorio, pero ya no hay .harvest-grid__text que lo contenga (sin
     caja no es bloque contenedor): se ancla a la grilla, y la esquina superior
     derecha de la grilla ES la fila del titulo, que va primera. 76px como
     antes; el titulo reserva ese ancho a la derecha para no pisarlo y fija un
     alto minimo que lo contiene, asi la regla de abajo queda siempre bajo el
     sello y no cortandolo. */
  .harvest-grid__text .harvest__stamp{
    top:1rem;right:1.1rem;width:76px;margin:0;padding:0;translate:none;
  }
  /* display:grid y no flex para centrar el titulo contra el sello: en una caja
     flex de una sola linea Chrome toma como ancho minimo el del texto entero
     (no el de la palabra mas larga), y a 360px ensanchaba la columna de la
     grilla a 367px, por encima del ancho de la pantalla. */
  .harvest-grid__text .title{
    order:-1;display:grid;align-content:center;
    min-height:calc(76px + 2rem);padding:1rem calc(76px + 2.1rem) 1rem 1.1rem;
    border-bottom:1px solid var(--pine-ink);
  }
  /* sin hueco a la derecha, la medida de lectura la pone la columna */
  .harvest-grid__text .title,
  .harvest-grid__text .lede{max-width:none}
  /* la regla que antes cerraba el bloque de texto. Con las pestañas activas ya
     no hace falta (solo se ve un panel a la vez): sin JS no hay pestañas y la
     regla tiene que seguir separando los parrafos de la ficha. */
  .harvest-grid:not(.harvest-grid--tabs) .harvest-grid__text > p:last-child{
    padding-bottom:1rem;border-bottom:1px solid var(--pine-ink);
  }

  /* --- pestañas: "Sul vino" (todo el texto) y la ficha tecnica ---
     Apilado, el bloque pasaba de 1.700px: la botella, cuatro parrafos y una
     ficha de 8 filas en una sola pasada. interactions/ficha-tabs.ts agrega la
     botonera y la clase --tabs (solo en telefono y solo con JS); queda titulo,
     botella y UN panel. Sin JS no hay botonera ni clase, asi que todo se lee
     abierto, como antes. La botonera es una regla de la grilla (borde arriba y
     abajo) partida en dos mitades; la activa va rellena de pino y letra de
     papel — no solo cambia el color, cambia el peso de la pieza — y el estado
     lo dice ademas aria-selected. */
  .harvest__tabs{
    order:1;padding-inline:0;display:grid;grid-template-columns:1fr 1fr;
    border-top:1px solid var(--pine-ink);border-bottom:1px solid var(--pine-ink);
  }
  .harvest__tab{
    min-height:48px;margin:0;padding:.75rem .5rem;
    background:transparent;border:0;border-radius:0;
    color:var(--pine);font-family:var(--f-mono);font-size:.75rem;font-weight:600;
    letter-spacing:.2em;text-transform:uppercase;text-align:center;cursor:pointer;
    touch-action:manipulation;
  }
  .harvest__tab + .harvest__tab{border-left:1px solid var(--pine-ink)}
  .harvest__tab[aria-selected="true"]{background:var(--pine);color:var(--paper)}
  .harvest__tab:hover:not([aria-selected="true"]),
  .harvest__tab:focus-visible:not([aria-selected="true"]){color:var(--raspberry-deep)}
  .harvest__tab:focus-visible{outline:1.5px solid var(--pine);outline-offset:-5px}
  .harvest__tab[aria-selected="true"]:focus-visible{outline-color:var(--paper)}
  /* el envoltorio del texto es el item de la grilla: lleva lo que antes llevaba
     cada hijo suelto (el padding lateral queda en los hijos) */
  .harvest__panel{order:1;padding-inline:0}
  .harvest__panel > *{padding-inline:1.1rem}
  .harvest__panel > .lede{margin-top:1rem}
  .harvest-grid--tabs:not(.is-tab-text) .harvest__panel,
  .harvest-grid--tabs:not(.is-tab-sheet) .harvest-grid__data{display:none}
  /* el panel que entra lo hace con un fundido de la duracion del sitio: una sola
     propiedad (opacity), como el resto. Con reduced motion los fundidos se
     quedan, asi que no hace falta una salida aparte. */
  .harvest-grid--tabs.is-tab-text .harvest__panel,
  .harvest-grid--tabs.is-tab-sheet .harvest-grid__data{animation:cosecha-abre var(--dur) var(--ease)}
  @keyframes cosecha-abre{from{opacity:0}to{opacity:1}}

  /* --- "Leer mas" en los bloques de texto largo ---
     interactions/read-more.ts agrega el enlace (solo en telefono y solo con JS)
     y marca la columna (.readmore-on) y los parrafos que se pliegan
     (.readmore__rest). Cerrada, la columna muestra su bajada y nada mas: una
     pantalla de lectura en vez de cuatro o cinco. Sin JS no hay clases y todo se
     lee abierto.
     Es un enlace de texto, no un boton: sin relleno ni borde, subrayado fino
     solo bajo la palabra (el chevron queda afuera del subrayado: es un <svg>, no
     texto) y el mismo tono de los demas rotulos del sitio. Mantiene los 44px de
     alto para el dedo aunque se vea como una linea. */
  /* display:flex + width:fit-content y no inline-flex: Historia es una columna
     centrada (.prose--center, text-align:center) y un item en linea heredaba el
     centrado; en bloque arranca siempre contra el borde izquierdo, como la
     bajada de todas las demas secciones, y mide lo que su texto. */
  .readmore{
    display:flex;width:fit-content;align-items:center;gap:.4rem;
    min-height:44px;margin:0 0 .75rem;padding:0;
    background:none;border:0;border-radius:0;cursor:pointer;touch-action:manipulation;
    font-family:var(--f-mono);font-size:.75rem;font-weight:600;
    letter-spacing:.2em;text-transform:uppercase;text-align:left;
    color:var(--pine);
    text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.4em;
  }
  .readmore svg{
    width:1.1em;height:1.1em;flex:none;fill:none;stroke:currentColor;
    stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
  }
  .readmore:hover,
  .readmore:focus-visible{color:var(--raspberry-deep)}
  .readmore:focus-visible{outline:1.5px solid var(--pine);outline-offset:4px}
  .readmore-on:not(.is-open) > .readmore__rest{display:none}
  /* La bajada tambien se corta si es larga: la de Expansion 2 pasa de 8 renglones
     a 360px, y con ella entera el "Leer mas" quedaba debajo de la pantalla. 4
     renglones con puntos suspensivos; si cabe en menos no cambia nada. Al
     desplegar se muestra completa. */
  .readmore-on:not(.is-open) > .lede{
    display:-webkit-box;-webkit-box-orient:vertical;
    -webkit-line-clamp:4;line-clamp:4;overflow:hidden;
    margin-bottom:.35rem;
  }
  /* lo que se despliega entra con el mismo fundido de la ficha: una sola
     propiedad (opacity), con la duracion del sitio */
  .readmore-on.is-open > .readmore__rest{animation:cosecha-abre var(--dur) var(--ease)}

  /* --- la composicion llega al borde ---
     El marco de la ficha arrancaba a 20px de cada costado (la canaleta del
     .wrap): en un telefono eso es una franja de aire que no aporta, y la botella
     y el texto quedaban en una columna de 350px. Como en Tenuta Monte Solare, el
     bloque se abre a todo el ancho: el .wrap pierde su padding en esta seccion y
     el marco conserva solo sus reglas de arriba y de abajo (las de los costados
     quedarian pegadas al borde del vidrio, sin nada que enmarcar). El texto
     sigue con su canaleta de 1.1rem adentro. */
  .vino-intro__ficha .vino-intro__ficha-body{padding-inline:0}
  .harvest-grid::after{border-inline:0}

  /* --- la botella entra entera en la pantalla ---
     Era 100% del ancho con aspect-ratio: 350px de ancho daban ~610px de alto, y
     con el nav y el titulo encima la botella quedaba cortada al pie de la
     primera pantalla. Ahora la celda mide lo que sobra de la pantalla (100svh,
     el alto chico: sin depender de la barra del navegador) menos el nav (76px,
     lo mismo que el scroll-margin del ancla: asi, al llegar desde el menu, la
     grilla empieza justo bajo el nav y la botella cierra justo en el borde de
     la pantalla) y la fila del titulo (76px del sello + 2rem de aire), y la
     botella toma ese alto; el ancho sale de la proporcion. El piso de 340px es para pantallas bajas
     (landscape): ahi prefiere cortarse a quedar de juguete. */
  .harvest-grid__photo{
    height:calc(100vh - 76px - 76px - 2rem);
    height:calc(100svh - 76px - 76px - 2rem);
    min-height:340px;padding-block:.75rem;
  }
  .wine-print{width:auto;height:100%;max-width:100%}

  /* --- 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}
}

/* ====================== COOKIES: cartel, pie y politica ====================== */
/* El cartel de cookies (components/CookieBanner.astro), los enlaces legales del
   pie y la pagina de la politica (components/CookiePolicy.astro).
   Mismas reglas que el resto del sitio: papel, tinta de pino, cero sombras,
   cero bordes redondeados, un solo movimiento (un fundido de la duracion del
   sitio). Con reduced motion el fundido se queda, como todos. */

/* ---- el cartel ---- */
/* Capa fija abajo. z-index 50: encima del nav (40), debajo del skip link (60);
   el cartel de edad es un <dialog> modal y va siempre arriba de todo. El padding
   de abajo suma la zona segura del iPhone. Tope de alto por si el panel abierto
   no entra en una pantalla baja: se desplaza adentro. */
.cookie-banner{
  position:fixed;left:0;right:0;bottom:0;z-index:50;
  background:var(--paper);color:var(--pine);border-top:1.5px solid var(--pine);
  padding:1.25rem 1.5rem calc(1.25rem + env(safe-area-inset-bottom));
  max-height:90vh;max-height:90svh;overflow-y:auto;
  animation:cookie-in var(--dur) var(--ease);
}
.cookie-banner[hidden]{display:none}
@keyframes cookie-in{from{opacity:0}to{opacity:1}}
.cookie-banner__inner{
  position:relative;max-width:var(--container);margin:0 auto;
  display:grid;grid-template-columns:minmax(0,1fr) auto;gap:1rem 2rem;align-items:center;
}
/* el hueco a la derecha es para la X */
.cookie-banner__copy{padding-right:2.75rem}
.cookie-banner__copy:focus{outline:none}
.cookie-banner__copy:focus-visible{outline:1.5px solid var(--pine);outline-offset:6px}
.cookie-banner__title{
  font-family:var(--f-mono);font-size:.78rem;font-weight:600;letter-spacing:.2em;
  text-transform:uppercase;margin:0 0 .5rem;color:var(--pine);
}
/* los <p> del sitio llevan justificado y tracking negativo (la mono del cuerpo):
   aca es texto corto y de lectura rapida, a la izquierda y sin apretar */
.cookie-banner__text,
.cookie-banner__note{margin:0;text-align:left;letter-spacing:0;font-size:.875rem;line-height:1.55}
.cookie-banner__note{margin-top:.35rem;font-size:.8rem;color:var(--charcoal)}
.cookie-banner__link{color:var(--pine);text-decoration:underline;text-underline-offset:.2em}
.cookie-banner__link:hover,
.cookie-banner__link:focus-visible{color:var(--raspberry-deep)}
.cookie-banner__actions{display:flex;flex-wrap:wrap;gap:.75rem;align-items:center;justify-content:flex-end}
/* Rechazar y Aceptar son el mismo .btn: ninguno se destaca sobre el otro. Lo
   unico propio es el alto minimo de un dedo. */
.cookie-banner__btn{min-height:48px;padding:.85rem 1.6rem;font-size:.8rem;cursor:pointer;text-align:center}
.cookie-banner__custom{
  min-height:44px;padding:0 .25rem;margin:0;background:none;border:0;border-radius:0;cursor:pointer;
  font-family:var(--f-mono);font-size:.75rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;
  color:var(--pine);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.4em;
  touch-action:manipulation;
}
.cookie-banner__custom:hover,
.cookie-banner__custom:focus-visible{color:var(--raspberry-deep)}
.cookie-banner__custom:focus-visible,
.cookie-banner__close:focus-visible{outline:1.5px solid var(--pine);outline-offset:3px}
.cookie-banner__close{
  position:absolute;top:-.5rem;right:-.5rem;width:44px;height:44px;
  display:grid;place-items:center;padding:0;margin:0;background:none;border:0;border-radius:0;
  color:var(--pine);cursor:pointer;touch-action:manipulation;
}
.cookie-banner__close:hover{color:var(--raspberry-deep)}
.cookie-banner__close svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round}

/* el panel de "Personalizar" */
.cookie-banner__panel{
  grid-column:1/-1;display:grid;gap:.9rem;
  border-top:1px solid var(--pine-ink);padding-top:1rem;
}
.cookie-banner__panel[hidden]{display:none}
.cookie-banner__option{display:grid;grid-template-columns:auto minmax(0,1fr);gap:.75rem;align-items:start}
.cookie-banner__option input{
  width:1.25rem;height:1.25rem;margin:.1rem 0 0;border-radius:0;accent-color:var(--pine);cursor:pointer;
}
.cookie-banner__option input:disabled{cursor:not-allowed}
.cookie-banner__option label{display:grid;gap:.2rem;font-size:.85rem;line-height:1.45;letter-spacing:0;cursor:pointer}
.cookie-banner__option label b{
  font-family:var(--f-mono);font-size:.75rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
}
.cookie-banner__option label span{color:var(--charcoal)}
.cookie-banner__save{justify-self:start}

/* Tablet y escritorio angosto (hasta 959px): el texto y los tres controles ya no
   caben uno al lado del otro sin dejarle al texto una columna de ~385px (seis o
   siete renglones). Se apilan: el texto a todo el ancho y los controles en una
   fila debajo, a la izquierda. Desde 960 el texto ya tiene 500px o mas y queda
   mejor al costado. */
@media (max-width:959px){
  .cookie-banner__inner{grid-template-columns:minmax(0,1fr)}
  .cookie-banner__actions{justify-content:flex-start}
}

/* Telefono. El cartel tapaba del 35 al 42% de la pantalla (300 a 356px de alto
   a 360-430 de ancho) y, en la pagina de la politica, justo el texto que se
   estaba leyendo. Se achica sin sacarle nada: el aviso de la X sigue al texto
   en el mismo renglon y los tres controles van en una sola fila (Personalizar
   tenia una fila propia de 44px). Queda en ~230px, un 27%. */
@media (max-width:860px){
  .cookie-banner{padding:.875rem 20px calc(.875rem + env(safe-area-inset-bottom))}
  .cookie-banner__inner{grid-template-columns:minmax(0,1fr);gap:.75rem}
  /* line-height en el contenedor: el texto y el aviso van en linea (abajo) y
     el alto de cada renglon lo pone el del bloque que los contiene */
  .cookie-banner__copy{padding-right:2.25rem;order:1;font-size:.8125rem;line-height:1.5}
  /* El panel va ENTRE el texto y los botones, no debajo: el cartel esta anclado
     abajo y crece hacia arriba, asi que los botones se quedan donde estan al
     abrirlo. Con el panel debajo, "Guardar" (a todo el ancho) caia justo donde
     estaba "Personalizar", y un doble toque rapido en este ultimo guardaba sin
     querer. */
  .cookie-banner__panel{order:2}
  .cookie-banner__actions{order:3}
  /* texto un punto mas chico, y el aviso de la X a continuacion del texto, en
     el mismo parrafo visual (el espacio entre los dos <p> del HTML hace de
     separador). Sigue a la vista en el primer nivel, como pide el Garante; solo
     deja de ocupar un renglon propio y su margen. */
  .cookie-banner__text,
  .cookie-banner__note{display:inline;font-size:inherit;line-height:inherit}
  .cookie-banner__note{margin:0}
  .cookie-banner__title{margin-bottom:.4rem}
  /* Rechazar y Aceptar del mismo ancho (1fr 1fr) y Personalizar al lado, a su
     medida. Para que entre a 360 en italiano y español (Personalizza /
     Personalizar, la palabra mas larga), los botones pierden relleno lateral
     y Personalizar algo de espaciado entre letras. Alto: 44px, el minimo de
     un dedo. */
  .cookie-banner__actions{display:grid;grid-template-columns:1fr 1fr auto;gap:.5rem}
  .cookie-banner__btn{min-height:44px;padding:.6rem .4rem}
  .cookie-banner__custom{letter-spacing:.1em;padding:0 .15rem}
  .cookie-banner__save{justify-self:stretch}
}

/* Telefono acostado (poca altura, mucho ancho): el cartel de 2 filas de botones
   se comia dos tercios de la pantalla. Los tres controles van en una sola fila y
   el cartel se achica; con el panel abierto se desplaza adentro (max-height). */
@media (max-width:860px) and (max-height:500px){
  .cookie-banner{padding-block:.75rem calc(.75rem + env(safe-area-inset-bottom))}
  .cookie-banner__inner{gap:.6rem}
  .cookie-banner__title{margin-bottom:.25rem}
  .cookie-banner__actions{display:flex;justify-content:flex-start}
  .cookie-banner__btn{padding:.6rem 1.4rem}
  .cookie-banner__save{justify-self:start}
}

/* ---- el pie ---- */
/* En pantallas anchas los dos enlaces van a los costados de la linea del ©, sobre
   ella y sin ocupar lugar propio (position:absolute): el pie mide lo mismo que
   en el diseño original (la paridad se mide a 1440). Hay que ser ancho de
   verdad: el © mide ~510px centrado y "Revisar sus elecciones sobre cookies"
   (español) ~220px, asi que a 861 y hasta ~1100 se pisaban. Por debajo de 1200
   van en una fila propia debajo del ©, centrados, como en telefono. */
.site-footer__bottom{position:relative}
.site-footer__legal{display:flex;flex-wrap:wrap;justify-content:center;gap:0 1.5rem;margin-top:.4rem}
.site-footer__legal a,
.site-footer__legal button{
  display:inline-flex;align-items:center;min-height:44px;padding:0;margin:0;
  background:none;border:0;border-radius:0;cursor:pointer;
  font-family:var(--f-mono);font-size:.7rem;font-weight:400;letter-spacing:.12em;text-transform:uppercase;
  color:var(--charcoal);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.3em;
}
.site-footer__legal a:hover,
.site-footer__legal a:focus-visible,
.site-footer__legal button:hover,
.site-footer__legal button:focus-visible{color:var(--raspberry-deep)}
/* sin JS no hay cartel que reabrir */
html:not(.js) .site-footer__legal button{display:none}
@media (min-width:1200px){
  .site-footer__legal{
    position:absolute;left:1.5rem;right:1.5rem;top:0;bottom:0;margin:0;
    flex-wrap:nowrap;justify-content:space-between;align-items:center;pointer-events:none;
  }
  .site-footer__legal a,
  .site-footer__legal button{pointer-events:auto;font-size:.62rem;letter-spacing:.1em}
}

/* ---- la pagina de la politica ---- */
/* Mientras el cartel esta a la vista, la pagina suma abajo un hueco de su mismo
   alto (--cookie-banner-h, lo mide interactions/cookies.ts; vale 0 con el
   cartel oculto). Aca se lee de corrido hasta el final, y sin el hueco el cartel
   tapaba el ultimo parrafo, el boton de las elecciones y el pie. Solo en esta
   pagina: en la portada el final es el pie, y cambiarle el alto a la pagina
   mientras corren los pins de ScrollTrigger no vale el riesgo. */
body:has(> .policy){padding-bottom:var(--cookie-banner-h,0px)}
.policy{padding-block:clamp(3rem,8vw,6rem)}
.policy__body{max-width:46rem}
.policy__mark{display:inline-block;margin-bottom:2.2rem}
.policy__mark img{display:block;width:150px;height:auto}
.policy .title{margin:0 0 .6rem}
.policy__updated{
  margin:0 0 1rem;text-align:left;letter-spacing:.14em;text-transform:uppercase;
  font-size:.72rem;font-weight:600;color:var(--charcoal);
}
.policy__section{margin-top:2.4rem}
.policy__heading{
  font-family:var(--f-display);font-weight:400;font-size:clamp(1.3rem,1.1rem + .8vw,1.7rem);
  line-height:1.15;text-transform:uppercase;margin:0 0 .9rem;color:var(--pine);
}
/* texto de lectura larga: a la izquierda y con tracking normal (el cuerpo del
   sitio va justificado y apretado, pensado para parrafos cortos) */
.policy p,
.policy li{text-align:left;letter-spacing:0;line-height:1.7}
.policy ul{margin:0 0 1.1em;padding-left:1.25rem}
.policy li{margin-bottom:.6rem;color:#2B2B2B;font-family:var(--f-mono);font-size:var(--fs-body)}
.policy a{color:var(--pine);text-decoration:underline;text-underline-offset:.2em;overflow-wrap:anywhere}
.policy a:hover,
.policy a:focus-visible{color:var(--raspberry-deep)}
.policy__prefs{margin-top:2.4rem}
html:not(.js) .policy__prefs{display:none}
