/* ==========================================================================
   Alcavo Solutions
   Criterio: estructura de consultora (Clay / thoughtbot / STRV).
   Contenido escaneable, scroll nativo, sin secuestro. El movimiento acompaña,
   nunca bloquea.

   Esta hoja no contiene ni un color: todos son tokens definidos en
   paletas.css, que se carga antes. Sirve igual para paletas claras y oscuras.
   ========================================================================== */

:root {
  /* Sin colores ni fuentes: el color vive en paletas.css y la tipografia en
     tipografias.css, las dos cargadas antes que esta hoja. */
  --pad-x: clamp(20px, 5vw, 72px);
  --maxw: 1240px;
  --sect-y: clamp(72px, 9vh, 128px);
  --nav-h: 66px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--f-body);
  font-size: 17px;
  line-height: 1.62;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4 { font-family: var(--f-display); letter-spacing: var(--ls-lg); font-weight: var(--w-display); margin: 0; }

:focus-visible { outline: 2px solid var(--acc); outline-offset: 3px; }

.mono {
  font-family: var(--f-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 500;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--acc); color: var(--acc-fg); padding: 12px 18px; font-size: 14px;
}
.skip:focus { left: 12px; top: 12px; }

/* ------------------------------------------------------------------ layout */

.sect { padding: var(--sect-y) var(--pad-x); position: relative; }
.in { max-width: var(--maxw); margin: 0 auto; }

.sect--alt { background: var(--bg-alt); }
.sect--dark { background: var(--inv-bg); color: var(--inv-fg); }
.sect--dark .mono { color: var(--inv-mut); }

.head { margin-bottom: clamp(36px, 5vh, 64px); }
.head h2 {
  font-size: clamp(30px, 4.2vw, 56px);
  line-height: 1.02;
  max-width: 20ch;
}
.head p {
  margin: 20px 0 0;
  font-size: clamp(16px, 1.5vw, 19px);
  color: var(--mut);
  max-width: 62ch;
}

/* --------------------------------------------------------------------- nav */

.nav {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: 0 var(--pad-x);
  height: var(--nav-h);
  /* fondo sólido a propósito: el nav translúcido con desenfoque es una de las
     marcas más reconocibles de plantilla generada, y encima cuesta rendimiento */
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
.nav__brand {
  display: flex; align-items: center; gap: 9px;
  font-family: var(--f-display); font-weight: var(--w-display); font-size: 16px; letter-spacing: var(--ls-md);
  white-space: nowrap;
}
.nav__links { display: flex; gap: 26px; font-size: 14px; color: var(--fg-2); }
.nav__links a { padding: 6px 0; border-bottom: 1px solid transparent; white-space: nowrap; }
.nav__links a:hover { color: var(--acc); border-bottom-color: var(--acc); }
.nav__right { display: flex; align-items: center; gap: 16px; }

/* Idioma como control segmentado: se ve que hay dos opciones y cuál está
   activa, en vez de dos enlaces sueltos separados por una barra. */
.lang {
  display: flex; align-items: center;
  border: 1px solid var(--line-2);
  font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.08em;
  overflow: hidden;
}
.lang a {
  display: flex; align-items: center; height: 38px;
  padding: 0 11px; color: var(--mut); line-height: 1;
  transition: background 0.2s ease, color 0.2s ease;
}
.lang a:hover { color: var(--fg); }
.lang a[aria-current="true"] { background: var(--fg); color: var(--bg); }

/* Botón de tema. La ola circular al pulsarlo la hace la View Transitions API,
   con el centro en el propio botón; el CSS está en paletas.css. */
.theme-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; flex: 0 0 auto;
  background: none; border: 1px solid var(--line-2); color: var(--fg);
  cursor: pointer; padding: 0;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.theme-btn:hover { border-color: var(--acc); color: var(--acc); }
.theme-btn .ico { width: 17px; height: 17px; }
/* Se muestra el icono de lo que se va a activar, no el del estado actual. */
.theme-btn .ico-sun { display: none; }
[data-theme="dark"] .theme-btn .ico-sun { display: block; }
[data-theme="dark"] .theme-btn .ico-moon { display: none; }

/* ----------------------------------------------------------------- botones */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 48px; padding: 13px 24px;
  background: var(--acc); color: var(--acc-fg);
  border: 1px solid var(--acc);
  font-family: var(--f-body); font-size: 15px; font-weight: 600;
  cursor: pointer;
  transition: background 0.22s ease, color 0.22s ease;
}
.btn:hover { background: var(--acc-hover); border-color: var(--acc-hover); color: var(--acc-fg); }
.btn--ghost { background: transparent; color: var(--fg); border-color: var(--line-2); }
.btn--ghost:hover { background: transparent; color: var(--acc); border-color: var(--acc); }
.btn--sm { min-height: 40px; padding: 9px 16px; font-size: 13px; }
.sect--dark .btn--ghost { color: var(--inv-fg); border-color: var(--inv-line); }
.sect--dark .btn--ghost:hover { color: var(--inv-acc); border-color: var(--inv-acc); }

/* -------------------------------------------------------------------- hero */

