/* =========================================================================
   Estudio Valiant — capa de efectos
   Movimiento sobre el diseño existente. No cambia la paleta ni la retícula:
   solo añade transición entre páginas, cursor propio, revelados cinéticos,
   parallax, banda deslizante y reacciones al ratón.

   Todo es progresivo: sin JavaScript el sitio queda como antes.
   ========================================================================= */

:root {
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out-quart: cubic-bezier(0.76, 0, 0.24, 1);

  /* Telón y menú a pantalla completa. El tema oscuro los cambia. */
  --curtain-bg: var(--accent);
  --curtain-fg: var(--accent-fg);
}

/* El logotipo es una imagen azul marino: en tema oscuro hay que aclararla */
img[src*="logo-vc"] {
  filter: var(--logo-filter, none);
}

/* "clip" recorta igual que "hidden" pero no convierte al <body> en un
   contenedor de scroll, que es lo que impediría que position:sticky
   funcionase en la portada. Los navegadores antiguos ignoran el valor y se
   quedan con el "hidden" de styles.css. */
body {
  overflow-x: clip;
}

/* Las secciones se apoyan sobre el fondo para poder deslizarse por encima
   de la portada, que queda fija mientras se sale de ella. */
.has-js main > *:not(.hero),
.has-js .footer {
  position: relative;
  z-index: 1;
  background: var(--bg);
}

@media (min-width: 768px) {
  .has-js .hero {
    position: sticky;
    top: 0;
    z-index: 0;
  }
}

/* ====================== Pantalla de carga y telón ======================
   El telón son cinco columnas que suben escalonadas al entrar y bajan
   escalonadas al salir hacia otra página.

   La salida la hace el CSS con retardos fijos, no el JavaScript: si este
   archivo fallara al cargar, el telón se retira igual y nadie se queda
   mirando una pantalla azul. El contador sí es JavaScript, pero es
   decorativo. */

.curtain {
  position: fixed;
  inset: 0;
  z-index: 1400;
  display: none;
  pointer-events: none;
}

.has-js .curtain {
  display: block;
}

.curtain__cols {
  position: absolute;
  inset: 0;
  display: flex;
}

.curtain__col {
  flex: 1 1 0;
  background: var(--curtain-bg);
  will-change: transform;
  /* El reparto en cinco columnas cae en anchos fraccionarios y el navegador
     deja costuras de subpixel por donde se cuela el fondo de la pagina. El
     halo de 1px sella la union sin cambiar el ancho ni el reparto. */
  box-shadow: 0 0 0 1px var(--curtain-bg);
}

.has-js .curtain__col {
  animation: col-up 0.9s var(--ease-in-out-quart) forwards;
  animation-delay: calc(1.45s + var(--c, 0) * 0.07s);
}

/* Ya se ha visto la intro en esta sesión: salida inmediata, sin contador */
.has-visto .curtain__col {
  animation-delay: calc(0.1s + var(--c, 0) * 0.05s);
}

@keyframes col-up {
  from {
    transform: translate3d(0, 0, 0);
  }
  to {
    transform: translate3d(0, -101%, 0);
  }
}

/* Al salir hacia otra página, las columnas vuelven a bajar */
.has-js .curtain.is-leaving .curtain__col {
  animation: col-down 0.5s var(--ease-in-out-quart) forwards;
  animation-delay: calc(var(--c, 0) * 0.055s);
}

@keyframes col-down {
  from {
    transform: translate3d(0, -101%, 0);
  }
  to {
    transform: translate3d(0, 0, 0);
  }
}

.curtain__inner {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
  color: var(--curtain-fg);
}

.has-visto .curtain__inner {
  display: none;
}

/* En la salida sí queremos la marca, aunque la intro ya se haya visto */
.curtain.is-leaving .curtain__inner {
  display: flex;
  animation: curtain-mark 0.5s var(--ease-out-expo) forwards;
}

.curtain.is-leaving .curtain__count,
.curtain.is-leaving .curtain__line {
  display: none;
}

