@charset "UTF-8";

/* =========================================================================
   TORONJA LAB - sitio publico
   =========================================================================

   SISTEMA VISUAL
   El logo de Toronja Lab no es una toronja dibujada: es una toronja
   CONSTRUIDA POR CAPAS, con la boquilla extruyendo el tallo. Esa es la
   idea de marca y es el dispositivo visual de toda la pagina. Las barras
   apiladas aparecen en el hero (se imprimen al cargar), en el proceso
   (cada etapa suma una capa) y en las muestras de material. No es
   decoracion: dice literalmente lo que hace el negocio.

   Hubo tambien un separador de capas entre secciones y se quito: ahi el
   motivo no decia nada, solo rellenaba. El mismo recurso repetido sin
   funcion deja de leerse como sistema y pasa a leerse como adorno.

   PALETA
   Los tokens son los mismos de cotizador3d/src/app/globals.css. Si cambia
   un hex alla, cambia aca. Un solo acento de marca: toronja en claro,
   coral en oscuro (sobre fondo oscuro el toronja pierde legibilidad, es
   la misma regla que ya aplica el cotizador).

   RADIOS - una sola regla, aplicada en toda la pagina:
     - botones, pildoras y barras de capa -> pastilla completa
     - tarjetas, marcos y fotos           -> var(--r-tarjeta)

   MOVIMIENTO
   Todo el movimiento de la pagina se calcula aqui, nunca en JavaScript.
   Las entradas por scroll usan animation-timeline: view(), encerrado en
   @supports: donde no exista, el contenido se ve completo desde el inicio
   en vez de quedar invisible. Todo se apaga con prefers-reduced-motion.

   La excepcion es el logo del hero, que es una escena three.js montada
   sobre el SVG (ver el modulo al pie del HTML). La animacion CSS de la
   pieza no se borro: es lo que se ve mientras three.js baja, y lo que
   queda si no hay WebGL, si el navegador no soporta import maps o si el
   CDN no responde. Por eso sigue viva aunque casi nadie la vea entera.
   ========================================================================= */

/* =========================================================================
   1. TOKENS
   ========================================================================= */

:root {
  /* --- Paleta citrica ---
     Copia exacta de cotizador3d/src/app/globals.css, que a su vez esta
     atada a src/lib/paleta.ts: el test paleta.test.ts falla si los dos
     se desincronizan. Si estos hex cambian alla, cambian aqui. */
  --toronja: #de3614;
  --coral: #f08457;
  --durazno: #fdd8b3;
  --amarillo: #fbd158;
  --oliva: #596542;

  /* Segundo coral del logo: el unico hex del archivo de marca que la
     paleta no nombra. Vive entre el coral y el durazno y solo se usa para
     la capa intermedia de la pila, que es donde el logo lo usa. */
  --coral-claro: #ee8666;

  /* --- Los dos temas, cada hex declarado UNA sola vez ------------------
     Abajo hay tres bloques que cambian de tema, y ninguno repite un color:
     solo reasignan estas referencias. Asi, sincronizar con el cotizador
     sigue siendo tocar una linea y no buscar el mismo hex en cuatro sitios.

     Claro: fondo crema (10% durazno), no blanco puro, porque el blanco
     absoluto junto a calidos se percibe azulado. Tinta con una pizca de
     oliva en vez de #000, que endurece la interfaz. Los dos salen
     derivados de paleta.ts, no elegidos a ojo. */
  --c-fondo: #fffbf7;
  --c-tinta: #0e100b;
  --c-tinta-suave: #434b31;
  --c-superficie: #fffefd;
  --c-superficie-2: #f3f0ea;
  --c-superficie-3: #f0eee7;
  --c-acento-suave: #fdeae1;
  --c-borde: #e4e3da;
  --c-primario: var(--toronja);
  --c-primario-tinta: #ffffff;
  /* El toronja de marca sobre el crema da 4.39: se queda a un pelo de AA.
     En bloque el texto va en blanco y pasa de sobra, pero cuando el acento
     ES el texto (un enlace en hover, un error de formulario) hace falta un
     paso hacia la tinta. Mismo valor que el --destructive del cotizador. */
  --c-primario-texto: #da3514;
  --c-oliva-tono: var(--oliva);

  /* Oscuro: carbon calido con oliva, no negro puro. */
  --d-fondo: #14170f;
  --d-tinta: #f5f2ec;
  --d-tinta-suave: #c4b08b;
  --d-superficie: #191c13;
  --d-superficie-2: #1c2015;
  --d-superficie-3: #1e2216;
  --d-acento-suave: #37281b;
  --d-borde: #353226;
  /* Sobre fondo oscuro el toronja pierde legibilidad: el acento pasa al
     coral, que es el mismo color aclarado. Y como el coral sobre el carbon
     da 7:1, aqui el acento sirve de texto sin correccion. */
  --d-primario: var(--coral);
  --d-primario-tinta: #0e100b;
  --d-primario-texto: var(--coral);
  /* El oliva de marca sobre el carbon queda casi invisible. El cotizador lo
     aclara a este valor para sus graficos; se usa el mismo para que las
     muestras de material no se apaguen. */
  --d-oliva-tono: #5c6846;

  /* --- Tema en uso: claro siempre, salvo que se active el interruptor --- */
  color-scheme: light;
  --fondo: var(--c-fondo);
  --tinta: var(--c-tinta);
  --tinta-suave: var(--c-tinta-suave);
  --superficie: var(--c-superficie);
  --superficie-2: var(--c-superficie-2);
  --superficie-3: var(--c-superficie-3);
  --acento-suave: var(--c-acento-suave);
  --borde: var(--c-borde);
  --primario: var(--c-primario);
  --primario-tinta: var(--c-primario-tinta);
  --primario-texto: var(--c-primario-texto);
  --oliva-tono: var(--c-oliva-tono);

  /* --- Tipografia ---
     Neue Haas Grotesk va primero: quien la tenga licenciada la usa sin
     tocar nada. Detras, Helvetica Neue cubre iPhone y Mac, y Schibsted
     Grotesk es el sustituto que se descarga para el resto. Una sola
     familia en toda la pagina: los titulos se distinguen por peso,
     tamano y tracking, no por cambiar de tipografia. */
  --fuente: 'Neue Haas Grotesk Display Pro', 'Neue Haas Grotesk Text Pro',
    'Helvetica Neue', 'Schibsted Grotesk', Helvetica, Arial, sans-serif;

  /* --- Radios --- */
  --r-tarjeta: 1rem;
  --r-pastilla: 999px;

  /* --- Ritmo vertical --- */
  --ancho: 1240px;
  --margen: clamp(1.25rem, 4vw, 2.5rem);
  --aire-seccion: clamp(5rem, 11vw, 9rem);

  /* --- Sombras tenidas ---
     Una sombra negra sobre fondo calido se ve sucia. Toma el tono del
     oliva para que parezca luz real atravesando la escena. */
  --sombra-s: 0 1px 3px color-mix(in oklab, var(--oliva) 12%, transparent),
    0 1px 2px -1px color-mix(in oklab, var(--oliva) 10%, transparent);
  --sombra-m: 0 4px 14px -2px color-mix(in oklab, var(--oliva) 16%, transparent),
    0 2px 6px -3px color-mix(in oklab, var(--oliva) 12%, transparent);
  --sombra-l: 0 18px 44px -10px color-mix(in oklab, var(--oliva) 22%, transparent),
    0 6px 14px -8px color-mix(in oklab, var(--oliva) 14%, transparent);

  --transicion: 180ms cubic-bezier(0.16, 1, 0.3, 1);
}

