/* ═══ nosotros.css ═══ */
/* ============================================================
   NOSOTROS

   Dos bloques, tres generaciones.

   1. EL ORIGEN — medio hero: retrato del abuelo a un costado,
      el relato al otro. 5/7, nunca 6/6.
   2. LA FAMILIA — padre e hijo, uno al lado del otro, pero con
      proporciones distintas y desfase vertical. Dos retratos
      idénticos en una grilla perfecta se leen como "página de
      equipo" de plantilla; distintas proporciones y una caída
      desplazada se leen como una publicación.

   Los espacios de foto vacíos NO son cajas grises. Son placas
   con la especificación de lo que va adentro — sirven de brief
   de fotografía y se ven deliberados hasta que llegue la imagen.
   ============================================================ */

.nosotros {
  background: var(--hueso);
  color: var(--tinta);
  padding-block: clamp(72px, 9vw, 132px);
}

/* ---- Bloque 1: el origen ------------------------------------ */
.origen {
  display: grid;
  gap: clamp(32px, 5vw, 72px);
}
@media (min-width: 900px) {
  .origen {
    grid-template-columns: 5fr 7fr;   /* nunca mitades exactas */
    align-items: center;
  }
}

.origen__texto { max-width: 54ch; }

.nosotros__eyebrow {
  margin: 0 0 var(--s4);
  font-size: var(--eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--piedra);
}

.origen__titulo {
  margin: 0 0 clamp(24px, 3vw, 36px);
  font-size: var(--d2);
  line-height: 1.06;
  letter-spacing: -0.015em;
  max-width: 17ch;
}

.origen__texto p {
  margin: 0 0 1.15em;
  color: var(--piedra);
  font-size: var(--lead);
  line-height: 1.62;
}
.origen__texto p:last-child { margin-bottom: 0; }

/* ---- Bloque 2: la familia ----------------------------------- */
.familia {
  margin-top: clamp(72px, 9vw, 132px);
  padding-top: clamp(48px, 6vw, 80px);
  border-top: 1px solid var(--linea);
  display: grid;
  gap: clamp(48px, 6vw, 80px);
}
@media (min-width: 900px) {
  .familia {
    grid-template-columns: 1fr 1fr;
    gap: clamp(48px, 6vw, 96px);
    align-items: start;
  }
  /* Sin desfase: padre e hijo arrancan a la misma altura.
     El argumento a favor del escalonado era evitar la "grilla de
     equipo", pero rompía la alineación con el resto de la página, y
     una jerarquía visual entre los dos no corresponde. La variedad
     la aportan las proporciones distintas de cada retrato (1:1 y
     3:4), que ya alcanza. */
  .familia { align-items: start; }
}

/* Los tres nombres al mismo tamaño y más grandes: son las personas,
   no un pie de foto. El del abuelo estaba en 11px en versalitas
   —tratamiento de leyenda— mientras padre e hijo iban en display. */
.persona__nombre {
  display: block;
  margin: clamp(20px, 2.4vw, 28px) 0 6px;
  font-family: var(--serif);
  font-variation-settings: var(--fraunces-texto);
  font-weight: 400;
  font-size: clamp(1.75rem, 1.1rem + 2.4vw, 2.75rem);
  line-height: 1.08;
  letter-spacing: -0.015em;
  color: var(--tinta);
}
.persona__pie { display: block; }
.persona__pie .persona__nombre { margin-top: clamp(18px, 2vw, 24px); }

.persona__rol {
  display: block;
  margin: 0 0 clamp(16px, 2vw, 22px);
  font-size: var(--small);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--laton);          /* ~2.9:1 sobre hueso: por eso va en
                                   versalitas y nunca como texto corrido */
}
.persona__bio {
  margin: 0;
  max-width: 46ch;
  color: var(--piedra);
  line-height: 1.62;
}

/* ---- Retratos ----------------------------------------------- */
.retrato { margin: 0; }
/* Los dos retratos no salen de la misma sesión: el del padre tiene
   fondo gris degradado y el del hijo blanco puro. Sobre hueso, uno
   se recorta y el otro flota. El filete y el fondo blanco común
   hacen que cada uno se lea como lámina montada y la diferencia
   pase a ser fotográfica en vez de accidental.
   Arreglo de fondo: una sesión nueva con los tres retratos —
   mismo fotógrafo, mismo fondo, mismo grado. */
.retrato img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
  background: #fff;
  border: 1px solid var(--linea);
}

/* Proporciones deliberadamente distintas entre las tres personas */
.retrato--abuelo img,
.retrato--abuelo .retrato__hueco { aspect-ratio: 4 / 5; }
.retrato--padre img,
.retrato--padre .retrato__hueco  { aspect-ratio: 1 / 1; }
.retrato--hijo img,
.retrato--hijo .retrato__hueco   { aspect-ratio: 3 / 4; }

/* El hueco: una placa con la especificación de la foto que falta.
   No es un marcador de posición gris — es un encargo escrito. */
.retrato__hueco {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 6px;
  padding: clamp(20px, 2.4vw, 28px);
  background: var(--cal);
  border: 1px solid var(--linea);
  color: var(--piedra);
}
.retrato__hueco b {
  display: block;
  font-family: var(--serif);
  font-variation-settings: var(--fraunces-texto);
  font-weight: 400;
  font-size: 1.375rem;
  line-height: 1.2;
  letter-spacing: -0.01em;
  color: var(--tinta);
  margin-bottom: 4px;
}
.retrato__hueco span {
  font-size: var(--micro);
  font-weight: 500;
  letter-spacing: 0.10em;
  text-transform: uppercase;
}

.retrato__pie {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--linea);
  font-size: var(--micro);
  font-weight: 500;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--piedra);
}

/* .muestra y .pendiente se movieron a tokens.css: son
   convención de todo el sitio. */

/* ---- Cuando Nosotros es su propia página ---------------------
   No hay hero que empuje el contenido, así que la sección tiene
   que despejar el header fijo por su cuenta. */
.nosotros--pagina {
  padding-top: calc(var(--header-h) + clamp(56px, 7vw, 104px));
}