@keyframes curtain-mark {
  from {
    opacity: 0;
    transform: translate3d(0, 1.5rem, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.curtain__word {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 11vw, 8rem);
  line-height: 1;
  letter-spacing: 0.12em;
  text-indent: 0.12em;
  opacity: 0;
  animation: curtain-word 1.45s var(--ease-out-expo) forwards;
}

.curtain.is-leaving .curtain__word {
  opacity: 1;
  animation: none;
}

@keyframes curtain-word {
  0% {
    opacity: 0;
    transform: translate3d(0, 1.25rem, 0);
  }
  25% {
    opacity: 1;
    transform: none;
  }
  80% {
    opacity: 1;
    transform: none;
  }
  100% {
    opacity: 0;
    transform: translate3d(0, -1.25rem, 0);
  }
}

.curtain__count {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  letter-spacing: 0.4em;
  text-indent: 0.4em;
  font-variant-numeric: tabular-nums;
  opacity: 0;
  animation: curtain-word 1.45s var(--ease-out-expo) forwards;
}

.curtain__line {
  width: min(20rem, 52vw);
  height: 1px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.22);
}

.curtain__line i {
  display: block;
  height: 100%;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: 0 50%;
  animation: curtain-load 1.4s var(--ease-out-expo) forwards;
}

@keyframes curtain-load {
  to {
    transform: scaleX(1);
  }
}

/* ====================== Entrada del contenido ====================== */

.has-js [data-intro] {
  opacity: 0;
  animation: intro-rise 1s var(--ease-out-expo) forwards;
  animation-delay: calc(0.5s + var(--i, 0) * 0.09s);
}

@keyframes intro-rise {
  from {
    opacity: 0;
    transform: translate3d(0, 1.75rem, 0);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* ====================== Cursor propio ====================== */

.has-cursor *,
.has-cursor *::before,
.has-cursor *::after {
  cursor: none;
}

.has-cursor input,
.has-cursor textarea {
  cursor: text;
}

.has-cursor select {
  cursor: none;
}

.cursor {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1300;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.3s;
}

.cursor.is-on {
  opacity: 1;
}

.cursor.is-blind {
  opacity: 0;
}

/* El aro es un punto sin tamaño que el JavaScript coloca con transform;
   el círculo visible va dentro y se centra solo, así puede cambiar de
   tamaño con una transición sin pelearse con el seguimiento del ratón. */
.cursor__ring {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
}

.cursor__ring-in {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--cursor-ring);
  border-radius: 999px;
  background: rgba(24, 50, 117, 0);
  transform: translate(-50%, -50%);
  transition: width 0.35s var(--ease-out-expo), height 0.35s var(--ease-out-expo),
    background-color 0.35s, border-color 0.35s, transform 0.25s ease-out;
}

.cursor__dot {
  position: absolute;
  top: 0;
  left: 0;
  width: 5px;
  height: 5px;
  margin: -2.5px 0 0 -2.5px;
  border-radius: 999px;
  background: var(--accent);
  transition: opacity 0.25s;
}

.cursor__label {
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  text-indent: 0.2em;
  color: var(--accent-fg);
  opacity: 0;
  transform: scale(0.8);
  transition: opacity 0.25s, transform 0.25s var(--ease-out-expo);
  white-space: nowrap;
}

/* Sobre un enlace: el aro crece y el punto desaparece */
.cursor.is-hover .cursor__ring-in {
  width: 3.75rem;
  height: 3.75rem;
  border-color: var(--cursor-ring-strong);
  background: var(--accent-wash-soft);
}

.cursor.is-hover .cursor__dot {
  opacity: 0;
}

/* Sobre una tarjeta: el aro se llena y muestra una etiqueta */
.cursor.is-label .cursor__ring-in {
  width: 5.5rem;
  height: 5.5rem;
  border-color: var(--accent);
  background: var(--accent);
}

.cursor.is-label .cursor__dot {
  opacity: 0;
}

.cursor.is-label .cursor__label {
  opacity: 1;
  transform: none;
}

.cursor.is-down .cursor__ring-in {
  transform: translate(-50%, -50%) scale(0.8);
}

/* ====================== Progreso de lectura ====================== */

.progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 1100;
  pointer-events: none;
}

.progress__bar {
  height: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

/* Antes iba a 1px sobre el borde de 1px del carril y no se veia. Ahora es
   una pista de 2px con relleno azul.

   Nada de punto marcador: el carril ya tiene seis puntos (los del menu, uno
   por pagina) y meter otro punto al lado hacia creer que eran lo mismo y
   que uno de los dos fallaba. Son ejes distintos: los seis dicen en que
   pagina estas, esta barra cuanto llevas de ella. Una barra continua no se
   confunde con una fila de puntos. */
.rail__progress {
  position: absolute;
  top: 0;
  right: 0;
  width: 2px;
  height: 100%;
  background: var(--line-faint);
}

.rail__progress i {
  display: block;
  height: 100%;
  background: var(--accent);
  transform: scaleY(0);
  transform-origin: 50% 0;
}

/* ====================== Titulares cinéticos ====================== */

.kin__word {
  display: inline-block;
}

.kin__word > .kin__in {
  display: inline-block;
  opacity: 0;
  transform: translate3d(0, 0.5em, 0) rotate(2deg);
  filter: blur(6px);
  transition: opacity 0.75s linear, transform 1.05s var(--ease-out-expo), filter 0.75s ease-out;
  transition-delay: var(--d, 0s);
}

.kin.is-in .kin__word > .kin__in {
  opacity: 1;
  transform: none;
  filter: blur(0);
}

/* ====================== Banda deslizante ====================== */

.marquee {
  position: relative;
  display: flex;
  overflow: hidden;
  padding-block: 1.25rem;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--bg);
  user-select: none;
}

.marquee__track {
  display: flex;
  flex: none;
  will-change: transform;
}

.marquee__group {
  display: flex;
  flex: none;
  align-items: center;
  gap: 2.5rem;
  padding-right: 2.5rem;
}

.marquee__item {
  font-family: var(--font-display);
  font-size: clamp(2rem, 5.5vw, 4.25rem);
  line-height: 1;
  letter-spacing: 0.02em;
  white-space: nowrap;
  color: var(--fg);
}

.marquee__item--outline {
  color: transparent;
  -webkit-text-stroke: 1px var(--accent-stroke);
}

.marquee__sep {
  flex: none;
  width: 0.5rem;
  height: 0.5rem;
  background: var(--accent);
  transform: rotate(45deg);
}

/* Sin JavaScript la banda se mueve igual, a velocidad fija */
.no-js .marquee__track {
  animation: marquee-slide 30s linear infinite;
}

@keyframes marquee-slide {
  to {
    transform: translate3d(-50%, 0, 0);
  }
}

/* ====================== Aviso de scroll en portada ====================== */

.scrollcue {
  position: absolute;
  bottom: 3rem;
  left: 1.5rem;
  display: none;
  align-items: center;
  gap: 0.75rem;
}

.scrollcue__label {
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.3em;
  color: var(--muted);
}

.scrollcue__line {
  position: relative;
  display: block;
  width: 4rem;
  height: 1px;
  overflow: hidden;
  background: var(--line);
}

.scrollcue__line::after {
  content: "";
  position: absolute;
  inset-block: 0;
  left: 0;
  width: 40%;
  background: var(--accent);
  animation: cue-run 2.4s var(--ease-in-out-quart) infinite;
}

@keyframes cue-run {
  0% {
    transform: translateX(-110%);
  }
  60%,
  100% {
    transform: translateX(260%);
  }
}

@media (min-width: 768px) {
  .scrollcue {
    display: flex;
    left: 7rem;
  }
}

/* ====================== Reacción de las tarjetas ====================== */

.service-card > *,
.project > * {
  z-index: 1;
}

.feature,
.tech {
  position: relative;
  overflow: hidden;
}

.feature > *,
.tech > * {
  position: relative;
  z-index: 1;
}

/* Foco de luz que sigue al ratón dentro de la tarjeta */
.service-card::after,
.project::after,
.feature::after,
.tech::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s;
  background: radial-gradient(
    18rem circle at var(--mx, 50%) var(--my, 50%),
    var(--accent-glow),
    rgba(24, 50, 117, 0) 70%
  );
}

