/* ==========================================================================
   PRAEVIS — praevis.uy

   Paleta de MARCA, no la de la aplicación. El amarillo #F4B400 y el verde
   #0E7A5F son de pantalla de planta y acá no entran: esto se lee en un
   escritorio o en un teléfono con luz normal, y ahí manda el ámbar.
   Ver CLAUDE.md.

   Móvil primero: todo arranca en una columna y crece con min-width.
   ========================================================================== */

/* Archivo (SIL OFL), linaje DIN — la norma alemana de rotulación industrial.
   Variable 100–900 en un solo archivo de 35 KB, servido desde acá:
   sin Google Fonts, sin terceros, sin una request que dependa de otro. */
@font-face {
  font-family: "Archivo";
  src: url("../fuentes/Archivo-latin.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --grafito:  #14181B;   /* logotipo y texto */
  --ambar:    #C07A15;   /* el pico — un solo acento por pieza */
  --petroleo: #0E3A44;   /* secundario, enlaces */
  --chapa:    #F7F8F8;   /* fondo claro */
  --neutro:   #6E7A80;   /* etiquetas y datos */
  --blanco:   #FFFFFF;

  /* Derivados. No son colores nuevos de marca: son los de arriba llevados a
     un contraste que aguante texto corrido. El --neutro puro da 3.6:1 sobre
     chapa y no alcanza para un párrafo. */
  --texto-2:   #48545A;
  --linea:     #E4E7E8;
  --tinta:     #0D1113;   /* el grafito un punto más hondo, para el pie */
  --ambar-vivo:#D68C1E;   /* sólo para :hover, nunca en el logotipo */

  --ancho:   1200px;
  --lectura: 60ch;

  /* Ritmo vertical: una sola variable gobierna el aire de todas las secciones */
  --aire: clamp(4rem, 9vw, 7.5rem);
  --radio: 4px;

  --sombra-baja:  0 1px 2px rgba(20,24,27,.05), 0 4px 12px rgba(20,24,27,.05);
  --sombra-alta:  0 24px 60px -12px rgba(0,0,0,.45), 0 8px 20px -8px rgba(0,0,0,.3);
  --transicion: 220ms cubic-bezier(.2,.6,.3,1);
}

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 84px;      /* la barra sticky no tapa el título del ancla */
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  margin: 0;
  font-family: "Archivo", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-weight: 400;
  font-size: clamp(1rem, 0.97rem + 0.16vw, 1.0625rem);
  line-height: 1.62;
  color: var(--grafito);
  background: var(--chapa);
  overflow-x: hidden;            /* nada de scroll horizontal, ni por accidente */
  -webkit-font-smoothing: antialiased;
}

img, svg { max-width: 100%; height: auto; }

a { color: var(--petroleo); text-underline-offset: .18em; transition: color var(--transicion); }
a:hover { color: var(--ambar); }

:focus-visible { outline: 3px solid var(--ambar); outline-offset: 3px; border-radius: 2px; }

::selection { background: var(--ambar); color: var(--grafito); }

/* ------------------------------------------------------------- estructura */

.contenedor {
  width: 100%;
  max-width: var(--ancho);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 5vw, 3rem);
}

section { padding-block: var(--aire); position: relative; }

.fondo-claro { background: var(--blanco); }
.fondo-chapa { background: var(--chapa); }

.oscuro {
  background: var(--grafito);
  color: var(--blanco);
  /* Un halo de petróleo, apenas perceptible, para que el negro no sea plano */
  background-image: radial-gradient(80% 120% at 85% 0%, rgba(14,58,68,.55) 0%, transparent 60%);
}

/* ------------------------------------------------------------- tipografía */

h1, h2, h3 { margin: 0; line-height: 1.1; letter-spacing: -.02em; text-wrap: balance; font-weight: 600; }

h1 { font-size: clamp(2.15rem, 1.25rem + 4vw, 4.25rem); }
h2 { font-size: clamp(1.7rem, 1.2rem + 2.2vw, 2.9rem); }
h3 { font-size: clamp(1.0625rem, 1rem + .35vw, 1.25rem); }

p { margin: 0 0 1.05rem; max-width: var(--lectura); }
p:last-child { margin-bottom: 0; }

/* La etiqueta chica sobre cada título: versalita espaciada, del linaje DIN.
   Lleva el pico de la marca como viñeta. */
.rotulo {
  display: flex;
  align-items: center;
  gap: .7rem;
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--neutro);
  margin-bottom: clamp(.8rem, 2vw, 1.1rem);
}
.rotulo::before {
  content: "";
  flex: 0 0 auto;
  width: 9px; height: 12px;
  background: var(--ambar);
  clip-path: polygon(50% 0%, 100% 100%, 77% 100%, 50% 44%, 23% 100%, 0% 100%);
}
.oscuro .rotulo { color: rgba(255,255,255,.6); }