/* ═══ inicio.css ═══ */
/* ============================================================
   INICIO — secciones nuevas, tomadas del formato de Grupo DAGS

   Lo que DAGS hace bien y se copia acá es el RITMO: alterna claro y
   oscuro de forma marcada, y reparte los roles — las bandas oscuras
   llevan fotografía y afirmaciones, las claras llevan tipografía y
   datos. No es decoración: cada cambio de suelo marca un cambio de
   tema, así que la página se puede recorrer sin leer.

   Dos diferencias respecto del original, y las dos son a favor:

   · DAGS alterna entre negro y blanco. Acá hay CINCO suelos
     (hueso, cal, cobalto, cobalto hondo, tinta), así que la misma
     estructura se lee con más matiz y sin el contraste de tablero
     de ajedrez.
   · DAGS llena sus tarjetas oscuras con fotografía. Grupo Suca casi
     no tiene fotos, así que donde DAGS pone una imagen acá va una
     tarjeta tipográfica. Es la misma jerarquía sin fingir un
     archivo que no existe.
   ============================================================ */

/* ============================================================
   1. Desde 2018 — la historia, en corto
   ============================================================ */
.desde {
  background: var(--hueso);
  padding-block: clamp(64px, 8vw, 112px);
}
.desde__grid { display: grid; gap: clamp(28px, 4vw, 64px); }
@media (min-width: 900px) {
  .desde__grid { grid-template-columns: 5fr 7fr; align-items: start; }
}
.desde__eyebrow {
  margin: 0 0 var(--s4);
  font-size: var(--eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--piedra);
}
.desde__titulo {
  margin: 0;
  font-size: var(--d2);
  line-height: 1;
  letter-spacing: -0.02em;
}
/* El año en cobalto, como el "1995" de la referencia: el dato
   ancla la frase y de paso justifica el color. */
.desde__anio { color: var(--cobalto); }

.desde__texto p {
  margin: 0 0 1.05em;
  max-width: 58ch;
  color: var(--piedra);
  font-size: var(--lead);
  line-height: 1.62;
}
.desde__texto p:last-of-type { margin-bottom: clamp(24px, 3vw, 32px); }

/* ============================================================
   2. La declaración — la caja con filete
   ============================================================ */
.declaracion {
  background: var(--cal);
  padding-block: clamp(56px, 7vw, 96px);
}
.declaracion__caja {
  max-width: 62ch;
  margin-inline: auto;
  padding: clamp(32px, 4.5vw, 64px);
  border: 1px solid var(--linea);
  border-radius: 18px;
  background: var(--hueso);
}
.declaracion__texto {
  margin: 0;
  font-family: var(--serif);
  font-variation-settings: 'opsz' 144, 'SOFT' 0, 'WONK' 0;
  font-weight: 400;
  font-size: clamp(1.5rem, 1rem + 2.1vw, 2.375rem);
  line-height: 1.18;
  letter-spacing: -0.015em;
  color: var(--tinta);
  text-wrap: balance;
}
.declaracion__firma {
  margin: clamp(24px, 3vw, 32px) 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--linea);
  font-size: var(--micro);
  font-weight: 600;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--piedra);
}

/* ============================================================
   3. Qué construimos — las tipologías
   ============================================================ */
.tipos {
  background: var(--hueso);
  padding-block: clamp(56px, 7vw, 96px);
}
.tipos__eyebrow {
  margin: 0 0 clamp(32px, 4vw, 56px);
  font-size: var(--eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--piedra);
}
.tipos__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--linea);   /* los filetes salen del fondo: una sola línea entre celdas */
  border: 1px solid var(--linea);
  border-radius: 18px;
  overflow: hidden;
}
@media (min-width: 760px)  { .tipos__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1100px) { .tipos__grid { grid-template-columns: repeat(5, 1fr); } }

/* Son cinco tipologías, y cinco no entra parejo ni en dos columnas
   ni en tres: el quinto queda solo y el hueco se pinta del color del
   contenedor, que se lee como una celda que falta y no como espacio.
   La última se estira para cerrar su fila. A cinco columnas encaja
   justo y no hace falta nada. */
@media (max-width: 1099px) {
  .tipo:last-child { grid-column: span 2; }
}

.tipo {
  background: var(--hueso);
  padding: clamp(22px, 2.6vw, 32px);
  display: flex;
  flex-direction: column;
  align-items: center;      /* el SVG, centrado con el texto */
  text-align: center;
  gap: var(--s4);
}
/* Marcas dibujadas a mano en SVG, no una fuente de iconos ni emoji.
   Cada una describe la tipología, no un concepto genérico. */
.tipo svg {
  width: 34px; height: 34px;
  fill: none;
  stroke: var(--cobalto);
  stroke-width: 1.25;
  stroke-linejoin: round;
}
.tipo__nombre {
  margin: 0;
  font-size: var(--small);
  font-weight: 600;
  line-height: 1.3;
  color: var(--tinta);
}
.tipo__dato {
  margin: 0;
  font-size: 12px;
  line-height: 1.4;
  color: var(--piedra);
  font-variant-numeric: lining-nums tabular-nums;
}

/* ============================================================
   4. Nuestro grupo — banda oscura con tarjetas
   ============================================================ */