.service-card:hover::after,
.project:hover::after,
.feature:hover::after,
.tech:hover::after {
  opacity: 1;
}

/* Inclinación suave en las dos tarjetas grandes */
.service-card {
  transform-style: preserve-3d;
  transition: border-color 0.5s, transform 0.6s var(--ease-out-expo);
}

.service-card.is-tilting {
  transition: border-color 0.5s, transform 0.15s ease-out;
}

/* Las esquinas del proyecto se dibujan en lugar de aparecer */
.project__corner::before {
  transform: scaleX(0);
  transform-origin: 100% 50%;
  transition: transform 0.55s var(--ease-out-expo);
}

.project__corner::after {
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform 0.55s var(--ease-out-expo) 0.1s;
}

.project:hover .project__corner::before,
.project.is-active .project__corner::before {
  transform: scaleX(1);
  transform-origin: 0 50%;
}

.project:hover .project__corner::after,
.project.is-active .project__corner::after {
  transform: scaleY(1);
}

/* ====================== Subrayado que barre ====================== */

.link-quiet,
.footer__col a,
.contact-aside__mail {
  position: relative;
}

.link-quiet::after,
.footer__col a::after,
.contact-aside__mail::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.25rem;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: 100% 50%;
  transition: transform 0.5s var(--ease-out-expo);
}

