/* ==========================================================================
   MOIETY — Studio Creativo
   Hoja de estilos única. Implementación del prototipo "Sitio MOIETY.dc.html".
   Orden: tokens → base → utilidades → nav → hero → servicios → proceso →
          muestras → nosotros → contacto → footer → movimiento
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Color */
  --ink: #0A0A0A;
  --paper: #FBFBFA;
  --sand: #F2EDE4;

  /* Acento de marca. Alternativas del sistema:
     #E0532B terracota · #FF3D00 naranja · #E4B200 amarillo (actual)
     #B8862F ocre · #8A6A4F café
     Se puede sobrescribir desde js/main.js (CONFIG.acento). */
  --ac: #E4B200;

  /* Variante del acento para TEXTO sobre fondo claro. El ámbar de marca sólo
     contrasta 1,69:1 contra --sand y 1,90:1 contra --paper, así que usarlo como
     color de enlace en :hover incumplía la SC 1.4.3 en el correo de contacto,
     en el enlace a la política dentro del consentimiento y en todas las páginas
     legales. Este oro oscuro es la misma familia y da 5,36:1 sobre --sand y
     6,04:1 sobre --paper.
     Regla: --ac sólo sobre fondo oscuro; --ac-texto sobre fondo claro. */
  --ac-texto: #7A5C00;

  /* Todos los grises de texto están comprobados a ≥4,5:1 sobre su fondo:
     los claros sobre --sand #F2EDE4 y los oscuros sobre --ink #0A0A0A. */
  --texto-claro: #4F4F4F;   /* párrafos sobre fondo claro — 6,55:1 */
  --texto-oscuro-1: #B9B6B0; /* párrafos sobre fondo oscuro */
  --texto-oscuro-2: #8A8782; /* labels sobre fondo oscuro — 5,53:1 */
  --texto-oscuro-3: #7E7B76; /* 4,70:1 */
  --texto-oscuro-4: #807D78; /* barra del pie — era #5E5B57 (2,93:1), ahora 4,83:1 */
  --nav-texto: #F2F0EC;

  --borde-paper: #DEDCD8;
  --borde-sand: #D9D1C2;
  /* Borde de los controles de formulario. --borde-sand da 1,30:1 sobre --sand,
     muy por debajo del 3:1 que la SC 1.4.11 exige al límite de un componente:
     los campos eran casi imperceptibles. Éste da 3,30:1 sobre --sand. */
  --borde-campo: #8A8170;
  --borde-suave: #EDEBE7;
  --borde-ink-1: #242424;
  --borde-ink-2: #2A2A2A;
  --borde-ink-3: #3A3A3A; /* borde en hover sobre fondo oscuro */

  /* Estados del formulario, medidos sobre --sand #F2EDE4 (no sobre --paper).
     El verde anterior (#2E7D4F) daba 4,33:1, por debajo del mínimo: era
     justamente el mensaje que confirma que el formulario se envió. */
  --ok: #2A7248;    /* 5,00:1 */
  --error: #B4442A; /* 4,74:1 */

  /* Tipografía */
  --f-display: Manrope, system-ui, sans-serif;
  --f-texto: Archivo, system-ui, sans-serif;
  --f-mono: "IBM Plex Mono", ui-monospace, monospace;

  /* Forma y movimiento */
  --r-pill: 60px;
  --r-card: 6px;
  --r-badge: 4px;
  --ease: cubic-bezier(.16, 1, .3, 1);

  /* Curva del hero: salida suave sin rebote, para la palabra rotativa y su
     subrayado. Es la del componente de referencia moiety-hero. */
  --ease-hero: cubic-bezier(.22, 1, .36, 1);

  /* Layout */
  --max: 1520px;
  --max-nav: 1360px;
  --pad-x: clamp(20px, 5vw, 72px);
  --sec-top: clamp(64px, 9vw, 140px);
  --sec-bottom: clamp(72px, 10vw, 150px);
}

/* --------------------------------------------------------------------------
   2. Base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

/* La barra de navegación es fija y flotante, así que un salto de ancla dejaba
   el kicker de la sección a 2-3px de ella en móvil. Esto reserva el hueco. */
section[id] { scroll-margin-top: clamp(84px, 8vw, 108px); }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--f-texto);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

a { color: var(--ink); text-decoration: none; }
/* Sobre fondo claro el hover usa --ac-texto (ver el token). Los enlaces que
   viven sobre fondo oscuro llevan su propia regla de :hover con --ac, que ahí
   sí da 10,06:1 — ver .footer__col a:hover. */
a:hover { color: var(--ac-texto); }

img, svg { display: block; max-width: 100%; }
input, textarea, button { font-family: inherit; }
::selection { background: var(--ink); color: var(--paper); }

/* Anillo de foco de dos tonos. El ámbar solo contrasta 1,68:1 contra --paper
   y --sand, así que sobre las secciones claras era prácticamente invisible.
   El aro interior de tinta resuelve el fondo claro (18:1) y el ámbar exterior
   resuelve el fondo oscuro (10:1): siempre hay uno de los dos por encima del
   3:1 que pide la SC 1.4.11, mire donde mire el usuario.
   El `outline` real (y no solo box-shadow) mantiene el indicador visible en
   modo de alto contraste de Windows, donde las sombras se descartan. */
:focus-visible {
  outline: 3px solid var(--ac);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--ink);
  border-radius: 2px;
}
/* Sobre fondo oscuro el aro de tinta no aporta y ensucia el borde */
.seccion-oscura :focus-visible,
.hero :focus-visible,
.nav :focus-visible,
.nav__cta:focus-visible { box-shadow: 0 0 0 2px rgba(10, 10, 10, .9); }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Enlace de salto (accesibilidad de teclado) */
.skip-link {
  position: absolute;
  top: 8px; left: 8px;
  z-index: 9999;
  transform: translateY(-200%);
  background: var(--ink);
  color: var(--paper);
  padding: 12px 20px;
  border-radius: var(--r-pill);
  font-size: 14px;
  font-weight: 600;
  transition: transform .3s var(--ease);
}
.skip-link:focus { transform: translateY(0); color: var(--paper); }

/* --------------------------------------------------------------------------
   3. Utilidades
   -------------------------------------------------------------------------- */
.wrap { max-width: var(--max); margin: 0 auto; }

/* `margin` y `font-weight` explícitos porque en "Sobre MOIETY" el kicker es un
   <h2> real (la sección no tenía ningún encabezado): sin esto heredaría el
   margen y la negrita del user-agent. */
.kicker {
  margin: 0;
  font-family: var(--f-mono);
  font-size: clamp(11px, 1vw, 13px);
  font-weight: 400;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--texto-claro);
}
.kicker--oscuro { color: var(--texto-oscuro-2); }
.kicker--ac { color: var(--ac); font-size: 12px; }

.h2 {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 800;
  letter-spacing: -.03em;
  line-height: .9;
  font-size: clamp(38px, 6vw, 84px);
  text-transform: uppercase;
}

.parrafo {
  margin: 0;
  font-family: var(--f-texto);
  font-size: clamp(15px, 1.2vw, 18px);
  line-height: 1.6;
  color: var(--texto-claro);
  text-wrap: pretty;
}
.parrafo--oscuro { color: var(--texto-oscuro-1); }

/* Rombo de marca (asterisco de 8 puntas) */
.rombo {
  flex: 0 0 auto;
  background: var(--ac);
  clip-path: polygon(50% 0%, 58% 42%, 100% 50%, 58% 58%, 50% 100%, 42% 58%, 0% 50%, 42% 42%);
}

.mono { font-family: var(--f-mono); }