.grupo {
  background: var(--tinta);
  color: var(--hueso);
  padding-block: clamp(64px, 8vw, 112px);
}
.grupo__eyebrow {
  margin: 0 0 var(--s4);
  font-size: var(--eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: rgba(250, 248, 245, 0.62);
}
.grupo__titulo {
  margin: 0 0 var(--s4);
  font-size: var(--d2);
  line-height: 1.04;
  letter-spacing: -0.015em;
  max-width: 18ch;
}
.grupo__entrada {
  margin: 0 0 clamp(36px, 4.5vw, 56px);
  max-width: 56ch;
  color: rgba(250, 248, 245, 0.82);
  font-size: var(--lead);
  line-height: 1.6;
}

/* Escalera de columnas para las CUATRO unidades. Se declara acá
   completa y en orden ascendente: había una regla de 3 columnas a
   820px que, al quedar antes de las nuevas, hacía que a 900px
   ganaran 2 columnas por orden de cascada. */
.grupo__grid { display: grid; gap: clamp(16px, 2vw, 24px); }

/* Donde DAGS pone una foto de fondo, acá va una tarjeta
   tipográfica: misma jerarquía, sin inventar un archivo. */
.unidad {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  min-height: 230px;
  padding: clamp(24px, 3vw, 32px);
  border: 1px solid rgba(250, 248, 245, 0.20);
  border-radius: 18px;
  background: rgba(250, 248, 245, 0.04);
  text-decoration: none;
  color: inherit;
  transition: border-color 220ms var(--ease), background-color 220ms var(--ease);
}
.unidad:hover {
  border-color: rgba(250, 248, 245, 0.45);
  background: rgba(250, 248, 245, 0.07);
}
.unidad__rol {
  margin: 0;
  font-size: var(--micro);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cobalto-claro);   /* 6.8:1 sobre tinta */
}
.unidad__nombre {
  margin: 0;
  font-size: var(--d3);
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--hueso);
}
.unidad__texto {
  margin: auto 0 0;
  font-size: var(--small);
  line-height: 1.55;
  color: rgba(250, 248, 245, 0.78);
}
.unidad__flecha {
  font-size: var(--small);
  color: var(--hueso);
  border-bottom: 1px solid rgba(250, 248, 245, 0.45);
  align-self: flex-start;
  padding-bottom: 2px;
}
.grupo :focus-visible { outline-color: var(--hueso); }

/* ============================================================
   5. Cierre — somos un grupo empresarial
   ============================================================ */
.cierre-grupo {
  background: var(--cal);
  padding-block: clamp(64px, 8vw, 112px);
}
.cierre-grupo__grid { display: grid; gap: clamp(28px, 4vw, 64px); }
@media (min-width: 900px) {
  .cierre-grupo__grid { grid-template-columns: 7fr 5fr; align-items: end; }
}
.cierre-grupo__titulo {
  margin: 0;
  font-size: var(--d2);
  line-height: 1.04;
  letter-spacing: -0.015em;
  max-width: 18ch;
}
.cierre-grupo__texto {
  margin: 0 0 clamp(24px, 3vw, 32px);
  max-width: 48ch;
  color: var(--piedra);
  font-size: var(--lead);
  line-height: 1.6;
}

/* Cuatro unidades: la grilla pasa a 2 y luego a 4 columnas. Con 3
   columnas la cuarta tarjeta quedaba sola en una fila. */
@media (min-width: 620px)  { .grupo__grid { grid-template-columns: 1fr 1fr; } }
/* Tres unidades desde que salió Edubol, no cuatro. Con `repeat(4, 1fr)`
   la tercera quedaba sola en una fila de cuatro llenando el 25%, que es
   el hueco que se lee como «falta una». */
@media (min-width: 1100px) { .grupo__grid { grid-template-columns: repeat(3, 1fr); } }
/* Entre 620 y 1099 son dos columnas: la tercera va sola y ocupa las dos. */
@media (min-width: 620px) and (max-width: 1099px) {
  .unidad:last-child:nth-child(odd) { grid-column: span 2; }
}

/* Tarjeta sin destino: mismo aspecto, sin el hover ni la flecha que
   prometen un enlace que no existe. */
.unidad--sin-enlace { cursor: default; }
.unidad--sin-enlace:hover {
  border-color: rgba(250, 248, 245, 0.20);
  background: rgba(250, 248, 245, 0.04);
}
.unidad__nota {
  margin-top: auto;
  font-size: var(--micro);
  line-height: 1.5;
}
.pie__sin-enlace {
  display: flex;
  align-items: center;
  min-height: var(--tap);
  color: rgba(250, 248, 245, 0.86);
}

/* ═══ galeria.css ═══ */
/* ============================================================
   ENTREGA + GALERÍA DE OBRA

   Dos bloques con propósitos opuestos.

   LA ENTREGA es la única fotografía del sitio que no se puede
   simular: la familia, la casa terminada y las llaves. Un render
   muestra lo que va a existir; esto prueba que ya existió. Va
   grande y sobre fondo oscuro, sin competencia.

   ⚠️ Aparecen personas identificables. Publicar la imagen de
   particulares reconocibles exige su autorización, así que la
   sección lleva marca de pendiente hasta tenerla — igual que los
   testimonios. No es un tecnicismo: es la familia de un cliente.

   LA GALERÍA es lo contrario: registro, no publicidad. Fotos de
   teléfono tomadas en las entregas, con luz plana y encuadres de
   ocasión. Se publican DELIBERADAMENTE contenidas —columnas de
   ~30 %— porque a ese tamaño la luz plana y la distorsión del
   lente dejan de leerse como defectos y empiezan a leerse como
   documento. Ampliadas a pantalla completa harían lo contrario.
   ============================================================ */

.entrega {
  background: var(--tinta);
  color: var(--hueso);
  padding-block: clamp(64px, 8vw, 104px);
}
.entrega__eyebrow {
  margin: 0 0 var(--s4);
  font-size: var(--eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: rgba(250, 248, 245, 0.72);
}
.entrega__titulo {
  margin: 0 0 var(--s4);
  font-size: var(--d2);
  line-height: 1.04;
  letter-spacing: -0.015em;
  max-width: 18ch;
}
.entrega__entrada {
  margin: 0 0 clamp(32px, 4vw, 52px);
  max-width: 54ch;
  color: rgba(250, 248, 245, 0.82);
  font-size: var(--lead);
  line-height: 1.6;
}
.entrega__lamina { margin: 0; }
.entrega__lamina img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: 18px;
}
.entrega__pie {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px var(--s5);
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid rgba(250, 248, 245, 0.22);
  font-size: var(--micro);
  font-weight: 500;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: rgba(250, 248, 245, 0.72);
}

/* ---- La galería --------------------------------------------- */
.galeria { background: var(--hueso); padding-block: clamp(56px, 7vw, 96px); }