.hero { position: relative; overflow: hidden; padding-top: clamp(56px, 8vh, 96px); padding-bottom: clamp(48px, 7vh, 84px); }
.hero canvas {
  position: absolute; top: 0; right: 0;
  width: 58%; height: 100%;
  display: block; pointer-events: none;
  opacity: 0.85;
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 42%, #000 100%);
  mask-image: linear-gradient(90deg, transparent 0%, #000 42%, #000 100%);
}
.hero__in { position: relative; z-index: 1; max-width: var(--maxw); margin: 0 auto; }

/* El hero abre con la pregunta del visitante, no con nuestro nombre: una
   empresa que todavía no se conoce no engancha por la marca, engancha por
   el problema. El nombre queda en el nav y en el título de la página. El
   párrafo de debajo es la respuesta, y vale para las seis preguntas. */
.hero__q {
  font-size: clamp(40px, 6.4vw, 92px);
  line-height: 1.02;
  letter-spacing: var(--ls-xl);
  font-weight: var(--w-display);
  /* El titular ocupa todo el ancho del contenedor aunque no lo llene: las
     preguntas entran y salen deslizándose y necesitan recorrido. El ancho de
     lectura lo pone cada pregunta, no el titular. */
  width: 100%;
  max-width: none;
  display: grid;
}

/* Las seis preguntas se turnan apiladas en la misma celda, así que el titular
   mide siempre lo que la más alta y el texto de debajo nunca se mueve al
   cambiar la pregunta. Con una sola celda tampoco hay saltos de altura.

   Las seis viven dentro del <h1>, que es único en la página: los buscadores
   leen las seis en el titular del documento. En pantalla se ve una. */
.hero__q-i {
  grid-area: 1 / 1;
  /* 16ch es lo que hace que en escritorio las seis ocupen tres líneas exactas:
     ninguna crece de alto respecto a las demás. */
  max-width: 16ch;
  /* reparte las líneas parejas: sin esto, en móvil la última palabra queda sola */
  text-wrap: balance;
  /* Sin JavaScript no hay turno: manda la primera, y las otras cinco se quedan
     fuera de vista, igual que las deja el aria-hidden que ya traen puestas. */
  opacity: 0;
}
.hero__q-i:first-child { opacity: 1; }

/* =============================================== el cambio, línea por línea

   site.js parte cada pregunta en líneas y mete cada una dentro de su propia
   máscara. La línea rueda por dentro: sale por arriba y la que la sustituye
   entra desde abajo, con un escalón de arriba abajo que hace que el relevo se
   lea como una ola y no como un bloque que se va y otro que llega.

   La máscara va por línea y no una sola para todo el titular porque las líneas
   de una misma pregunta tienen que poder estar en sitios distintos a la vez:
   con una máscara única, la que sale y la que entra se cruzarían a la vista.

   Con el turno en marcha la opacidad no hace falta y además estorba: esconder
   ya lo hace cada máscara, y un fundido por encima volvería a enseñar dos
   preguntas mezcladas a media transición. */
.hero__q[data-rotando] .hero__q-i { opacity: 1; }

.hero__q-l {
  display: block;
  /* Ancho del texto y no del contenedor: así una línea no se parte en dos y la
     máscara mide exactamente lo que mide su línea. */
  width: max-content;
  max-width: 100%;
  /* El recorte va con clip-path y no con overflow para no meter ni un píxel de
     más en el flujo: el titular tiene que seguir midiendo lo mismo. Se estira
     0.2em por arriba y por abajo porque los acentos y las colas sobresalen de
     la caja de línea y con el recorte justo se cortarían. */
  clip-path: inset(-0.2em -0.04em);
}

.hero__q-lm {
  display: block;
  /* 145% es lo que necesita una línea para salir de su máscara: su caja más el
     estirado del recorte más lo que le cuelga a un acento. */
  transform: translateY(145%);
}

/* Con el turno apagado, nada se mueve: las líneas se quedan donde estén y el
   reajuste de después de volver a medir no se ve. */
.hero__q[data-rotando] .hero__q-lm {
  transform: translateY(145%);
  /* Volver de la posición de salida a la de espera no puede verse: la línea
     cruzaría su máscara de vuelta. Sin transición, el salto no se nota. */
  transition: none;
}

/* La que sale, en orden y de arriba abajo. */
.hero__q[data-rotando] .hero__q-i.hero__q-i--sale .hero__q-lm {
  transform: translateY(-145%);
  transition: transform var(--linea, 280ms) cubic-bezier(0.22, 0.61, 0.24, 1);
  transition-delay: calc(var(--l, 0) * var(--paso, 50ms));
}

/* La que llega: la línea k arranca cuando la suya ha terminado de salir y ha
   dejado libre el renglón, así que nunca coinciden dos en el mismo sitio. El
   relevo entero queda por debajo de los 700ms. */
.hero__q[data-rotando] .hero__q-i.es-actual .hero__q-lm {
  transform: none;
  transition: transform var(--linea, 280ms) cubic-bezier(0.22, 0.61, 0.24, 1);
  transition-delay: calc(var(--l, 0) * var(--paso, 50ms) + var(--entrada, 310ms));
}

/* Mientras se vuelven a medir las líneas (giro de pantalla, cambio de
   tipografía), nada se mueve: las líneas nuevas aparecen ya puestas. */
.hero__q[data-sin-movimiento] .hero__q-lm { transition: none !important; }
.hero__lead {
  margin: clamp(22px, 3vh, 32px) 0 0;
  font-size: clamp(17px, 1.6vw, 22px);
  line-height: 1.5;
  color: var(--fg-2);
  max-width: 44ch;
  text-wrap: pretty;
}
.hero__cta { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 34px; }

/* franja de datos verificables: sustituye a los logos de cliente que no existen */
.facts {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--bg-alt);
}
.facts__in {
  max-width: var(--maxw); margin: 0 auto;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
}
.facts__in > div {
  padding: 22px 26px;
  border-right: 1px solid var(--line);
}
.facts__in > div:first-child { padding-left: 0; }
.facts__in > div:last-child { border-right: 0; padding-right: 0; }
.facts b { display: block; font-family: var(--f-display); font-size: 15px; font-weight: var(--w-display-2); letter-spacing: var(--ls-md); }
.facts span { display: block; margin-top: 3px; font-size: 13.5px; color: var(--mut); line-height: 1.45; }
.facts__wrap { padding: 0 var(--pad-x); }

/* ---------------------------------------------------------------- problema */

/* Lista editorial, no tres tarjetas con icono en grilla: esa retícula de tres
   cajas iguales es el patrón más reconocible de página generada. */
.probs { border-top: 1px solid var(--line); }
.probs article {
  display: grid; grid-template-columns: 68px 1fr 1fr;
  gap: clamp(16px, 3vw, 44px);
  padding: clamp(24px, 3.4vh, 38px) 0;
  border-bottom: 1px solid var(--line);
  align-items: baseline;
}
.probs .mono { color: var(--acc); }
.probs h3 { font-size: clamp(21px, 2.5vw, 31px); line-height: 1.1; font-weight: var(--w-display-2); }
.probs p { margin: 0; font-size: 16px; line-height: 1.6; color: var(--mut); max-width: 46ch; }
.probs__note {
  margin: 40px 0 0;
  font-size: clamp(17px, 1.7vw, 22px);
  line-height: 1.55;
  max-width: 60ch;
  font-weight: 500;
}