/* Botones pill */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  border-radius: var(--r-pill);
  font-size: 14px;
  font-weight: 600;
  padding: 17px 28px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform .35s var(--ease), background .35s ease, color .35s ease, border-color .35s ease;
}
.btn .mono { font-family: var(--f-mono); }

/* Sobre el ámbar el texto va en TINTA, nunca en papel: --paper sobre --ac da
   1,90:1 y hacía ilegibles estos botones justo al apuntarlos. Con --ink son
   10,06:1, que es lo que ya hacía .hero__cta:hover. */
.btn--solido { background: var(--ink); color: var(--paper); }
.btn--solido:hover { transform: translateY(-3px); background: var(--ac); color: var(--ink); }

.btn--outline { border-color: var(--ink); color: var(--ink); }
.btn--outline:hover { background: var(--ink); color: var(--paper); transform: translateY(-3px); }

.btn--claro { background: var(--paper); color: var(--ink); }
.btn--claro:hover { transform: translateY(-3px); background: var(--ac); color: var(--ink); }

/* Secundario sobre fondo oscuro (404) */
.btn--outline-claro { border-color: rgba(251, 251, 250, .4); color: var(--paper); background: transparent; }
.btn--outline-claro:hover { background: var(--paper); color: var(--ink); transform: translateY(-3px); }

/* Grano de película */
.grano {
  position: fixed;
  inset: -10%;
  z-index: 9000;
  pointer-events: none;
  opacity: .32;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  animation: moi-grain 14s ease-in-out infinite;
}

/* --------------------------------------------------------------------------
   4. Navegación
   -------------------------------------------------------------------------- */
.header {
  position: fixed;
  top: clamp(12px, 2vw, 22px);
  left: 0; right: 0;
  z-index: 8000;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 clamp(12px, 3vw, 32px);
  pointer-events: none;
}

.header__inner {
  width: 100%;
  max-width: var(--max-nav);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

.header__fila {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.nav {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: nowrap;
  padding: 6px;
  border-radius: var(--r-pill);
  /* Bastante translúcida, pero sigue siendo un tinte OSCURO y no claro como
     el del componente de referencia: esta barra también pasa por encima de
     secciones claras (servicios, muestras, nosotros) y con tinte claro se
     volvería ilegible ahí. */
  background: rgba(10, 10, 10, .58);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  backdrop-filter: blur(20px) saturate(1.5);
  box-shadow: 0 18px 44px -26px rgba(10, 10, 10, .55);
  transition: box-shadow .4s ease, background .4s ease;
}
.nav.is-scrolled {
  background: rgba(10, 10, 10, .8);
  box-shadow: 0 24px 56px -26px rgba(10, 10, 10, .65);
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 2px;
  font-family: var(--f-texto);
  font-size: 14px;
  font-weight: 500;
}

.nav__link {
  color: var(--nav-texto);
  padding: 11px clamp(14px, 1.3vw, 20px);
  border-radius: var(--r-pill);
  background: transparent;
  white-space: nowrap;
  transition: background .35s ease, color .35s ease;
}
.nav__link:hover { background: rgba(251, 251, 250, .12); color: var(--nav-texto); }
.nav__link.is-active { background: var(--paper); color: var(--ink); }

.nav__cta {
  pointer-events: auto;
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 12px 12px 12px 22px;
  border-radius: var(--r-pill);
  /* Bastante translúcida, pero sigue siendo un tinte OSCURO y no claro como
     el del componente de referencia: esta barra también pasa por encima de
     secciones claras (servicios, muestras, nosotros) y con tinte claro se
     volvería ilegible ahí. */
  background: rgba(10, 10, 10, .58);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  backdrop-filter: blur(20px) saturate(1.5);
  box-shadow: 0 18px 44px -26px rgba(10, 10, 10, .55);
  color: var(--nav-texto);
  font-family: var(--f-texto);
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  transition: transform .35s var(--ease);
}
.nav__cta:hover { transform: translateY(-2px); color: var(--nav-texto); }

.nav__cta-circulo {
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--ac);
  color: var(--ink);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--f-mono);
  font-size: 14px;
  line-height: 1;
}

/* Barra compacta (≤900px) */
.nav__compacta { display: none; align-items: center; gap: 6px; }

.nav__boton-menu {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 0;
  background: transparent;
  color: var(--nav-texto);
  font-family: var(--f-texto);
  font-size: 14px;
  font-weight: 500;
  padding: 11px 16px;
  border-radius: var(--r-pill);
  cursor: pointer;
}
.nav__hamburguesa { display: flex; flex-direction: column; gap: 4px; }
.nav__hamburguesa span {
  display: block;
  width: 16px; height: 1.5px;
  background: var(--nav-texto);
}

/* Es el CTA principal en móvil, así que el contraste manda: --paper sobre --ac
   daba 1,90:1; con --ink son 10,06:1. */
.nav__wa-compacto {
  color: var(--ink);
  background: var(--ac);
  padding: 11px 18px;
  border-radius: var(--r-pill);
  font-family: var(--f-texto);
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
}
.nav__wa-compacto:hover { color: var(--ink); }

/* El panel se desplaza por dentro. Sin esto, en un viewport bajo (móvil
   apaisado, o 375px al 400% de zoom — el escenario de la SC 1.4.10) el panel
   medía 366px de alto sobre 360px de ventana y "Contacto" y "Agendar consulta"
   quedaban fuera de pantalla: el panel vive en un .header fijo y, con el menú
   abierto, `menu-abierto` bloquea el scroll de la página, así que no había
   ninguna forma de alcanzarlos.
   Los ~112px reservados son el hueco de la barra flotante: `top` del .header
   (hasta 22px) + alto de la barra (~57px) + los 8px de margin-top + holgura. */
.menu-panel {
  pointer-events: auto;
  margin-top: 8px;
  width: 100%;
  max-width: 440px;
  max-height: calc(100vh - 112px);
  max-height: calc(100dvh - 112px);
  overflow-y: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--borde-paper);
  border-radius: 24px;
  background: rgba(251, 251, 250, .96);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  padding: 14px;
  display: none;
  flex-direction: column;
  box-shadow: 0 24px 50px -32px rgba(10, 10, 10, .5);
}
.menu-panel.is-open { display: flex; }

/* Con el panel abierto el fondo no se desplaza por detrás */
.menu-abierto, .menu-abierto body { overflow: hidden; }

.menu-panel__link {
  padding: 14px 12px;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: 19px;
  letter-spacing: -.01em;
  border-bottom: 1px solid var(--borde-suave);
  color: var(--ink);
}

.menu-panel__cta {
  margin-top: 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--ink);
  color: var(--paper);
  border-radius: var(--r-pill);
  padding: 16px 22px;
  font-size: 14px;
  font-weight: 600;
}
.menu-panel__cta:hover { color: var(--paper); }

@media (max-width: 900px) {
  .nav__links { display: none; }
  .nav__compacta { display: flex; }
  .nav__cta { display: none; }
}

/* Por debajo de 360px la barra (botón de menú + "Escríbenos") medía 316px con
   296px disponibles y se salía 8px por la derecha. */
@media (max-width: 360px) {
  .header { padding: 0 10px; }
  .nav { padding: 5px; }
  .nav__boton-menu { padding: 10px 12px; gap: 8px; }
  .nav__wa-compacto { padding: 10px 14px; }
}

