/* ==========================================================================
   Secciones específicas
   ========================================================================== */

/* ---- Hero ----
   Exactamente 100vh: header (parte superior del bloque azul, ver
   layout.css) + hero__top completan 50vh azules; hero__media es el
   otro 50vh, full-bleed, futuro <video>.

   Ojo con lo que es "apilable" (.stack-section) y lo que no: el título
   (hero__top) va en flujo normal, NO sticky — así se esconde con
   normalidad debajo del header fijo al scrollear, sin quedar congelado
   a media altura (eso era lo que se veía mal). Lo único que se apila es
   hero__media (la imagen/video): se queda pegada arriba hasta que Qué
   resolvemos se desliza por encima y la cubre del todo. */
.hero {
  display: flex;
  flex-direction: column;
  background: var(--color-blue);
  color: var(--color-black);
}

.hero__top {
  height: var(--hero-top-h);
  min-height: 0;
  display: flex;
  align-items: flex-end;
}

.hero__intro {
  width: 100%;
  display: grid;
  /* Las 3 primeras columnas se ajustan a su contenido (título, subtítulo,
     @handle quedan pegados entre sí); la última es flexible y empuja el
     punto hasta el borde derecho. */
  grid-template-columns: auto auto auto 1fr;
  align-items: start; /* los 3 textos + el punto arrancan alineados arriba */
  column-gap: var(--logo-title-gap);
  padding: 0 var(--gutter) clamp(1.5rem, 4vh, 3rem);
}

.hero__title {
  font-size: var(--fs-hero);
  font-weight: 500; /* Helvetica Neue Medium, no Bold */
  line-height: 1.15;
  margin-right: 3.75rem; /* +60px de separación extra pedidos, sobre el gap de 30px del grid */
}

.hero__subtitle {
  font-size: var(--fs-hero-subtitle);
  line-height: 1.15;
  margin-top: 0.5em; /* nivela ópticamente con el título/@handle */
  margin-right: 3.75rem; /* mismo espacio (+60px) que hay entre título y subtítulo */
}

.hero__handle {
  font-weight: 700;
  font-size: var(--fs-hero-subtitle);
  line-height: 1.15;
  margin-top: 0.65em; /* nivela ópticamente con título/subtítulo */
  transition: color 0.2s var(--ease);
}

/* Rosa de marca al hover — mismo --color-pink que ya usa el resto del
   sitio (paleta del punto animado), pedido explícito (antes amarillo). */
.hero__handle:hover { color: var(--color-pink); }

/* Ocupa el lugar donde "viviría" el punto real (que ahora es un único
   elemento fixed, fuera de este grid — ver .dot-dock en components.css y
   initDotDock() en main.js). Mismo tamaño y mismo margin-top que tenía el
   punto antes, para que la referencia de posición sea exacta. */
.hero__dot-anchor {
  width: 28px;
  height: 28px;
  justify-self: end;
  margin-top: 0.3em;
  visibility: hidden;
}

.hero__media {
  --stack-index: 0;
  height: 50vh;
  position: relative;
  overflow: hidden;
}

.hero__media-asset {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ---- Qué resolvemos ----
   REESTRUCTURADO: antes .intro-statement__stage vivía DENTRO de un
   wrapper (.intro-statement__pin) más alto que ella misma — eso hacía
   que su "contenedor de sticky" fuera angosto (stage+runway nomás), y
   position:sticky SOLO se queda pegada mientras cabe dentro de su propio
   contenedor: en cuanto el scroll superaba ese contenedor angosto, stage
   se despegaba SOLA y se deslizaba como bloque normal — eso era el bug
   ("sube todo el módulo 2 Y el 3 juntos" en vez de quedarse quieto). La
   solución no es ajustar tiempos, es sacarle el contenedor angosto:
   ahora #que-resolvemos ES la propia stage (sticky, top:0) colgando
   DIRECTO de <main>, exactamente igual que #como-trabajamos y el resto
   de módulos — su "contenedor de sticky" pasa a ser el resto entero de
   la página (larguísimo), así que NUNCA se despega sola. Quien la tapa
   es pura y exclusivamente el siguiente módulo (mayor z-index) subiendo
   por encima, igual que ya pasa entre módulo 3 y 4.

   .intro-statement__runway es un div aparte, común y silvestre (NO
   sticky), después de #que-resolvemos en el documento — solo reserva
   distancia de scroll para el "dwell" de la animación de texto; nunca se
   ve (queda tapado todo el rato por #que-resolvemos, que sigue pegada
   arriba mientras se scrollea por acá). initIntroReveal() en main.js mide
   EN VIVO su getBoundingClientRect().top para calcular el progreso 0→1
   del reveal, usando como referencia exactamente la distancia real hasta
   que "Cómo trabajamos" empieza a asomar — así el reveal termina siempre
   justo cuando arranca la cubierta del siguiente módulo, sin importar si
   el alto de #que-resolvemos es 100vh exacto o no (ver los 70px menos
   pedidos más abajo). */
.intro-statement__stage {
  --stack-index: 1;
  /* Vuelve a 100vh, igual que el resto de módulos (.screen): el intento
     de altura "según contenido" (auto + padding-bottom:12px) dejaba el
     párrafo pegado arriba con un tramo en blanco enorme debajo (el
     runway, sin fondo propio, se ve como si fuera parte de la misma
     sección blanca) — pedido explícito del cliente fue centrar el
     párrafo en esa altura visible, no pegarlo arriba. Con 100vh + el
     centrado de .intro-statement__inner de abajo, el párrafo queda
     centrado dentro de una pantalla completa, como el resto del sitio.
     Sin position:relative acá — .stack-section ya pone position:sticky
     (mismo selector de una sola clase, misma especificidad; si esta
     regla trajera position:relative la pisaría por venir después en la
     cascada y el módulo dejaría de pinearse). */
  height: 100vh;
  overflow: hidden;
  background: var(--color-white);
}

/* Con stage de vuelta a 100vh, el runway vuelve a su valor original de
   40vh (ver fórmula en initIntroReveal(), main.js:
   stage.offsetHeight + runway.offsetHeight - window.innerHeight —
   con stage=100vh, esto se simplifica a runway=40vh, el tramo de dwell
   ya afinado y aprobado antes). */
.intro-statement__runway {
  --intro-runway-h: 40vh;
  height: var(--intro-runway-h);
}

.intro-statement__inner {
  height: 100%;
  display: flex;
  flex-direction: column;
  /* Centrado completo: vertical (justify-content) y horizontal
     (align-items) + texto centrado (text-align). */
  justify-content: center;
  align-items: center;
  text-align: center;
}

/* Ocultos por ahora (no borrados): "QUÉ RESOLVEMOS" arriba, "Papito"
   abajo, y el sticker de la derecha. Si más adelante hacen falta de
   nuevo, es cuestión de quitar este display:none. */
.intro-statement__eyebrow,
.intro-statement__byline,
.intro-statement__media {
  display: none;
}