/* ----------------------------------------------------------------- proceso */

.steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 1px; background: var(--line); border: 1px solid var(--line); }
.steps article { background: var(--bg); padding: 30px 26px; display: flex; flex-direction: column; gap: 12px; }
.steps .mono { color: var(--acc); }
.steps h3 { font-size: clamp(21px, 2.2vw, 27px); line-height: 1.1; font-weight: var(--w-display-2); }
.steps p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--mut); }
.steps__tag {
  margin-top: auto; padding-top: 16px;
  font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--mut);
}
.steps__note { margin: 26px 0 0; font-size: 15.5px; color: var(--mut); max-width: 66ch; }

/* ------------------------------------------- productos y ejemplos de producto */

.frame { border: 1px solid var(--line-3); background: var(--surface); overflow: hidden; }
.frame__bar {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 13px; border-bottom: 1px solid var(--line);
  background: var(--bg-alt);
}
.frame__dots { display: flex; gap: 5px; flex: 0 0 auto; }
.frame__dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--line-2); display: block; }
.frame__url {
  font-family: var(--f-mono); font-size: 11px; color: var(--mut);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Rejilla de ejemplos de producto. Dos columnas: las capturas son pantallas
   completas y a un tercio de ancho el texto de dentro deja de leerse. Todas
   las piezas pesan lo mismo, incluido el proyecto real, que va uno mas.

   La unica que rompe la rejilla es el antes/despues, y no por jerarquia sino
   porque su razon de ser es comparar: dos pantallas a media columna no se
   comparan, se adivinan. Va a lo ancho y hace de corte de ritmo entre las dos
   filas de ejemplos. */
.gal {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  /* Aire generoso a proposito. Con las piezas pegadas la seccion se lee dura,
     y lo que la ablandaba no era una esquina redonda sino el hueco. */
  gap: clamp(46px, 6vh, 76px) clamp(26px, 3.2vw, 44px);
}
.gal__pieza { margin: 0; min-width: 0; }
.gal__pieza--ancha { grid-column: 1 / -1; }
.gal__shot {
  display: block; width: 100%; height: auto;
  aspect-ratio: 16 / 10; object-fit: cover; object-position: top left;
  background: var(--bg-alt);
}
.gal__cap { margin: 16px 0 0; }
.gal__cap h3 { font-size: clamp(19px, 1.9vw, 23px); line-height: 1.15; }
.gal__cap p { margin: 7px 0 0; font-size: 15px; line-height: 1.58; color: var(--mut); max-width: 56ch; }
/* La etiqueta marca la excepcion, no la norma: la llevan las piezas que no son
   una maqueta. Nueve maquetas rotuladas serian ruido; asi el aviso se lee. */
.gal__tag {
  display: inline-block; margin-top: 9px;
  font-family: var(--f-mono); font-size: 10px; letter-spacing: 0.11em; text-transform: uppercase;
  color: var(--acc); background: var(--acc-soft); border: 1px solid var(--acc-line); padding: 5px 9px;
  white-space: nowrap;
}
.gal__link {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 13px; padding-bottom: 2px;
  font-size: 14px; font-weight: 600; color: var(--acc);
  border-bottom: 1px solid var(--acc-line);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.gal__link .ico { width: 15px; height: 15px; }
.gal__link:hover { color: var(--acc-hover); border-bottom-color: var(--acc-hover); }

/* Lupa. El enlace envuelve el marco entero, asi que tambien es la zona de
   clic. cursor: zoom-in es la pista de que la captura se puede ampliar, y el
   subrayado se apaga porque aqui el enlace no lleva a otra pagina. */
.gal__zoom { display: block; color: inherit; cursor: zoom-in; }
.gal__zoom .frame { transition: border-color 0.24s ease; }
.gal__zoom:hover .frame { border-color: var(--acc); }
/* El empujon de dentro va sobre la imagen, no sobre el marco: el marco lo
   anima la entrada de la seccion y una animacion en curso gana a la
   transicion, asi que ahi el hover no se veria. */
.gal__zoom img { transition: transform 0.42s cubic-bezier(0.22, 0.61, 0.24, 1); }
.gal__zoom:hover img { transform: scale(1.018); }
.ba__half { overflow: hidden; }

/* Visor. Un <dialog> nativo trae de serie el foco encerrado, el cierre con Esc
   y el cierre al pulsar fuera. El ancho es contenido a proposito: la idea es
   ver el detalle, no que la captura se coma la pantalla. */
.lupa {
  width: min(1000px, 90vw); max-width: none;
  max-height: 90vh; margin: auto; padding: 0;
  border: 1px solid var(--line-3); background: var(--surface); color: var(--fg);
}
.lupa::backdrop { background: rgb(0 0 0 / 0.74); }
.lupa__cuerpo { max-height: calc(90vh - 86px); overflow: auto; overscroll-behavior: contain; }
.lupa__cuerpo .frame { border: 0; }
.lupa__cuerpo img { display: block; width: 100%; height: auto; }
/* Dentro del visor el antes/despues se apila: en paralelo cada mitad volveria
   a quedarse pequena y la comparacion no gana nada. */
.lupa__cuerpo .ba { grid-template-columns: 1fr; }
.lupa__pie {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 15px 20px; border-top: 1px solid var(--line);
}
.lupa__texto { margin: 0; font-size: 15px; line-height: 1.5; color: var(--mut); }
.lupa__cerrar {
  flex: 0 0 auto; background: none; border: 1px solid var(--line-3); color: var(--fg);
  font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 9px 15px; cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.lupa__cerrar:hover { border-color: var(--acc); color: var(--acc); }
html.con-lupa, html.con-lupa body { overflow: hidden; }

@media (prefers-reduced-motion: no-preference) {
  .lupa[open] .lupa__cuerpo { animation: lupa-entra 0.24s cubic-bezier(0.22, 0.61, 0.24, 1) both; }
  @keyframes lupa-entra {
    from { opacity: 0; transform: scale(0.985); }
    to   { opacity: 1; transform: scale(1); }
  }
}
/* Cierre: lo que sabemos hacer y no tiene pieza propia en la rejilla. */
.gal__nota {
  margin: clamp(32px, 4.4vh, 50px) 0 0;
  padding-top: clamp(20px, 2.6vh, 28px);
  border-top: 1px solid var(--line);
  font-size: 15.5px; line-height: 1.6; color: var(--mut); max-width: 78ch;
}

/* Antes y después en el mismo marco, lado a lado y con la pantalla completa en
   cada mitad: el mismo pedido, el mismo cliente y el mismo total en la misma
   posición, así el ojo compara en lugar de ver dos imágenes sueltas. */
.ba { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; background: var(--line-2); }
.ba__half { background: var(--surface); }
.ba__half img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; }
.ba__tag {
  display: block; padding: 11px 16px;
  font-size: clamp(16px, 1.5vw, 19px); font-weight: 600; line-height: 1.2;
  color: var(--mut); border-bottom: 1px solid var(--line);
}
.ba__half--after .ba__tag { color: var(--acc); }

/* ------------------------------------------------------------- tecnologías

   Un medio disco por borde. Cada contenedor mide media anchura de disco y
   recorta lo que sobra; el disco va de borde a borde por dentro, así que su
   centro cae justo sobre el borde de la ventana y se ve exactamente la mitad.
   La mitad que se ve es la que mira al texto, en los dos casos.

   Sin listado de tecnologías a propósito: al cliente no le dice nada un stack,
   y esta sección solo tiene que sostener el titular. Las veinte marcas que
   giran son las que hay.

   Gira despacio por CSS, sin JavaScript, sin escucha de scroll y sin bucle por
   fotograma. El disco de la izquierda gira al revés para que la pareja se lea
   como un espejo y no como la misma pieza repetida. Cada icono contra-rota con
   la misma duración para no leerse nunca torcido. Con prefers-reduced-motion el
   bloque global deja la animación en un fotograma y los dos discos se quedan
   quietos.

   El par solo entra a partir de 1100px de ancho: por debajo, los dos discos se
   comen el sitio que necesita el titular para no partirse en cinco líneas. */

#tecnologia, #technology {
  --d: clamp(330px, 36vw, 480px);
  display: flex; align-items: center;
  /* la sección mide lo que mide la rueda, ni una franja más */
  min-height: calc(var(--d) + 2 * var(--sect-y));
  overflow: hidden;
}
/* flex:1 hace que .in llegue a su max-width y se centre igual que en el resto
   de secciones. Sin esto sería un item encogido al contenido y el titular
   arrancaría más a la derecha que en las demás. */
#tecnologia .in, #technology .in { flex: 1 1 auto; }
#tecnologia .head, #technology .head { margin-bottom: 0; }

.rueda {
  position: absolute; top: 50%; right: 0; translate: 0 -50%;
  width: calc(var(--d) / 2);
  height: var(--d);
  overflow: hidden;
  pointer-events: none;
}
.rueda__disco {
  --dur: 50s;
  --paso: calc(360deg / var(--n));
  /* 0.39 deja el icono justo en el centro de la banda entre el circulo interior
     (0.28) y el exterior (0.4975). */
  --radio: calc(var(--d) * 0.39);
  position: absolute; top: 0; left: 0;
  width: var(--d); height: var(--d);
  animation: rueda-gira var(--dur) linear infinite;
}
.rueda__lineas { position: absolute; inset: 0; width: 100%; height: 100%; }
.rueda__lineas circle, .rueda__lineas line {
  fill: none; stroke: var(--line-2); stroke-width: 1;
  vector-effect: non-scaling-stroke;   /* el pelo se queda en 1px a cualquier tamano */
}
.rueda__ico {
  position: absolute; top: 50%; left: 50%;
  width: calc(var(--d) * 0.09); height: calc(var(--d) * 0.09);
  margin: calc(var(--d) * -0.045) 0 0 calc(var(--d) * -0.045);
  display: flex; align-items: center; justify-content: center;
  transform: rotate(calc(var(--i) * var(--paso))) translateY(calc(-1 * var(--radio)));
}
/* Dos animaciones por icono y las dos por CSS, sin JavaScript:

   1. Contra-rotacion. Deshace, con la misma duracion, lo que el disco gira,
      asi que el icono nunca se lee torcido.
   2. Foco. Se enciende cuando el icono pasa por el punto mas horizontal del
      disco: las nueve en punto, que con el centro justo sobre el borde de la
      ventana es el punto izquierdo, el que queda en la mitad de la parte
      visible.

      El retraso sale del propio indice. El icono i esta a i*36 grados en el
      disco, y el disco gira 360 en una vuelta: llegar a las nueve en punto
      (270 grados) le lleva (270 - i*36)/360 de vuelta. Pasado a retraso
      negativo eso da 0.25 + i*0.1, que se repite cada vuelta y por eso el
      relevo entre un icono y el siguiente, diez veces por vuelta, queda
      encadenado sin huecos. */
.rueda__ico .ico {
  width: calc(var(--d) * 0.073); height: calc(var(--d) * 0.073);
  color: var(--acc);                 /* en reposo, todo en el dorado del sitio */
  transform: rotate(calc(-1 * var(--i) * var(--paso)));
  animation: rueda-contra var(--dur) linear infinite,
             rueda-foco var(--dur) linear infinite;
  /* El atajo 'animation' reinicia el retraso: tiene que ir despues.

     El 0.613 es EL MANDO del momento en que se enciende cada icono: subirlo lo
     enciende antes, bajarlo despues. El 0.1 es la separacion entre un icono y
     el siguiente (una vuelta entre diez) y no conviene tocarlo. */
  animation-delay: 0s, calc((0.26 + var(--i) * 0.1) * var(--dur) * -1);
}

@keyframes rueda-gira { from { rotate: 0deg; } to { rotate: 360deg; } }
@keyframes rueda-contra { from { rotate: 0deg; } to { rotate: -360deg; } }
/* Destello: al pasar por la horizontal el icono recupera un instante el color
   de su marca y vuelve al dorado. Los colores de marca son contenido (lo que
   identifica cada tecnologia), no color de interfaz: el sitio sigue teniendo
   un solo acento en todo lo demas.

   La ventana encendida va del 97% al 7%, o sea una decima parte de la vuelta:
   justo lo que separa un icono del siguiente, asi que el relevo es continuo,
   uno se apaga mientras el siguiente empieza. Ensanchar mas alla de 0.1 haria
   que hubiera dos encendidos a la vez. */
@keyframes rueda-foco {
  0%    { color: var(--marca); scale: 1.3; }
  2.5%  { color: var(--marca); scale: 1.18; }
  7%    { color: var(--acc); scale: 1; }
  97%   { color: var(--acc); scale: 1; }
  100%  { color: var(--marca); scale: 1.3; }
}

/* El disco de la izquierda es el mismo, espejado: el contenedor se pega al
   borde izquierdo en lugar del derecho y el disco se alinea por su borde
   derecho, así que su centro cae sobre el borde izquierdo de la ventana y solo
   se ve la mitad derecha, la que mira al texto.

   Va oculto por defecto y solo entra a partir de 1100px, junto con el aire que
   necesita el titular para no quedarse sin ancho. */
.rueda--izq { display: none; right: auto; left: 0; }
.rueda--izq .rueda__disco {
  left: auto; right: 0;
  /* al revés que el de la derecha: la pareja se lee como un espejo */
  animation-direction: reverse;
}
/* Aquí el punto de lectura es las tres en punto, el que mira al texto desde la
   izquierda, y la vuelta va al revés, así que el relevo también se cuenta al
   revés: al icono i le quedan (0.26 - i*0.1) de vuelta para encenderse, y con
   eso queda encendido justo medio segundo antes de llegar a las tres en punto,
   el mismo adelanto que en el disco de la derecha. El 0.1 sigue siendo la
   separación entre un icono y el siguiente y no conviene tocarlo. */
.rueda--izq .rueda__ico .ico {
  animation-direction: reverse, normal;
  animation-delay: 0s, calc((0.26 - var(--i) * 0.1) * var(--dur) * -1);
}

/* Debajo de 1100px se queda solo el disco de la derecha y el texto recupera el
   margen izquierdo del resto de secciones. */
@media (min-width: 1100px) {
  #tecnologia .in, #technology .in {
    padding-left: calc(var(--d) / 2 + clamp(20px, 3vw, 48px));
    padding-right: calc(var(--d) / 2 + clamp(20px, 3vw, 48px));
  }
  /* con el ancho ya limitado por el contenedor, el tope de 20ch dejaría el
     titular más corto que el hueco que dejan los dos discos */
  #tecnologia .head h2, #technology .head h2 { max-width: none; }
  .rueda--izq { display: block; }
}