/* La frase que abre cada sección — sale del PPT, es contenido aprobado */
.frase {
  font-size: clamp(1.0625rem, 1rem + .6vw, 1.4rem);
  line-height: 1.5;
  color: var(--texto-2);
  margin-top: 1.25rem;
  max-width: 48ch;
}
.oscuro .frase { color: rgba(255,255,255,.75); }
.oscuro p      { color: rgba(255,255,255,.75); }

/* Sobre grafito el petróleo no se lee: los enlaces de texto van en claro.
   Los que ya traen su propio color —el botón, el teléfono— se quedan afuera. */
.oscuro a:not(.boton):not(.boton-liso):not(.telefono),
.pie a {
  color: rgba(255,255,255,.75);
  text-decoration-color: rgba(255,255,255,.35);
}
.oscuro a:not(.boton):not(.boton-liso):not(.telefono):hover,
.pie a:hover { color: var(--ambar); text-decoration-color: currentColor; }

.encabezado-seccion { margin-bottom: clamp(2.5rem, 5vw, 4rem); }

/* Título a la izquierda y bajada a la derecha, en pantalla ancha. Apilados,
   los dos quedaban en la mitad izquierda —el texto tiene un ancho de lectura
   y no puede estirarse— y la otra mitad de la sección quedaba en blanco.
   No es que sobre ancho: es que no se estaba usando. */
@media (min-width: 62rem) {
  .encabezado--par {
    display: grid;
    grid-template-columns: 1.1fr .9fr;
    gap: clamp(2.5rem, 6vw, 5rem);
    align-items: end;
  }
  .encabezado--par h2 { max-width: 20ch; }
  .encabezado--par .frase { margin-top: 0; padding-bottom: .35rem; max-width: 44ch; }
}

/* ---------------------------------------------------------- barra superior */

.barra {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(20,24,27,.86);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid rgba(255,255,255,.09);
  transition: border-color var(--transicion), background var(--transicion);
}
.barra .contenedor { position: relative; }   /* ancla del panel del menú */
/* Al despegarse del hero, la barra se afirma con la línea ámbar */
.barra.desplazada { border-bottom-color: var(--ambar); }

.barra .contenedor {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: 62px;
  padding-block: .7rem;
}

.barra__logo { display: flex; flex: 0 0 auto; }
.barra__logo img { width: clamp(108px, 24vw, 136px); display: block; }

.barra nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: clamp(1.1rem, 2.4vw, 2.1rem);
}

.barra nav a {
  position: relative;
  color: rgba(255,255,255,.86);
  text-decoration: none;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding-block: .25rem;
}
.barra nav a::after {
  content: "";
  position: absolute;
  left: 0; right: 100%; bottom: 0;
  height: 2px;
  background: var(--ambar);
  transition: right var(--transicion);
}
.barra nav a:hover { color: var(--blanco); }
.barra nav a:hover::after { right: 0; }

/* ── El menú ────────────────────────────────────────────────────────────────
   En escritorio es una fila de enlaces. En el teléfono, el mismo <ul> se
   convierte en un panel que baja desde la barra. El botón queda arriba, que es
   donde se lo busca; el teléfono sigue abajo, donde llega el pulgar. */