.intro-statement__text {
  font-family: var(--font-body);
  font-size: var(--fs-h2);
  font-weight: 500; /* Prueba: Helvetica Neue Medium en todo el párrafo, incluida la parte negra */
  line-height: 1.25;
  max-width: 58ch;
}

.intro-statement__solid {
  font-weight: 500; /* Medium, a prueba (antes Regular) */
  color: var(--color-black);
}

/* Palabra por palabra: initIntroReveal() envuelve cada palabra del
   párrafo gris en un <span class="word">. Arranca casi invisible y se
   revela de forma continua (opacity 0.14→1, calculada palabra por
   palabra en cada frame de scroll, ver main.js) a medida que avanza el
   progreso — nunca se mueve ni cambia de tamaño, solo aparece. La parte
   negra (.intro-statement__solid) no pasa por esto: siempre está
   visible. */
.intro-statement__reveal {
  color: var(--color-intro-muted);
  font-weight: 400; /* Regular: la parte gris se queda en Regular, solo la negra en Medium */
}

/* Sin transition acá a propósito: la opacidad de cada palabra la fija
   initIntroReveal() en cada frame de scroll como un valor continuo ya
   calculado a partir de la posición real del scroll (no un simple
   on/off) — agregar una transition encima solo metería un retraso
   (la palabra "persiguiendo" al scroll) en vez de seguirlo 1:1, que es
   lo que da la sensación fluida. .is-revealed queda solo como fallback
   para el caso sin JS / mobile (ver revealAll() en main.js). */
.intro-statement__reveal .word {
  opacity: 0.14;
}

.intro-statement__reveal .word.is-revealed { opacity: 1; }

.intro-statement__byline { margin: 0; }

.intro-statement__media {
  position: absolute;
  right: var(--gutter);
  /* Un poco más arriba que antes (bottom más grande = sube desde el borde). */
  bottom: clamp(3rem, 9vh, 6rem);
  /* 30% más chica que antes (clamp(160px,16vw,260px) × 0.7). */
  width: clamp(112px, 11.2vw, 182px);
}

.intro-statement__media-asset {
  width: 100%;
  height: auto;
  display: block;
}

/* ---- Cómo trabajamos ----
   Módulo de una sola pantalla (.screen, ver layout.css): el grid de dos
   columnas (.work-tabs) llena el 100vh completo de la sección.

   SIN margin-top: este módulo arranca (en el documento) justo donde
   termina .intro-statement__runway. Como todo elemento en flujo normal,
   empieza a asomar por el borde inferior de la pantalla ANTES de llegar
   a su propio offsetTop — exactamente 1 viewport antes—, y
   initIntroReveal() (main.js) calcula el reveal para que termine
   EXACTAMENTE en ese mismo instante (ver comentario largo en
   .intro-statement__stage/.intro-statement__runway, arriba). #que-resolvemos
   se queda pegada arriba sin moverse todo este tiempo (sticky "de
   verdad", sin contenedor angosto que la despegue sola) — es
   #como-trabajamos quien hace el 100% del movimiento, subiendo y
   tapándola, igual que pasa entre módulo 3 y 4. */
#como-trabajamos {
  --stack-index: 2;
  /* .section (layout.css) trae padding-block propio (y .section--tight
     otro tanto encima), pensado para secciones de alto libre — acá deja
     un margen blanco arriba y abajo DENTRO de los 100vh de .screen, así
     el contenido (work-tabs, con su propio height:100%) no llega a
     tapar la pantalla completa. Se anula acá para que el módulo sea
     full-screen de verdad, sin ese aire extra. */
  padding-block: 0;
}

#como-trabajamos .work-tabs { height: 100%; }

.work-tabs__media {
  position: relative;
  min-height: 420px;
  height: 100%;
  background: var(--color-black);
}

/* Stage de medios: un elemento por estado (Comprender/Dirigir/Construir),
   apilados exactamente encima del otro; initWorkTabs() en main.js les pone
   .is-active según la pestaña activa (mismo dato data-media-theme que ya
   usa el panel para el color de fondo) y el cambio se ve como un crossfade
   suave en vez de un salto. Mientras Dirigir/Construir no tengan su propio
   video, se quedan en el placeholder de siempre. */
.work-tabs__media-stage { position: absolute; inset: 0; }

.work-tabs__media-item {
  min-height: 100%;
  height: 100%;
  width: 100%;
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
}

.work-tabs__media-item.is-active { opacity: 1; }

video.work-tabs__media-item {
  object-fit: cover;
  display: block;
  background: var(--color-black);
}

/* Comprender: el video original ya viene con su propio encuadre circular
   de ojo de pez (con el marco negro incluido, es del lente con el que se
   grabó, no algo que se agregó acá). object-fit:cover lo recortaría y
   perdería justo ese marco/círculo; con contain se ve el encuadre
   completo, y como el fondo de esta caja ya es negro (ver arriba), el
   negro del video se funde con el negro del contenedor sin verse como un
   recuadro aparte. */
video.work-tabs__media-item--contain { object-fit: contain; }

/* Capa oscura pareja sobre los 3 videos (Comprender/Dirigir/Construir):
   un ::after dentro del stage, por encima de todos los .work-tabs__media-item
   pero por debajo del eyebrow/título (que están fuera de este stage, con
   z-index:2 propio) — un solo elemento cubre los 3 estados sin repetir
   la regla en cada video. */
.work-tabs__media-stage::after {
  content: '';
  position: absolute;
  inset: 0;
  /* 10% inicial + 20 puntos más de oscuridad pedidos ahora = 30%. */
  background: rgba(0, 0, 0, 0.3);
  pointer-events: none;
  z-index: 1;
}

.work-tabs__eyebrow {
  position: absolute;
  top: 1.5rem;
  left: var(--gutter);
  z-index: 2;
  color: var(--color-white);
}

.work-tabs__overlay-title {
  position: absolute;
  /* Pegada al borde inferior y al borde derecho de la imagen, sin
     distancia (antes 1.5rem abajo / 1rem a la derecha). */
  bottom: 0;
  left: var(--gutter);
  right: 0;
  z-index: 2;
  font-family: var(--font-display);
  font-weight: 400; /* Helvetica Neue Regular: mayúscula + tamaño grande, no un corte Black */
  text-transform: uppercase;
  color: var(--color-white);
  /* Mucho más grande a propósito: "COMPRENDER" (la más larga de las 3
     palabras que rota este mismo elemento) debe ocupar todo el ancho de
     la columna izquierda. Calculado sobre columna ≈ 960px a 1920px de
     viewport (mitad del .work-tabs, menos gutter/inset): a ese ancho
     ~124px de font-size hace que "COMPRENDER" llegue borde a borde. Al
     ser un único font-size para el elemento, "Dirigir" y "Construir"
     (más cortas) salen automáticamente del mismo tamaño, como se pidió. */
  font-size: clamp(3rem, 6.5vw, 8rem);
  line-height: 0.9;
  /* Misma red de seguridad que .display-xl (ver typography.css): palabra
     suelta sin espacio donde partir — en mobile angosto, si no cupiera
     en una línea pasa a dos en vez de desbordar el borde derecho de la
     pantalla. */
  overflow-wrap: break-word;
  word-break: break-word;
  /* Transición de la palabra al cambiar de pestaña (initWorkTabs() en
     main.js agrega/quita .is-swapping): la palabra saliente baja 5px y
     se desvanece en el mismo lugar; el texto se reemplaza mientras está
     invisible y la nueva palabra entra con el mismo movimiento (fade +
     baja desde -5px hasta su posición). Duración acá debe calzar con el
     setTimeout del swap en JS (240ms). */
  transition: opacity 0.24s var(--ease), transform 0.24s var(--ease);
}