/* ---------------------------------------------------------------- nosotros */

/* La marca a la izquierda y el texto a la derecha. Antes el párrafo iba en una
   sola columna y el margen izquierdo quedaba sin nada.

   El hueco de la marca se queda con lo que sobre, porque va a llevar el logo
   del estudio. La marca se centra en su columna, en las dos direcciones: la
   caja mide lo que mide el texto, así que el logo queda centrado contra el
   bloque de texto y no contra la sección. Mientras el logo no exista va un
   icono de Claude a tamaño de logotipo en ese sitio.

   El texto conserva su medida de 70ch y queda pegado al borde derecho del
   contenedor, así que su columna derecha coincide con la del resto de
   secciones. */
.about {
  display: grid;
  grid-template-columns: minmax(140px, 1fr) minmax(0, 70ch);
  gap: clamp(28px, 5vw, 76px);
}
.about__marca {
  display: flex; align-items: center; justify-content: center;
  color: var(--fg);
}
.about__marca .ico { width: clamp(84px, 10vw, 150px); height: clamp(84px, 10vw, 150px); }

.about__body p { margin: 0 0 20px; font-size: 16.5px; line-height: 1.68; color: var(--fg-2); }
.about__body p:last-child { margin-bottom: 0; }
.about__body strong { font-weight: 600; color: var(--fg); }