/* -------------------------------------------------------------------------
   CAMBIO DE TEMA

   La pagina es CLARA por defecto, pase lo que pase: la marca es crema y
   toronja, y el oscuro es la variante, no el punto de partida. No se sigue
   al sistema operativo a proposito. El interruptor del encabezado pasa a
   oscuro, y nada mas.

   OJO: el interruptor no recuerda la eleccion entre recargas. Guardarla
   exige localStorage, es decir JavaScript, y esta pagina es HTML y CSS a
   proposito. Al recargar se vuelve al claro.

   Este bloque usa :has(). Donde no exista, el interruptor no hace nada y la
   pagina se queda clara, que es justamente el valor por defecto que se
   quiere: no hay forma de quedar en un estado raro.
   ------------------------------------------------------------------------- */

:root:has(#tema:checked) {
  --fondo: var(--d-fondo);
  --tinta: var(--d-tinta);
  --tinta-suave: var(--d-tinta-suave);
  --superficie: var(--d-superficie);
  --superficie-2: var(--d-superficie-2);
  --superficie-3: var(--d-superficie-3);
  --acento-suave: var(--d-acento-suave);
  --borde: var(--d-borde);
  --primario: var(--d-primario);
  --primario-tinta: var(--d-primario-tinta);
  --primario-texto: var(--d-primario-texto);
  --oliva-tono: var(--d-oliva-tono);
  color-scheme: dark;
}

/* =========================================================================
   2. BASE
   ========================================================================= */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  /* El nav es pegajoso: sin esto los anclajes quedan tapados por la barra. */
  scroll-padding-top: 6rem;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--fondo);
  color: var(--tinta);
  font-family: var(--fuente);
  font-size: 1rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img,
svg {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
  transition: color var(--transicion);
}

:where(h1, h2, h3, h4) {
  margin: 0;
  /* Una grotesca a tamano grande necesita tracking negativo: con el
     espaciado por defecto los titulos se ven flojos y despegados. */
  letter-spacing: -0.025em;
  line-height: 1.1;
  text-wrap: balance;
  font-weight: 700;
}

p {
  margin: 0;
  text-wrap: pretty;
}

ul,
ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

:focus-visible {
  outline: 2px solid var(--primario);
  outline-offset: 3px;
  border-radius: 4px;
}

::selection {
  background: var(--primario);
  color: var(--primario-tinta);
}

/* Solo para lectores de pantalla. */
.oculto-visual {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* =========================================================================
   3. ESTRUCTURA
   ========================================================================= */

.envoltura {
  width: 100%;
  max-width: var(--ancho);
  margin-inline: auto;
  padding-inline: var(--margen);
}

.seccion {
  padding-block: var(--aire-seccion);
}

.seccion--apagada {
  background: var(--superficie-2);
}

/* Dos secciones seguidas con el mismo fondo sumaban su padding y dejaban
   un vacio del doble (materiales -> proceso). Sin cambio de color que
   marque el corte, basta el aire de una sola. */
.seccion:not(.seccion--apagada) + .seccion:not(.seccion--apagada) {
  padding-top: 0;
}

.titulo-seccion {
  font-size: clamp(2rem, 4.4vw, 3.25rem);
  max-width: 18ch;
}

.bajada-seccion {
  margin-top: 1.1rem;
  max-width: 54ch;
  font-size: clamp(1rem, 1.4vw, 1.125rem);
  color: var(--tinta-suave);
}

.encabezado-seccion {
  margin-bottom: clamp(2.5rem, 5vw, 4rem);
}

/* =========================================================================
   4. BOTONES
   Pastilla completa, siempre. Respuesta fisica al pulsar: sin esto los
   botones se sienten muertos.
   ========================================================================= */

.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  /* white-space: nowrap evita que una etiqueta de 3 palabras parta en dos
     lineas y rompa la pastilla. */
  white-space: nowrap;
  padding: 0.85rem 1.6rem;
  border: 1px solid transparent;
  border-radius: var(--r-pastilla);
  font: inherit;
  font-size: 0.975rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: background-color var(--transicion), border-color var(--transicion),
    color var(--transicion), transform 120ms ease, box-shadow var(--transicion);
}