.work-tabs__overlay-title.is-swapping {
  opacity: 0;
  transform: translateY(5px);
}

.work-tabs__panel {
  padding: clamp(2rem, 4vw, 3.5rem) var(--gutter);
  transition: background-color var(--dur) var(--ease);
}

/* Ajustes pedidos solo para Cómo trabajamos, sin tocar Capacidades (que
   reusa la misma .numbered-list): líneas divisorias en negro (igual que
   el texto de descripción, también en negro); número y título se quedan
   en blanco, y ambos suben 10% de tamaño y pasan a Regular (nada de
   Bold/Medium). */
#como-trabajamos {
  /* Ancho fijo del número: se usa acá Y en el padding del párrafo
     descriptivo (mismo valor, una sola fuente de verdad) para que el
     párrafo quede alineado con el arranque del título, no del número. */
  --wt-index-w: 2.75rem;
}

#como-trabajamos .numbered-list {
  border-top-color: var(--color-black);
  border-top-width: 2px; /* +1px sobre el 1px base */
}
#como-trabajamos .numbered-list__item {
  border-bottom-color: var(--color-black);
  border-bottom-width: 2px; /* +1px sobre el 1px base */
}

/* Número y título alineados por el borde superior (flex-start): con
   baseline el número (mucho más chico) quedaba pegado a la parte de
   abajo del renglón del título, muy por debajo de su borde superior. Lo
   que se quiere es lo contrario: el número arriba, a la misma altura
   que el borde superior de las letras del título. */
#como-trabajamos .numbered-list__trigger { align-items: flex-start; }

#como-trabajamos .numbered-list__index,
#como-trabajamos .numbered-list__label {
  color: var(--color-white);
  font-weight: 400; /* Regular, antes 700 (índice) / 500 (título) */
}

#como-trabajamos .numbered-list__index {
  width: var(--wt-index-w); /* antes min-width: 2.5ch heredado de la base */
  font-size: 1.1rem; /* +10% sobre el 1rem heredado del body */
}

#como-trabajamos .numbered-list__label {
  /* +10% y +20% (pedidos anteriores) y ahora +5pt más (≈0.42rem) sobre
     ese resultado: clamp(1.45rem,2.11vw,1.98rem) + 5pt */
  font-size: clamp(1.87rem, 2.46vw, 2.4rem);
}

#como-trabajamos .numbered-list__desc {
  color: var(--color-black);
  /* Alineado con el título, no con el número: mismo ancho que ocupan
     número + gap del trigger (--wt-index-w + el gap:1.25rem del flex). */
  padding-left: calc(var(--wt-index-w) + 1.25rem);
  /* +2pt (pedido anterior) y ahora +3pt más (≈0.25rem) sobre ese
     resultado: 1.1667rem + 3pt */
  font-size: 1.4167rem;
  /* Interlineado reducido (antes 1.55 heredado de la base). */
  line-height: 1.35;
}

/* Oculto por ahora: la imagen/avatar chico bajo cada párrafo y el
   espacio que reserva (display:none, no solo visibility, para que no
   quede un hueco en blanco donde iba). Fácil de revertir cuando haya
   contenido real para ese lugar. */
#como-trabajamos .numbered-list__meta {
  display: none;
}

/* Distancia de scroll reservada para recorrer los 3 estados (ver
   initWorkTabsScroll(), main.js) — 60vh repartidos en tercios iguales,
   20vh de "dwell" por estado. Mismo patrón que .intro-statement__runway/
   .work-quote__runway: sin fondo ni contenido, invisible mientras
   #como-trabajamos sigue pegada arriba tapándolo. */
.work-tabs__runway {
  height: 60vh;
}

/* ---- Proyectos (nuevo módulo, entre "Cómo trabajamos" y "Antes del
   brief") ----
   Fila horizontal de tarjetas de proyecto: en reposo cada una muestra
   su portada; al hover crece un poco, aparece el título-badge del
   proyecto y arranca a "rodar" la secuencia de fotos de esa carpeta
   como si fuera un gif (ver initProyectosHover(), main.js — datos en
   assets/js/proyectos-data.js). Sin runway: la navegación es
   horizontal, por arrastre con el cursor o el dedo (initProyectosDrag(),
   main.js), no atada al scroll vertical de la página como el resto de
   los módulos con "dwell". */
/* height: 100px más que el resto de módulos .screen (pedido explícito,
   "quiero que esta sección sea más alta, 100px más alta") — se
   sobreescribe puntualmente acá, .screen sigue dando 100vh a todos los
   demás. Como es sticky (.stack-section), esos 100px de más se sienten
   como 100px extra de scroll "quieta" antes de que el módulo 4 empiece
   a cubrirla. */
.proyectos-section {
  --stack-index: 3;
  height: calc(100vh + 100px);
  background: var(--color-white); /* antes negro, pedido explícito */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(1.5rem, 4vh, 2.5rem);
}

/* "WORK" arriba, centrada, negro, MISMO cuerpo que "Capacidades" o
   "Experiencia" (pedido explícito: "el mismo estilo cuerpo y puntaje
   que las palabras capacidades o experiencia no debe estar separado su
   interletrado") — se reusa .display-xl tal cual (ver clase en HTML) y
   acá se afinan puntualmente tamaño/posición sin tocar la clase
   compartida (no debe afectar a Capacidades/Experiencia).
   -20% de tamaño y -20px de posición: pedido explícito de esta ronda.
   font-size sobreescribe el clamp de .display-xl (3.5rem/9vw/8rem) por
   uno 20% más chico; transform sube la palabra sin mover el gap del
   flex (no cambia el alto que ocupa en el layout, solo la pinta
   20px más arriba). */
.proyectos-section__eyebrow {
  color: var(--color-black);
  text-align: center;
  font-size: clamp(2.8rem, 7.2vw, 6.4rem);
  transform: translateY(-20px);
}

/* padding-block (antes 0): sin esto, el título-badge de cada tarjeta
   (que sobresale del borde vía transform, ver más abajo) queda por
   fuera del área "propia" del track. Un contenedor con overflow-x:auto
   sin overflow-y explícito pasa a computar overflow-y:auto también (regla
   del spec de CSS: si un eje no es "visible" el otro deja de serlo) —
   ese contenido que se sale por arriba/abajo terminaba recortado/en una
   zona de scroll vertical fantasma que nunca se usa, así que las
   etiquetas no se veían NUNCA (bug real) y encima el track quedaba con
   una franja de scroll vertical de sobra: cualquier gesto diagonal de
   trackpad la disparaba un poco, dando esa sensación de "salto" /
   bloque blanco tapando cosas al desplazarse (el otro bug reportado).
   Con suficiente padding-block, los badges caben DENTRO de la caja del
   track — ya no hay overflow real que recortar ni scroll vertical
   fantasma que disparar. */