/* Un poco más de alto que el resto de secciones: con la marca al lado, el
   bloque se veía apretado contra los bordes. */
#nosotros, #about {
  padding-top: calc(var(--sect-y) + 24px);
  padding-bottom: calc(var(--sect-y) + 24px);
}

/* Sin ancho para dos columnas la marca pasa encima del texto, en el mismo
   orden en que se lee, y se queda centrada en la columna, que ahora es todo el
   ancho: centrada sobre el texto en vez de sobre el hueco de al lado. */
@media (max-width: 900px) {
  .about { grid-template-columns: minmax(0, 1fr); gap: 28px; }
}

/* --------------------------------------------------------------- preguntas */

.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  list-style: none; cursor: pointer; position: relative;
  padding: 24px 48px 24px 0;
  font-family: var(--f-display); font-size: clamp(18px, 2vw, 25px); line-height: 1.25;
  font-weight: var(--w-display-2); letter-spacing: var(--ls-md);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+'; position: absolute; right: 2px; top: 50%; transform: translateY(-50%);
  font-family: var(--f-mono); font-size: 21px; color: var(--acc); line-height: 1;
}
.faq details[open] summary::after { content: '\2212'; }
/* al recogerse, el signo vuelve a + desde el primer instante, no al final */
.faq details.is-cerrando summary::after { content: '+'; }
.faq summary:hover { color: var(--acc); }
.faq p { margin: 0 0 26px; padding-right: 48px; font-size: 16.5px; line-height: 1.68; color: var(--mut); max-width: calc(68ch + 40px); }
.faq ul { margin: 0 0 26px; padding: 0 48px 0 0; list-style: none; display: grid; gap: 10px; max-width: calc(68ch + 40px); }
.faq p + ul { margin-top: -12px; }
.faq li { display: flex; gap: 12px; align-items: baseline; font-size: 16.5px; line-height: 1.6; color: var(--mut); }
.faq li::before { content: ''; width: 6px; height: 6px; flex: 0 0 auto; background: var(--acc); transform: translateY(-2px); }

/* ---------------------------------------------------------------- contacto */