.boton--primario {
  background: var(--primario);
  color: var(--primario-tinta);
  box-shadow: var(--sombra-s);
}

.boton--primario:hover {
  background: color-mix(in oklab, var(--primario) 88%, var(--tinta));
  box-shadow: var(--sombra-m);
  transform: translateY(-1px);
}

.boton--secundario {
  background: transparent;
  color: var(--tinta);
  border-color: var(--borde);
}

.boton--secundario:hover {
  background: var(--acento-suave);
  border-color: color-mix(in oklab, var(--primario) 32%, var(--borde));
  transform: translateY(-1px);
}

.boton:active:not(:disabled) {
  transform: translateY(1px) scale(0.985);
}

.boton--ancho {
  width: 100%;
}

.boton i {
  font-size: 1.15em;
  line-height: 1;
}

/* Enlace con subrayado que crece desde la izquierda. */
.enlace-flecha {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-weight: 600;
  color: var(--primario-texto);
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0 1.5px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  padding-bottom: 2px;
  transition: background-size var(--transicion);
}

.enlace-flecha:hover {
  background-size: 100% 1.5px;
}

.enlace-flecha i {
  transition: transform var(--transicion);
}

.enlace-flecha:hover i {
  transform: translateX(3px);
}

/* =========================================================================
   5. NAVEGACION
   Una sola linea en escritorio, altura maxima 72px. En movil los enlaces
   se pliegan tras una casilla (sin JavaScript).
   ========================================================================= */

.nav {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in oklab, var(--fondo) 86%, transparent);
  backdrop-filter: blur(12px) saturate(140%);
  -webkit-backdrop-filter: blur(12px) saturate(140%);
  border-bottom: 1px solid color-mix(in oklab, var(--borde) 70%, transparent);
}

.nav__barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  height: 72px;
}

.marca {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  flex-shrink: 0;
}

.marca__icono {
  width: 38px;
  height: auto;
}

.marca__nombre {
  display: flex;
  flex-direction: column;
  line-height: 1;
}

.marca__nombre strong {
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: -0.03em;
}

.marca__nombre span {
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  color: var(--tinta-suave);
  margin-top: 2px;
}

.nav__enlaces {
  display: flex;
  align-items: center;
  font-size: 0.95rem;
  font-weight: 500;
}

.nav__enlaces > ul {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.2vw, 2rem);
}

.nav__enlaces a:hover {
  color: var(--primario-texto);
}

.nav__acciones {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-shrink: 0;
}

.nav__acciones .boton {
  padding: 0.6rem 1.15rem;
  font-size: 0.9rem;
}

/* Interruptor de menu movil: la casilla queda accesible por teclado pero
   fuera de la vista; la etiqueta es el boton visible. */
.nav__interruptor {
  position: absolute;
  opacity: 0;
  pointer-events: none;
  width: 1px;
  height: 1px;
}

.nav__tema,
.nav__hamburguesa {
  display: none;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border: 1px solid var(--borde);
  border-radius: var(--r-pastilla);
  cursor: pointer;
  font-size: 1.25rem;
  color: var(--tinta);
  transition: background-color var(--transicion), border-color var(--transicion);
}

.nav__tema:hover,
.nav__hamburguesa:hover {
  background: var(--acento-suave);
  border-color: color-mix(in oklab, var(--primario) 30%, var(--borde));
}

/* El de tema se ve siempre; el de menu solo en pantallas estrechas. */
.nav__tema {
  display: inline-flex;
}

/* Se muestra el icono del tema al que se va a cambiar, no el actual. Como
   la pagina arranca clara, de entrada se ve la luna; al activarse el
   interruptor pasa al sol. Misma estructura que los tokens. */
.tema__sol {
  display: none;
}

:root:has(#tema:checked) .tema__luna {
  display: none;
}

:root:has(#tema:checked) .tema__sol {
  display: block;
}

#menu:focus-visible ~ .nav__barra .nav__hamburguesa,
#tema:focus-visible ~ .nav__barra .nav__tema {
  outline: 2px solid var(--primario);
  outline-offset: 3px;
}

.nav__hamburguesa .ph-x {
  display: none;
}

#menu:checked ~ .nav__barra .nav__hamburguesa .ph-x {
  display: block;
}

#menu:checked ~ .nav__barra .nav__hamburguesa .ph-list {
  display: none;
}

@media (max-width: 920px) {
  .nav__hamburguesa {
    display: inline-flex;
  }

  .nav__enlaces {
    position: absolute;
    inset-inline: 0;
    top: 72px;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 0 var(--margen);
    background: var(--fondo);
    border-bottom: 1px solid var(--borde);
    box-shadow: var(--sombra-m);
    /* grid-template-rows 0fr -> 1fr anima el plegado sin alturas fijas. */
    display: grid;
    grid-template-rows: 0fr;
    overflow: hidden;
    transition: grid-template-rows 260ms cubic-bezier(0.16, 1, 0.3, 1);
  }

  .nav__enlaces > ul {
    display: block;
    min-height: 0;
    overflow: hidden;
  }

  #menu:checked ~ .nav__barra .nav__enlaces {
    grid-template-rows: 1fr;
  }

  .nav__enlaces a {
    display: block;
    padding: 0.95rem 0;
    border-bottom: 1px solid var(--borde);
    font-size: 1.05rem;
  }

  .nav__enlaces li:last-child a {
    border-bottom: 0;
    padding-bottom: 1.4rem;
  }

  .nav__acciones .boton--secundario {
    display: none;
  }
}