/* Cursor circular azul de marca en vez de la manito/grab del sistema
   (pedido explícito) — SVG inline como data-URI, ~22px (similar al
   tamaño real de un cursor de mano), con el hotspot en su propio
   centro (11 11). Se define una sola vez acá y se reutiliza en :active
   (mismo círculo — no hacía falta distinguir "agarrando" con otra
   forma, no fue parte del pedido). Fallback de palabra clave (grab/
   grabbing) por si algún navegador raro no soporta cursores a medida. */
.proyectos-section__track {
  display: flex;
  align-items: center;
  gap: clamp(0.5rem, 1vw, 0.9rem); /* antes 1.25rem/2.5vw/2.5rem — más pegadas, pedido explícito */
  width: 100%;
  padding-block: 120px; /* subido de 105px: los badges sobresalen más ahora (68%→78% translateY, pedido explícito "saca un poco más los títulos"), necesitan más aire para no recortarse — ver comentario grande arriba de .proyectos-card__titulo */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-inline: var(--gutter);
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22'%3E%3Ccircle cx='11' cy='11' r='10' fill='%230061E5'/%3E%3C/svg%3E") 11 11, grab;
  /* Sin scrollbar visible a propósito: la navegación es por arrastre
     (cursor/touch), no hace falta mostrarla — mismo criterio que
     cualquier carrusel de portafolio. */
  scrollbar-width: none;
}

.proyectos-section__track::-webkit-scrollbar {
  display: none;
}

/* Clase que agrega initProyectosDrag() mientras el cursor sostiene el
   click — mismo círculo, el scroll en sí lo mueve JS ajustando
   track.scrollLeft. */
.proyectos-section__track.is-dragging {
  cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22'%3E%3Ccircle cx='11' cy='11' r='10' fill='%230061E5'/%3E%3C/svg%3E") 11 11, grabbing;
}

.proyectos-card {
  position: relative;
  z-index: 1;
  flex: none;
  width: clamp(230px, 19vw, 320px);
  /* Ver más abajo (:hover): esto es lo que hace que la tarjeta en hover
     empuje de verdad a sus vecinas inmediatas (margin es layout real,
     no un transform visual — sí mueve a los hermanos del flex). */
  transition: margin-inline 0.3s var(--ease);
}

/* Por encima de sus vecinas mientras crece — con el gap tan chico, sin
   esto la tarjeta en hover se dibujaría a veces DETRÁS del borde de la
   vecina en vez de superponerse limpio por encima.

   margin-inline es la pieza clave del pedido "la tarjeta que se
   agranda en el hover SÍ debe ampliar su distancia [con sus vecinas],
   pero las demás NO entre sí": al ser margin (layout real, no un
   transform solo visual), de verdad empuja a sus dos vecinas
   inmediatas hacia los costados dentro del flex — pero como es SOLO
   esta tarjeta la que cambia, la separación entre cualquier OTRO par
   de tarjetas (que no tocan a la que está en hover) queda exactamente
   igual que siempre. */
.proyectos-card:hover {
  z-index: 2;
  margin-inline: 14px;
}

.proyectos-card__frame {
  position: relative;
  aspect-ratio: 3 / 4;
  border-radius: 14px; /* esquinas curvas, pedido explícito (antes 0/recta) */
  overflow: hidden;
  background: var(--color-white); /* antes negro, a juego con el fondo nuevo de la sección */
  transition: transform 0.35s var(--ease);
}

/* La tarjeta en hover crece (pedido explícito, "quiero que la tarjeta
   se agrande en proporcion un poco"). */
.proyectos-card:hover .proyectos-card__frame {
  transform: scale(1.08);
}

.proyectos-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  pointer-events: none; /* el drag/hover siempre lo captura la tarjeta, no la imagen suelta */
  -webkit-user-drag: none;
}

/* Título-badge: invisible en reposo, solo aparece al hover (pedido
   explícito, "los titulos que solo aparecen al hacer over... de resto
   no aparecen"). El rectángulo de color YA viene recto en el PNG — la
   rotación la pone --rot acá (variada tarjeta por tarjeta, ver HTML),
   mismo criterio de "etiqueta pegada a mano" que ya usan las pills de
   Contacto. Historial de tamaño: 120/11vw/190px → +15% (ronda anterior)
   → +20% (esta ronda, pedido explícito) = clamp 166/15.1vw/262px.

   "Deben salir de la tarjeta como en el diseño" — medido a mano sobre
   la imagen de referencia que compartió Alejo (pixeles reales de los
   badges CONINSA/HILTON contra el borde de sus tarjetas): la etiqueta
   sobresale del borde bastante más de lo que tenía acá antes (un
   offset fijo de apenas 14px, casi no se notaba) — cerca de 2/3 de su
   propio alto queda AFUERA de la tarjeta. top:0/bottom:0 + translateY
   en porcentaje (relativo al alto propio del badge, no al de la
   tarjeta) da ese mismo efecto sin importar el tamaño real en cada
   breakpoint. */
.proyectos-card__titulo {
  position: absolute;
  left: 50%;
  width: clamp(166px, 15.1vw, 262px);
  height: auto;
  opacity: 0;
  pointer-events: none;
  z-index: 2;
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
}

.proyectos-card__titulo--bottom {
  bottom: 0;
  transform: translate(-50%, 78%) rotate(var(--rot, 0deg)) scale(0.85);
}
.proyectos-card__titulo--top {
  top: 0;
  transform: translate(-50%, -78%) rotate(var(--rot, 0deg)) scale(0.85);
}

.proyectos-card:hover .proyectos-card__titulo--bottom {
  opacity: 1;
  transform: translate(-50%, 78%) rotate(var(--rot, 0deg)) scale(1);
}
.proyectos-card:hover .proyectos-card__titulo--top {
  opacity: 1;
  transform: translate(-50%, -78%) rotate(var(--rot, 0deg)) scale(1);
}

/* ---- Firma, no agencia (módulo 4) ----
   Diseño final aportado por Alejo: título azul + párrafo blanco + botón
   de contacto, centrados como bloque en la pantalla completa; estrella
   verde de fondo (decorativa) que gira con el scroll. Se sacó la
   etiqueta "Ser útiles" que tenía antes a la derecha (ver más abajo). */