.link-quiet:hover::after,
.link-quiet:focus-visible::after,
.footer__col a:hover::after,
.footer__col a:focus-visible::after,
.contact-aside__mail:hover::after,
.contact-aside__mail:focus-visible::after {
  transform: scaleX(1);
  transform-origin: 0 50%;
}

/* El botón se rellena de azul al pasar por encima */
.btn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}

.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--accent);
  transform: translate3d(0, 101%, 0);
  transition: transform 0.55s var(--ease-in-out-quart);
}

.btn:hover,
.btn:focus-visible {
  color: var(--accent-fg);
  border-color: var(--accent);
}

.btn:hover::before,
.btn:focus-visible::before {
  transform: translate3d(0, 0, 0);
}

/* ====================== Firma del pie ====================== */

.footer {
  overflow: hidden;
}

.footer__word {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -0.16em;
  z-index: 0;
  font-family: var(--font-display);
  font-size: clamp(4.5rem, 19vw, 16rem);
  line-height: 0.78;
  letter-spacing: 0.02em;
  text-align: center;
  color: transparent;
  -webkit-text-stroke: 1px var(--accent-ghost);
  pointer-events: none;
  user-select: none;
  will-change: transform;
}

.footer > .container {
  position: relative;
  z-index: 1;
}

/* ====================== Ayudas de movimiento ====================== */

[data-parallax],
[data-magnetic] {
  will-change: transform;
}

/* ====================== Si se pide reducir el movimiento ====================== */

@media (prefers-reduced-motion: reduce) {
  .has-js [data-intro] {
    opacity: 1;
    animation-delay: 0s !important;
  }

  .kin__word > .kin__in {
    opacity: 1;
    transform: none;
    filter: none;
    transition-delay: 0s !important;
  }

  .has-js .curtain {
    display: none;
  }

  .scrollcue__line::after {
    animation: none;
  }

  .no-js .marquee__track {
    animation: none;
  }

  .has-js .hero {
    position: relative;
  }
}

/* =========================================================================
   SEGUNDA CAPA — menú a pantalla completa, scroll horizontal anclado,
   red de nodos, tema oscuro, volver arriba y micro-interacciones.
   ========================================================================= */

/* Reserva el hueco de la barra de desplazamiento para que la página no
   pegue un salto lateral al abrir el menú. */
html {
  scrollbar-gutter: stable;
}

html.menu-abierto {
  overflow: hidden;
}

/* ====================== Grano animado ====================== */

.has-js .noise-overlay {
  inset: -15%;
  background-size: 220px 220px;
  background-repeat: repeat;
  animation: grain 0.9s steps(5) infinite;
}

/* El grano animado es una capa fija a pantalla completa repintandose sin
   parar. En escritorio no se nota; en un movil es gasto puro. Se deja la
   textura, quieta. */
@media (hover: none), (max-width: 47.9375em) {
  .has-js .noise-overlay {
    inset: 0;
    animation: none;
  }
}

@keyframes grain {
  0% {
    transform: translate3d(0, 0, 0);
  }
  20% {
    transform: translate3d(-4%, -3%, 0);
  }
  40% {
    transform: translate3d(3%, -4%, 0);
  }
  60% {
    transform: translate3d(-3%, 3%, 0);
  }
  80% {
    transform: translate3d(4%, 2%, 0);
  }
  100% {
    transform: translate3d(0, 0, 0);
  }
}