@media (max-width: 540px) {
  .marca__nombre {
    display: none;
  }
}

/* =========================================================================
   6. HERO
   Division asimetrica: el texto manda a la izquierda, la marca se imprime
   capa por capa a la derecha.
   ========================================================================= */

.hero {
  position: relative;
  overflow: hidden;
  padding-top: clamp(3rem, 7vw, 5.5rem);
  padding-bottom: clamp(4rem, 9vw, 7rem);
}

/* Resplandor citrico muy suave detras de la pieza impresa. Reemplaza el
   tipico "blob" de gradiente con algo que sigue la paleta. */
.hero::before {
  content: '';
  position: absolute;
  top: -22%;
  right: -14%;
  width: min(760px, 86vw);
  aspect-ratio: 1;
  background: radial-gradient(
    circle,
    color-mix(in oklab, var(--coral) 24%, transparent) 0%,
    transparent 66%
  );
  pointer-events: none;
  z-index: 0;
}

.hero__reja {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(2.5rem, 5vw, 4.5rem);
  align-items: center;
}

.hero__titular {
  font-size: clamp(2.6rem, 6.2vw, 4.5rem);
  letter-spacing: -0.04em;
  line-height: 1.02;
  max-width: 13ch;
}

.hero__titular em {
  font-style: normal;
  color: var(--primario-texto);
}

.hero__bajada {
  margin-top: 1.5rem;
  max-width: 46ch;
  font-size: clamp(1.05rem, 1.7vw, 1.2rem);
  color: var(--tinta-suave);
}

.hero__acciones {
  margin-top: 2.25rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
}

/* --- La pieza que se imprime --- */

/* El relleno es menor que en el resto de las tarjetas a proposito: el 3D
   necesita todo el ancho que pueda para que la pieza no salga diminuta. */
.impresion {
  position: relative;
  display: grid;
  place-items: center;
  padding: clamp(1.25rem, 2.4vw, 1.75rem);
  background: linear-gradient(
    168deg,
    var(--superficie) 0%,
    color-mix(in oklab, var(--acento-suave) 70%, var(--superficie)) 100%
  );
  border: 1px solid var(--borde);
  border-radius: calc(var(--r-tarjeta) * 1.75);
  box-shadow: var(--sombra-l);
}

/* Aqui conviven las dos versiones de la pieza: el SVG, que es lo que se ve
   siempre, y el lienzo 3D, que se monta encima cuando three.js termina de
   bajar. La relacion de aspecto esta fijada para que el hueco no cambie de
   alto en el relevo: sin esto la pagina salta cuando entra el lienzo. */
.impresion__objeto {
  position: relative;
  width: min(520px, 100%);
  aspect-ratio: 522 / 390;
}

.impresion__pieza {
  display: block;
  width: 100%;
  height: 100%;
}

/* El lienzo tapa al SVG en vez de reemplazarlo: si WebGL se cae a mitad de
   camino (el navegador puede perder el contexto), basta con sacar la clase
   y el SVG sigue ahi. */
.impresion__lienzo {
  position: absolute;
  inset: 0;
  opacity: 0;
  touch-action: none;
  transition: opacity 600ms ease;
}

.impresion__lienzo canvas {
  display: block;
  width: 100%;
  height: 100%;
}

.impresion--3d .impresion__lienzo {
  opacity: 1;
  cursor: grab;
}

.impresion--3d .impresion__lienzo:active {
  cursor: grabbing;
}

/* El logo plano es el ULTIMO RECURSO, no lo que se ve mientras carga: con
   JavaScript activo se esconde de entrada y solo vuelve si el 3D no llega
   (sin WebGL, sin import maps, CDN caido o contexto perdido). Sin
   JavaScript la clase .con-js nunca se pone y el plano queda a la vista,
   que es exactamente lo que corresponde. */
.con-js .impresion__pieza {
  visibility: hidden;
}

.impresion--plano .impresion__pieza {
  visibility: visible;
}

/* Mientras baja three.js se ve la cama sola: una impresora vacia esperando
   antes de empezar. Es mejor relleno que el logo plano, porque no adelanta
   el resultado. Desaparece cuando entra el 3D, que trae su propia cama con
   sombra de verdad. */
.impresion--3d .impresion__cama {
  visibility: hidden;
}

/* La cama de impresion: una base sobre la que se apoyan las capas. */
.impresion__cama {
  width: min(520px, 100%);
  height: 10px;
  margin-top: 0.9rem;
  border-radius: var(--r-pastilla);
  background: linear-gradient(
    90deg,
    transparent,
    color-mix(in oklab, var(--oliva-tono) 38%, transparent) 18%,
    color-mix(in oklab, var(--oliva-tono) 38%, transparent) 82%,
    transparent
  );
}

.impresion__pie {
  margin-top: 1.25rem;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--tinta-suave);
  text-align: center;
}

/* Cifras de apoyo bajo el hero, en seccion propia (no dentro del hero:
   el hero es un solo momento). */
.cifras {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: clamp(1.5rem, 3vw, 3rem);
  padding-block: clamp(2.5rem, 5vw, 3.5rem);
  border-top: 1px solid var(--borde);
}

.cifra__dato {
  font-size: clamp(1.6rem, 2.6vw, 2.1rem);
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--primario-texto);
}

.cifra__texto {
  margin-top: 0.35rem;
  font-size: 0.95rem;
  color: var(--tinta-suave);
  max-width: 24ch;
}