.work-quote {
  --stack-index: 4; /* antes 3: se corrió un lugar para hacerle espacio a Proyectos, ver más abajo */
  /* SIN position:relative acá — .stack-section ya pone position:sticky
     (mismo selector de una sola clase, misma especificidad; al venir
     sections.css después de layout.css en la cascada, un
     position:relative acá lo pisaría y el módulo dejaría de pinearse,
     exactamente el mismo bug que ya se dio y se resolvió en "Qué
     resolvemos"). position:sticky YA cuenta como "positioned" para
     CSS, así que .work-quote__star (position:absolute) igual usa este
     mismo elemento como referencia sin necesitar relative aparte. */
  background: var(--color-black);
  color: var(--color-white);
  display: flex;
  align-items: center;
}

/* Estrella decorativa de fondo — initWorkQuoteStar() (main.js) la anima
   en un loop propio (no solo scroll): "flota" y rebota dentro de los
   bordes de la sección (posición vía transform: translate(), calculada
   cuadro a cuadro con física simple de velocidad+rebote) y ADEMÁS gira
   proporcional al scroll total de la página (rotate()). top:0/left:0
   son solo el punto de anclaje — la posición real la da el transform,
   que JS recalcula todo el tiempo. pointer-events:none para que nunca
   interfiera con el click del botón de abajo; z-index:0 para quedar
   detrás del texto (.work-quote__grid tiene z-index:1); overflow:hidden
   ya lo trae .screen, así que nunca se ve salir de la sección. */
.work-quote__star {
  position: absolute;
  top: 0;
  left: 0;
  width: clamp(200px, 20vw, 380px);
  height: auto;
  pointer-events: none;
  z-index: 0;
  will-change: transform;
}

/* Sin la columna de "Ser útiles", el grid de 2 columnas ya no hace
   falta: el grupo entero (título + párrafo) se centra como bloque único
   en la pantalla. */
.work-quote__grid {
  position: relative;
  z-index: 1;
  display: flex;
  justify-content: center;
  width: 100%;
}

/* Antes título y párrafo iban lado a lado (fila); ahora el párrafo va
   apilado DEBAJO del título, alineado a la izquierda con él (pedido
   explícito, "pongamos el parrafo animado debajo de la frase antes del
   brief alineado a la izquierda"). El bloque entero se sigue centrando
   en pantalla vía .work-quote__grid, arriba. */
.work-quote__group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.5rem;
}

.work-quote__heading {
  font-family: var(--font-display);
  font-weight: 500; /* Medium, pedido explícito (antes Regular) */
  color: var(--color-blue);
  font-size: clamp(2.25rem, 4vw, 3.75rem); /* agrandado un poco (antes 2rem→3.25rem) */
  line-height: 1.05;
  letter-spacing: -0.01em;
}

.work-quote__col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.work-quote__text {
  font-size: clamp(1.25rem, 1.9vw, 1.75rem); /* agrandado un poco (antes 1.1rem→1.5rem) */
  font-weight: 400;
  line-height: 1.4;
  max-width: 42ch;
  color: var(--color-white);
}

/* Reserva la distancia de scroll del "dwell" de la animación del
   párrafo (ver initWordRevealOnScroll(), main.js) — mismo patrón que
   .intro-statement__runway en "Qué resolvemos". */
.work-quote__runway {
  height: 40vh;
}

/* Palabra por palabra, ola continua — mismo tratamiento que el párrafo
   gris de "Qué resolvemos". "¿Café?" quedó afuera a propósito (ya no es
   hijo de [data-quote-reveal], ver HTML): siempre visible, verde fijo.
   Sin transition a propósito: la opacidad
   de cada palabra la fija initWordRevealOnScroll() en cada frame de
   scroll como un valor ya continuo (ver esa función, main.js).
   .is-revealed queda como fallback para mobile (ver responsive.css). */
.work-quote__text .word {
  opacity: 0.14;
}

.work-quote__text .word.is-revealed { opacity: 1; }

/* ---- Capacidades ----
   Composición tomada tal cual de la referencia de Alejo: título grande
   "CAPACIDADES" en negro arriba de todo (ancho completo), y debajo dos
   columnas — izquierda: tarjeta giratoria + párrafo de intro (ambos en
   negro); derecha: lista numerada (mismo tratamiento visual que "Cómo
   trabajamos", ver más abajo). */
.capacidades {
  --stack-index: 5; /* antes 4, ver comentario en .work-quote */
  --wt-index-w: 2.75rem; /* mismo valor que #como-trabajamos: la lista de la derecha vuelve a ser igual, ya no 30% más chica */
  background: var(--color-blue);
  color: var(--color-white);
  display: flex;
  align-items: center;
}

.capacidades__inner { width: 100%; }

/* Ahora es el primer elemento de .capacidades__left (ver HTML) — así,
   con .capacidades__grid en align-items:start, su borde superior queda
   a la misma altura que el primer renglón de la lista de la derecha
   (pedido explícito). Tamaño: sin font-size propio = hereda el de
   .display-xl (--fs-display-xl), para quedar exactamente igual que
   "Experiencia" — pedido explícito. Animación: mismo data-reveal (fade +
   sube desde abajo) que "Experiencia" — ver atributo en el HTML.
   margin-left:-100px: SOLO el título cancela el margin-left:100px que
   trae todo .capacidades__left (tarjeta y párrafo se quedan donde
   estaban), para que el borde izquierdo del texto quede exactamente
   alineado con el de "Experiencia" — pedido explícito ("corre la
   palabra Capacidades a la izquierda, alineada a la palabra
   Experiencia"). */
.capacidades__title {
  color: var(--color-black);
  margin-bottom: clamp(1.5rem, 4vh, 3rem);
  margin-left: -100px;
}

/* Fix: "CAPACIDADES" y "EXPERIENCIA" heredaban --fs-display-xl (clamp
   con 9vw, pensado para texto a todo el ancho de pantalla), pero estos
   títulos viven en columnas de ~mitad de ancho (capacidades__grid /
   experiencia__grid son grids de 2 columnas). A resoluciones de
   escritorio normales (1280-1920px) ese tamaño no cabe en la columna y
   la palabra se parte en dos renglones. Les damos su propio clamp,
   escalado al ancho de columna real, un poco más chico que antes. */
.capacidades__title,
.experiencia__title {
  font-size: clamp(2.6rem, 5vw, 6rem);
}

/* Se deja el split 1fr/1fr tal cual quedó (pedido explícito: "deja la
   sección de la derecha donde está") — este ajuste ya no toca la
   posición, solo el estilo de sus números/títulos/párrafos (ver más
   abajo) y el tamaño de la tarjeta. */
.capacidades__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}

/* Corre TODO el bloque izquierdo (título + tarjeta + párrafo, en ese
   orden ahí adentro) 100px a la derecha de una sola vez, como grupo —
   pedido explícito. align-self:stretch + flex column: hace que esta
   columna ocupe todo el alto real de la fila del grid (que lo define la
   columna derecha, más alta), para poder empujar el párrafo de IA hasta
   el fondo (ver margin-top:auto en .capacidades__intro, más abajo) y
   que su borde inferior quede a la misma altura que el final de la
   lista de la derecha — pedido explícito. */
.capacidades__left {
  margin-left: 100px;
  align-self: stretch;
  display: flex;
  flex-direction: column;
}