.barra__enlaces {
  display: flex;
  align-items: center;
  gap: clamp(1.1rem, 2.4vw, 2.1rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.barra__boton {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  background: none;
  border: 1px solid rgba(255,255,255,.25);
  border-radius: var(--radio);
  color: var(--blanco);
  font: inherit;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  padding: .5rem .85rem;
  cursor: pointer;
  transition: border-color var(--transicion), background var(--transicion);
}
.barra__boton:hover { border-color: var(--ambar); background: rgba(192,122,21,.14); }

/* Dos rayas que se cruzan al abrir. Dos y no tres: con dos, la equis sale del
   propio dibujo y no hay una tercera raya que esconder. */
.barra__rayas { display: block; width: 16px; height: 12px; position: relative; }
.barra__rayas span {
  position: absolute;
  left: 0; right: 0;
  height: 2px;
  background: currentColor;
  transition: transform var(--transicion), top var(--transicion);
}
.barra__rayas span:first-child { top: 2px; }
.barra__rayas span:last-child  { top: 8px; }

[aria-expanded="true"] .barra__rayas span:first-child { top: 5px; transform: rotate(45deg); }
[aria-expanded="true"] .barra__rayas span:last-child  { top: 5px; transform: rotate(-45deg); }

/* — Teléfono y tableta angosta — */
@media (max-width: 59.999rem) {
  .barra__cta { display: none; }

  .barra__enlaces {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--grafito);
    border-bottom: 2px solid var(--ambar);
    box-shadow: 0 20px 40px rgba(0,0,0,.4);

    /* Cerrado: sin alto y sin foco alcanzable. `visibility` es lo que saca los
       enlaces del tabulador; sólo con opacidad seguirían siendo enfocables. */
    display: grid;
    grid-template-rows: 0fr;
    visibility: hidden;
    transition: grid-template-rows var(--transicion), visibility var(--transicion);
  }
  .barra__enlaces.abierto { grid-template-rows: 1fr; visibility: visible; }

  .barra__enlaces > li { min-height: 0; overflow: hidden; }
  .barra__enlaces li a {
    display: block;
    padding: 1.05rem clamp(1.25rem, 5vw, 3rem);
    border-top: 1px solid rgba(255,255,255,.1);
    font-size: .875rem;
  }
  .barra__enlaces li a::after { display: none; }

  /* El <ul> es un grid de una sola celda: los <li> van adentro de esa celda. */
  .barra__enlaces { grid-template-columns: 100%; }
  .barra__enlaces > li { grid-column: 1; }
}

/* — Escritorio — */
@media (min-width: 60rem) {
  .barra__boton { display: none; }
  .barra__cta   { display: inline-block; }
}

/* ---------------------------------------------------------------- apertura */

.apertura {
  position: relative;
  overflow: hidden;
  padding-block: clamp(2.75rem, 7vw, 7rem);
  display: flex;
  align-items: center;
  min-height: min(72svh, 700px);
}

/* Cuando la apertura sale de pantalla, sus animaciones se congelan. Si no, el
   navegador sigue dibujando tres capas por cuadro mientras el visitante lee el
   pie de la página: gasto de batería a cambio de nada. */
.apertura.quieta .apertura__malla,
.apertura.quieta .apertura__barrido::after,
.apertura.quieta .apertura__pico { animation-play-state: paused; }

/* ── El movimiento del fondo ─────────────────────────────────────────────────
   Tres capas que se mueven muy despacio. Ninguna dice nada: si el navegador no
   las dibuja, o el visitante pidió menos movimiento, la apertura se lee igual.
   Todo se anima con `transform` y `opacity`, que el navegador resuelve en la
   placa de video: nada que obligue a recalcular la página en cada cuadro. */

/* La cuadrícula, derivando. Es lo que da la sensación de pantalla sin caer en
   las partículas conectadas que tiene cualquier plantilla. Se difumina hacia
   los bordes con una máscara: si llegara entera al borde, se vería el corte. */
.apertura__malla {
  position: absolute;
  inset: -55%;
  pointer-events: none;
  background-image:
    linear-gradient(to right,  rgba(255,255,255,.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(255,255,255,.05) 1px, transparent 1px);
  background-size: 76px 76px;
  -webkit-mask-image: radial-gradient(58% 48% at 50% 48%, #000 0%, transparent 72%);
          mask-image: radial-gradient(58% 48% at 50% 48%, #000 0%, transparent 72%);
  animation: deriva 46s linear infinite;
  will-change: transform;
}
@keyframes deriva {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(76px, 76px, 0); }
}

/* El barrido: una luz ámbar que cruza cada tanto y se toma una pausa larga.
   Si pasara sin parar sería un cartel de neón; con la pausa, se nota apenas. */
.apertura__barrido {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.apertura__barrido::after {
  content: "";
  position: absolute;
  top: -60%; bottom: -60%;
  width: 38%;
  background: linear-gradient(100deg,
              transparent,
              rgba(192,122,21,.09) 42%,
              rgba(192,122,21,.15) 50%,
              rgba(192,122,21,.09) 58%,
              transparent);
  filter: blur(8px);
  transform: translateX(-160%) rotate(9deg);
  animation: barre 11s ease-in-out infinite;
  will-change: transform;
}
@keyframes barre {
  0%       { transform: translateX(-160%) rotate(9deg); }
  38%, 100% { transform: translateX(360%) rotate(9deg); }
}

/* El pico de la marca, gigante y casi invisible: es el símbolo, no un adorno
   cualquiera. Se recorta contra el borde derecho. */
.apertura__pico {
  position: absolute;
  right: -14%;
  bottom: -18%;
  width: min(62vw, 640px);
  opacity: .07;
  pointer-events: none;
  user-select: none;
}
@media (min-width: 60rem) { .apertura__pico { right: -2%; bottom: -22%; opacity: .09; } }

/* Respira: sube y baja de intensidad en catorce segundos. Es tan lento que no
   se ve mirándolo; se nota al volver la vista. */
.apertura__pico { animation: respira 14s ease-in-out infinite; }
@keyframes respira {
  0%, 100% { opacity: .07; transform: translate3d(0, 0, 0)      scale(1); }
  50%      { opacity: .13; transform: translate3d(0, -1.5%, 0)  scale(1.03); }
}

.apertura .contenedor { position: relative; z-index: 1; }

.apertura h1 { max-width: 17ch; }
.apertura h1 em {
  font-style: normal;
  color: var(--ambar);
}

.apertura__bajada {
  font-size: clamp(1.0625rem, .98rem + .65vw, 1.4rem);
  line-height: 1.5;
  color: rgba(255,255,255,.82);
  max-width: 44ch;
  margin-top: clamp(1.1rem, 2.5vw, 1.5rem);
}

.acciones {
  margin-top: clamp(1.75rem, 4vw, 2.75rem);
  display: flex;
  flex-wrap: wrap;
  gap: .9rem 1.5rem;
  align-items: center;
}

.boton {
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  background: var(--ambar);
  color: var(--grafito);
  font-weight: 600;
  font-size: .95rem;
  letter-spacing: .02em;
  text-decoration: none;
  padding: .95rem 1.7rem;
  border-radius: var(--radio);
  transition: background var(--transicion), transform var(--transicion), box-shadow var(--transicion);
}
.boton:hover {
  background: var(--ambar-vivo);
  color: var(--grafito);
  transform: translateY(-2px);
  box-shadow: 0 12px 28px -10px rgba(192,122,21,.7);
}
.boton:active { transform: translateY(0); }

.boton-liso {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  color: rgba(255,255,255,.85);
  font-weight: 600;
  font-size: .95rem;
  text-decoration: none;
  padding-block: .35rem;
  border-bottom: 1px solid rgba(255,255,255,.28);
  transition: color var(--transicion), border-color var(--transicion);
}
.boton-liso:hover { color: var(--blanco); border-color: var(--ambar); }

/* ------------------------------------------------------------- diferencial */

/* Lo que distingue a PRAEVIS: plataforma propia Y gente en planta. Va arriba
   de todo el resto porque casi nadie ofrece las dos cosas. */
.dupla {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  grid-template-columns: 1fr;
}
@media (min-width: 48rem) { .dupla { grid-template-columns: 1fr 1fr; } }

.dupla__item {
  padding-top: 1.5rem;
  border-top: 3px solid var(--grafito);
}
.dupla__item h3 { margin-bottom: .7rem; }
.dupla__item p  { color: var(--texto-2); }

.dupla__n {
  display: block;
  font-size: .7rem;
  font-weight: 600;
  letter-spacing: .18em;
  color: var(--ambar);
  margin-bottom: .9rem;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- servicios */

.rejilla-3 {
  display: grid;
  gap: clamp(1.25rem, 2.5vw, 1.75rem);
  grid-template-columns: 1fr;
}
@media (min-width: 44rem) { .rejilla-3 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 66rem) { .rejilla-3 { grid-template-columns: repeat(3, 1fr); } }

/* La tarjeta es blanca y la sección es chapa: al revés —blanco sobre blanco—
   lo único que las separaba era un filete de un píxel, y quedaban planas.
   La sombra hace el resto: son objetos apoyados, no rectángulos dibujados. */
.tarjeta {
  background: var(--blanco);
  border: 1px solid var(--linea);
  border-radius: var(--radio);
  padding: clamp(1.5rem, 3vw, 2.1rem);
  position: relative;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(20,24,27,.03), 0 8px 20px -16px rgba(20,24,27,.16);
  transition: transform var(--transicion), box-shadow var(--transicion), border-color var(--transicion);
}

/* La línea superior crece de izquierda a derecha al pasar por encima */
.tarjeta::before {
  content: "";
  position: absolute;
  inset: 0 100% auto 0;
  height: 3px;
  background: var(--ambar);
  transition: inset-inline-end var(--transicion);
}

.tarjeta:hover {
  transform: translateY(-5px);
  border-color: rgba(192,122,21,.4);
  /* El halo: sobre fondo claro el resplandor no se hace con luz sino con una
     sombra del color del acento, muy abierta y muy diluida. Va acompañada de
     una sombra neutra que le da el peso; sola, el ámbar se vería como una
     mancha flotando. */
  box-shadow:
    0 1px 2px rgba(20,24,27,.04),
    0 14px 30px -22px rgba(20,24,27,.20),
    0 0 0 1px rgba(192,122,21,.22),
    0 8px 30px -14px rgba(192,122,21,.26);
}
.tarjeta:hover::before { inset-inline-end: 0; }

/* El teclado llega a los mismos lugares que el mouse */
.tarjeta:focus-within {
  border-color: rgba(192,122,21,.4);
  box-shadow:
    0 1px 2px rgba(20,24,27,.04),
    0 14px 30px -22px rgba(20,24,27,.20),
    0 0 0 1px rgba(192,122,21,.22),
    0 8px 30px -14px rgba(192,122,21,.26);
}

/* ── En un teléfono no hay hover ────────────────────────────────────────────
   Todo lo de arriba se dispara al pasar el mouse, que en un teléfono no pasa
   nunca: ahí las tarjetas se quedaban planas para siempre. Dos reemplazos:
   la línea de acento ya viene puesta, y la tarjeta se enciende sola cuando
   pasa por el medio de la pantalla al ir bajando. */
@media (hover: none) {
  .tarjeta::before { inset-inline-end: 0; }        /* la línea, siempre */

  .tarjeta {
    /* Un poco más de peso de base: en una pantalla chica y con reflejos, una
       sombra de escritorio no se ve. */
    box-shadow: 0 1px 2px rgba(20,24,27,.04), 0 10px 22px -16px rgba(20,24,27,.20);
  }

  /* La que está pasando por el centro. La clase la pone el script; sin script
     quedan todas en su estado normal, que se ve bien igual. */
  .tarjeta.destacada {
    border-color: rgba(192,122,21,.45);
    box-shadow:
      0 1px 2px rgba(20,24,27,.04),
      0 14px 30px -22px rgba(20,24,27,.20),
      0 0 0 1px rgba(192,122,21,.22),
      0 8px 30px -14px rgba(192,122,21,.26);
  }

  /* Y el toque responde, que si no parece que la pantalla se colgó */
  .tarjeta:active { transform: scale(.99); }
}

.tarjeta h3 {
  margin-bottom: 1.15rem;
  padding-bottom: .9rem;
  border-bottom: 1px solid var(--linea);
}

.lista { margin: 0; padding: 0; list-style: none; }
.lista li {
  position: relative;
  padding: .45rem 0 .45rem 1.15rem;
  color: var(--texto-2);
  font-size: .96rem;
}
.lista li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 1.02em;
  width: 6px; height: 1px;
  background: var(--ambar);
}

/* Cómo se contrata: no hay un formato único, el servicio se adapta */
.nota {
  margin-top: clamp(2.25rem, 4vw, 3rem);
  border-left: 3px solid var(--ambar);
  padding: .5rem 0 .5rem 1.5rem;
}
.nota p {
  font-size: clamp(1.0625rem, 1rem + .4vw, 1.2rem);
  line-height: 1.55;
  color: var(--grafito);
  max-width: 56ch;
}

/* --------------------------------------------------------------- plataforma */

.par {
  display: grid;
  gap: clamp(2.5rem, 5vw, 4.5rem);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 58rem) {
  .par { grid-template-columns: 1fr 1fr; }
  .par--invertido > *:first-child { order: 2; }
}

.puntos { margin: 1.9rem 0 0; padding: 0; list-style: none; }
/* Los cuatro puntos: una sola lista, en dos columnas cuando hay lugar. Antes
   eran dos listas de dos, y en el teléfono el espacio que las separaba caía en
   el medio de lo que se lee como una lista sola: parecía un error. */
.puntos--doble {
  margin-top: 0;
  display: grid;
  grid-template-columns: 1fr;
  column-gap: clamp(2rem, 5vw, 3.5rem);
}
/* En dos columnas se llena hacia abajo y después al costado, no por filas: así
   el orden del documento —que es el que se lee en el teléfono y el que lee un
   lector de pantalla— sigue siendo el del PPT, sin intercalar. */
@media (min-width: 48rem) {
  .puntos--doble {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: repeat(2, auto);
    grid-auto-flow: column;
  }
}
.puntos li {
  display: flex;
  align-items: baseline;
  gap: .85rem;
  padding: .95rem 0;
  border-top: 1px solid var(--linea);
  font-weight: 500;
}
.oscuro .puntos li { border-color: rgba(255,255,255,.14); }
.puntos li::before {
  content: "";
  flex: 0 0 auto;
  width: 9px; height: 12px;
  background: var(--ambar);
  clip-path: polygon(50% 0%, 100% 100%, 77% 100%, 50% 44%, 23% 100%, 0% 100%);
  transform: translateY(1px);
}

/* Los cuatro puntos en fila: es un índice de lo que hace la plataforma, y en
   fila se leen de un vistazo en vez de como una lista larga. */
.puntos--fila {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0 clamp(1.5rem, 3vw, 2.5rem);
  margin-top: clamp(2rem, 4vw, 2.75rem);
}
@media (min-width: 40rem) { .puntos--fila { grid-template-columns: 1fr 1fr; } }
@media (min-width: 64rem) { .puntos--fila { grid-template-columns: repeat(4, 1fr); } }

.puntos--fila li {
  align-items: flex-start;
  border-top: 2px solid var(--ambar);
  padding-top: 1rem;
  font-weight: 600;
  line-height: 1.4;
}
.oscuro .puntos--fila li { border-color: var(--ambar); }
.puntos--fila li::before { transform: translateY(3px); }

/* La sección que termina en mosaico no lleva aire abajo: las fotos cierran
   contra la sección siguiente y el bloque pesa lo que tiene que pesar. */
#en-planta { padding-bottom: 0; }

/* ── El mosaico de fotos de planta ──────────────────────────────────────────
   A ancho completo y pegadas entre sí: ocho fotos con aire alrededor se leen
   como ocho cosas sueltas; juntas, como un bloque de trabajo. */
.mosaico {
  margin: clamp(3rem, 6vw, 4.5rem) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 2px;
  background: var(--linea);       /* asoma entre las fotos y hace de separador */
}
@media (min-width: 48rem) { .mosaico { grid-template-columns: repeat(4, 1fr); } }

.mosaico li {
  position: relative;
  overflow: hidden;
  background: var(--grafito);
}

.mosaico img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  /* Un punto por debajo del blanco puro: así el mosaico no compite con el
     texto de la sección, y al acercarse levanta. */
  filter: brightness(.93);
  transform: scale(1);
  transition: transform 700ms cubic-bezier(.2,.6,.3,1), filter var(--transicion);
}

@media (hover: hover) {
  .mosaico li:hover img { transform: scale(1.06); filter: brightness(1.04); }
}

/* En el teléfono no hay hover: la que está pasando por el centro se levanta,
   igual que las tarjetas de servicios. La clase la pone el mismo script. */
@media (hover: none) {
  .mosaico li.destacada img { filter: brightness(1.06); transform: scale(1.04); }
}

@media (prefers-reduced-motion: reduce) {
  .mosaico img { transition: filter .01ms; }
  .mosaico li:hover img { transform: none; }
}

/* ── El visor de pantallas ──────────────────────────────────────────────────
   Las capturas salen del producto real corrido con datos inventados: ningún
   cliente nombrado, ninguna persona, ningún número que se pueda leer como un
   resultado medido. Se generan con material/plataforma/capturar.py. */

.visor { margin-top: clamp(2.5rem, 5vw, 4rem); }

.visor__pestanas {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-bottom: 1.25rem;
}

.visor__pestanas button {
  background: none;
  border: 1px solid rgba(255,255,255,.22);
  border-radius: 999px;
  color: rgba(255,255,255,.72);
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  padding: .5rem 1.05rem;
  cursor: pointer;
  transition: color var(--transicion), border-color var(--transicion), background var(--transicion);
}
.visor__pestanas button:hover { color: var(--blanco); border-color: rgba(255,255,255,.45); }
.visor__pestanas button[aria-selected="true"] {
  background: var(--ambar);
  border-color: var(--ambar);
  color: var(--grafito);
}

.visor__marco { position: relative; }

.visor__hoja { margin: 0; }

.visor__hoja img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 8px;
  box-shadow: var(--sombra-alta);
}

/* El pie va DEBAJO de la imagen y no encima. Superpuesto tapaba la última fila
   de la pantalla que se está mostrando, que es justo lo que se fue a mirar. */
.visor__hoja figcaption {
  display: flex;
  flex-wrap: wrap;
  gap: .4rem 1.5rem;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 1rem;
  font-size: .875rem;
  color: rgba(255,255,255,.72);
}
.visor__hoja figcaption span {
  font-size: .7rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: rgba(255,255,255,.38);
  white-space: nowrap;
}

/* El cambio de pantalla es un fundido corto. `hidden` sigue mandando: si el
   JavaScript no corre, se ve la primera y nada más, que es lo correcto. */
.js .visor__hoja:not([hidden]) { animation: aparece 420ms cubic-bezier(.2,.6,.3,1); }
@keyframes aparece { from { opacity: 0; } to { opacity: 1; } }

@media (prefers-reduced-motion: reduce) {
  .js .visor__hoja:not([hidden]) { animation: none; }
}

/* ----------------------------------------------------------------- clientes */

/* Una banda de tres celdas iguales, separadas por línea fina. Cada logo se
   centra en una caja de la misma altura: así los tres se alinean ópticamente
   aunque uno sea un escudo alto y otro un wordmark chato. */
.clientes {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: 1fr;
  border-top: 1px solid var(--linea);
}
@media (min-width: 44rem) { .clientes { grid-template-columns: repeat(3, 1fr); } }

.clientes li {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.35rem;
  padding: clamp(2rem, 4vw, 2.9rem) 1rem;
  border-bottom: 1px solid var(--linea);
}
@media (min-width: 44rem) {
  .clientes li + li { border-left: 1px solid var(--linea); }
}

.clientes__marca {
  height: clamp(70px, 14vw, 92px);
  display: flex;
  align-items: center;
  justify-content: center;
}
.clientes__marca img {
  display: block;
  width: auto;
  max-width: 100%;
  transition: transform var(--transicion);
}
.clientes li:hover .clientes__marca img { transform: scale(1.05); }

.clientes span {
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--neutro);
  text-align: center;
}

/* Alturas ajustadas a ojo, no por fórmula: el escudo de UPM pesa más que un
   wordmark del mismo alto, así que va más chico de lo que diría la regla. */
.cliente-upm       img { height: clamp(58px, 12vw, 76px); }
.cliente-proyectos img { height: clamp(26px, 5.5vw, 34px); }
.cliente-andritz   img { height: clamp(24px, 5vw, 30px); }

/* Las copias que el script agrega para la cinta sólo existen para el teléfono.
   Al girarlo a horizontal se cruza este umbral y, sin esto, la banda de tres
   pasaría a mostrar seis logos. */
@media (min-width: 48rem) {
  .clientes li[aria-hidden="true"] { display: none; }
}

/* ── La cinta, sólo en el teléfono ──────────────────────────────────────────
   Apilados uno debajo del otro, los tres logos son tres pantallazos de scroll
   y nunca se ven juntos: se pierde justamente lo que la sección quiere decir,
   que son tres. Deslizando, se leen como una fila. */
@media (max-width: 47.99rem) {
  .clientes-cinta {
    overflow: hidden;
    /* Los bordes se desvanecen: sin esto los logos aparecen y desaparecen de
       golpe contra el filo de la pantalla. */
    -webkit-mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
            mask-image: linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
  }

  .clientes {
    display: flex;
    width: max-content;
    border-top: 0;
    animation: desliza 24s linear infinite;
    will-change: transform;
  }

  .clientes li {
    flex: 0 0 auto;
    width: 46vw;
    border-bottom: 0;
    border-left: 0;
    padding-block: clamp(1.5rem, 5vw, 2.25rem);
  }

  /* La copia empieza donde termina el original, así que al llegar a la mitad
     el dibujo es idéntico al del arranque y el salto no se ve. */
  @keyframes desliza {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(-50%, 0, 0); }
  }

  /* Si el visitante pidió menos movimiento, la cinta se queda quieta y se
     puede recorrer con el dedo. */
  @media (prefers-reduced-motion: reduce) {
    .clientes-cinta { overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .clientes { animation: none; }
  }
}

/* -------------------------------------------------------------- trayectoria */

/* Cifras a un lado, texto al otro. Apilado, el bloque dejaba media pantalla
   vacía a la derecha y las cifras se perdían arriba de un párrafo largo. */
.trayectoria {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2.5rem, 5vw, 4.5rem);
  align-items: start;
}
@media (min-width: 56rem) {
  .trayectoria { grid-template-columns: minmax(240px, .8fr) 1.4fr; }
}