/* ====================== Menú a pantalla completa ====================== */

.navtoggle {
  position: fixed;
  top: 1.1rem;
  right: 1.25rem;
  z-index: 1250;
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  min-height: 48px;
  padding: 0.55rem 0.95rem;
  border: 1px solid var(--btn-line);
  background: var(--rail-bg);
  backdrop-filter: blur(6px);
  color: var(--fg);
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  text-indent: 0.2em;
  cursor: pointer;
  transition: border-color 0.25s, color 0.25s, background-color 0.25s;
}

.navtoggle:hover,
.navtoggle:focus-visible {
  border-color: var(--accent);
  color: var(--accent);
}

.navtoggle__bars {
  position: relative;
  display: block;
  width: 18px;
  height: 10px;
  flex: none;
}

.navtoggle__bars i {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transition: transform 0.4s var(--ease-in-out-quart);
}

.navtoggle__bars i:first-child {
  top: 2px;
}

.navtoggle__bars i:last-child {
  bottom: 2px;
}

.navtoggle.is-open {
  color: var(--curtain-fg);
  background: transparent;
  border-color: rgba(255, 255, 255, 0.3);
}

.navtoggle.is-open .navtoggle__bars i:first-child {
  transform: translateY(3px) rotate(45deg);
}

.navtoggle.is-open .navtoggle__bars i:last-child {
  transform: translateY(-3px) rotate(-45deg);
}

.navpanel {
  position: fixed;
  inset: 0;
  z-index: 1200;
}

.navpanel[hidden] {
  display: none;
}

/* Las mismas columnas del telón, aquí bajando desde arriba */
.navpanel__cols {
  position: absolute;
  inset: 0;
  display: flex;
}

.navpanel__cols i {
  flex: 1 1 0;
  background: var(--curtain-bg);
  box-shadow: 0 0 0 1px var(--curtain-bg);
  transform: translate3d(0, -101%, 0);
  transition: transform 0.65s var(--ease-in-out-quart);
  transition-delay: calc(var(--c, 0) * 0.05s);
}

.navpanel.is-open .navpanel__cols i {
  transform: none;
}

.navpanel__inner {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2.5rem;
  height: 100%;
  padding: 5.5rem 1.5rem 4rem;
  overflow-y: auto;
}

.navpanel__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.navpanel__item {
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}

.navpanel__item:last-child {
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}

.navpanel__link {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  padding-block: 0.5rem;
  color: var(--curtain-fg);
  opacity: 0;
  transform: translate3d(0, 1.75rem, 0);
  transition: opacity 0.8s var(--ease-out-expo), transform 0.8s var(--ease-out-expo);
  transition-delay: calc(0.35s + var(--n, 0) * 0.07s);
}

.navpanel.is-open .navpanel__link {
  opacity: 1;
  transform: none;
}

.navpanel__num {
  flex: none;
  width: 2rem;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.25em;
  opacity: 0.45;
  transition: opacity 0.35s;
}

.navpanel__text {
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 8vw, 5.5rem);
  line-height: 1.1;
  letter-spacing: 0.01em;
  transition: transform 0.5s var(--ease-out-expo), color 0.35s;
}

.navpanel__arrow {
  display: none;
  margin-left: auto;
  flex: none;
  opacity: 0;
  transform: translate3d(-1.25rem, 0, 0);
  transition: opacity 0.45s var(--ease-out-expo), transform 0.45s var(--ease-out-expo);
}

/* Al apuntar a uno, los demás se apagan */
.navpanel__list:hover .navpanel__text {
  color: rgba(255, 255, 255, 0.28);
}

.navpanel__link:hover .navpanel__text,
.navpanel__link:focus-visible .navpanel__text {
  color: var(--curtain-fg);
  transform: translate3d(1.25rem, 0, 0);
}

.navpanel__link:hover .navpanel__arrow,
.navpanel__link:focus-visible .navpanel__arrow {
  opacity: 1;
  transform: none;
}

.navpanel__link[aria-current="page"] .navpanel__num {
  opacity: 1;
}

/* Con teclado hace falta ver dónde estás, pero el aro por defecto del
   navegador se sale de la fila y queda descuadrado. Este va por dentro. */