.end { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(30px, 5vw, 64px); align-items: center; }
.end h2 { font-size: clamp(32px, 5vw, 66px); line-height: 1.02; max-width: 14ch; }
.end p { margin: 22px 0 0; font-size: clamp(16px, 1.6vw, 20px); color: var(--inv-mut); max-width: 46ch; }
.end__lines { display: grid; }
.end__lines a {
  display: flex; align-items: baseline; justify-content: space-between; gap: 18px;
  padding: 22px 0; border-top: 1px solid var(--inv-line);
  font-family: var(--f-display); font-size: clamp(17px, 2vw, 26px); font-weight: var(--w-display-2); letter-spacing: var(--ls-md);
  transition: color 0.22s ease, padding-left 0.22s ease;
}
.end__lines a:last-of-type { border-bottom: 1px solid var(--inv-line); }
.end__lines a:hover { color: var(--inv-acc); padding-left: 8px; }
.end__lines .mono { color: var(--inv-mut); }
.end__note { margin: 22px 0 0; font-size: 14px; color: var(--inv-mut); }

.foot {
  display: flex; justify-content: space-between; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 22px var(--pad-x);
  background: var(--inv-bg); color: var(--inv-mut);
  border-top: 1px solid var(--inv-line);
}
.foot .mono { font-size: 10px; }
.foot a:hover { color: var(--inv-acc); }

/* --------------------------------------------------------------- iconos

   Un único set para interfaz (Lucide) y otro solo para marcas de tecnología
   (Simple Icons). Mezclar sets es lo que hace que una interfaz se vea
   incoherente, así que no se mete un tercero.
   Todos heredan el color del texto y ninguno lleva significado por sí solo:
   siempre van acompañados de su etiqueta.
*/

.ico { width: 20px; height: 20px; flex: 0 0 auto; display: block; }
.ico--sm { width: 16px; height: 16px; }
.ico--lg { width: 26px; height: 26px; }

/* Icono dentro de un cuadro, para encabezar bloques */
.ico-box {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex: 0 0 auto;
  border: 1px solid var(--line-2); color: var(--acc);
  transition: border-color 0.3s ease, background 0.3s ease;
}
.ico-box .ico { width: 21px; height: 21px; }

/* franja de datos */
.facts b { display: flex; align-items: center; gap: 9px; }
.facts b .ico { width: 16px; height: 16px; color: var(--acc); }

/* método */
.steps article:hover .ico-box { border-color: var(--acc); background: var(--acc-soft); }
.steps .ico-box { margin-bottom: 4px; }

/* contacto: cada línea con su icono */
.end__lines a { align-items: center; }
.end__lines .lbl { display: flex; align-items: center; gap: 12px; }
.end__lines .ico { color: var(--inv-mut); transition: color 0.22s ease; }
.end__lines a:hover .ico { color: var(--inv-acc); }

/* enlaces externos */
.btn .ico { width: 15px; height: 15px; }

/* ------------------------------------------------------------ animación

   Estado inicial de las piezas coreografiadas. Se ocultan desde CSS y no
   desde JavaScript, para que no se vean un instante antes de animarse.

   Todo cuelga de la clase .js, que pone el script del <head>. Ese script no
   la pone si el sistema pide movimiento reducido, y la retira si site.js no
   llega a cargar: nunca queda texto escondido esperando un script que quizá
   no venga.

   Esta lista se genera junto con la tabla de coreografías de site.js, así que
   las dos no pueden desincronizarse.
*/

.js .about .about__body p,
.js .end .end__lines a,
.js .end .end__note,
.js .end h2 + p,
.js .facts__in > div b,
.js .facts__in > div span,
.js .faq details summary,
.js .gal__cap p,
.js .gal__link,
.js .gal__nota,
.js .gal__pieza .frame,
.js .gal__tag,
.js .hero__in .hero__cta > *,
.js .hero__in .hero__lead,
.js .probs article .mono,
.js .probs article h3,
.js .probs article p,
.js .probs__note,
.js .sect--alt .head p,
.js .sect:not(.sect--alt) .head p,
.js .steps article .ico-box,
.js .steps article .mono,
.js .steps article .steps__tag,
.js .steps article p,
.js .steps__note,
.js .rueda { opacity: 0; }

.js .hero__in .hero__q,
.js .sect:not(.sect--alt) .head h2,
.js .steps article h3 { clip-path: inset(105% 0 -0.25em 0); }

.js .end h2,
.js .gal__cap h3,
.js .sect--alt .head h2 { clip-path: inset(0 100% -0.25em 0); }

/* ------------------------------------------------------------ menú y anclas

   Las anclas dejan sitio al nav fijo al llegar, tanto con el viaje animado
   de site.js como al abrir la página con #seccion en la dirección.
   El menú desplegable solo existe por debajo de 1080px, donde las seis
   secciones ya no caben en la barra: el nav no se esconde, se pliega. */

main [id] { scroll-margin-top: var(--nav-h); }
[tabindex="-1"]:focus { outline: none; }
.end > * { min-width: 0; }
.menu-btn, .nav__panel-cta { display: none; }