.gal {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(16px, 2vw, 28px);
}
@media (min-width: 620px) { .gal { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px) { .gal { grid-template-columns: repeat(3, 1fr); } }

.gal__item { margin: 0; }
.gal__item img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 14px;
  border: 1px solid var(--linea);
}
.gal__pie {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin-top: 10px;
}
.gal__pie b {
  font-size: var(--small);
  font-weight: 600;
  color: var(--tinta);
}
.gal__pie span {
  font-size: 12px;
  color: var(--piedra);
  font-variant-numeric: lining-nums tabular-nums;
}

/* ---- Marca de las tarjetas del grupo ------------------------- */
/* Los logos de los colegios son JPG cuadrados con fondo blanco.
   Sobre la banda oscura eso sería un recuadro blanco pegado, así
   que van dentro de un disco: el fondo del logo deja de leerse
   como error y pasa a ser parte de la forma. */
.unidad__marca {
  display: block;
  width: 44px; height: 44px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--hueso);
  flex: none;
}
.unidad__marca img,
.unidad__marca picture { display: block; width: 100%; height: 100%; object-fit: cover; }

/* ---- Banda de Casa Alicia en el índice de Proyectos ----------
   Es el único edificio del portafolio, así que no entra en la
   lista de casas ni en la tabla de "otras obras": tiene su propia
   banda, con la fachada al lado. */
.alicia { background: var(--cal); padding-block: clamp(56px, 7vw, 96px); }
.alicia__grid { display: grid; gap: clamp(28px, 4vw, 56px); align-items: center; }
@media (min-width: 900px) {
  .alicia__grid { grid-template-columns: 6fr 5fr; }   /* desiguales */
}
.alicia__lamina { margin: 0; }
.alicia__lamina img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 18px;
  border: 1px solid var(--linea);
}

/* ---- Proyecto entregado destacado (Calle 11) -----------------
   No es una página propia: sigue la regla de que solo lo que está
   en venta se gana una. Pero es la obra entregada mejor
   documentada que hay, así que va como sección con su fachada
   grande y la galería debajo. Sirve de prueba del estándar, no
   de aviso de venta — y el pie lo dice explícitamente. */
.destacada { background: var(--hueso); padding-block: clamp(56px, 7vw, 96px); }
.destacada__intro {
  display: grid;
  gap: clamp(20px, 3vw, 48px);
  margin-bottom: clamp(28px, 3.5vw, 44px);
}
@media (min-width: 900px) {
  .destacada__intro { grid-template-columns: 6fr 6fr; align-items: end; }
}
.destacada__lamina { margin: 0; }
.destacada__lamina img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: 18px;
  border: 1px solid var(--linea);
}
@media (min-width: 900px) {
  .destacada__lamina img { aspect-ratio: 16 / 9; }
}


/* La última fotografía sola en su fila deja medio ancho vacío y se lee
   como una imagen que falta. Que ocupe la fila. Al final del archivo a
   propósito: con igual especificidad gana la última regla, y en este
   proyecto ya se perdió tiempo poniendo overrides antes de su base. */
@media (min-width: 620px) and (max-width: 899px) {
  .gal__item:last-child:nth-child(odd) { grid-column: span 2; }
  .gal__item:last-child:nth-child(odd) img { aspect-ratio: 16 / 9; }
}
@media (min-width: 900px) {
  .gal__item:last-child:nth-child(3n + 1) { grid-column: span 3; }
  .gal__item:last-child:nth-child(3n + 1) img { aspect-ratio: 16 / 9; }
}

/* ═══ ciudad.css ═══ */
/* ============================================================
   NOSOTROS — bloques adicionales

   MISIÓN / VISIÓN en dos columnas DESIGUALES separadas por un
   filete vertical. No son dos tarjetas: son dos declaraciones
   en la misma hoja. Dos cajas iguales lado a lado es el patrón
   de plantilla; un filete entre dos columnas de distinto ancho
   se lee como un documento.

   LOS PRINCIPIOS son verificables uno por uno — cada línea puede
   comprobarse contra un contrato, una visita o la página de
   proyectos. Eso es lo que los distingue de una lista de valores
   corporativos ("compromiso, excelencia, innovación"), que no
   dice nada porque nadie puede desmentirla.

   LA CIUDAD cierra con la fotografía a sangre. Va rotulada: esas
   torres no son obra de Grupo Suca, y el sitio no puede dar a
   entender lo contrario.
   ============================================================ */

.vision {
  background: var(--cal);
  padding-block: clamp(64px, 8vw, 104px);
}
.vision__grid { display: grid; gap: clamp(32px, 4vw, 56px); }
@media (min-width: 860px) {
  .vision__grid {
    grid-template-columns: 5fr 7fr;   /* desiguales, nunca mitades */
    gap: clamp(40px, 5vw, 80px);
  }
  /* El filete que separa: vive en la segunda columna, no es un
     borde de caja. */
  .vision__col + .vision__col {
    padding-left: clamp(40px, 5vw, 80px);
    border-left: 1px solid var(--linea);
  }
}
.vision__titulo {
  margin: 0 0 var(--s4);
  font-size: var(--d3);
  line-height: 1.1;
  letter-spacing: -0.01em;
}
.vision__texto {
  margin: 0;
  max-width: 52ch;
  color: var(--piedra);
  font-size: var(--lead);
  line-height: 1.62;
}

/* ---- Los principios ----------------------------------------- */
.principios {
  margin: clamp(48px, 6vw, 80px) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 0;
  border-top: 1px solid var(--linea);
}
@media (min-width: 860px) {
  .principios { grid-template-columns: 1fr 1fr; column-gap: clamp(40px, 5vw, 80px); }
}
.principios li {
  padding-block: clamp(18px, 2.2vw, 26px);
  border-bottom: 1px solid var(--linea);
  color: var(--piedra);
  line-height: 1.6;
}
.principios b {
  display: block;
  margin-bottom: 4px;
  font-weight: 600;
  color: var(--tinta);
}

/* ============================================================
   La ciudad
   ============================================================ */