.navpanel__link:focus-visible {
  outline: 1px solid rgba(255, 255, 255, 0.5);
  outline-offset: -0.5rem;
}

.navpanel__link:focus {
  outline: none;
}

.navpanel__foot {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.75rem 2.5rem;
  color: var(--curtain-fg);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  opacity: 0;
  transform: translate3d(0, 1rem, 0);
  transition: opacity 0.8s var(--ease-out-expo) 0.75s, transform 0.8s var(--ease-out-expo) 0.75s;
}

.navpanel__foot span {
  opacity: 0.6;
}

.navpanel__foot a:hover {
  text-decoration: underline;
  text-underline-offset: 0.35em;
}

.navpanel.is-open .navpanel__foot {
  opacity: 1;
  transform: none;
}

/* Sobre el panel azul, el cursor propio tiene que verse en claro */
.cursor.is-invert .cursor__ring-in {
  border-color: rgba(255, 255, 255, 0.55);
  background: rgba(255, 255, 255, 0.06);
}

.cursor.is-invert .cursor__dot {
  background: var(--curtain-fg);
}

@media (min-width: 768px) {
  .navtoggle {
    top: 1.5rem;
    right: 2rem;
  }

  .navpanel__inner {
    padding: 6rem 3rem 4rem 7rem;
  }

  .navpanel__link {
    padding-block: 0.75rem;
  }

  .navpanel__num {
    width: 2.5rem;
  }

  .navpanel__arrow {
    display: block;
  }
}

/* ====================== Texto letra a letra ====================== */

/* line-height algo holgado: Bebas pone las tildes de las mayúsculas por
   encima de la altura de caja y con 1 exacto se recortarían. */
.roll {
  position: relative;
  display: block;
  overflow: hidden;
  line-height: 1.2;
}

.roll__row {
  display: block;
  white-space: nowrap;
}

.roll__row--b {
  position: absolute;
  top: 0;
  left: 0;
}

.roll i {
  display: inline-block;
  font-style: normal;
  transition: transform 0.55s var(--ease-out-expo);
  transition-delay: calc(var(--l, 0) * 0.022s);
}

.roll__row--b i {
  transform: translate3d(0, 100%, 0);
}

a:hover .roll__row--a i,
a:focus-visible .roll__row--a i {
  transform: translate3d(0, -100%, 0);
}

a:hover .roll__row--b i,
a:focus-visible .roll__row--b i {
  transform: none;
}

/* ====================== Scroll horizontal anclado ====================== */

.hpin {
  position: relative;
}

/* Sin anclar, el escenario no pinta nada: lleva dentro el .container de
   siempre, que ya trae su margen lateral, y los pasos van dentro de él. */
.hpin__stage {
  display: block;
}

/* Anclado ocupa la pantalla entera, y reparte a lo alto el titular y los
   pasos. Antes el titular se quedaba fuera y los 100vh se iban en aire
   vacío arriba y abajo de una fila de 300 px. */
.hpin.is-pinned .hpin__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(1.25rem, 4vh, 2.5rem);
  overflow: hidden;
}

.hpin.is-pinned .hpin__stage > .container {
  flex: none;
}

/* La cabecera trae un margen inferior en línea que aquí sobra: lo separa
   el gap del escenario. */
.hpin.is-pinned .hpin__stage > .container > .reveal {
  margin-bottom: 0 !important;
}

/* El bloque ya mide una pantalla: el relleno vertical de la sección sobra */
.section--pinned {
  padding-block: 0;
}

.hpin.is-pinned .steps {
  display: flex;
  grid-template-columns: none;
  border-top: 0;
  will-change: transform;
}

.hpin.is-pinned .step {
  flex: none;
  width: clamp(19rem, 25vw, 25rem);
  margin-right: 2.5rem;
  padding: 0 2.5rem 0 0;
  border-bottom: 0;
  border-right: 1px solid var(--line);
}

.hpin.is-pinned .step:last-child {
  margin-right: 7rem;
  border-right: 0;
}

.hpin.is-pinned .step__num {
  font-size: clamp(4rem, 8vw, 7rem);
}

.hpin.is-pinned .step__text {
  max-width: none;
}