/* --------------------------------------------------------------------------
   5. Hero
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
}

/* Ocupa toda la ventana, sin márgenes ni esquinas redondeadas. */
.hero__tarjeta {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  /* Sin la barra inferior que había antes, .hero__contenido es el único hijo:
     centrarlo aquí (en vez de solo con el `align-items` de su grid interno)
     es lo que lo reproporciona en toda la altura de la tarjeta. */
  justify-content: center;
  overflow: hidden;
  color: var(--paper);
  /* Respaldo si WebGL no está disponible: el canvas queda oculto y se ve esto */
  background:
    radial-gradient(120% 90% at 12% 40%, rgba(228, 178, 0, .22) 0%, transparent 60%),
    radial-gradient(90% 80% at 85% 75%, rgba(184, 134, 47, .18) 0%, transparent 65%),
    #0C0A08;
}

/* Lienzo del fondo animado. Va detrás de todo lo demás de su contenedor;
   el resto de hijos se elevan con .seccion-oscura (o con z-index propio). */
.fondo-shader {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
  z-index: 0;
}
/* main.js añade .sin-webgl al contenedor cuando no puede crear el contexto:
   se oculta el lienzo y queda el fondo sólido o el degradado de respaldo. */
.sin-webgl > .fondo-shader { display: none; }

/* Secciones oscuras con fondo animado (proceso, contacto, footer) */
.seccion-oscura { position: relative; }
.seccion-oscura > *:not(.fondo-shader) { position: relative; z-index: 1; }

/* El tramo del 68% subió de .10 a .22: justo ahí caen las tres tarjetas de
   servicio y ahí es donde el shader produce el brillo dorado, de modo que el
   texto quedaba sobre la zona más clara del fondo con casi nada de velo. */
.hero__velo {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg,
    rgba(10, 9, 7, .82) 0%,
    rgba(10, 9, 7, .55) 38%,
    rgba(10, 9, 7, .22) 68%,
    rgba(10, 9, 7, .40) 100%);
}

.hero__anillos span {
  position: absolute;
  top: 50%;
  left: -6%;
  width: var(--anillo);
  height: var(--anillo);
  margin: calc(var(--anillo) / -2) 0 0 calc(var(--anillo) / -2);
  border: 1px solid rgba(255, 255, 255, var(--opacidad));
  border-radius: 50%;
  pointer-events: none;
}

.hero__contenido {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--max);
  margin: 0 auto;
  /* Ya no hay barra inferior compitiendo por espacio, así que el contenido se
     centra en toda la altura de la tarjeta (ver `justify-content: center` en
     .hero__tarjeta) en vez de ocupar `flex: 1` y autocentrarse por dentro.
     El padding queda casi simétrico; arriba lleva un poco más para despejar
     la barra de navegación flotante y por equilibrio óptico. */
  padding: clamp(88px, 10vh, 120px) var(--pad-x) clamp(64px, 8vh, 96px);
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}

.hero__kicker {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: clamp(16px, 2.6vh, 32px);
}
.hero__kicker .rombo { width: 12px; height: 12px; }
.hero__tarjeta .kicker { color: rgba(251, 251, 250, .72); }

.hero__title {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: .95;
  /* El contenedor de la palabra rotativa reserva siempre el ancho de
     "ESTRATEGIA." (ver .rotador__medida), así que en móvil el titular cabe en
     dos renglones a partir de ~375px y en tres por debajo de eso. Las dos
     versiones se ven bien y —esto es lo que importa— el salto de línea no
     cambia al rotar la palabra, porque el ancho reservado es constante. */
  font-size: clamp(36px, min(5.6vw, 8.4vh), 78px);
  text-transform: uppercase;
  color: var(--paper);
}
.hero__title-1 { display: block; overflow: hidden; }
.hero__title-2 { display: block; overflow: visible; }

/* Palabra rotativa.
   La ventana necesita aire arriba o el acento de "Ó" se corta: Manrope 300
   tiene ink-ascent ≈ .95em y la baseline cae a ≈ .885em con line-height 1.
   Ventana de 1.25em con margin-top -.23em + palabras en top .22em deja la
   posición óptica idéntica y headroom para los acentos. */
/* El ancho lo fija .rotador__medida (la palabra más larga, invisible pero en
   flujo), así la línea nunca se reajusta al cambiar de palabra: lo único que
   se anima es el ancho del subrayado. */
.rotador {
  position: relative;
  display: inline-block;
  vertical-align: bottom;
}
.rotador__ventana {
  display: block;
  position: relative;
  height: 1.25em;
  margin-top: -.23em;
  overflow: hidden;
}
.rotador__medida {
  display: inline-block;
  visibility: hidden;
  line-height: 1;
  font-weight: 300;
  white-space: nowrap;
}
.rotador__palabra {
  position: absolute;
  left: 0;
  top: .22em;
  line-height: 1;
  font-weight: 300;
  white-space: nowrap;
  transition: transform .55s var(--ease-hero), opacity .4s ease;
}
/* Sin JS solo se ve la primera palabra ("UNA IDEA."), no las cinco apiladas. */
.rotador__palabra:not(:first-child) {
  opacity: 0;
  transform: translate3d(0, 115%, 0);
}

/* Por debajo de ~380px el rotador ya no cabe junto a "UNA" y salta a su propio
   renglón. Ahí el margen negativo de -.23em —pensado para cuando va en línea—
   lo sube hasta chocar con la línea de arriba, así que se reduce. */
@media (max-width: 380px) {
  .rotador__ventana { margin-top: -.04em; }
}

.rotador__subrayado {
  position: absolute;
  left: 0;
  bottom: .02em;
  width: 100%;            /* sin JS marca todo el ancho; con JS, la palabra activa */
  height: clamp(3px, .45vw, 6px);
  background: var(--ac);
  transform-origin: left;
  transition: width .45s var(--ease-hero), transform 1.1s var(--ease) .5s;
}
/* main.js la usa para fijar el ancho inicial sin animarlo */
.rotador.sin-transicion .rotador__subrayado,
.rotador.sin-transicion .rotador__palabra { transition: none; }
/* El trazo solo se anima cuando hay JS; sin él aparece ya dibujado. */
.js .rotador__subrayado { transform: scaleX(0); }
.js .rotador__subrayado.is-on { transform: scaleX(1); }

.hero__parrafo {
  margin: clamp(18px, 2.6vh, 30px) 0 0;
  max-width: 34em;
  font-size: clamp(15px, 1.1vw, 17px);
  line-height: 1.65;
  color: rgba(251, 251, 250, .74);
  text-wrap: pretty;
}
.hero__parrafo strong { color: var(--paper); font-weight: 600; }

/* CTAs sobre fondo oscuro */
.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(12px, 1.6vw, 20px);
  margin-top: clamp(22px, 3.2vh, 38px);
}

.hero__cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--paper);
  color: var(--ink);
  border-radius: var(--r-pill);
  padding: 15px 26px;
  font-size: 14px;
  font-weight: 600;
  white-space: nowrap;
  transition: transform .35s var(--ease), background .35s ease, color .35s ease;
}
.hero__cta:hover {
  transform: translateY(-3px);
  background: var(--ac);
  color: var(--ink);
}

.hero__cta-fantasma {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 14px;
  font-weight: 500;
  color: rgba(251, 251, 250, .78);
  white-space: nowrap;
  transition: color .35s ease;
}
.hero__cta-fantasma:hover { color: var(--paper); }
.hero__cta-circulo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px; height: 40px;
  flex: 0 0 auto;
  border: 1px solid rgba(255, 255, 255, .35);
  border-radius: 50%;
  font-size: 14px;
  transition: border-color .35s ease, transform .35s var(--ease);
}
.hero__cta-fantasma:hover .hero__cta-circulo {
  border-color: var(--paper);
  transform: translateY(3px);
}