@keyframes nav-entra {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* -------------------------------------------------------------- responsive */

@media (max-width: 1080px) {
  .facts__in { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .facts__in > div { border-bottom: 1px solid var(--line); padding-right: 24px; }
  .facts__in > div:nth-child(2) { border-right: 0; }
  .facts__in > div:nth-child(3), .facts__in > div:nth-child(4) { border-bottom: 0; }
  .facts__in > div:nth-child(3) { padding-left: 0; }
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .probs { grid-template-columns: 1fr; }
  .gal { grid-template-columns: 1fr; }
  .end { grid-template-columns: 1fr; }
  .hero canvas { width: 100%; opacity: 0.4; -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 55%); mask-image: linear-gradient(180deg, transparent 0%, #000 55%); }
}

@media (max-width: 900px) {
  .probs article { grid-template-columns: 44px 1fr; }
  .probs p { grid-column: 2 / -1; margin-top: 8px; }

  /* Por debajo de 900 no cabe el medio disco al lado del texto: el disco pasa
     debajo, entero y centrado, asi que se ve el circulo completo en lugar de
     una mitad recortada. */
  #tecnologia { --d: min(86vw, 400px); flex-direction: column; min-height: 0; gap: 36px; padding-bottom: 0; }
  /* relative, no static: el disco de dentro es absoluto y un padre estatico no
     es bloque contenedor, asi que se posicionaria contra la seccion y se iria
     encima del titular. Estando en flujo relativo se queda en su sitio.

     La caja mide media rueda de alto y recorta: se ve la mitad de arriba del
     disco, y al no haber relleno inferior el corte queda a ras de la seccion
     siguiente, que es la que aparenta taparlo. */
  .rueda {
    position: relative; inset: auto; translate: none;
    width: var(--d); height: calc(var(--d) / 2);
    overflow: hidden; align-self: center;
  }
  /* Aqui la rueda va suelta y centrada, no al lado del texto, asi que el punto
     de lectura pasa a ser las doce en punto, la posicion natural de un circulo
     solo, en vez de las nueve, que es la que mira al texto en escritorio.
     0.01 = las 12 en punto con el mismo adelanto que en escritorio. */
  .rueda__ico .ico { animation-delay: 0s, calc((0.01 + var(--i) * 0.1) * var(--dur) * -1); }
}

@media (max-width: 720px) {
  body { font-size: 16px; }
  :root { --nav-h: 60px; }
  .nav__right { gap: 10px; }
  .nav { gap: 12px; }
  .nav__cta { display: none; }
  .facts__in { grid-template-columns: 1fr; }
  .facts__in > div { border-right: 0; padding: 16px 0 !important; }
  .facts__in > div:nth-child(3) { border-bottom: 1px solid var(--line); }
  .facts__in > div:last-child { border-bottom: 0; }
  .steps { grid-template-columns: 1fr; }
  .ba { grid-template-columns: 1fr; }
  /* En el visor la captura no se encoge al ancho del telefono: se queda en un
     ancho que si se lee y se recorre en horizontal. Es la unica forma de que
     estas pantallas densas dejen de ser decorativas en movil.

     El minimo va en el marco y no en la imagen: el marco recorta con
     overflow: hidden, asi que un minimo puesto en la imagen la dejaria
     recortada dentro de un marco que sigue midiendo el ancho del visor, y no
     habria nada que desplazar. */
  .lupa { width: 94vw; max-height: 92vh; }
  .lupa__cuerpo { max-height: calc(92vh - 86px); }
  .lupa__cuerpo .frame { min-width: 560px; }
  .lupa__pie { flex-direction: column; align-items: flex-start; gap: 12px; }
  .lupa__cerrar { align-self: stretch; }
  .faq summary { padding-right: 36px; }
  .faq p, .faq ul { padding-right: 0; }
}

@media (max-width: 1080px) {
  .menu-btn {
    display: inline-flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
    width: 40px; height: 40px; flex: 0 0 auto;
    background: none; border: 1px solid var(--line-2); color: var(--fg);
    cursor: pointer; padding: 0;
    transition: border-color 0.2s ease, color 0.2s ease;
  }
  .menu-btn:hover { border-color: var(--acc); color: var(--acc); }
  .menu-btn span {
    display: block; width: 16px; height: 1.5px; background: currentColor;
    transition: transform 0.32s cubic-bezier(0.22, 0.61, 0.24, 1);
  }
  .nav.is-open .menu-btn span:first-child { transform: translateY(3.25px) rotate(45deg); }
  .nav.is-open .menu-btn span:last-child { transform: translateY(-3.25px) rotate(-45deg); }

  .nav__links {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; gap: 0;
    padding: 6px var(--pad-x) 26px;
    background: var(--bg); border-bottom: 1px solid var(--line);
    font-size: 19px; color: var(--fg);
    max-height: calc(100vh - var(--nav-h)); max-height: calc(100dvh - var(--nav-h)); overflow-y: auto;
    opacity: 0; visibility: hidden; transform: translateY(-10px);
    transition: opacity 0.26s ease, transform 0.36s cubic-bezier(0.22, 0.61, 0.24, 1), visibility 0s linear 0.36s;
  }
  .nav.is-open .nav__links {
    opacity: 1; visibility: visible; transform: translateY(0);
    transition: opacity 0.26s ease, transform 0.36s cubic-bezier(0.22, 0.61, 0.24, 1), visibility 0s;
  }
  .nav__links a {
    padding: 15px 0; border-bottom: 1px solid var(--line);
    font-family: var(--f-display); font-weight: var(--w-display-2); letter-spacing: var(--ls-md);
  }
  .nav__links a:hover { border-bottom-color: var(--line); }
  .nav.is-open .nav__links a { animation: nav-entra 0.42s cubic-bezier(0.22, 0.61, 0.24, 1) both; }
  .nav.is-open .nav__links a:nth-child(2) { animation-delay: 35ms; }
  .nav.is-open .nav__links a:nth-child(3) { animation-delay: 70ms; }
  .nav.is-open .nav__links a:nth-child(4) { animation-delay: 105ms; }
  .nav.is-open .nav__links a:nth-child(5) { animation-delay: 140ms; }
  .nav.is-open .nav__links a:nth-child(6) { animation-delay: 175ms; }
  .nav.is-open .nav__links a:nth-child(7) { animation-delay: 210ms; }
  .nav__links .nav__panel-cta {
    display: none; align-self: flex-start; margin-top: 22px; padding: 13px 24px;
    border: 1px solid var(--acc); color: var(--acc-fg);
    font-family: var(--f-body); font-size: 15px; letter-spacing: normal;
  }
  .nav__links .nav__panel-cta:hover { color: var(--acc-fg); border-color: var(--acc-hover); }
}

@media (max-width: 720px) {
  /* la letra va encima del titulo y el texto recupera todo el ancho */
  .probs article { grid-template-columns: 1fr; gap: 8px; }
  .probs p { grid-column: auto; margin-top: 4px; }
  /* sin CTA en la barra, el panel lo lleva */
  .nav__links .nav__panel-cta { display: inline-flex; }
}

@media (max-width: 480px) {
  .hero__cta .btn { flex: 1 1 100%; }
  .end__lines a { flex-direction: column; align-items: flex-start; gap: 6px; }
  .end__lines .lbl { min-width: 0; overflow-wrap: anywhere; }
}

@media (max-width: 420px) {
  .nav__brand-sub { display: none; }
  .nav__right { gap: 8px; }
  .lang a { padding: 0 9px; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .rv { opacity: 1; transform: none; }
  /* Acortar la transicion no basta: el empujon de la lupa seguiria dando un
     salto de tamano al pasar el raton. */
  .gal__zoom:hover img { transform: none; }
}

/* ------------------------------------------------------------- páginas legales

   Aviso legal y política de privacidad. Texto corrido en una sola columna,
   con el mismo nav y pie que la portada. .pend marca los datos del titular
   que todavía faltan, para no publicarlos por descuido: se buscan con
   grep "class=\"pend\"" antes de subir. */

.legal { padding: clamp(48px, 8vh, 96px) var(--pad-x) clamp(64px, 9vh, 120px); }
.legal__in { max-width: 760px; margin: 0 auto; }
.legal h1 { font-size: clamp(34px, 5vw, 58px); line-height: 1.02; }
.legal__meta { margin: 18px 0 0; color: var(--mut); font-size: 14px; }
.legal h2 { margin-top: clamp(32px, 5vh, 52px); font-size: clamp(21px, 2.4vw, 28px); line-height: 1.15; font-weight: var(--w-display-2); }
.legal p, .legal li { font-size: 16.5px; line-height: 1.68; color: var(--fg-2); }
.legal p { margin: 14px 0 0; }
.legal ul { margin: 14px 0 0; padding-left: 20px; display: grid; gap: 8px; }
.legal a:not(.btn) { color: var(--acc); border-bottom: 1px solid var(--line-3); }
.legal a:not(.btn):hover { border-bottom-color: var(--acc); }
.legal dl { margin: 18px 0 0; border-top: 1px solid var(--line); }
.legal dl > div { display: grid; grid-template-columns: 200px 1fr; gap: 16px; padding: 12px 0; border-bottom: 1px solid var(--line); }
.legal dt { font-family: var(--f-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--mut); padding-top: 4px; }
.legal dd { margin: 0; font-size: 16.5px; color: var(--fg); }

.pend {
  background: var(--acc-soft); color: var(--fg);
  border: 1px dashed var(--acc); padding: 1px 7px;
  font-style: normal; font-size: 0.92em;
}

.foot__legal { display: flex; gap: 18px; flex-wrap: wrap; }

@media (max-width: 720px) {
  .legal dl > div { grid-template-columns: 1fr; gap: 2px; }
}

/* ------------------------------------------------------------------ precios

   Lista editorial como la de .probs, no tres tarjetas iguales. Las filas con
   precio de partida llevan la cifra grande en el acento; las «a consultar»
   la llevan en tono apagado para que la vista vaya primero a lo que ya tiene
   precio. */

#precios + #metodo, #pricing + #method { border-top: 1px solid var(--line); }

.tarifas { border-top: 1px solid var(--line); }
.tarifas article {
  display: grid; grid-template-columns: 68px 1fr minmax(150px, auto);
  gap: clamp(16px, 3vw, 44px);
  padding: clamp(22px, 3vh, 32px) 0;
  border-bottom: 1px solid var(--line);
  align-items: center;
}
.tarifas .mono { color: var(--acc); }
.tarifas h3 { font-size: clamp(21px, 2.5vw, 31px); line-height: 1.1; font-weight: var(--w-display-2); }
.tarifas p { margin: 8px 0 0; font-size: 16px; line-height: 1.6; color: var(--mut); max-width: 56ch; }
.tarifas__precio { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; text-align: right; }
.tarifas__precio b {
  font-family: var(--f-display); font-weight: var(--w-display);
  font-size: clamp(28px, 3.4vw, 44px); line-height: 1; letter-spacing: var(--ls-lg);
  color: var(--acc);
}
.tarifas__precio--cons b { font-size: clamp(18px, 1.9vw, 24px); color: var(--mut); font-weight: var(--w-display-2); }
.tarifas__nota { margin: 22px 0 0; font-size: 14px; line-height: 1.6; color: var(--mut); max-width: 78ch; }

.nueva {
  margin-top: clamp(36px, 6vh, 64px);
  display: grid; grid-template-columns: 1.1fr 1fr; gap: clamp(24px, 5vw, 64px);
  padding: clamp(26px, 4vw, 48px);
  background: var(--surface); border: 1px solid var(--line-2);
  align-items: center;
}
.nueva h3 { font-size: clamp(24px, 3vw, 38px); line-height: 1.08; font-weight: var(--w-display-2); max-width: 20ch; }
.nueva p { margin: 14px 0 26px; font-size: 16.5px; line-height: 1.65; color: var(--mut); max-width: 46ch; }
.nueva__lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.nueva__lista li { display: flex; gap: 12px; align-items: flex-start; font-size: 16px; line-height: 1.5; color: var(--fg-2); }
.nueva__lista .ico { width: 18px; height: 18px; margin-top: 2px; color: var(--acc); }

.end__lines a.is-main .lbl { font-weight: 600; color: var(--inv-acc); }
.end__lines a.is-main .ico { color: var(--inv-acc); }

@media (max-width: 900px) {
  .tarifas article { grid-template-columns: 44px 1fr; }
  .tarifas__precio { grid-column: 2 / -1; align-items: flex-start; text-align: left; flex-direction: row; align-items: baseline; gap: 10px; }
  .nueva { grid-template-columns: 1fr; }
}

/* Tres puntos de lo que incluye cada servicio, en línea para no alargar la fila */
.tarifas__lista { list-style: none; margin: 16px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px 26px; max-width: 70ch; }
.tarifas__lista li { display: flex; gap: 10px; align-items: baseline; font-size: 14.5px; line-height: 1.45; color: var(--fg-2); }
.tarifas__lista li::before { content: ''; width: 6px; height: 6px; flex: 0 0 auto; background: var(--acc); transform: translateY(-2px); }

.tarifas__otro {
  display: flex; align-items: center; justify-content: space-between; gap: 20px 32px; flex-wrap: wrap;
  padding: clamp(20px, 3vh, 28px) 0; border-bottom: 1px solid var(--line);
}
.tarifas__otro p { margin: 0; font-size: 16.5px; line-height: 1.55; color: var(--fg-2); max-width: 58ch; }