/* Regla de avance del carrusel */
.hpin__rail {
  position: absolute;
  bottom: 15vh;
  height: 1px;
  background: var(--line-faint);
  overflow: hidden;
}

.hpin__rail i {
  display: block;
  height: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

.hpin:not(.is-pinned) .hpin__rail {
  display: none;
}

/* ====================== Red de nodos de la portada ====================== */

/* Dos lienzos transparentes: al fondo los nodos sueltos, encima el nombre.
   Los dos ocupan la portada entera. */
.has-js .hero {
  overflow: hidden;
}

.hero__net {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* ====================== El nombre ======================================
   Tipografía de verdad: Bebas Neue, nítida, seleccionable y accesible. Ni
   lienzo ni partículas — la marca no se deforma.

   Lo que se anima es su aparición (cada palabra sube desde detrás de una
   máscara) y la reacción al ratón (la barra azul del propio lenguaje de la
   casa, la misma de los titulares subrayados). */

.wordmark {
  position: relative;
  width: 100%;
}

.wordmark__text {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(3rem, 11.5vw, 12rem);
  line-height: 1;
  letter-spacing: 0.04em;
  color: var(--fg);
}

.wordmark__text > span {
  position: relative;
  display: inline-block;
}

/* Cada letra, su propia caja. El transform mueve y estira la caja; el
   dibujo del glifo no se toca, así que sigue siendo Bebas Neue nítida. */
.wordmark__text i {
  display: inline-block;
  font-style: normal;
  will-change: transform;
}

/* clip-path recorta sin tocar la línea base ni la caja: la maquetación no
   se mueve ni un píxel mientras la palabra sube. */
.has-js .wordmark__text > span {
  clip-path: inset(-12% -6% 108% -6%);
  transform: translate3d(0, 0.2em, 0);
  transition: clip-path 1.1s var(--ease-out-expo), transform 1.1s var(--ease-out-expo),
    color 0.4s;
  transition-delay: calc(0.55s + var(--w, 0) * 0.13s);
}

.has-js .wordmark.is-in .wordmark__text > span {
  clip-path: inset(-12% -6% -12% -6%);
  transform: none;
}

.has-js .wordmark.is-done .wordmark__text > span {
  clip-path: none;
  transition: none;
}

/* Sin ratón no hay estirón: al menos que el nombre reaccione al tocarlo */
@media (hover: none) {
  .wordmark__text > span:active {
    color: var(--accent);
  }
}

.wordmark__hint {
  margin: 1.25rem 0 0;
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.25em;
  color: var(--muted);
  transition: color 0.3s;
}

.wordmark__hint::before {
  content: "";
  display: inline-block;
  width: 1.5rem;
  height: 1px;
  margin-right: 0.75rem;
  vertical-align: middle;
  background: var(--accent);
}

/* Sin ratón no hay nada que arrastrar */
@media (hover: none) {
  .wordmark__hint {
    visibility: hidden;
  }
}

/* En pantallas estrechas, el nombre siempre en dos líneas y a toda anchura */
@media (max-width: 47.9375em) {
  .wordmark__text {
    font-size: min(26vw, 7rem);
  }

  .wordmark__text > span {
    display: block;
  }
}

/* Orden de capas de la portada: tinta (0) · nodos (1) · contenido (2) ·
   rótulos sueltos (3). */
.hero > .container {
  position: relative;
  z-index: 2;
}

.hero__side,
.hero__tag,
.scrollcue {
  z-index: 3;
}

/* ====================== Volver arriba ====================== */

.topbtn {
  position: fixed;
  right: 1.25rem;
  bottom: 4.75rem;
  z-index: 1150;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--bar-bg);
  backdrop-filter: blur(6px);
  color: var(--accent);
  cursor: pointer;
  opacity: 0;
  transform: translate3d(0, 0.75rem, 0) scale(0.9);
  pointer-events: none;
  transition: opacity 0.45s var(--ease-out-expo), transform 0.45s var(--ease-out-expo);
}

.topbtn.is-on {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

.topbtn svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
}

.topbtn circle {
  fill: none;
  stroke-width: 1.5;
}

.topbtn__track {
  stroke: var(--line);
}

.topbtn__bar {
  stroke: currentColor;
  stroke-dasharray: 138.2;
  stroke-dashoffset: 138.2;
}

.topbtn__arrow {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--fg);
  transition: transform 0.35s var(--ease-out-expo), color 0.25s;
}