/* Columna derecha del hero: tarjetas de servicio + sello */
.hero__col-media {
  position: relative;
  justify-self: end;
  width: 100%;
  max-width: 520px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(14px, 2vh, 22px);
}

/* La perspectiva va en el contenedor, no en cada tarjeta: así todas comparten
   el mismo punto de fuga y el conjunto se lee como un solo plano inclinado. */
.hero__tarjetas {
  width: 100%;
  display: grid;
  gap: clamp(10px, 1.4vh, 16px);
  perspective: 1000px;
}

.tarjeta3d {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: start;
  gap: 4px clamp(12px, 1.4vw, 18px);
  padding: clamp(15px, 1.8vw, 21px) clamp(16px, 1.9vw, 23px);
  border: 1px solid rgba(255, 255, 255, .15);
  border-radius: clamp(10px, 1vw, 14px);
  /* Base oscura propia en vez del velo blanco al 4,5%: el fondo de detrás es
     un shader animado, así que sin una base con opacidad suficiente el
     contraste del texto cambia de fotograma a fotograma y no se puede
     garantizar el 4,5:1. Con esto el peor caso queda en ~6,7:1.
     Se usa color plano, no backdrop-filter: el filtro aplana el contexto 3D
     y se perdería el relieve de los translateZ de los hijos. */
  background: rgba(12, 10, 8, .44);
  color: var(--paper);
  transform-style: preserve-3d;
  /* Al salir vuelve despacio; mientras el cursor está encima (regla :hover de
     abajo) la transición se acorta para que el giro siga al puntero sin lag. */
  transition: transform .5s var(--ease), border-color .35s ease, background .35s ease;
}
.tarjeta3d:hover {
  border-color: rgba(255, 255, 255, .32);
  background: rgba(12, 10, 8, .56);
  color: var(--paper);
  transition: transform .12s linear, border-color .35s ease, background .35s ease;
}

/* Brillo que sigue al cursor. --mx/--my las escribe main.js. */
.tarjeta3d::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  /* El respaldo usa el amarillo por defecto; con color-mix sigue al acento real */
  background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 50%), rgba(228, 178, 0, .16), transparent 62%);
  background: radial-gradient(220px circle at var(--mx, 50%) var(--my, 50%), color-mix(in srgb, var(--ac) 16%, transparent), transparent 62%);
  opacity: 0;
  transition: opacity .35s ease;
}
.tarjeta3d:hover::after { opacity: 1; }

/* Los hijos se despegan del plano de la tarjeta: es lo que da el relieve real
   en vez de una simple inclinación plana. */
.tarjeta3d__rombo,
.tarjeta3d__titulo,
.tarjeta3d__flecha { transform: translateZ(22px); }
.tarjeta3d__texto { transform: translateZ(12px); }

.tarjeta3d__rombo {
  grid-row: 1 / 3;
  width: 11px; height: 11px;
  margin-top: .34em;
}

.tarjeta3d__titulo {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(15px, 1.25vw, 18px);
  letter-spacing: -.01em;
  line-height: 1.25;
  text-transform: none;
  color: var(--paper);
}

.tarjeta3d__texto {
  margin: 0;
  font-size: clamp(13px, 1vw, 14px);
  line-height: 1.5;
  color: rgba(251, 251, 250, .76);
  text-wrap: pretty;
}

.tarjeta3d__flecha {
  grid-row: 1 / 3;
  align-self: center;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  flex: 0 0 auto;
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: 50%;
  font-size: 12px;
  transition: border-color .35s ease, background .35s ease, color .35s ease;
}
.tarjeta3d:hover .tarjeta3d__flecha {
  border-color: var(--ac);
  background: var(--ac);
  color: var(--ink);
}

.hero__badge {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 18px;
  border: 1px solid rgba(255, 255, 255, .2);
  border-radius: var(--r-badge);
  background: rgba(12, 10, 8, .72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.hero__badge .rombo {
  width: 13px; height: 13px;
  background: var(--ac);
  animation: moi-spin 18s linear infinite;
}
.hero__tarjeta .hero__badge .kicker { color: var(--paper); }

/* Una sola columna: el retrato pasa debajo del texto */
@media (max-width: 900px) {
  /* Los laterales se ajustan para dar al titular los píxeles que necesita y no
     partir "UNA" de la palabra rotativa; arriba se mantiene el hueco de la
     barra de navegación flotante, que si no se solapa con el kicker. En
     móvil el contenido (dos filas: texto + retrato) suele superar la altura
     del viewport, así que el centrado vertical de .hero__tarjeta no llega a
     notarse — el padding es el que manda. */
  .hero__contenido {
    grid-template-columns: 1fr;
    padding: clamp(88px, 11vh, 116px) clamp(22px, 5vw, 34px) clamp(48px, 7vh, 72px);
  }
  .hero__col-media { justify-self: stretch; max-width: none; }
}

/* Placeholder reutilizable de la galería */
.placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  text-align: center;
  background: var(--sand);
  color: var(--texto-claro);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  line-height: 1.6;
}

/* --------------------------------------------------------------------------
   6. Servicios
   -------------------------------------------------------------------------- */
.servicios {
  background: var(--sand);
  padding: var(--sec-top) var(--pad-x) var(--sec-bottom);
}

.seccion__head {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(24px, 4vw, 64px);
  align-items: end;
  margin-bottom: clamp(44px, 6vw, 88px);
}
.seccion__head .kicker { display: block; margin-bottom: clamp(18px, 2.4vw, 30px); }
.seccion__head p { max-width: 460px; }

/* Banner Diagnóstico 360° */
.diagnostico {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: clamp(20px, 3vw, 40px);
  align-items: center;
  background: var(--ink);
  color: var(--paper);
  padding: clamp(26px, 3.5vw, 44px);
  border-radius: var(--r-card);
  margin-bottom: clamp(40px, 5vw, 72px);
}
.diagnostico .kicker--ac { display: block; margin-bottom: 14px; }
.diagnostico h3 {
  margin: 0 0 12px;
  font-family: var(--f-display);
  font-weight: 600;
  letter-spacing: -.02em;
  font-size: clamp(24px, 2.6vw, 40px);
  line-height: 1.05;
}
.diagnostico p {
  margin: 0;
  font-size: clamp(15px, 1.1vw, 17px);
  line-height: 1.6;
  color: var(--texto-oscuro-1);
  max-width: 520px;
  text-wrap: pretty;
}
.diagnostico .btn { justify-self: start; padding: 16px 26px; }

/* Lista de servicios */
.servicios__lista { border-top: 1px solid var(--borde-sand); }

/* Tres columnas o una, nunca dos.
   Con `auto-fit` la fila caía en un estado intermedio de 2 columnas entre
   ~580 y ~1000px: los tags y el círculo "↗" bajaban debajo del título y la
   mitad derecha de la fila quedaba vacía, con la flecha flotando a media
   altura y las filas sin alinearse entre sí. */
.servicio {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(14px, 2vw, 32px);
  align-items: start;
  padding: clamp(24px, 3vw, 40px) clamp(12px, 2vw, 28px);
  border-bottom: 1px solid var(--borde-sand);
  color: var(--ink);
  transition: background .45s var(--ease), color .45s ease, padding-left .45s var(--ease);
}
@media (min-width: 1000px) {
  .servicio { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.servicio:hover,
.servicio:focus-visible {
  background: var(--ink);
  color: var(--paper);
  padding-left: clamp(20px, 3vw, 44px);
}

.servicio__titulo {
  display: flex;
  gap: clamp(14px, 2vw, 26px);
  align-items: baseline;
}
/* La opacidad se mantiene (es lo que permite que la fila entera se invierta en
   :hover conservando `color: inherit`), pero subida al mínimo que cumple 4,5:1
   en los dos estados: .5 daba 3,59:1 sobre arena. */
.servicio__num {
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: .14em;
  color: inherit;
  opacity: .7;
}
.servicio__titulo h3 {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 600;
  letter-spacing: -.02em;
  font-size: clamp(22px, 2.3vw, 34px);
  line-height: 1.05;
  color: inherit;
}
.servicio__desc {
  margin: 0;
  font-size: clamp(14px, 1.05vw, 17px);
  line-height: 1.6;
  color: inherit;
  opacity: .68;
  max-width: 460px;
  text-wrap: pretty;
}
/* El círculo "↗" queda anclado a la derecha y son los tags los que envuelven:
   si se deja envolver a la fila entera, la flecha cae bajo los tags y las
   filas dejan de alinearse entre sí. */
.servicio__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: nowrap;
}
.servicio__tags { display: flex; flex-wrap: wrap; gap: 8px; }
/* .55 daba 4,23:1 sobre arena, por debajo del 4,5 exigido a 11px. Con .68
   sube a 6,5:1 y en el estado invertido (:hover de la fila) a 7,6:1. */
.tag {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  border: 1px solid currentColor;
  opacity: .68;
  border-radius: 40px;
  padding: 6px 12px;
  color: inherit;
}
.servicio__flecha {
  width: 46px; height: 46px;
  border-radius: 50%;
  border: 1px solid currentColor;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  font-family: var(--f-mono);
  font-size: 14px;
  color: inherit;
  transition: transform .45s var(--ease);
}
.servicio:hover .servicio__flecha { transform: translate(2px, -2px); }

/* Planes trimestrales */
.planes { margin-top: clamp(64px, 9vw, 130px); }
.planes__head {
  display: flex;
  align-items: baseline;
  gap: clamp(16px, 2vw, 28px);
  flex-wrap: wrap;
  margin-bottom: clamp(28px, 3.5vw, 48px);
}
.planes__head h3 {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 800;
  letter-spacing: -.03em;
  font-size: clamp(30px, 4vw, 58px);
  line-height: .95;
  text-transform: uppercase;
}
.planes__intro { margin: 0 0 clamp(32px, 4vw, 56px); max-width: 620px; }

.planes__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr));
  gap: clamp(16px, 2vw, 28px);
}