.cifras {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.5rem, 4vw, 2.5rem);
}
@media (min-width: 56rem) { .cifras { grid-template-columns: 1fr; } }

/* Cada cifra apoyada sobre una línea ámbar: es lo que la vuelve un dato y no
   un número suelto en el medio de un texto. */
.cifra {
  margin: 0;
  max-width: none;
  padding-top: 1.1rem;
  border-top: 3px solid var(--ambar);
}

.cifra strong {
  display: block;
  font-size: clamp(3.5rem, 2rem + 7vw, 6.5rem);
  font-weight: 600;
  line-height: .88;
  letter-spacing: -.045em;
  font-variant-numeric: tabular-nums;   /* sin esto las cifras no alinean */
}

/* El signo, en ámbar y en volado. Va sobre el número, no en su propia línea. */
.cifra strong sup {
  font-size: .36em;
  vertical-align: super;
  line-height: 0;
  letter-spacing: 0;
  color: var(--ambar);
  margin-left: .04em;
}

/* Hijo directo, y no `.cifra span` a secas: el número también está dentro de
   un <span> —el que anima el contador— y se llevaba puesto este estilo, así
   que la cifra salía en cuerpo de etiqueta y partida en dos líneas. */
.cifra > span {
  display: block;
  margin-top: .85rem;
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--neutro);
}