.topbtn:hover .topbtn__arrow,
.topbtn:focus-visible .topbtn__arrow {
  transform: translateY(-3px);
  color: var(--accent);
}

@media (min-width: 768px) {
  .topbtn {
    right: 2rem;
    bottom: 2rem;
  }
}

/* ====================== Marco de las tarjetas de proyecto ====================== */

/* El marco completo sustituye a la escuadra original */
.has-js .project__corner {
  display: none;
}

.project__frame {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
}

.project__frame i {
  position: absolute;
  background: var(--accent);
  transition: transform 0.45s var(--ease-out-expo);
}

.project__frame i:nth-child(1) {
  top: 0;
  left: 0;
  width: 100%;
  height: 1px;
  transform: scaleX(0);
  transform-origin: 0 50%;
}

.project__frame i:nth-child(2) {
  top: 0;
  right: 0;
  width: 1px;
  height: 100%;
  transform: scaleY(0);
  transform-origin: 50% 0;
}

.project__frame i:nth-child(3) {
  right: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  transform: scaleX(0);
  transform-origin: 100% 50%;
}

.project__frame i:nth-child(4) {
  bottom: 0;
  left: 0;
  width: 1px;
  height: 100%;
  transform: scaleY(0);
  transform-origin: 50% 100%;
}

.project:hover .project__frame i,
.project.is-active .project__frame i {
  transform: scale(1);
}

/* El retardo solo al entrar: al salir se recogen las cuatro a la vez */
.project:hover .project__frame i:nth-child(2),
.project.is-active .project__frame i:nth-child(2) {
  transition-delay: 0.09s;
}

.project:hover .project__frame i:nth-child(3),
.project.is-active .project__frame i:nth-child(3) {
  transition-delay: 0.18s;
}

.project:hover .project__frame i:nth-child(4),
.project.is-active .project__frame i:nth-child(4) {
  transition-delay: 0.27s;
}

/* ====================== Conmutador de tema ====================== */

.temabtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.25s, transform 0.45s var(--ease-out-expo);
}

.temabtn:hover,
.temabtn:focus-visible {
  color: var(--accent);
  transform: rotate(25deg);
}

/* El carril reparte sus hijos con space-between: el conmutador y la etiqueta
   van juntos en una caja para no descolocar ese reparto. */
.rail__foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
}

.mobilebar .temabtn {
  flex: none;
  width: 48px;
  height: 48px;
  margin-left: auto;
}

/* ====================== Micro-interacciones sueltas ====================== */

.tech svg {
  transition: color 0.3s, transform 0.5s var(--ease-out-expo);
}

.tech:hover svg {
  transform: rotate(12deg) scale(1.12);
}

.checklist li {
  transition: color 0.3s, padding-left 0.4s var(--ease-out-expo);
}

.checklist li:hover {
  color: var(--accent);
  padding-left: 0.75rem;
}

.checklist__mark {
  transition: transform 0.4s var(--ease-out-expo);
}

.checklist li:hover .checklist__mark {
  transform: rotate(45deg) scale(1.4);
}

.reason {
  transition: padding-left 0.45s var(--ease-out-expo);
}

.reason:hover {
  padding-left: 0.75rem;
}

.reason__title {
  transition: color 0.3s;
}

.reason:hover .reason__title {
  color: var(--accent);
}

/* Párrafos que entran palabra a palabra, sin el desenfoque de los titulares */
.kin--soft .kin__word > .kin__in {
  transform: translate3d(0, 0.35em, 0);
  filter: none;
  transition: opacity 0.6s linear, transform 0.8s var(--ease-out-expo);
  transition-delay: var(--d, 0s);
}

/* ====================== Si se pide reducir el movimiento ====================== */

@media (prefers-reduced-motion: reduce) {
  .has-js .noise-overlay {
    inset: 0;
    animation: none;
  }

  .hpin.is-pinned .hpin__stage {
    position: static;
    height: auto;
  }

  .hero__net {
    display: none;
  }

  .has-js .wordmark__text > span {
    clip-path: none;
    transform: none;
    transition-delay: 0s;
  }

  .roll__row--b {
    display: none;
  }
}