/* Historial de tamaño: 50% → 35% → 40.25% → 46.29% → ahora vuelve a
   achicarse a pedido explícito, para quedar EXACTAMENTE del mismo
   tamaño que la tarjeta de "Experiencia" (mismos valores literales:
   clamp(220px,18vw,340px) + aspect-ratio 4/5, en vez del % relativo a la
   columna que traía antes). margin-top:40px se mantiene (la corre hacia
   abajo, sin afectar el título de arriba). El giro (rotateY) va ACÁ, no
   en la imagen de adentro: así rota la tarjeta completa (forma
   redondeada incluida), no solo lo que hay dentro — mismo truco que el
   punto de marca (.dot-spin, components.css): un solo elemento girando
   sin parar nunca, y la "cara nueva" se resuelve cambiando el src de la
   imagen adentro exactamente en el instante en que está de canto (ver
   initRotatingCard(), main.js). overflow:hidden + border-radius acá (no
   en la imagen) para que el recorte redondeado gire junto con todo lo
   demás, como una sola pieza rígida. Alineada a la izquierda por
   defecto (block, sin auto-margin ni centrado). */
.capacidades__media {
  width: clamp(220px, 18vw, 340px);
  margin-top: 40px;
  aspect-ratio: 4 / 5;
  border-radius: 24px;
  overflow: hidden;
  background: var(--color-black);
  animation: capacidades-card-rotate 7s linear infinite;
}

@keyframes capacidades-card-rotate {
  0%   { transform: perspective(1400px) rotateY(0deg); }
  100% { transform: perspective(1400px) rotateY(360deg); }
}

/* object-fit:cover + tamaño 100%/100% del contenedor: la imagen de
   adentro SIEMPRE mide lo mismo que la tarjeta, sin importar la
   proporción real de cada foto. Ya no tiene su propia animación (ver
   .capacidades__media arriba). */
.capacidades__card {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Caja más ancha (60ch, antes 40ch) y tipografía casi igualada a la de
   los párrafos negros de la lista de la derecha (partió del mismo
   1.4167rem que #capacidades .numbered-list__desc, ahora 2pt menos:
   2pt ≈ 0.1667rem, 1.4167rem − 0.1667rem = 1.25rem). margin-top:auto
   (en vez de 1rem fijo): empuja el párrafo hasta el fondo de la columna
   (que ahora ocupa toda la fila, ver align-self:stretch en
   .capacidades__left) para que su borde inferior quede a la misma
   altura que el final de la lista de la derecha — pedido explícito. */
.capacidades__intro {
  color: var(--color-black);
  max-width: 60ch;
  margin-top: auto;
  font-size: 1.25rem;
}

/* Lista numerada: EXACTAMENTE los mismos valores que "Cómo trabajamos"
   (líneas negras más gruesas, número/título blancos, número alineado
   con el borde superior del título, descripción en negro alineada con
   el título — no con el número — y sin la imagen/avatar chica bajo cada
   fila). El 30% más chico que se probó en la vuelta anterior se
   revirtió a pedido: mismo estilo que el módulo 3, punto. Ver
   comentarios largos junto a las reglas equivalentes de
   #como-trabajamos, arriba en este archivo. */
/* margin-right:40px acá (no en __item): la UL es la que manda su
   propio ancho a los <li> (width:auto, heredan el content-box ya
   angosto de su padre), así que alcanza con acortar la UL para que
   ambas líneas (border-top de la UL y border-bottom de cada __item)
   quedelas 40px más cortas del lado derecho — pedido explícito, "muy
   largas". */
#capacidades .numbered-list {
  border-top-color: var(--color-black);
  border-top-width: 2px;
  margin-right: 40px;
}
#capacidades .numbered-list__item {
  border-bottom-color: var(--color-black);
  border-bottom-width: 2px;
}

#capacidades .numbered-list__trigger { align-items: flex-start; }

#capacidades .numbered-list__index,
#capacidades .numbered-list__label {
  color: var(--color-white);
  font-weight: 400;
}

#capacidades .numbered-list__index {
  width: var(--wt-index-w);
  font-size: 1.1rem;
}

/* position:relative + top negativo: con flex-start el título y el
   número comparten el mismo borde superior de SU CAJA, pero el título
   (mucho más grande) tiene más "leading" propio arriba del glifo por
   su tamaño de fuente, así que visualmente se ve más abajo que el
   número aunque las cajas empiecen igual — este nudge hacia arriba
   corrige ESO, sin tocar el número (pedido explícito). */
#capacidades .numbered-list__label {
  font-size: clamp(1.87rem, 2.46vw, 2.4rem);
  position: relative;
  top: -6px;
}

#capacidades .numbered-list__desc {
  color: var(--color-black);
  padding-left: calc(var(--wt-index-w) + 1.25rem);
  font-size: 1.4167rem;
  line-height: 1.35;
}

#capacidades .numbered-list__meta {
  display: none;
}

/* ---- Experiencia ----
   Módulo de una sola pantalla (.screen, 100vh), fondo blanco. Dos bloques
   apilados verticalmente DENTRO del mismo módulo (no son secciones
   separadas): arriba, el renglón de 3 columnas (título+intro / lista de
   industrias / collage), misma lógica compositiva que "Capacidades";
   abajo, la fila de Stats (años/proyectos/etc), separada por una línea.
   space-between (en vez de center) + padding-bottom:0 (pisa el
   padding-block heredado de .section, la regla de #experiencia con ID
   gana por especificidad): empuja el bloque de Stats hasta pegarlo del
   todo al borde inferior de la pantalla, sin margen — pedido explícito. */
#experiencia {
  --stack-index: 6; /* antes 5, ver comentario en .work-quote */
  background: var(--color-white);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding-bottom: 0;
  gap: clamp(1.5rem, 4vh, 3rem);
}

.experiencia__grid {
  display: grid;
  grid-template-columns: 1.15fr 1fr auto;
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
}

.experiencia__title { margin-bottom: 1.5rem; }

/* width:50% (en vez de max-width:34ch): la caja del párrafo pasa a medir
   la mitad del ancho de la columna donde también vive el título
   "Experiencia" (que ocupa prácticamente toda esa columna) — así el
   párrafo se extiende hasta la mitad de la palabra "EXPERIENCIA",
   pedido explícito. */
.experiencia__intro { width: 50%; color: var(--color-muted-on-white); }

/* +25% (pedido explícito) sobre calc() del mismo clamp() de siempre —
   la lista sigue anclada arriba a la izquierda (align-items:start en
   .experiencia__grid, sin centrado ni transform), así que solo crece
   desde ese mismo punto, sin moverse de ubicación. */
#experiencia .industry-list {
  font-size: calc(clamp(1.4rem, 2vw, 2.1rem) * 1.25);
  padding-top: 0.5rem;
  color: var(--color-muted-on-white); /* mismo gris claro que el resto de la landing */
  font-weight: 400; /* Regular, pedido explícito (heredaba 700/Bold de .industry-list base) — sigue en mayúscula (text-transform ya viene de la base) */
}