.plan {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: clamp(24px, 2.6vw, 36px);
  border: 1px solid var(--borde-sand);
  border-radius: var(--r-card);
  background: var(--paper);
  transition: transform .5s var(--ease), box-shadow .5s ease, border-color .5s ease;
}
.plan:hover {
  transform: translateY(-8px);
  box-shadow: 0 40px 60px -46px rgba(10, 10, 10, .55);
  border-color: var(--ink);
}
.plan__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.plan__top .kicker { font-size: 12px; }
.plan__top .rombo { width: 10px; height: 10px; }
.plan h4 {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 800;
  letter-spacing: -.02em;
  font-size: clamp(26px, 2.6vw, 38px);
  line-height: 1;
  text-transform: uppercase;
}
.plan__para {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--texto-claro);
  text-wrap: pretty;
}
.plan__lista {
  margin: 0;
  padding: 20px 0 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
  border-top: 1px solid var(--borde-paper);
}
.plan__lista li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  font-size: 14px;
  line-height: 1.5;
  color: var(--ink);
}
.plan__lista .rombo {
  width: 8px; height: 8px;
  margin-top: 6px;
  background: var(--ink);
}
.plan__cta {
  margin-top: auto;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border: 1px solid var(--ink);
  border-radius: var(--r-pill);
  padding: 14px 22px;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  transition: background .35s ease, color .35s ease;
}
.plan__cta:hover { background: var(--ink); color: var(--paper); }

/* --------------------------------------------------------------------------
   7. Proceso
   -------------------------------------------------------------------------- */
.proceso { background: var(--ink); color: var(--paper); }
.proceso__inner { padding: var(--sec-top) var(--pad-x) var(--sec-bottom); }
.proceso .kicker { display: block; margin-bottom: clamp(18px, 2.4vw, 30px); }

.proceso__head {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(24px, 4vw, 64px);
  align-items: end;
  margin-bottom: clamp(48px, 7vw, 110px);
}
.proceso__head p {
  max-width: 520px;
  font-size: clamp(15px, 1.2vw, 19px);
}
.proceso__head p strong { color: var(--paper); font-weight: 400; }

.pasos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
  gap: 1px;
  background: var(--borde-ink-1);
  border: 1px solid var(--borde-ink-1);
}

.paso {
  background: var(--ink);
  padding: clamp(24px, 2.6vw, 38px);
  display: flex;
  flex-direction: column;
  gap: 18px;
  transition: background .5s ease;
}
.paso:hover { background: #121212; }

.paso__top { display: flex; align-items: center; gap: 14px; }
.paso__num {
  font-family: var(--f-mono);
  font-size: clamp(28px, 3vw, 44px);
  letter-spacing: -.02em;
  color: var(--ac);
  line-height: 1;
}
.paso__linea { flex: 1 1 auto; height: 1px; background: var(--borde-ink-2); }
.paso h3 {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 600;
  letter-spacing: -.02em;
  font-size: clamp(20px, 1.9vw, 27px);
  line-height: 1.1;
}
.paso__bloques {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-top: 6px;
}
.paso__label {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  margin-bottom: 8px;
}
.paso__label--humano { color: var(--paper); }
.paso__label--ia { color: var(--texto-oscuro-2); }
.paso__bloques p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  text-wrap: pretty;
}
.paso__texto--humano { color: var(--texto-oscuro-1); }
.paso__texto--ia { color: var(--texto-oscuro-3); }

/* --------------------------------------------------------------------------
   8. Muestras
   -------------------------------------------------------------------------- */
.muestras { background: var(--paper); }
.muestras__inner { padding: var(--sec-top) var(--pad-x) var(--sec-bottom); }
.muestras .seccion__head { gap: clamp(20px, 3vw, 48px); margin-bottom: clamp(32px, 4vw, 60px); }
.muestras .seccion__head p { max-width: 440px; }

/* Galería de columna fija.
   Tres columnas: las laterales avanzan con el scroll y la central se queda
   pegada al viewport. Es CSS puro — `position: sticky` sobre un ítem de grid,
   por eso el grid necesita `align-items: start` (si los ítems se estiran a la
   altura de la fila, no queda recorrido y sticky no hace nada). */
.galeria {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(8px, 1vw, 16px);
  align-items: start;
}

.galeria__col {
  display: grid;
  gap: clamp(8px, 1vw, 16px);
}

.galeria__col--fija {
  position: sticky;
  top: 0;
  height: 100svh;
  grid-template-rows: repeat(2, 1fr);
}

.galeria__item {
  margin: 0;
  position: relative;
  overflow: hidden;
  background: var(--sand);
  border: 1px solid var(--borde-paper);
  border-radius: var(--r-card);
  /* Alto fijo + object-fit: cover, para que el ritmo de la columna no dependa
     de las proporciones de cada archivo. */
  height: clamp(300px, 40vw, 540px);
}
.galeria__col--fija .galeria__item { height: 100%; }

.galeria__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .7s var(--ease);
}
.galeria__item:hover .galeria__img { transform: scale(1.04); }
/* La imagen que no carga se oculta y deja ver el placeholder que tiene debajo */
.galeria__img.is-missing { display: none; }