.trayectoria__texto p { max-width: 56ch; }

/* ── Los ámbitos ────────────────────────────────────────────────────────────
   Rejilla de celdas iguales, no cápsulas sueltas. La cápsula supone textos
   cortos y de largo parecido; acá son ocho frases de 17 a 24 caracteres, y
   acomodadas al correr dejaban siempre una fila huérfana —en el teléfono
   quedaban casi todas de a una, como una lista larga, con un par apareado al
   final—. Con celdas de igual ancho el bloque se lee de una sola vez. */
.etiquetas {
  margin: clamp(2.5rem, 5vw, 3.5rem) 0 0;
  padding: clamp(2rem, 4vw, 2.5rem) 0 0;
  border-top: 1px solid var(--linea);
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  /* Todas las filas del alto de la más alta: si no, la fila cuyos textos
     entran en un renglón queda más baja y el bloque pierde la cuadrícula. */
  grid-auto-rows: 1fr;
  gap: .5rem;
}
/* Dos columnas o cuatro, nunca tres: son ocho ámbitos, y con tres columnas la
   última fila queda con dos celdas y un hueco. */
@media (min-width: 48rem) { .etiquetas { grid-template-columns: repeat(4, 1fr); } }

.etiquetas li {
  display: flex;
  align-items: center;
  gap: .6rem;
  border: 1px solid var(--linea);
  background: var(--blanco);
  border-radius: var(--radio);
  padding: .85rem 1rem;
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1.3;
  color: var(--texto-2);
  box-shadow: 0 1px 2px rgba(20,24,27,.03);
  transition: border-color var(--transicion), color var(--transicion), box-shadow var(--transicion);
}
@media (min-width: 48rem) { .etiquetas li { font-size: .875rem; padding: .9rem 1.1rem; } }