.ciudad {
  position: relative;
  background: var(--cobalto-hondo);
  color: var(--hueso);
  overflow: hidden;
  padding-block: clamp(72px, 9vw, 132px);
}
.ciudad__lamina {
  position: absolute;
  inset: 0;
  margin: 0;
  z-index: 0;
}
.ciudad__lamina img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 55% center;
}
/* Velo tintado con el azul de marca. Al 62 % el peor píxel detrás
   del texto medía 4.19:1 — apenas por debajo del mínimo. Al 68 %
   (el mismo valor calculado para la barra del header) el texto
   blanco pasa 4.5:1 incluso sobre los puntos más claros de la
   fotografía: ventanas encendidas y la brasa del atardecer. */
.ciudad__lamina::after {
  content: "";
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--cobalto-hondo) 68%, transparent);
}
.ciudad .contenedor { position: relative; z-index: 1; }

.ciudad__texto { max-width: 58ch; }
.ciudad__eyebrow {
  margin: 0 0 var(--s4);
  font-size: var(--eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: rgba(250, 248, 245, 0.78);
}
.ciudad__titulo {
  margin: 0 0 var(--s5);
  font-size: var(--d2);
  line-height: 1.04;
  letter-spacing: -0.015em;
}
.ciudad__entrada {
  margin: 0;
  color: var(--hueso);
  font-size: var(--lead);
  line-height: 1.62;
}
.ciudad__pie {
  margin: clamp(28px, 3.5vw, 40px) 0 0;
  padding-top: 14px;
  border-top: 1px solid rgba(250, 248, 245, 0.28);
  font-size: var(--micro);
  font-weight: 500;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: rgba(250, 248, 245, 0.78);
}

/* ═══ visor.css ═══ */
/* ============================================================
   VISOR DE IMÁGENES

   Fondo casi opaco en el azul de la marca —no negro— para que
   ampliar una foto siga sintiéndose parte del sitio y no una
   ventana del navegador.

   Los tres controles son círculos de 48px: es el único lugar del
   sitio donde hay botones redondos, y se justifica porque flotan
   sobre una fotografía, donde una píldora se leería como una
   calcomanía pegada.
   ============================================================ */

.visor {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 48px);
  background: rgba(9, 20, 42, 0.985);   /* medido: el 0,96 dejaba pasar el texto de atrás */
  animation: visor-entra 180ms var(--ease) both;
}
@keyframes visor-entra { from { opacity: 0; } to { opacity: 1; } }

/* El fondo no se desplaza mientras el visor está abierto. */
.visor-abierto { overflow: hidden; }

.visor__marco {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(12px, 2vw, 18px);
  max-width: min(100%, 1500px);
  max-height: 100%;
}

.visor__img {
  display: block;
  max-width: 100%;
  /* Se reserva el alto del pie y de la barra de controles para que
     una imagen alta no empuje la leyenda fuera de la pantalla. */
  max-height: calc(100svh - clamp(120px, 20vh, 190px));
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 6px;
}
/* La entrada es una TRANSICIÓN, no un keyframe, y esto se midió.
   Con `animation` reactivada por clase, avanzar dos fotos con 60ms de
   diferencia devolvía la opacidad a 0,00 y rehacía los 260ms enteros:
   un keyframe reinicia desde cero, no retoma. Una transición
   interpola desde el valor actual, así que pasar rápido se ve
   continuo en vez de parpadear.

   Además desaparece el problema de cascada que obligó a la clase: una
   propiedad animada le gana a cualquier declaración normal, pero una
   transición no — solo interpola entre valores calculados. Por eso
   `.visor--cargando` ya puede usar `opacity` y no `visibility`, y el
   JS se ahorra el baile de sacar la clase, forzar reflow y reponerla.

   Nota deliberada: cuando la foto ya está precargada —lo habitual,
   porque se piden las dos vecinas— no hay transición ninguna, porque
   `.visor--cargando` nunca llega a aplicarse. Es lo correcto: avanzar
   con la flecha es una acción de teclado, y esas no llevan animación.
   El fundido queda solo para cuando de verdad hubo que esperar. */
.visor__img {
  transition: opacity 160ms var(--ease), transform 160ms var(--ease);
}

.visor__pie {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 6px 16px;
  max-width: 62ch;
  text-align: center;
  font-size: var(--small);
  line-height: 1.5;
  color: rgba(250, 248, 245, 0.92);    /* 13,9:1 sobre el fondo */
}
.visor__cuenta {
  font-size: var(--micro);
  font-weight: 600;
  letter-spacing: 0.12em;
  color: rgba(250, 248, 245, 0.62);
  font-variant-numeric: lining-nums tabular-nums;
}

/* ---- Los tres controles ---- */
.visor__cerrar,
.visor__nav {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 1px solid rgba(250, 248, 245, 0.28);
  border-radius: 50%;
  background: rgba(9, 20, 42, 0.55);
  color: var(--hueso);
  cursor: pointer;
  transition: background-color 160ms linear, border-color 160ms linear;
}
.visor__cerrar:hover,
.visor__nav:hover {
  background: rgba(250, 248, 245, 0.16);
  border-color: rgba(250, 248, 245, 0.55);
}
.visor__cerrar:focus-visible,
.visor__nav:focus-visible {
  outline: 2px solid var(--hueso);
  outline-offset: 3px;
}
.visor__cerrar svg,
.visor__nav svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.visor__cerrar { top: clamp(12px, 3vw, 24px); right: clamp(12px, 3vw, 24px); }
.visor__nav--antes { left:  clamp(8px, 2vw, 24px); top: 50%; transform: translateY(-50%); }
.visor__nav--luego { right: clamp(8px, 2vw, 24px); top: 50%; transform: translateY(-50%); }

/* En el teléfono las flechas bajan al pie: a los costados tapan la
   foto, y el pulgar llega mucho mejor abajo que al centro del borde. */
@media (max-width: 559px) {
  .visor__nav {
    top: auto;
    bottom: clamp(12px, 4vw, 20px);
    transform: none;
  }
  .visor__nav--antes { left: 50%; margin-left: -60px; }
  .visor__nav--luego { right: 50%; margin-right: -60px; }
  .visor__img { max-height: calc(100svh - 210px); }
  .visor__pie { padding-bottom: 56px; }
}