@media (max-width: 900px) {
  .hero__reja {
    grid-template-columns: 1fr;
    gap: 2rem;
  }

  .hero__titular {
    max-width: 100%;
  }

  /* La pieza va primero: es el momento de marca. Para que quepa junto al
     titular y los botones en una pantalla corta (un iPhone SE son 667px de
     alto), se encoge en vez de mandar los botones fuera de la pantalla. */
  .impresion {
    order: -1;
    padding: 1.5rem 1.5rem 1.25rem;
  }

  .impresion__objeto,
  .impresion__cama {
    width: min(320px, 100%);
  }

  .impresion__pie {
    margin-top: 0.9rem;
    font-size: 0.8rem;
  }

  .hero {
    padding-top: 2rem;
  }

  .hero__bajada {
    margin-top: 1.1rem;
  }

  .hero__acciones {
    margin-top: 1.6rem;
  }
}

/* A 375px de ancho los dos botones suman 343px y la franja util mide 335:
   se pasan por 8px y el segundo cae a una fila nueva, que cuesta 67px de
   alto. Un poco menos de relleno los deja lado a lado. */
@media (max-width: 560px) {
  .hero__acciones .boton {
    padding: 0.8rem 1.2rem;
    font-size: 0.92rem;
  }
}

/* Pantallas cortas (un iPhone SE son 667px de alto). Aqui el hero compite
   por cada pixel, asi que la pieza se encoge y el pie, que es un comentario
   y no informacion necesaria, se retira. Lo que no se negocia es que los
   botones queden sobre el pliegue. */
@media (max-width: 900px) and (max-height: 740px) {
  .impresion__objeto,
  .impresion__cama {
    width: min(190px, 100%);
  }

  .impresion {
    padding: 1.1rem;
  }

  .impresion__pie {
    display: none;
  }

  .hero__titular {
    font-size: clamp(2rem, 8.6vw, 2.7rem);
  }

  .hero__reja {
    gap: 1.5rem;
  }
}

/* =========================================================================
   7. SERVICIOS (reja bento)
   5 servicios, 5 celdas. Tamanos distintos y dos celdas con tratamiento
   visual propio para que la reja no sea seis cajas blancas iguales.
   ========================================================================= */

.bento {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 1rem;
}

.celda {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 0.7rem;
  padding: clamp(1.5rem, 2.6vw, 2.25rem);
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--r-tarjeta);
  transition: transform var(--transicion), box-shadow var(--transicion),
    border-color var(--transicion);
}

.celda:hover {
  transform: translateY(-3px);
  box-shadow: var(--sombra-m);
  border-color: color-mix(in oklab, var(--primario) 28%, var(--borde));
}

.celda__icono {
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pastilla);
  background: var(--acento-suave);
  color: var(--primario);
  font-size: 1.4rem;
  margin-bottom: auto;
}

.celda h3 {
  font-size: clamp(1.15rem, 1.8vw, 1.4rem);
}

.celda p {
  color: var(--tinta-suave);
  font-size: 0.975rem;
  max-width: 42ch;
}

/* Celda grande con foto: ocupa 3 columnas y 2 filas. */
.celda--retrato {
  grid-column: span 3;
  grid-row: span 2;
  position: relative;
  overflow: hidden;
  padding: 0;
  min-height: 420px;
  justify-content: flex-end;
}

.celda--retrato .celda__contenido {
  position: relative;
  z-index: 2;
  padding: clamp(1.5rem, 2.6vw, 2.25rem);
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
}

.celda--retrato h3,
.celda--retrato p {
  color: #fffefd;
}

.celda--retrato p {
  max-width: 34ch;
}

.celda__foto {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.celda__foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Velo para que el texto blanco sobre la foto cumpla contraste AA.
   La tinta va literal y no como var(--tinta): esa variable se invierte a
   crema en modo oscuro, y un velo claro sobre la foto dejaria el texto
   blanco ilegible. El velo tiene que ser oscuro en los dos modos. */
.celda--retrato::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    to top,
    color-mix(in oklab, #0e100b 86%, transparent) 0%,
    color-mix(in oklab, #0e100b 52%, transparent) 42%,
    transparent 78%
  );
}

.celda--ancha {
  grid-column: span 3;
}

/* Celda con degradado citrico: la variacion visual que pide la reja.
   El texto va en TINTA, no en blanco. Primero se intento al reves, con el
   degradado terminando en toronja para apoyar texto blanco, y al medir el
   pixel realmente renderizado dio 2.33 y 1.87: el texto caia sobre el
   coral, no sobre el toronja. Sobre un citrico claro el blanco no tiene
   nada que hacer. Con tinta, el punto mas oscuro del degradado (el coral)
   da 7.4:1 y el mas claro (el amarillo) 13:1.
   El degradado usa los tokens de la paleta base, que no se invierte entre
   modos: esta celda se ve igual en claro y en oscuro, por eso su texto va
   en hex literal y no en var(--tinta). */
.celda--citrica {
  grid-column: span 4;
  background: linear-gradient(200deg, var(--amarillo) 0%, var(--coral) 100%);
  border-color: transparent;
}

.celda--citrica h3,
.celda--citrica p {
  color: #0e100b;
}

.celda--citrica p {
  max-width: 46ch;
}

.celda--citrica .celda__icono {
  background: #fffefd;
  color: var(--toronja);
}

.celda--angosta {
  grid-column: span 2;
}

@media (max-width: 1000px) {
  .bento {
    grid-template-columns: repeat(2, 1fr);
  }

  .celda--retrato {
    grid-column: span 2;
    grid-row: auto;
    min-height: 340px;
  }

  .celda--ancha,
  .celda--citrica,
  .celda--angosta {
    grid-column: span 1;
  }

  .celda--citrica {
    grid-column: span 2;
  }
}

@media (max-width: 620px) {
  .bento {
    grid-template-columns: 1fr;
  }

  .celda--retrato,
  .celda--ancha,
  .celda--citrica,
  .celda--angosta {
    grid-column: span 1;
  }
}

/* =========================================================================
   8. MATERIALES (carril con anclaje de scroll)
   Seis materiales en una lista vertical serian seis filas con hairline.
   En carril se recorren de un vistazo y cada uno conserva su color.
   ========================================================================= */

/* Marco del carril: solo existe para colgar el degradado del borde
   derecho, que avisa de que hay mas tarjetas hacia el lado. Sin esa senal
   la ultima tarjeta parece cortada por error. */
.carril-marco {
  position: relative;
}

.carril-marco::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 1.75rem;
  right: 0;
  width: clamp(40px, 7vw, 90px);
  background: linear-gradient(to right, transparent, var(--fondo));
  pointer-events: none;
}