.etiquetas li::before {
  content: "";
  flex: 0 0 auto;
  width: 8px; height: 11px;
  background: var(--ambar);
  clip-path: polygon(50% 0%, 100% 100%, 77% 100%, 50% 44%, 23% 100%, 0% 100%);
}

@media (hover: hover) {
  .etiquetas li:hover {
    border-color: rgba(192,122,21,.45);
    color: var(--grafito);
    box-shadow: 0 1px 2px rgba(20,24,27,.04), 0 6px 18px -12px rgba(20,24,27,.3);
  }
}

/* ----------------------------------------------------------------- contacto */

.contacto { overflow: hidden; }
/* «¿Trabajamos juntos?» va en un solo renglón, también en el teléfono: son
   dos palabras y partidas pierden el tono de pregunta. Tenía un tope de 15
   caracteres y la frase mide 19, así que se partía siempre.
   El cuerpo se ata al ancho de la pantalla —no a un salto de tamaño— para que
   entre en un renglón hasta en las más angostas. */
.contacto h2 {
  max-width: none;
  white-space: nowrap;
  font-size: clamp(1.45rem, 7.2vw, 2.9rem);
}

.telefono {
  display: inline-block;
  margin-top: clamp(2rem, 4vw, 2.75rem);
  font-size: clamp(1.85rem, 1.1rem + 3.4vw, 3.25rem);
  font-weight: 600;
  letter-spacing: -.025em;
  font-variant-numeric: tabular-nums;
  color: var(--blanco);
  text-decoration: none;
  border-bottom: 2px solid var(--ambar);
  padding-bottom: .25rem;
  transition: color var(--transicion), border-color var(--transicion);
}
.telefono:hover { color: var(--ambar); }