/* ---- La imagen ampliable, en la página ---- */
.visor-listo img { cursor: zoom-in; }
.visor-listo img:focus-visible {
  outline: 3px solid var(--cobalto);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .visor { animation: none; }
}

/* ============================================================
   INDICADOR DE CARGA

   Aparece solo cuando de verdad hay espera. El truco está en el
   `transition-delay` de 160 ms: si la imagen ya estaba en caché —que
   con la precarga de vecinas es el caso habitual— la clase se pone y
   se saca dentro de ese margen y el círculo nunca llega a verse. Un
   indicador que parpadea en cada toque hace sentir la interfaz MÁS
   lenta, no menos, porque anuncia una espera que no existió.

   Mientras carga, la imagen se oculta del todo. Es a propósito: antes
   se veía la foto anterior con el rótulo de la nueva, y un marco
   vacío con un indicador es honesto donde eso era falso.
   ============================================================ */
.visor__cargador {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 38px;
  height: 38px;
  margin: -19px 0 0 -19px;
  border: 2px solid rgba(250, 248, 245, 0.22);
  border-top-color: var(--hueso);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  transition: opacity 140ms linear 160ms;
  animation: visor-gira 720ms linear infinite;
}
.visor--cargando .visor__cargador { opacity: 1; }

@keyframes visor-gira { to { transform: rotate(360deg); } }

/* Ya puede ser `opacity` y no `visibility`: sin animación de por medio
   la declaración se aplica, y encima es lo que la transición necesita
   para tener desde dónde interpolar. */
.visor--cargando .visor__img { opacity: 0; transform: scale(0.985); }

@media (prefers-reduced-motion: reduce) {
  .visor__cargador { animation: none; border-top-color: rgba(250, 248, 245, 0.75); }
  /* El fundido se queda —no marea a nadie y avisa que la foto llegó—;
     lo que se va es el desplazamiento. */
  .visor__img { transition: opacity 160ms linear; }
  .visor--cargando .visor__img { transform: none; }
}

/* ═══ footer.css ═══ */
/* ============================================================
   PIE DE PÁGINA

   Cobalto profundo, el mismo suelo que la banda de cifras — así
   el sitio cierra con el color con el que abre.

   Columnas DESIGUALES (5/2/2/3): la marca se queda con el ancho,
   los índices ocupan lo que necesitan. Cuatro columnas idénticas
   son el pie de plantilla.

   La línea inferior nombra al grupo — constructora y los dos
   colegios. Eso establece hoy la estructura multi-negocio, así
   que sumarla en serio más adelante es un cambio de contenido y
   no un rediseño.
   ============================================================ */

.pie {
  background: var(--cobalto-hondo);
  color: rgba(250, 248, 245, 0.78);   /* 8.0:1 sobre #102A70 */
  padding-block: clamp(56px, 7vw, 96px) clamp(28px, 3vw, 40px);
  font-size: var(--small);
}

.pie__grid {
  display: grid;
  gap: clamp(40px, 5vw, 64px);
}
@media (min-width: 900px) {
  .pie__grid {
    grid-template-columns: 5fr 2fr 2fr 3fr;
    gap: clamp(32px, 4vw, 72px);
  }
}

/* ---- Columna de marca ---- */
.pie__marca { max-width: 34ch; }
.pie__logo {
  display: inline-flex;
  align-items: center;
  color: var(--hueso);
  padding-block: 10px;      /* 24 + 10 + 10 = 44px de área táctil */
}
.pie__logo svg { display: block; width: 190px; height: 24px; }

.pie__nota {
  margin: clamp(20px, 2.4vw, 28px) 0 0;
  line-height: 1.6;
}

.pie__contacto {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  margin-top: clamp(20px, 2.4vw, 28px);
}
.pie__contacto a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  color: var(--hueso);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: border-color 160ms linear;
}
.pie__contacto a:hover { border-bottom-color: var(--laton); }

/* ---- Columnas de enlaces ---- */
.pie__titulo {
  margin: 0 0 var(--s4);
  font-size: var(--eyebrow);
  font-weight: 500;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: rgba(250, 248, 245, 0.60);
}

.pie__lista { margin: 0; padding: 0; list-style: none; }
.pie__lista a {
  display: flex;
  align-items: center;
  min-height: var(--tap);          /* 44px sin necesidad de rellenos */
  color: rgba(250, 248, 245, 0.86);
  text-decoration: none;
  transition: color 160ms linear;
}
.pie__lista a:hover { color: var(--hueso); }
.pie__lista a[aria-current="page"] { color: var(--hueso); }

/* Los enlaces externos llevan una marca discreta: se sale del
   sitio, y conviene decirlo antes del clic y no después. */
.pie__lista a[target="_blank"]::after {
  content: "↗";
  margin-left: 8px;
  font-size: 0.85em;
  color: rgba(250, 248, 245, 0.50);
}