.galeria__item figcaption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 14px 16px;
  display: flex;
  justify-content: space-between;
  gap: 12px;
  pointer-events: none;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink);
  background: linear-gradient(to top, rgba(242, 237, 228, .92), rgba(242, 237, 228, 0));
}
.galeria__item figcaption span:last-child { opacity: .6; }

/* Una sola columna: sin columna fija, que en 1 columna no aporta nada */
@media (max-width: 900px) {
  .galeria { grid-template-columns: 1fr; }
  .galeria__col--fija {
    position: static;
    height: auto;
    grid-template-rows: none;
  }
  .galeria__col--fija .galeria__item { height: clamp(300px, 40vw, 540px); }
}

/* --------------------------------------------------------------------------
   9. Nosotros
   -------------------------------------------------------------------------- */
.nosotros {
  background: var(--ink);
  color: var(--paper);
}
.nosotros__inner { padding: var(--sec-top) var(--pad-x) var(--sec-bottom); }
.nosotros .kicker { display: block; margin-bottom: clamp(24px, 3vw, 40px); color: var(--texto-oscuro-2); }

.nosotros__declaracion {
  margin: 0 0 clamp(48px, 7vw, 110px);
  max-width: 1180px;
  font-family: var(--f-display);
  font-weight: 300;
  letter-spacing: -.025em;
  font-size: clamp(26px, 3.6vw, 56px);
  line-height: 1.14;
  color: var(--paper);
  text-wrap: pretty;
}
.nosotros__declaracion strong { font-weight: 800; }

.nosotros__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));
  gap: clamp(28px, 4vw, 72px);
  align-items: start;
}
.nosotros__col {
  border-top: 1px solid var(--borde-ink-1);
  padding-top: clamp(20px, 2.4vw, 32px);
}
.nosotros__col .kicker--ac { display: block; margin-bottom: 18px; color: var(--ac); }
.nosotros__col p {
  margin: 0;
  font-size: clamp(15px, 1.25vw, 19px);
  line-height: 1.62;
  color: var(--texto-oscuro-1);
  text-wrap: pretty;
}

.nosotros__marca {
  display: flex;
  flex-direction: column;
  gap: 18px;
  align-items: flex-start;
  justify-self: end;
}
.nosotros__marca .kicker { font-size: 11px; margin: 0; color: var(--texto-oscuro-2); }

/* Recorte del logotipo: el arte no llena el lienzo del SVG (ver README).
   Cada versión necesita sus propios valores. */
.logo-crop {
  position: relative;
  overflow: hidden;
  aspect-ratio: 2.31;
}
/* `max-width: none` es imprescindible: el recorte amplía la imagen por encima
   del 100% del contenedor, y el `max-width: 100%` global de la base la volvía
   a encoger, dejando el logotipo cortado por la derecha. */
.logo-crop img {
  position: absolute;
  display: block;
  max-width: none;
}

/* El positivo ya no se usa en la página (Sobre MOIETY pasó a fondo oscuro),
   pero se conserva por si vuelve una sección clara con logotipo. */
.logo-crop--positivo { width: clamp(200px, 20vw, 260px); }
.logo-crop--positivo img { width: 134.75%; left: -17.87%; top: -31.16%; }

.logo-crop--negativo { width: clamp(178px, 16vw, 212px); }
.logo-crop--negativo img { width: 134.05%; left: -16.97%; top: -33.36%; }

/* En Sobre MOIETY va más grande que en el footer */
.logo-crop--nosotros { width: clamp(200px, 20vw, 260px); }

/* --------------------------------------------------------------------------
   10. Contacto
   -------------------------------------------------------------------------- */
.contacto { background: var(--sand); color: var(--ink); }
.contacto__inner { padding: var(--sec-top) var(--pad-x) clamp(64px, 8vw, 120px); }
.contacto .kicker { display: block; margin-bottom: clamp(18px, 2.4vw, 30px); color: var(--texto-claro); }

.contacto__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
  gap: clamp(40px, 6vw, 110px);
  align-items: start;
}

.contacto__titulo {
  margin: 0 0 clamp(20px, 2.6vw, 34px);
  font-size: clamp(40px, 6.4vw, 92px);
}

/* Efecto máquina de escribir (ver index.html, junto a #contacto-titulo).
   Cada línea es una ventana `overflow:hidden` cuyo ancho va saltando de un
   carácter al siguiente; el salto lo da main.js, no una transición CSS —ver
   allí por qué. El cursor va FUERA de la ventana, como hermano en un flex,
   para que se vea avanzar en vez de quedar recortado dentro. */
.typewriter__linea {
  display: flex;
  align-items: baseline;
}
.typewriter__ventana {
  display: block;
  overflow: hidden;
  flex: 0 0 auto;
}
/* El ancho 0 inicial solo con JS: sin él el título tiene que verse entero. */
.js .typewriter__ventana { width: 0; }
.typewriter__texto { display: block; white-space: nowrap; }
/* `pre` evita que se colapsen los espacios al quedar cada uno en su propio
   span; sin esto "de tu marca" se tecleaba como "detumarca". */
.typewriter__char { white-space: pre; }

.typewriter__cursor {
  flex: 0 0 auto;
  width: 3px;
  height: .72em;
  margin-left: .08em;
  background: var(--ac);
  opacity: 0;
}
/* Sólido mientras teclea esa línea (un cursor real no parpadea al escribir) */
.typewriter__linea.is-activa .typewriter__cursor { opacity: 1; }
/* Al terminar, solo queda el de la última línea, ya parpadeando */
.contacto__titulo--typewriter.is-visible .typewriter__linea:last-child .typewriter__cursor {
  opacity: 1;
  animation: typewriter-parpadeo .9s step-end infinite;
}

@keyframes typewriter-parpadeo { 50% { opacity: 0; } }

@media (prefers-reduced-motion: reduce) {
  .typewriter__cursor { animation: none; }
}
.contacto__parrafo {
  margin: 0 0 clamp(28px, 3.5vw, 44px);
  max-width: 480px;
  font-size: clamp(15px, 1.2vw, 19px);
}
.contacto__cta { gap: 16px; padding: 19px 30px; font-size: 15px; }

.contacto__datos {
  margin-top: clamp(36px, 5vw, 64px);
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-family: var(--f-mono);
  font-size: 13px;
  letter-spacing: .06em;
  color: var(--texto-claro);
}
/* 26px de alto + 8px de separación: por encima del mínimo de la SC 2.5.8,
   que con 17px de alto y 10px de hueco quedaba justo en el límite. */
.contacto__datos a,
.contacto__datos span { display: flex; align-items: center; min-height: 26px; }
.contacto__datos a { color: var(--ink); }
.contacto__datos a:hover { color: var(--ac-texto); }

/* Formulario */
.form {
  display: flex;
  flex-direction: column;
  gap: clamp(20px, 2.4vw, 30px);
}
.form__campo { display: flex; flex-direction: column; gap: 10px; }
.form__label {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--texto-claro);
}
.form__input,
.form__textarea {
  background: transparent;
  border: 0;
  /* --borde-campo y no --borde-sand: el límite de un control tiene que llegar
     a 3:1 (SC 1.4.11) y --borde-sand daba 1,30:1 sobre la arena. */
  border-bottom: 1px solid var(--borde-campo);
  color: var(--ink);
  font-size: 17px;
  padding: 10px 0;
  outline: none;
  transition: border-color .3s ease;
}
.form__textarea { resize: vertical; }
/* El ámbar sobre arena da 1,69:1: como indicador de foco no basta por sí solo,
   pero aquí no está solo — el anillo :focus-visible de la base es el que
   cumple. Esto es sólo el refuerzo de color de la propia línea. */