/* --------------------------------------------------------------------- pie */

.pie {
  background: var(--tinta);
  color: rgba(255,255,255,.5);
  padding-block: clamp(2.75rem, 5vw, 4rem);
  font-size: .875rem;
}

.pie__fila {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
  align-items: flex-end;
  justify-content: space-between;
  padding-bottom: 2rem;
  border-bottom: 1px solid rgba(255,255,255,.1);
}

.pie__logo img { width: clamp(170px, 42vw, 210px); display: block; }

/* El teléfono, otra vez, al final de todo: quien llegó hasta acá abajo leyendo
   ya decidió, y no tiene por qué volver a subir a buscarlo. */
.pie__tel {
  font-size: clamp(1.15rem, 1rem + .7vw, 1.6rem);
  font-weight: 600;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  text-decoration: none;
  border-bottom: 2px solid var(--ambar);
  padding-bottom: .15rem;
}
.pie a.pie__tel { color: var(--blanco); }
.pie a.pie__tel:hover { color: var(--ambar); }

.pie__legal {
  margin: 1.75rem 0 0;
  max-width: none;
  color: rgba(255,255,255,.38);
  font-size: .8rem;
}

/* ------------------------------------------ barra de llamada, sólo en móvil */

/* La acción real en un teléfono es llamar. Va abajo, donde llega el pulgar,
   y se respeta el área segura del iPhone. */