/* ---- Barra inferior ---- */
.pie__base {
  margin-top: clamp(48px, 6vw, 80px);
  padding-top: 20px;
  border-top: 1px solid rgba(250, 248, 245, 0.20);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 10px var(--s5);
  font-size: 12px;
  color: rgba(250, 248, 245, 0.66);
}
.pie__grupo { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.pie__grupo span:not(:last-child)::after {
  content: " ·";
  margin-left: 8px;
  color: rgba(250, 248, 245, 0.40);
}

.pie :focus-visible { outline-color: var(--hueso); }


/* ============================================================
   Pie en celular

   Cuatro columnas apiladas dan un pie larguísimo: en un teléfono
   son casi dos pantallas de desplazamiento para llegar al final.
   Se compacta en tres pasos:
     · las dos listas de enlaces van a dos columnas, no a una
     · la descripción de marca se oculta: ya está en Nosotros y en
       el inicio, y acá solo estira
     · la línea del grupo del pie se oculta: repite la columna
       "El grupo" que está justo arriba

   Los 44px de área táctil NO se tocan: es la regla del sitio y
   ahorrar 4px por enlace no justifica romperla.
   ============================================================ */
@media (max-width: 767px) {
  .pie { padding-block: clamp(40px, 8vw, 56px) 24px; }
  .pie__grid { gap: 32px; }
  .pie__nota { display: none; }
  /* El logo se achica, pero el área táctil no: 20 + 12 + 12 = 44. */
  .pie__logo svg { width: 158px; height: 20px; }
  .pie__logo { padding-block: 12px; }

  /* Navegación y El grupo, lado a lado */
  .pie__grid > :nth-child(2),
  .pie__grid > :nth-child(3) {
    grid-column: span 1;
  }
  .pie__grid {
    grid-template-columns: 1fr 1fr;
  }
  .pie__grid > :first-child,
  .pie__grid > :last-child { grid-column: 1 / -1; }

  .pie__contacto { margin-top: 16px; }

  .pie__base {
    margin-top: 28px;
    padding-top: 16px;
    font-size: var(--micro);
  }
  /* La línea del grupo se repite con la columna "El grupo": sobra. */
  .pie__grupo { display: none; }
}

/* ═══ motion.css ═══ */
/* ============================================================
   MOVIMIENTO — un sistema, no efectos sueltos

   Reglas que sostienen todo lo de abajo:

   1. UNA SOLA CURVA. Todo usa --ease. Cuando cada elemento tiene
      su propio easing, el sitio se lee escrito por varias manos.
   2. DISTANCIAS CORTAS. 14px, no 40. Lo caro se mueve poco: un
      desplazamiento grande grita "animación", uno chico solo se
      siente.
   3. UNA SOLA VEZ. Nada se re-anima al volver a pasar. Repetir
      convierte el movimiento en ruido durante el resto de la
      sesión.
   4. NADA SE MUEVE ANTES DE ESTAR EN PANTALLA. El hero anima al
      cargar; el resto espera a entrar en cuadro.
   5. EL CONTENIDO EXISTE SIN JS. Si el script falla, todo queda
      visible: las clases de partida solo se aplican cuando el JS
      marca el documento con `js-mov`.
   ============================================================ */

:root {
  --mov-dist: 14px;
  --mov-dur: 700ms;
  --mov-paso: 80ms;      /* desfase entre hermanos de un grupo */

  /* Estas eran cifras fijas repartidas por el archivo. Son variables
     porque el celular necesita las mismas animaciones más cortas, y
     eso no se puede hacer si el valor está escrito en cada regla. */
  --mov-img-op:   900ms;   /* la imagen sube su opacidad          */
  --mov-img-tr:   600ms;   /* y cede la escala, algo más lenta    */
  --mov-hero-bg: 1800ms;   /* el fondo del hero                   */
  --mov-hero-tx:  900ms;   /* cada línea del hero                 */
  --mov-carga:    760ms;   /* cascada de entrada de página        */
  --mov-lamina:  1100ms;   /* la portada de las páginas de obra   */
  --mov-hero-d1:  180ms;
  --mov-hero-d2:  300ms;
  --mov-hero-d3:  520ms;
  --mov-hero-d4:  640ms;
}

/* ---- Aparición base ----------------------------------------- */
/* El estado de partida solo aplica si el JS está vivo. Sin JS no
   hay `js-mov` en el <html> y el contenido se ve normal. */
.js-mov .revelar {
  opacity: 0;
  transform: translateY(var(--mov-dist));
  transition: opacity var(--mov-dur) var(--ease),
              transform var(--mov-dur) var(--ease);
  transition-delay: var(--mov-retraso, 0ms);
}
.js-mov .revelar.esta-visible {
  opacity: 1;
  transform: none;
}

/* ---- Imágenes: se destapan, no aparecen ---------------------- */
/* La figura recorta y la imagen entra desde una escala levemente
   mayor. Da la sensación de que la foto ya estaba ahí y se
   descubre, en vez de materializarse. */
.js-mov .revelar-img {
  overflow: hidden;
}
.js-mov .revelar-img > img,
.js-mov .revelar-img > picture > img {
  opacity: 0;
  transform: scale(1.04);
  transition: opacity var(--mov-img-op) var(--ease), transform var(--mov-img-tr) var(--ease);
  transition-delay: var(--mov-retraso, 0ms);
}
.js-mov .revelar-img.esta-visible > img,
.js-mov .revelar-img.esta-visible > picture > img {
  opacity: 1;
  transform: none;
}

/* ---- Hero: el único momento orquestado ----------------------- */
/* Ocurre al cargar, no al hacer scroll: ya está en pantalla.
   La imagen cede escala mientras el texto sube en cascada, así
   que las dos cosas terminan juntas y se lee como un solo gesto. */
.js-mov .hero__fondo img {
  animation: hero-fondo var(--mov-hero-bg) var(--ease) both;
}
@keyframes hero-fondo {
  from { transform: scale(1.06); }
  to   { transform: scale(1); }
}

.js-mov .hero__eyebrow,
.js-mov .hero__titulo,
.js-mov .hero__filete,
.js-mov .hero__pie {
  animation: hero-sube var(--mov-hero-tx) var(--ease) both;
}
.js-mov .hero__eyebrow { animation-delay: var(--mov-hero-d1); }
.js-mov .hero__titulo  { animation-delay: var(--mov-hero-d2); }
.js-mov .hero__filete  { animation-delay: var(--mov-hero-d3); }
.js-mov .hero__pie     { animation-delay: var(--mov-hero-d4); }

@keyframes hero-sube {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

/* El filete además se dibuja hacia abajo en vez de aparecer. */
.js-mov .hero__filete {
  transform-origin: top;
  animation: hero-filete var(--mov-hero-tx) var(--ease) var(--mov-hero-d3) both;
}
@keyframes hero-filete {
  from { opacity: 0; transform: scaleY(0); }
  to   { opacity: 1; transform: scaleY(1); }
}

/* ---- Cifras: los números cuentan ----------------------------- */
/* `tabular-nums` es obligatorio acá: sin él el ancho del número
   cambia en cada cuadro y la etiqueta de al lado tiembla. */
.cifra__valor { font-variant-numeric: lining-nums tabular-nums; }

/* ---- Micro-interacciones ------------------------------------ */
/* Los enlaces del pie ya suben su filete; se le agrega el
   desplazamiento mínimo que indica "esto responde". */
.pie__lista a { transition: color 160ms linear, transform 220ms var(--ease); }
.pie__lista a:hover { transform: translateX(3px); }

/* El muro no se detiene nunca, así que un hover que levante la
   tarjeta obligaría a perseguir un objeto en movimiento. Solo
   cambia el borde: se nota sin pedirle puntería a nadie. */
.testimonio { transition: border-color 320ms var(--ease); }
.testimonio:hover { border-color: var(--piedra); }

/* ============================================================
   Sin movimiento: TODO se apaga.
   No es una versión degradada — es el sitio completo, quieto.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .js-mov .revelar,
  .js-mov .revelar-img > img,
  .js-mov .revelar-img > picture > img {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .js-mov .hero__fondo img,
  .js-mov .hero__eyebrow,
  .js-mov .hero__titulo,
  .js-mov .hero__filete,
  .js-mov .hero__pie {
    animation: none !important;
    opacity: 1;
    transform: none;
  }
  .pie__lista a:hover { transform: none; }
}

/* ============================================================
   TRANSICIÓN ENTRE PÁGINAS

   El sitio son archivos HTML separados, así que cada clic en el nav
   provocaba un parpadeo blanco y un salto seco. Con la API de View
   Transitions el navegador toma una instantánea de la página que se
   va, otra de la que llega, y las cruza — sin JavaScript y sin
   convertir el sitio en una SPA.

   Donde el navegador no la soporta, la navegación ocurre como antes:
   no hay degradación, simplemente no hay transición. Por eso se
   puede usar hoy sin condicionar nada.

   El armazón (header y pie) lleva `view-transition-name` propio, así
   que NO se desvanece con el resto: se queda quieto mientras cambia
   el contenido. Eso es lo que hace que se sienta una sola aplicación
   en vez de siete documentos.
   ============================================================ */
@view-transition { navigation: auto; }

::view-transition-old(root) {
  animation: salir 220ms var(--flip-ease) both;
}
::view-transition-new(root) {
  animation: entrar 220ms var(--ease) both;   /* era 380ms: navegar es lo más frecuente que hay */
}
@keyframes salir {
  to { opacity: 0; transform: translateY(-8px); }
}
@keyframes entrar {
  from { opacity: 0; transform: translateY(12px); }
}

/* El header y el pie no se cruzan: permanecen. */
.hdr { view-transition-name: armazon-header; }
.pie { view-transition-name: armazon-pie; }
::view-transition-group(armazon-header),
::view-transition-group(armazon-pie) { animation-duration: 0ms; }

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; }
}