/* Cada palabra cambia a un color distinto de marca al hacer hover
   (verde, rojo, rosa, amarillo, azul — pedido explícito) + un leve
   agrandado. Solo 4 colores (pedido explícito: verde, azul, rojo, rosa —
   se sacó el amarillo). Con 8 mercados y 4 colores, el ciclo se repite
   cada 4 ítems (nth-child(4n+…)), dos vueltas completas exactas.
   transform-origin a la izquierda para que crezcan sin desplazar el
   bloque hacia la derecha. */
#experiencia .industry-list li {
  transition: color 0.2s var(--ease), transform 0.2s var(--ease);
  transform-origin: 0 50%;
  cursor: default;
}

#experiencia .industry-list li:hover { transform: scale(1.06); }

#experiencia .industry-list li:nth-child(4n + 1):hover { color: var(--color-green); }
#experiencia .industry-list li:nth-child(4n + 2):hover { color: var(--color-blue); }
#experiencia .industry-list li:nth-child(4n + 3):hover { color: var(--color-red); }
#experiencia .industry-list li:nth-child(4n + 4):hover { color: var(--color-pink); }

/* Misma tarjeta giratoria que "Capacidades" (mismo truco: rotateY
   continuo en la tarjeta completa + swap de imagen "de canto", ver
   initRotatingCard() en main.js) — reutiliza el mismo set de fotos de
   M5-tarjetas porque todavía no hay fotos propias en
   assets/img/experiencia/. */
.experiencia__media {
  width: clamp(220px, 18vw, 340px);
  aspect-ratio: 4 / 5;
  border-radius: 24px;
  overflow: hidden;
  align-self: start;
  background: var(--color-black);
  animation: capacidades-card-rotate 7s linear infinite;
}

.experiencia__card {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.experiencia__stats {
  padding-top: clamp(1.5rem, 3vh, 2.5rem);
  padding-bottom: clamp(1.5rem, 3vh, 2.5rem);
}

/* ---- Marquee de Stats: loop infinito derecha → izquierda ----
   overflow:hidden en el wrapper recorta el movimiento; adentro, el
   "track" pone dos copias IDÉNTICAS de .experiencia__figures una al
   lado de la otra (la segunda, aria-hidden, solo para el loop) y se
   anima con translateX(-50%) — como las dos copias miden exactamente lo
   mismo, ese -50% del ancho total del track equivale al ancho de UNA
   copia: cuando la primera termina de salir por la izquierda, la
   segunda ya está exactamente en su lugar, sin salto ni corte visible,
   y el ciclo se repite para siempre (infinite). */
.stats-marquee {
  overflow: hidden;
  width: 100%;
  padding-left: var(--gutter);
}

.stats-marquee__track {
  display: flex;
  width: max-content;
  animation: stats-marquee-scroll 30s linear infinite;
}

@keyframes stats-marquee-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* La frase "14-AÑOS/120-PROYECTOS/8-INDUSTRIAS": arrancó al mismo
   tamaño que tenían los números grandes de antes (calc() sobre
   --fs-stat), y después se redujo un 20% (pedido explícito, esta
   vuelta) — de ahí el *0.8 al final. Cada tramo en un color de marca
   distinto (ver .experiencia__figures-item--* abajo). white-space:nowrap
   + flex-shrink:0: no se parte de línea, cada copia mide lo que pide su
   contenido — el padding-right es el aire entre una copia y la otra del
   marquee (mismo gap que tenía el bloque viejo). */
.experiencia__figures {
  white-space: nowrap;
  flex-shrink: 0;
  font-family: var(--font-display);
  font-weight: 500; /* Medium, igual que tenían los números grandes */
  font-size: calc(var(--fs-stat) * 1.3 * 1.2 * 0.8);
  line-height: 1;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  padding-right: clamp(15px, 1.5vw, 32px);
}

.experiencia__figures-item--red { color: var(--color-red); }
.experiencia__figures-item--blue { color: var(--color-blue); }
.experiencia__figures-item--green { color: var(--color-green); }

/* ---- Team ----
   Ya no es una grilla de tarjetas: una sola foto real del equipo entero
   (fondo negro propio, igual que el resto del sistema) a pantalla
   completa, con "EQUIPO" centrado encima en el verde de marca — pedido
   explícito, calcado de la referencia que compartió Alejo. */
.team-section {
  --stack-index: 7; /* antes 6, ver comentario en .work-quote */
  background: var(--color-black);
  /* SIN position:relative acá — .stack-section (layout.css) ya trae
     position:sticky, que alcanza como contenedor de los hijos absolute
     de abajo; agregar relative acá pisaría el sticky y rompería el pin
     (regla ya aprendida en otros módulos, ver BITACORA). */

  /* Oculto por ahora, pedido explícito ("no lo vamos a usar por ahora")
     — el módulo de Contacto pasó a ser el que cierra el sitio. Queda
     todo el HTML/CSS armado por si se retoma más adelante: alcanza con
     sacar este display:none. */
  display: none;
}

.team-section__photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.team-section__word {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700; /* Bold: en la referencia se ve más pesada que las palabras Regular de otros módulos */
  font-size: clamp(1.75rem, 3.5vw, 3rem);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--color-green);
  text-align: center;
}

/* ---- Contacto ----
   Módulo final del sitio (reemplaza al footer azul anterior). Fondo
   rojo de marca a pantalla completa; adentro, una tarjeta blanca
   (formulario) con el pimiento GRANDE detrás suyo (no al lado — pedido
   explícito, "mucho más grande y detrás del módulo blanco"), y una
   barra de cierre (logo + ciudad + contacto) pegada abajo, alineada al
   mismo margen izquierdo que la tarjeta.

   Segunda vuelta sobre el primer build: Alejo lo vio muy chico contra el
   diseño real que trajo — se midió el diseño (Contacto/diseño.png) y la
   tarjeta ahí ocupa ~52% del ancho y ~64% del alto del canvas ("casi la
   mitad de la pantalla", confirmado explícito), con tipografía bastante
   más grande que la primera pasada acá. Los tamaños de abajo apuntan a
   esas proporciones. */
.contact-section {
  --stack-index: 7; /* mismo lugar que tiene Team en la secuencia de apilado (ahora oculto), ver comentario en .work-quote */
  background: var(--color-red);
  color: var(--color-black);
  display: flex;
  flex-direction: column;
  /* flex-start (antes center): a Alejo le gustó cómo quedaba arriba a la
     izquierda, así que se ancla ahí en vez de centrarse verticalmente
     (pedido explícito, "anclándola ahí"). */
  justify-content: flex-start;
  padding-block: clamp(2rem, 5vh, 3.5rem);
}

/* flex:1 + space-between (pedido explícito): antes el footer (logo,
   ciudad, correo) quedaba pegado justo debajo de la tarjeta porque
   .inner solo medía lo que ocupaba su contenido. Con flex:1 pasa a
   ocupar todo el alto disponible de la sección (100vh menos el
   padding-block), y space-between empuja el footer hasta el borde
   inferior mientras la tarjeta se queda anclada arriba. */