.llamar-movil {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .6rem;
  background: var(--ambar);
  color: var(--grafito);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: .02em;
  text-decoration: none;
  padding: .95rem 1rem calc(.95rem + env(safe-area-inset-bottom));
  box-shadow: 0 -8px 24px rgba(0,0,0,.18);
}
.llamar-movil svg { width: 18px; height: 18px; flex: 0 0 auto; }

@media (min-width: 60rem) { .llamar-movil { display: none; } }
@media (max-width: 59.999rem) { body { padding-bottom: 4rem; } }

/* --------------------------------------------------------- entrada al scroll */

/* Sólo esconde si el JavaScript está andando: la clase .js la pone el propio
   script en el <head>. Sin JS —o si el script falla— el contenido se ve
   igual, que es lo único aceptable en un sitio que se lee. */
.js .revelar {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 620ms cubic-bezier(.2,.6,.3,1), transform 620ms cubic-bezier(.2,.6,.3,1);
}
.js .revelar.visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  /* Nada se mueve: ni la cuadrícula, ni el barrido, ni el pico. */
  .apertura__malla,
  .apertura__barrido::after,
  .apertura__pico { animation: none; }
  .apertura__barrido { display: none; }

  .js .revelar { opacity: 1; transform: none; transition: none; }
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ------------------------------------------------------------ accesibilidad */

.saltar {
  position: absolute;
  left: -9999px;
  background: var(--ambar);
  color: var(--grafito);
  padding: .8rem 1.25rem;
  font-weight: 600;
  z-index: 100;
  border-radius: var(--radio);
}
.saltar:focus { left: 1rem; top: 1rem; }