/* ============================================================
   Entrada al cargar — la portada de cada página

   El hero del inicio tenía su cascada al cargar, pero las demás
   páginas aparecían de golpe: su encabezado está sobre el pliegue,
   así que el observador de scroll se dispara antes de que se vea
   nada y la entrada se pierde. Es el mismo motivo por el que el
   hero se anima al cargar y no al entrar en cuadro.

   No se lista qué páginas ni qué secciones. `motion.js` toma la
   PRIMERA sección de <main> —sea cual sea— y a lo que hay adentro
   le pone `revelar--carga` en vez de observarlo. Una página nueva
   queda cubierta sin tocar nada.
   ============================================================ */
.js-mov .revelar--carga {
  opacity: 0;
  transform: translateY(var(--mov-dist, 14px));
  animation: mov-carga var(--mov-carga) var(--ease) both;
  animation-delay: var(--mov-retraso, 0ms);
}
@keyframes mov-carga {
  to { opacity: 1; transform: none; }
}

/* La imagen de portada de un proyecto entra antes que su título:
   se lee "primero la casa, después su nombre".

   ⚠️ La escala va en la IMAGEN dentro de una figura que recorta, no en
   la figura. Cuando la escala estaba en la figura, un 1,03 sobre 320 px
   son 329,6: durante el segundo que dura la entrada la página se podía
   arrastrar 10 px de costado en un teléfono angosto. Un transform NO se
   recorta a sí mismo — desborda a su padre —, así que ponerle overflow
   a la figura solo sirve si lo que se mueve es su contenido. Es además
   el mismo patrón que ya usa `.revelar-img`. */
.js-mov .pr-hero__lamina { overflow: hidden; }
.js-mov .pr-hero__lamina img {
  animation: pr-lamina var(--mov-lamina) var(--ease) both;
}
@keyframes pr-lamina {
  from { opacity: 0; transform: scale(1.03); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .js-mov .revelar--carga,
  .js-mov .pr-hero__lamina img {
    animation: none !important;
    opacity: 1;
    transform: none;
  }
}

/* ============================================================
   PRESUPUESTO DE MOVIMIENTO EN CELULAR

   Medido: el scroll va a 60 fps con la CPU frenada 4×, con un salto
   máximo de 20 ms entre fotogramas. O sea que no era falta de
   fluidez — era duración. En un teléfono se hace scroll rápido y con
   el pulgar: un revelado de 1.200 ms sigue corriendo cuando el
   elemento ya salió de pantalla, y lo que se percibe no es una
   animación elegante sino contenido que llega tarde.

   Las distancias no cambian (14 px sigue siendo 14 px). Solo el
   tiempo. La misma coreografía, tocada más rápido.

   Va al final del archivo a propósito: con igual especificidad gana
   la última regla, y en este proyecto ya se perdieron tres tardes
   por poner un override antes de su base.
   ============================================================ */
@media (max-width: 860px) {
  :root {
    --mov-dur:      420ms;
    --mov-paso:      45ms;
    --mov-img-op:   520ms;
    --mov-img-tr:   700ms;
    --mov-hero-bg: 1100ms;
    --mov-hero-tx:  560ms;
    --mov-carga:    480ms;
    --mov-lamina:   650ms;
    --mov-hero-d1:   90ms;
    --mov-hero-d2:  160ms;
    --mov-hero-d3:  280ms;
    --mov-hero-d4:  350ms;
  }
}