.form__input:focus,
.form__textarea:focus { border-bottom-color: var(--ac-texto); }
/* #8C8A85 daba 2,96:1. Éste, 4,77:1. */
.form__input::placeholder,
.form__textarea::placeholder { color: #6A6864; }

/* Error por campo. Antes solo había un mensaje genérico al pie ("revisa nombre,
   email y mensaje"): con tres campos obligatorios el visitante tenía que
   adivinar cuál había fallado. */
.form__input[aria-invalid="true"],
.form__textarea[aria-invalid="true"] { border-bottom-color: var(--error); }

.form__error {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: .06em;
  line-height: 1.4;
  color: var(--error);
  min-height: 0;
}
.form__error:empty { display: none; }

/* Autorización de tratamiento de datos */
.form__consentimiento { display: flex; flex-direction: column; gap: 8px; }

.form__check {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--texto-claro);
  cursor: pointer;
}
.form__check input {
  flex: 0 0 auto;
  /* 20px + los 12px de gap dejan un paso muy por encima del mínimo táctil */
  width: 20px; height: 20px;
  margin: 1px 0 0;
  accent-color: var(--ink);
  cursor: pointer;
}
.form__check a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.form__check a:hover { color: var(--ac-texto); }
.form__check input[aria-invalid="true"] { outline: 2px solid var(--error); outline-offset: 2px; }

/* Honeypot anti-spam: invisible para personas, tentador para bots */
.form__trampa {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}

.form__pie {
  display: flex;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.form__estado {
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: .08em;
  color: var(--texto-claro);
  max-width: 320px;
  line-height: 1.5;
  margin: 0;
}
.form__estado.is-ok { color: var(--ok); }
.form__estado.is-error { color: var(--error); }

/* --------------------------------------------------------------------------
   10b. Páginas secundarias (legales y 404)
   Comparten tokens y componentes con la portada; solo cambia el contenedor,
   que es de una sola columna y con medida de lectura corta.
   -------------------------------------------------------------------------- */
.legal__barra {
  padding: clamp(20px, 3vw, 34px) var(--pad-x) 0;
}
.legal__volver {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 26px;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texto-claro);
}
.legal__volver:hover { color: var(--ac-texto); }

.legal { background: var(--paper); }
.legal__inner { padding: clamp(36px, 5vw, 64px) var(--pad-x) clamp(64px, 8vw, 110px); }
.legal .kicker { display: block; margin-bottom: clamp(16px, 2vw, 24px); }

.legal__titulo { margin: 0 0 clamp(24px, 3vw, 40px); font-size: clamp(34px, 5vw, 68px); }

.legal__aviso {
  max-width: 68ch;
  margin: 0 0 clamp(20px, 2.5vw, 30px);
  padding: 16px 20px;
  border-left: 3px solid var(--ac);
  background: var(--sand);
  border-radius: 0 var(--r-card) var(--r-card) 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--texto-claro);
}
.legal__aviso strong { color: var(--ink); }

.legal__meta {
  margin: 0 0 clamp(32px, 4vw, 52px);
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texto-claro);
}

/* 68ch mantiene la línea en la zona cómoda de lectura (~75 caracteres) en
   lugar de estirarse a los 1520px del contenedor. */
.legal__cuerpo { max-width: 68ch; }
.legal__cuerpo h2 {
  margin: clamp(34px, 4vw, 52px) 0 12px;
  font-family: var(--f-display);
  font-weight: 600;
  letter-spacing: -.02em;
  font-size: clamp(19px, 1.8vw, 25px);
  line-height: 1.2;
}
.legal__cuerpo h2:first-child { margin-top: 0; }
.legal__cuerpo p,
.legal__cuerpo li {
  font-size: clamp(15px, 1.1vw, 17px);
  line-height: 1.7;
  color: var(--texto-claro);
  text-wrap: pretty;
}
.legal__cuerpo p { margin: 0 0 14px; }
.legal__cuerpo ul { margin: 0 0 14px; padding-left: 20px; }
.legal__cuerpo li { margin-bottom: 8px; }
.legal__cuerpo strong { color: var(--ink); font-weight: 600; }
.legal__cuerpo em { color: var(--error); font-style: normal; font-family: var(--f-mono); font-size: .9em; }
.legal__cuerpo a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.legal__cuerpo a:hover { color: var(--ac-texto); }

.legal__pie { margin: clamp(40px, 5vw, 64px) 0 0; }

/* --------------------------------------------------------------------------
   11b. Ventana de textos legales

   <dialog> nativo. Va sin padding propio a propósito: así el único punto donde
   un clic tiene como objetivo el <dialog> es el fondo, que es lo que usa
   main.js para cerrar al pulsar fuera. Las tres franjas (barra, cuerpo, pie)
   llevan el suyo.
   -------------------------------------------------------------------------- */
.modal-legal {
  padding: 0;
  border: 1px solid var(--borde-paper);
  border-radius: var(--r-card);
  background: var(--paper);
  color: var(--ink);
  width: min(760px, calc(100vw - clamp(24px, 8vw, 80px)));
  max-height: min(84vh, 900px);
  overflow: hidden;
  box-shadow: 0 60px 120px -50px rgba(10, 10, 10, .75);
}
/* El UA ya oculta el diálogo cerrado; solo hace falta el flex al abrirse */
.modal-legal[open] { display: flex; flex-direction: column; }

.modal-legal::backdrop {
  background: rgba(10, 10, 10, .72);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}

/* Mientras la ventana está abierta el fondo no debe desplazarse */
.modal-abierto { overflow: hidden; }

.modal-legal__barra {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 14px 14px clamp(18px, 3vw, 30px);
  border-bottom: 1px solid var(--borde-suave);
}
.modal-legal__titulo { margin: 0; color: var(--texto-claro); }

.modal-legal__cerrar {
  flex: 0 0 auto;
  width: 40px; height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--borde-paper);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  transition: background .3s ease, color .3s ease, border-color .3s ease;
}
.modal-legal__cerrar:hover {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}

.modal-legal__cuerpo {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: clamp(20px, 3vw, 32px);
}
/* Dentro de la ventana el ancho lo manda el panel, no la medida de lectura
   de la página completa. */
.modal-legal__cuerpo .legal__cuerpo { max-width: none; }
.modal-legal__cuerpo .legal__meta { margin: 0 0 22px; }
.modal-legal__cuerpo .legal__aviso { margin-top: 0; }
.modal-legal__aviso {
  margin: 0;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: .06em;
  color: var(--texto-claro);
}

.modal-legal__pie {
  flex: 0 0 auto;
  display: flex;
  justify-content: flex-end;
  padding: 12px clamp(18px, 3vw, 30px);
  border-top: 1px solid var(--borde-suave);
}
.modal-legal__enlace {
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--texto-claro);
  padding: 6px 2px;
}
.modal-legal__enlace:hover { color: var(--ac-texto); }

/* En móvil ocupa la pantalla: un panel centrado deja franjas inútiles y
   obliga a desplazar dentro de un hueco muy corto. */
@media (max-width: 600px) {
  .modal-legal {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    border: 0;
    border-radius: 0;
  }
}

@keyframes modal-legal-entra {
  from { opacity: 0; transform: translate3d(0, 16px, 0); }
  to   { opacity: 1; transform: none; }
}
.modal-legal[open] { animation: modal-legal-entra .35s var(--ease); }
@media (prefers-reduced-motion: reduce) {
  .modal-legal[open] { animation: none; }
}
.sin-movimiento .modal-legal[open] { animation: none; }