.carril {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* El padding lateral entra por aqui para que las tarjetas de los
     extremos no queden pegadas al borde de la ventana. */
  padding-inline: var(--margen);
  padding-block: 0.5rem 1.75rem;
  margin-inline: calc(var(--margen) * -1);
  scroll-padding-inline: var(--margen);
  scrollbar-width: thin;
  scrollbar-color: color-mix(in oklab, var(--oliva) 45%, transparent) transparent;
}

.carril::-webkit-scrollbar {
  height: 7px;
}

.carril::-webkit-scrollbar-thumb {
  background: color-mix(in oklab, var(--oliva) 42%, transparent);
  border-radius: var(--r-pastilla);
}

.carril::-webkit-scrollbar-track {
  background: transparent;
}

.material {
  scroll-snap-align: start;
  flex: 0 0 min(300px, 78vw);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 1.6rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--r-tarjeta);
  transition: border-color var(--transicion), box-shadow var(--transicion);
}

.material:hover {
  border-color: color-mix(in oklab, var(--primario) 30%, var(--borde));
  box-shadow: var(--sombra-m);
}

/* Muestra de material: tres capas finas, el mismo motivo del logo a
   escala de tarjeta. */
.material__muestra {
  display: flex;
  flex-direction: column;
  gap: 3px;
  width: 54px;
}

.material__muestra span {
  height: 7px;
  border-radius: var(--r-pastilla);
  background: var(--tono);
}

.material__muestra span:nth-child(2) {
  width: 84%;
  opacity: 0.78;
}

.material__muestra span:nth-child(3) {
  width: 62%;
  opacity: 0.56;
}

.material__nombre {
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.material__uso {
  font-size: 0.95rem;
  color: var(--tinta-suave);
}

.material__rasgo {
  margin-top: auto;
  padding-top: 0.9rem;
  border-top: 1px solid var(--borde);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--tono-texto, var(--tinta-suave));
}

/* En escritorio ancho las cinco caben en una fila: el carril escondia
   tarjeta y media detras del degradado sin ninguna necesidad. El carril
   queda para las pantallas donde de verdad no caben. */
@media (min-width: 1200px) {
  .carril {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    overflow: visible;
    margin-inline: 0;
    padding-inline: 0;
    padding-bottom: 0.5rem;
  }

  .carril-marco::after {
    content: none;
  }

  .material {
    padding: 1.4rem;
  }
}

/* =========================================================================
   9. PROCESO (altura Z)
   Cada etapa suma una capa: la barra crece paso a paso igual que crece
   una pieza en la cama. La linea vertical es la boquilla subiendo.
   ========================================================================= */

.proceso {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(2.5rem, 5vw, 5rem);
  align-items: start;
}

.proceso__lista {
  display: flex;
  flex-direction: column;
}

.etapa {
  position: relative;
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: clamp(1.25rem, 2.5vw, 2rem);
  padding-block: 1.75rem;
}

.etapa + .etapa {
  border-top: 1px solid var(--borde);
}

/* Barra de capa: crece etapa a etapa, de 45% a 100% de la columna. El
   avance lo fija el HTML con --avance, de 1 a 5.
   Estas barras NO se animan al hacer scroll. Se intento y quedo mal: con
   una animacion por barra, cada una entra a un progreso distinto segun
   donde este la pantalla, asi que nunca se ven las cinco juntas y la
   progresion (que es justo lo que la seccion cuenta) desaparece. Quietas
   se leen de un vistazo. */
.etapa__capa {
  align-self: center;
  height: 0.75rem;
  width: calc(32% + var(--avance) * 13.6%);
  border-radius: var(--r-pastilla);
  background: var(--tono);
}

.etapa h3 {
  font-size: clamp(1.2rem, 1.9vw, 1.5rem);
}

.etapa p {
  margin-top: 0.45rem;
  color: var(--tinta-suave);
  max-width: 48ch;
}

.proceso__panel {
  position: sticky;
  top: 7rem;
  padding: clamp(1.75rem, 3vw, 2.5rem);
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--r-tarjeta);
  box-shadow: var(--sombra-s);
}

.proceso__panel h3 {
  font-size: 1.35rem;
}

.proceso__panel p {
  margin-top: 0.75rem;
  color: var(--tinta-suave);
}

.proceso__panel .boton {
  margin-top: 1.5rem;
}

.proceso__nota {
  margin-top: 1.25rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--borde);
  font-size: 0.9rem;
  color: var(--tinta-suave);
}

@media (max-width: 900px) {
  .proceso {
    grid-template-columns: 1fr;
  }

  .proceso__panel {
    position: static;
  }

  .etapa {
    grid-template-columns: 88px minmax(0, 1fr);
  }
}

/* =========================================================================
   10. PERSONALIZACION (division foto + texto)
   La unica seccion de este tipo en la pagina: dos iguales seguidas ya
   serian un patron.
   ========================================================================= */

.personalizacion {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2.5rem, 5vw, 4.5rem);
  align-items: center;
}