.contact-section__inner {
  display: flex;
  flex-direction: column;
  flex: 1;
  justify-content: space-between;
  gap: clamp(1.5rem, 4vh, 2.5rem);
}

/* Envuelve pimiento + tarjeta: display:inline-block para que su propio
   ancho sea el de la tarjeta (el pimiento es position:absolute, no
   cuenta para el tamaño de esta caja) — así la barra de cierre de abajo,
   que es hermana de este wrapper (no está adentro), arranca exactamente
   en el mismo borde izquierdo que la tarjeta sin tener que calcularlo a mano. */
.contact-section__stage {
  position: relative;
  display: inline-block;
}

/* Detrás de la tarjeta, corrido un poco a la derecha del centro (antes
   left:50% en punto — pedido explícito "córrelo a la derecha un poco")
   y un 30% más chico que la vuelta anterior: 170% × 0.7 ≈ 120%. Sigue
   sobresaliendo por los bordes, solo que menos. */
.contact-section__pepper {
  position: absolute;
  top: 50%;
  left: 58%;
  transform: translate(-50%, -50%);
  height: 120%;
  width: auto;
  z-index: 0;
  pointer-events: none;
}

/* -10% de proporción sobre toda la tarjeta (pedido explícito, "anclada
   arriba a la izquierda, reducila un 10%") — valores de la vuelta
   anterior × 0.9: width 420/50vw/900 → 378/45vw/810; padding
   2/3.5vw/3rem → 1.8/3.15vw/2.7rem. */
.contact-card {
  position: relative;
  z-index: 1;
  background: var(--color-white);
  border-radius: 0; /* esquinas rectilíneas, pedido explícito (antes 20px) */
  width: clamp(378px, 45vw, 810px);
  padding: clamp(1.8rem, 3.15vw, 2.7rem);
}

.contact-card__heading {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: clamp(2.25rem, 3.6vw, 3.375rem); /* -10% sobre 2.5/4vw/3.75rem */
  margin-bottom: 1.125rem;
}

.contact-card__form {
  display: flex;
  flex-direction: column;
}

/* Cada campo es un <label> completo (mejor accesibilidad: el texto de
   ayuda queda asociado al input) — el nombre del campo se repite como
   placeholder Y como texto visualmente oculto arriba (.contact-card__field-label),
   así el diseño se ve igual (solo el placeholder, gris, como en la
   referencia) pero un lector de pantalla sí anuncia qué campo es. */
.contact-card__field-label {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* Espacio entre renglones reducido (pedido explícito, "reduce el
   espacio entre renglones"): 1rem 0 → 0.55rem 0. */
.contact-card__field {
  position: relative;
  display: block;
  border-bottom: 2px solid var(--color-black);
  padding: 0.55rem 0;
}

.contact-card__field input {
  width: 100%;
  border: 0;
  background: none;
  font-family: var(--font-body);
  font-size: clamp(1.35rem, 2.07vw, 1.8rem); /* -10% sobre 1.5/2.3vw/2rem */
  color: var(--color-black);
}

.contact-card__field input::placeholder { color: var(--color-muted-on-white); }

/* Sin esto el navegador dibuja su recuadro azul de foco por defecto
   (pedido explícito, "quitalo que no se vea nada" — bug visto en
   captura del usuario). No se agrega ningún indicador de reemplazo. */
.contact-card__field input:focus {
  outline: none;
  box-shadow: none;
}

/* Mismo alto que el botón fijo de WhatsApp (52.8px) y misma animación
   de "campaneo" al hover (pedido explícito, "el mismo tamaño del vamos
   fijo y la misma animación") — @keyframes whatsapp-fab-ring está
   definido una sola vez en components.css y se reutiliza acá. */
.contact-card__submit {
  align-self: flex-start;
  margin-top: 1.75rem;
  height: 52.8px;
  padding: 0 2rem;
  display: inline-flex;
  align-items: center;
  border-radius: 999px;
  background: var(--color-yellow);
  color: var(--color-blue);
  font-weight: 700;
  font-size: clamp(1.3rem, 1.8vw, 1.6rem);
  transform-origin: 72% 100%;
}

.contact-card__submit:hover {
  animation: whatsapp-fab-ring 0.5s ease-in-out;
}

/* Sin max-width: la línea de arriba (border-top) y el ancho del texto
   deben llegar hasta el final de la tarjeta, igual que los renglones
   del formulario (pedido explícito, "debe igual tener el largo de las
   de arriba" + "la caja de texto debe ir hasta el final de las
   lineas"). Tamaño de letra un poco más grande (NO el -10% general que
   sí aplica al resto de la tarjeta — pedido explícito "debe ser un
   poco mas grande"). */
.contact-card__text {
  margin-top: 2.25rem;
  padding-top: 1.5rem;
  border-top: 2px solid var(--color-black);
  font-size: clamp(1.15rem, 1.65vw, 1.4rem);
  line-height: 1.5;
}

.contact-card__actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 1.5rem;
}

.contact-card__pill {
  padding: 0.55rem 1.25rem;
  border: 2px solid var(--color-black);
  border-radius: 999px;
  font-size: clamp(0.9rem, 1.26vw, 1.08rem); /* -10% sobre 1/1.4vw/1.2rem */
  transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}

/* Mismo esquema de color que Vamos al pasar el mouse (pedido explícito,
   "por over sobre los botones de agendar y WH... cambia el color a
   amarillo con letra azul"). */
.contact-card__pill:hover {
  background: var(--color-yellow);
  color: var(--color-blue);
  border-color: var(--color-yellow);
}

.contact-card__handle {
  margin-left: auto;
  font-weight: 700;
  font-size: clamp(0.945rem, 1.35vw, 1.17rem); /* -10% sobre 1.05/1.5vw/1.3rem */
  color: var(--color-black);
}

/* flex-end (antes center): pedido explícito de que la ciudad y el
   correo se alineen con la parte BAJA del logo, no con su centro
   vertical. */
.contact-section__footer {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.75rem 2rem;
  color: var(--color-black);
}

/* Mismo tamaño que el logo del Hero/header cuando está grande (pedido
   explícito) — reusa la misma imagen Y la misma variable --logo-h-large
   (variables.css) que .site-header__logo-img, en vez de imitar el
   tamaño a ojo con texto. */
.contact-section__logo {
  height: var(--logo-h-large);
  width: auto;
  display: block;
}

.contact-section__footer span,
.contact-section__footer a {
  font-size: clamp(1rem, 1.3vw, 1.2rem);
}

/* display:contents en desktop: el wrapper en sí desaparece del layout,
   span y "a" siguen siendo flex-items sueltos de .contact-section__footer
   tal cual estaban antes de agregar este div — cero cambio visual acá.
   Se agrupan de verdad solo en mobile (ver responsive.css). */
.contact-section__footer-info {
  display: contents;
}

/* ---- Fade-in on scroll ---- */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}

[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}