/* 404 */
.error404 {
  min-height: 100svh;
  display: flex;
  align-items: center;
  background: var(--ink);
  color: var(--paper);
}

/* Esta página también tiene grano animado y fondo WebGL, así que necesita el
   mismo control de movimiento que las demás (SC 2.2.2), y ese control vive en
   la barra del pie. Con `min-height: 100svh` en .error404 el pie quedaba fuera
   de la ventana y aparecía una barra de desplazamiento en una página que no
   tiene nada que desplazar. Repartiendo la altura desde <body> el bloque de
   error ocupa lo que sobra y el pie se apoya abajo, sin scroll. */
.pagina-404 {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
}
.pagina-404 .error404 {
  flex: 1 1 auto;
  min-height: 0;
}
/* En el pie de esta página sólo va el control, así que la barra no necesita el
   margen superior que la separa de las columnas en el pie completo. */
.pagina-404 .footer__barra { margin-top: 0; }
.error404__inner {
  width: 100%;
  max-width: var(--max);
  margin: 0 auto;
  padding: clamp(80px, 10vh, 120px) var(--pad-x);
}
.error404 .kicker { display: block; margin-bottom: clamp(16px, 2vw, 24px); color: var(--texto-oscuro-2); }
.error404__titulo { margin: 0 0 clamp(18px, 2.4vw, 28px); color: var(--paper); }
.error404__texto {
  max-width: 48ch;
  margin: 0 0 clamp(28px, 3.5vw, 44px);
  font-size: clamp(15px, 1.2vw, 18px);
  line-height: 1.65;
  color: var(--texto-oscuro-1);
  text-wrap: pretty;
}
.error404__enlaces { display: flex; flex-wrap: wrap; gap: 14px; }

/* --------------------------------------------------------------------------
   11. Footer
   -------------------------------------------------------------------------- */
/* Sin padding propio: la onda de entrada tiene que llegar a los cuatro bordes.
   El espaciado vive en .footer__inner. */
.footer {
  background: var(--ink);
  color: var(--paper);
}
.footer__inner {
  padding: clamp(40px, 5vw, 72px) var(--pad-x) clamp(28px, 3vw, 44px);
}
.footer__grid {
  max-width: var(--max);
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
.footer__col {
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-family: var(--f-mono);
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--texto-oscuro-2);
}
.footer__col-titulo { color: var(--paper); }
/* Enlaces de 26px de alto: con 15px y 12px de hueco el paso quedaba en 27px,
   justo en el límite de la excepción de espaciado de la SC 2.5.8. */
.footer__col a {
  display: flex;
  align-items: center;
  min-height: 26px;
  color: var(--texto-oscuro-2);
}
.footer__col a:hover { color: var(--ac); }

.footer__barra {
  max-width: var(--max);
  margin: clamp(40px, 5vw, 72px) auto 0;
  padding-top: 22px;
  border-top: 1px solid var(--borde-ink-1);
  display: flex;
  justify-content: space-between;
  /* `center` y no el `stretch` por defecto: el botón de pausar animación vive
     en esta barra y sin esto se estiraría a toda la altura de la línea. */
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--texto-oscuro-4);
}

/* --------------------------------------------------------------------------
   11b. Control de movimiento

   Detiene todo el movimiento automático de la página. Existe porque la SC 2.2.2
   exige poder pausar cualquier animación que arranque sola y dure más de cinco
   segundos, y aquí hay cuatro fondos animados, una palabra que rota, grano y un
   cursor parpadeante.

   Vive en la barra del pie, no flotando sobre el contenido: flotando tapaba
   texto en móvil y competía con el diseño. La norma pide que el mecanismo
   exista y sea alcanzable, no que esté siempre a la vista.

   Los valores de tipografía se declaran, no se heredan. Con `inherit` el botón
   solo se veía bien dentro de .footer__barra: en cualquier otro sitio caía a la
   tipografía del body y salía en minúsculas y proporcional, desentonando. Ahora
   coincide con la barra por declararlo, no por dónde esté colocado.
   -------------------------------------------------------------------------- */
.ctrl-movimiento {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* Alto mínimo de objetivo táctil sin engordar la línea del pie */
  min-height: 24px;
  padding: 4px 12px 4px 10px;
  border: 1px solid var(--borde-ink-1);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--texto-oscuro-2);
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color .3s ease, border-color .3s ease;
}
/* Sin `opacity` sobre el botón entero: rebajaría también el rótulo por debajo
   del 4,5:1 —justo el control que existe para cumplir la norma—. El color sale
   de --texto-oscuro-2, que está verificado a 5,53:1 sobre la tinta del pie. */
.ctrl-movimiento:hover,
.ctrl-movimiento:focus-visible {
  color: var(--paper);
  border-color: var(--borde-ink-3);
}
.ctrl-movimiento[hidden] { display: none; }

/* Dos barras = pausar. Con la animación ya detenida pasa a un triángulo. */
.ctrl-movimiento__icono {
  width: 10px; height: 10px;
  flex: 0 0 auto;
  background: var(--ac);
  clip-path: polygon(0 0, 36% 0, 36% 100%, 0 100%, 0 0, 64% 0, 100% 0, 100% 100%, 64% 100%, 64% 0);
}
.ctrl-movimiento[aria-pressed="true"] .ctrl-movimiento__icono {
  clip-path: polygon(6% 0, 100% 50%, 6% 100%);
}

/* Estado "movimiento detenido". Congela lo mismo que prefers-reduced-motion,
   salvo que aquí lo decide la persona en el momento. Los lienzos WebGL los
   para main.js, que además deja pintado el último fotograma. */
.sin-movimiento .grano,
.sin-movimiento .hero__badge .rombo,
.sin-movimiento .typewriter__cursor { animation: none !important; }
.sin-movimiento { scroll-behavior: auto; }
.sin-movimiento .galeria__item:hover .galeria__img { transition: none; transform: none; }

/* --------------------------------------------------------------------------
   12. Movimiento
   -------------------------------------------------------------------------- */
@keyframes moi-grain {
  0%   { transform: translate3d(0, 0, 0); }
  50%  { transform: translate3d(-1.5%, 1.5%, 0); }
  100% { transform: translate3d(0, 0, 0); }
}
@keyframes moi-spin { to { transform: rotate(360deg); } }

/* Reveals al hacer scroll. El estado oculto solo se aplica con JS activo
   (clase .js en <html>), así el contenido nunca queda invisible sin JS. */
.js [data-reveal] {
  opacity: 0;
  transform: translate3d(0, 26px, 0);
  transition:
    opacity .9s var(--ease) var(--reveal-delay, 0s),
    transform .9s var(--ease) var(--reveal-delay, 0s);
}
.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .grano { animation: none; }
  .hero__badge .rombo { animation: none; }
  .js [data-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .rotador,
  .rotador__subrayado { transition: none; }
  .btn:hover,
  .plan:hover,
  .nav__cta:hover,
  .hero__cta:hover { transform: none; }
  .hero__cta-fantasma:hover .hero__cta-circulo { transform: none; }
  /* La columna fija (.galeria__col--fija) NO se desactiva aquí a propósito:
     `position: sticky` no tiene transición propia, se mueve 1:1 con el scroll
     del usuario sin inercia ni aceleración añadida — no es el tipo de
     movimiento que esta preferencia busca evitar (a diferencia del parallax,
     los reveals o el grano animado, que sí son movimiento añadido). Lo único
     que se suprime aquí es el zoom suave al hacer hover sobre cada pieza. */
  .galeria__item:hover .galeria__img { transition: none; transform: none; }
}