.marco-foto {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-tarjeta);
  background: var(--superficie-2);
  aspect-ratio: 4 / 5;
}

/* Las fotos van a color. Hubo un duotono citrico aqui y se quito: servia
   para que un monton de fotos de archivo sin relacion pareciesen una serie
   elegida, pero con fotos del taller tapaba el color del filamento, que es
   justo lo que vende la pagina. Queda el acercamiento al pasar el cursor,
   que no esconde nada. */
.marco-foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 620ms cubic-bezier(0.16, 1, 0.3, 1);
}

.marco-foto:hover img {
  transform: scale(1.04);
}

.ejes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 2rem;
}

.eje {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.55rem 1.05rem;
  border: 1px solid var(--borde);
  border-radius: var(--r-pastilla);
  background: var(--superficie);
  font-size: 0.9rem;
  font-weight: 600;
  transition: border-color var(--transicion), background-color var(--transicion);
}

.eje:hover {
  background: var(--acento-suave);
  border-color: color-mix(in oklab, var(--primario) 30%, var(--borde));
}

.eje i {
  color: var(--primario);
  font-size: 1.05rem;
}

@media (max-width: 860px) {
  .personalizacion {
    grid-template-columns: 1fr;
  }

  .marco-foto {
    aspect-ratio: 4 / 3;
  }
}

/* =========================================================================
   11. GALERIA
   ========================================================================= */

/* Grilla pareja en vez de bento: las fotos ya vienen como serie en 4:5 y
   mezclar celdas altas, anchas y cuadradas obligaba a recortarlas. Aqui el
   ritmo lo dan los colores de las piezas, no el tamano de las celdas. El
   espacio entre filas es mayor que entre columnas porque debajo de cada
   foto va su pie, y sin ese aire el pie parece de la foto de abajo. */
.galeria {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: clamp(0.75rem, 1.6vw, 1.25rem);
  row-gap: clamp(1.75rem, 3vw, 2.5rem);
}

.pieza {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
}

/* Gana en especificidad al .marco-foto 4:3 de personalizacion en pantallas
   angostas: en la galeria la foto conserva siempre su 4:5. */
.pieza .marco-foto {
  aspect-ratio: 4 / 5;
}

/* Pie de foto debajo de la imagen, nunca encima: una etiqueta flotando
   sobre la foto tapa justo lo que se quiere mostrar. */
.pieza__pie {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  font-size: 0.9rem;
  line-height: 1.35;
}

.pieza__pie strong {
  font-weight: 600;
}

.pieza__pie span {
  color: var(--tinta-suave);
  font-size: 0.82rem;
  white-space: nowrap;
}

.galeria__cierre {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  margin-top: clamp(3rem, 6vw, 4.5rem);
  padding-top: clamp(1.75rem, 3vw, 2.25rem);
  border-top: 1px solid var(--borde);
}

.galeria__cierre p {
  font-size: clamp(1rem, 1.4vw, 1.125rem);
  color: var(--tinta-suave);
}

.galeria__cierre strong {
  color: var(--tinta);
  font-weight: 600;
}

@media (max-width: 900px) {
  .galeria {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* En telefono se quedan dos columnas: una sola haria ocho fotos a todo el
   ancho, casi cuatro pantallas de scroll para una muestra. El material
   baja bajo el nombre porque al lado ya no cabe. */
@media (max-width: 520px) {
  .pieza__pie {
    flex-direction: column;
    gap: 0.15rem;
  }

  .galeria__cierre {
    flex-direction: column;
    align-items: stretch;
    text-align: center;
  }
}

/* =========================================================================
   12. PREGUNTAS (acordeon nativo)
   ========================================================================= */

.preguntas {
  max-width: 820px;
  margin-inline: auto;
}

.pregunta {
  border-bottom: 1px solid var(--borde);
}

.pregunta summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: 1.4rem;
  cursor: pointer;
  list-style: none;
  font-size: clamp(1.05rem, 1.6vw, 1.2rem);
  font-weight: 600;
  letter-spacing: -0.015em;
  transition: color var(--transicion);
}

.pregunta summary::-webkit-details-marker {
  display: none;
}

.pregunta summary:hover {
  color: var(--primario-texto);
}

.pregunta summary i {
  flex-shrink: 0;
  font-size: 1.35rem;
  color: var(--primario);
  transition: transform var(--transicion);
}

.pregunta[open] summary i {
  transform: rotate(45deg);
}

.pregunta__cuerpo {
  padding-bottom: 1.5rem;
  color: var(--tinta-suave);
  max-width: 68ch;
}

/* =========================================================================
   13. CONTACTO
   Sin formulario: la seccion es una columna centrada con los tres canales
   en fila. Apilados a lo ancho dejaban media tarjeta vacia a la derecha y
   el bloque entero se leia corrido a la izquierda, aunque estuviera
   centrado: tres tarjetas angostas llenan el espacio y se ven parejas.
   ========================================================================= */

.contacto {
  max-width: 54rem;
  margin-inline: auto;
  text-align: center;
}

/* El titulo y la bajada traen max-width propio (18ch y 54ch). Sin esto el
   bloque queda centrado pero el texto pegado a la izquierda. */
.contacto .titulo-seccion,
.contacto .bajada-seccion {
  margin-inline: auto;
}

.contacto__directo {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
  margin-top: clamp(2rem, 4vw, 3rem);
}

.via {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.7rem;
  padding: 1.75rem 1.25rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--r-tarjeta);
  transition: transform var(--transicion), border-color var(--transicion),
    box-shadow var(--transicion);
}

/* En fila el gesto natural es levantar, no empujar al costado. */
.via:hover {
  transform: translateY(-4px);
  border-color: color-mix(in oklab, var(--primario) 32%, var(--borde));
  box-shadow: var(--sombra-s);
}

.via i {
  font-size: 1.75rem;
  color: var(--primario);
}

.via__texto {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  line-height: 1.35;
}

/* El correo es la etiqueta mas larga y no se puede partir en dos lineas
   sin que se lea como dos cosas: baja de tamano hasta caber. */
.via__texto strong {
  font-weight: 600;
  font-size: 0.95rem;
  overflow-wrap: anywhere;
}

.via__texto span {
  font-size: 0.82rem;
  color: var(--tinta-suave);
}

@media (max-width: 760px) {
  .contacto__directo {
    grid-template-columns: 1fr;
  }
}

.contacto__pie {
  margin-top: 1.75rem;
  font-size: 0.85rem;
  color: var(--tinta-suave);
}

/* =========================================================================
   14. PIE DE PAGINA
   ========================================================================= */

.pie {
  background: var(--superficie-3);
  border-top: 1px solid var(--borde);
  padding-block: clamp(3rem, 6vw, 4.5rem) 2rem;
}

.pie__reja {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: clamp(2rem, 4vw, 3.5rem);
}

.pie__intro {
  max-width: 34ch;
  margin-top: 1.1rem;
  font-size: 0.95rem;
  color: var(--tinta-suave);
}

.pie h4 {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin-bottom: 1rem;
}

.pie ul {
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  font-size: 0.95rem;
}

.pie a:hover {
  color: var(--primario-texto);
}

.pie__cierre {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: 1.75rem;
  border-top: 1px solid var(--borde);
  font-size: 0.875rem;
  color: var(--tinta-suave);
}

.pie__redes {
  display: flex;
  gap: 0.6rem;
}

.pie__redes a {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--borde);
  border-radius: var(--r-pastilla);
  font-size: 1.15rem;
  transition: background-color var(--transicion), border-color var(--transicion),
    color var(--transicion), transform var(--transicion);
}

.pie__redes a:hover {
  background: var(--primario);
  border-color: var(--primario);
  color: var(--primario-tinta);
  transform: translateY(-2px);
}

@media (max-width: 860px) {
  .pie__reja {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .pie__marca {
    grid-column: span 2;
  }
}

@media (max-width: 480px) {
  .pie__reja {
    grid-template-columns: 1fr;
  }

  .pie__marca {
    grid-column: span 1;
  }
}

/* =========================================================================
   15. MOVIMIENTO
   Todo lo de abajo es opcional por definicion: si el navegador no soporta
   animation-timeline, o si la persona pidio menos movimiento, el
   contenido se ve completo y quieto. El estado inicial invisible vive
   DENTRO del @supports, nunca fuera: si quedara fuera, un navegador sin
   soporte dejaria la pagina en blanco.
   ========================================================================= */

@media (prefers-reduced-motion: no-preference) {
  /* --- La marca se imprime al cargar ---
     Las capas suben una tras otra desde la cama, y la hoja (que en el
     logo es la boquilla extruyendo) baja al final. Dura menos de un
     segundo y medio y no se repite. */
  .capa-impresa {
    animation: imprimir 520ms cubic-bezier(0.16, 1, 0.3, 1) backwards;
    transform-box: fill-box;
    transform-origin: center;
  }

  .capa-impresa:nth-of-type(1) { animation-delay: 120ms; }
  .capa-impresa:nth-of-type(2) { animation-delay: 240ms; }
  .capa-impresa:nth-of-type(3) { animation-delay: 360ms; }
  .capa-impresa:nth-of-type(4) { animation-delay: 480ms; }
  .capa-impresa:nth-of-type(5) { animation-delay: 600ms; }

  .boquilla {
    animation: bajar-boquilla 560ms cubic-bezier(0.16, 1, 0.3, 1) 720ms backwards;
    transform-box: fill-box;
    transform-origin: center bottom;
  }

  /* --- La espera del 3D ---
     Mientras baja three.js solo se ve la cama. Este latido evita que el
     hueco parezca roto, sin adelantar como va a quedar la pieza. Se corta
     en cuanto el lienzo entra o el plano toma su lugar. */
  .con-js .impresion__cama {
    animation: latir-cama 1.8s ease-in-out infinite;
  }

  .impresion--3d .impresion__cama,
  .impresion--plano .impresion__cama {
    animation: none;
  }

  @keyframes latir-cama {
    0%, 100% { opacity: 0.45; transform: scaleX(0.9); }
    50% { opacity: 1; transform: scaleX(1); }
  }

  @keyframes imprimir {
    from {
      opacity: 0;
      transform: translateY(14px) scaleX(0.55);
    }
    to {
      opacity: 1;
      transform: translateY(0) scaleX(1);
    }
  }

  @keyframes bajar-boquilla {
    from {
      opacity: 0;
      transform: translateY(-34px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  /* --- Entradas del hero --- */
  .entra {
    animation: entrar 620ms cubic-bezier(0.16, 1, 0.3, 1) backwards;
  }

  .entra--1 { animation-delay: 60ms; }
  .entra--2 { animation-delay: 160ms; }
  .entra--3 { animation-delay: 260ms; }

  @keyframes entrar {
    from {
      opacity: 0;
      transform: translateY(16px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  /* --- Revelado por scroll ---
     Sirve para jerarquia: cada seccion entra cuando toca, en vez de que
     la pagina aparezca entera de golpe. */
  @supports (animation-timeline: view()) {
    .revela {
      animation: revelar linear both;
      animation-timeline: view();
      animation-range: entry 8% cover 26%;
    }

    @keyframes revelar {
      from {
        opacity: 0;
        transform: translateY(26px);
      }
      to {
        opacity: 1;
        transform: translateY(0);
      }
    }

  }
}

/* Quien prefiera menos movimiento no deberia sufrirlo. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
