/* Fuente auto-hosteada (subset latin, woff2 variable). Nunca @import remoto. */
/* Satoshi (Indian Type Foundry, ITF Free Font License, fontshare.com). Variable
   300-900 en UN archivo de 42 KB (42.588 bytes), contra los 69 KB en tres que
   pedia Lato (69.124).
   400 cuerpo · 600 titulos y etiquetas · 800 el numeral de los pasos. */
@font-face{font-family:'Satoshi';font-style:normal;font-weight:300 900;font-display:swap;src:url(fonts/satoshi-var.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}

/* ==== POR QUE CAMBIARON LAS MEDIDAS AL ENTRAR SATOSHI ====================
   Cambiar de familia no es cambiar una linea: Lato y Satoshi no miden igual.
   Medido con Chromium sobre los dos archivos, a 100px de cuerpo:

     Lato 400     x .520  mayuscula .730  ancho de frase 36.83
     Satoshi 400  x .490  mayuscula .720  ancho de frase 37.21
     Lato 700     x .520  mayuscula .730  ancho de frase 37.70
     Satoshi 600  x .500  mayuscula .740  ancho de frase 38.96

   1. La x de Satoshi es 6% mas baja, asi que al mismo px se lee mas chica. El
      cuerpo subio de 17.5 a 18.5px y el texto de interfaz un 5%. El interlineado
      bajo de 1.7 a 1.66: con el renglon mas alto ya no hacia falta tanto aire.
   2. Satoshi 600 pesa como Lato 700 pero es 3% mas ancha, y es una grotesca, no
      una humanista: aguanta --y pide-- mas tracking negativo en tamanos grandes.
      Los titulos van en 600 con -.012em (antes 700 con -.005em), el titular del
      hero en -.03em, y el numeral de los pasos en 800, porque el 900 se empasta.
   3. El titular del hero baja de clamp(...,5.4vw,3.9rem) a (...,5.2vw,3.8rem):
      compensa ese 3% de ancho de mas para que siga entrando en dos renglones.
   ====================================================================== */

/* ==== TOKENS — VERSION C =================================================
   Misma paleta de marca que la version A, pero al reves: acá el turquesa es el
   FONDO del hero y el navy es la tinta. Eso cambia todas las cuentas, y por eso
   los ratios de abajo no son los mismos que en la version A.

   Combinacion pedida: el layout del hero de la version B (low-poly, titular en
   mayusculas, mockup que se desborda) con la PALETA del hero de la version A
   (navy con toques de turquesa y violeta). Como el hero vuelve a ser oscuro, el
   texto vuelve a blanco y el CTA recupera el naranja, que sobre navy da 7.03:1.
   De la cintura para abajo la pagina sigue siendo la B: clara y alternada.
   ====================================================================== */
:root{
  --teal:#3AAFA9;         /* turquesa de marca */
  --neon:#51E4D1;         /* turquesa claro (extremo claro de la malla low-poly) */
  --teal-ink:#15706B;     /* turquesa apto para texto sobre claro — 5.54:1 ✓ */
  --navy:#112D42;         /* tinta principal — 13.36:1 sobre blanco, 5.34:1 sobre --teal */
  --navy-2:#0C2234;       /* footer */
  --orange:#FCA311;       /* acento decorativo, y CTA sobre fondo oscuro (7.03:1 con texto navy) */

  --paper:#FFFFFF;
  --tint:#F5F7FA;         /* gris de seccion alterna, como el de la referencia */
  --ink:#112D42;
  --ink-2:#48606F;        /* secundario — 6.21:1 sobre blanco ✓ */
  --line:#E4E9ED;
  --line-2:#D3DBE1;
  --on-dark:#FFFFFF;
  --on-dark-2:#C3D2DD;    /* secundario sobre los fondos oscuros — 9.8:1 ✓ */
  --on-dark-3:#ADC0CF;    /* terciario. Se mide sobre el punto MAS CLARO de la seccion
                             oscura, que no es el navy pelado sino el centro del radial
                             de neon del ::before (#1E525F): ahi da 4.62:1 ✓. El #7C97AB
                             daba 4.65 sobre navy pelado pero 2.83 sobre ese punto ✗. */

  --sh-sm:0 1px 2px rgba(17,45,66,.05), 0 2px 10px rgba(17,45,66,.05);
  --sh-md:0 8px 26px rgba(17,45,66,.08), 0 2px 6px rgba(17,45,66,.05);
  --sh-lg:0 22px 54px rgba(17,45,66,.14), 0 6px 18px rgba(17,45,66,.07);

  --maxw:1180px;
  --r:14px; --r-lg:18px;
  /* cuanto se monta un bloque sobre el siguiente (proceso -> proyectos) */
  --over:clamp(58px,6.5vw,104px);
  --ease:cubic-bezier(.2,.7,.2,1);
  --hdr-h:78px;
}

/* ==== RESET ============================================================== */
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;scroll-padding-top:calc(var(--hdr-h) + 12px);-webkit-text-size-adjust:100%}
body{
  background:var(--paper);color:var(--ink);overflow-x:hidden;
  font-family:'Satoshi',system-ui,sans-serif;font-size:18.5px;line-height:1.66;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button,input,textarea,select{font:inherit;color:inherit}
h1,h2,h3{font-family:'Satoshi',system-ui,sans-serif;font-weight:600;line-height:1.14;letter-spacing:-.012em}
::selection{background:var(--neon);color:var(--navy)}
:focus-visible{outline:2.5px solid var(--navy);outline-offset:3px;border-radius:4px}
.sprite{position:absolute;width:0;height:0;overflow:hidden}
.wrap{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:24px}
/* Visible solo para lectores de pantalla: no usa display:none, que los saca del
   arbol de accesibilidad, ni left:-9999px, que en RTL desplaza la pagina. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
.skip{position:absolute;left:-9999px;top:0;z-index:99;background:var(--navy);color:#fff;padding:12px 20px;font-weight:600;border-radius:0 0 10px 0}
.skip:focus{left:0}

/* ==== BOTONES ============================================================
   El naranja NO se usa como boton en esta version: sobre el turquesa del hero
   da 1.28:1 de limite y sobre blanco 2.02:1, muy por debajo del 3:1 que pide
   WCAG 1.4.11. El boton principal es navy, que pasa en los dos fondos.
   ====================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font-family:'Satoshi',system-ui,sans-serif;font-weight:600;font-size:16.2px;
  letter-spacing:.02em;padding:13px 26px;border-radius:999px;
  border:2px solid transparent;cursor:pointer;
  transition:background .25s var(--ease),border-color .25s var(--ease),color .25s var(--ease),transform .25s var(--ease),box-shadow .25s var(--ease);
}
.btn svg{width:17px;height:17px;flex:0 0 auto;transition:transform .3s var(--ease)}
.btn:hover svg{transform:translateX(4px)}
.btn--solid{background:var(--navy);border-color:var(--navy);color:#fff}
.btn--solid:hover{background:#1B4463;border-color:#1B4463;transform:translateY(-2px);box-shadow:0 12px 28px rgba(17,45,66,.26)}
.btn--line{border-color:var(--navy);color:var(--navy)}
/* Solo para fondos oscuros. El naranja con texto NAVY da 7.03:1; con blanco
   daria 2.02:1, asi que el texto de este boton no se cambia. */
.btn--cta{background:var(--orange);border-color:var(--orange);color:var(--navy);box-shadow:0 0 0 1px rgba(17,45,66,.45)}
.btn--cta:hover{background:#E8940A;border-color:#E8940A;transform:translateY(-2px);box-shadow:0 12px 28px rgba(252,163,17,.3)}
.btn--ghost{border-color:rgba(255,255,255,.75);color:#fff}
.btn--ghost:hover{border-color:var(--neon);color:var(--neon);transform:translateY(-2px)}
.btn--line:hover{background:var(--navy);color:#fff;transform:translateY(-2px)}
.btn--sm{padding:9px 20px;font-size:15.2px;border-width:2px}
/* El aire tiene que crecer con la letra, no aparte. El --lg estaba en 34px de
   padding contra 16.8px de texto: el aire crecia 70% respecto del --sm y la
   letra solo 10%, asi que los tres botones grandes --los dos del hero y el
   "Enviar consulta"-- se leian como una pastilla vacia con el texto chico
   adentro. La proporcion horizontal (padding / font-size) ahora es la misma
   que la del boton base:

     .btn--sm   20 / 15.2 = 1.32      9 / 15.2 = 0.59
     .btn       26 / 16.2 = 1.60     13 / 16.2 = 0.80
     .btn--lg   28 / 17.6 = 1.59     15 / 17.6 = 0.85   <- era 2.02 y 0.95

   La altura no se mueve: lo que se saca de padding lo repone el renglon mas
   alto (16.8x1.66 + 32 = 63.9px antes, 17.6x1.66 + 30 = 63.2px ahora), asi que
   no hay salto en el hero ni en el pie del formulario. */
.btn--lg{padding:15px 28px;font-size:17.6px}
.btn--lg svg{width:18px;height:18px}

/* ==== LOGO ===============================================================
   Recoloreo por custom properties: las clases CSS no cruzan el shadow tree de <use>.
   Sobre el hero turquesa el logo va en navy (el blanco daria 2.6:1).
   ====================================================================== */
/* Version horizontal completa: isotipo + palabra. La palabra se recolorea con
   --lg-a/--lg-b y el isotipo con --mk-a/--mk-b, por separado, porque sobre blanco
   el neon del isotipo queda lavado y hay que darle cuerpo. */
.logo{
  width:164px;height:auto;aspect-ratio:20051/4765;display:block;
  --lg-a:#FFFFFF;--lg-b:var(--neon);--mk-a:var(--neon);--mk-b:var(--teal);
}
.hdr.scrolled .logo{--lg-a:var(--navy);--lg-b:var(--teal-ink);--mk-a:var(--teal);--mk-b:var(--teal-ink)}
/* ⚠️ 2026-09-25: el logo del HEADER es una imagen, no este <svg>. En pantallas
   1x el vector a 164px se veia escalonado (el isotipo tiene formas finas en
   diagonal) y agrandarlo no ayudo. Se probaron cinco variantes en
   una pagina de prueba (ya borrada) -vector con colores por CSS, SVG con los colores adentro,
   el original sin tocar, PNG 1x y PNG 2x- y el estudio eligio el PNG 2x que
   el navegador achica a la mitad. Despues, a pedido, 164 -> 180px (las
   imagenes se regeneraron a 360 de ancho, no se estiraron) y el pie pasa a
   usar la misma imagen clara, que tiene sus mismos colores. Se generan desde el mismo vector (render
   supersampleado + reduccion por promedio); si cambian los colores de arriba
   hay que regenerarlas. El .hdr.scrolled .logo de arriba ya no pinta nada en
   el header, pero se deja por si se vuelve al vector. */
.logo-img{display:block;width:180px;height:auto}
.logo-img--oscuro,.hdr.scrolled .logo-img--claro{display:none}
.hdr.scrolled .logo-img--oscuro{display:block}
.logo--ft{--lg-a:#FFFFFF;--lg-b:var(--neon);--mk-a:var(--neon);--mk-b:var(--teal)}

/* ==== HEADER ============================================================= */
.hdr{
  position:fixed;inset:0 0 auto;z-index:50;height:var(--hdr-h);display:flex;align-items:center;
  border-bottom:1px solid transparent;
  transition:background .3s var(--ease),border-color .3s var(--ease),box-shadow .3s var(--ease);
}
.hdr.scrolled{background:rgba(255,255,255,.94);backdrop-filter:blur(12px);border-bottom-color:var(--line);box-shadow:var(--sh-sm)}
.hdr__in{display:flex;align-items:center;justify-content:space-between;gap:24px}
.nav{display:flex;align-items:center;gap:28px}
.nav a{color:#fff;font-size:15px;font-weight:500;position:relative}
.hdr.scrolled .nav a{color:var(--navy)}
/* El CTA del header arranca naranja sobre el hero oscuro y pasa a navy cuando el
   header se vuelve blanco: el naranja sobre blanco da 2.02:1 de limite y no
   llega al 3:1 que pide WCAG 1.4.11 para el borde de un control. */
.nav a.btn--solid{background:var(--orange);border-color:var(--orange);color:var(--navy)}
.nav a.btn--solid:hover{background:#E8940A;border-color:#E8940A}
.hdr.scrolled .nav a.btn--solid{background:var(--navy);border-color:var(--navy);color:#fff}
.hdr.scrolled .nav a.btn--solid:hover{background:#1B4463;border-color:#1B4463}
.nav a:not(.btn)::after{
  content:'';position:absolute;left:0;right:0;bottom:-7px;height:2px;background:var(--orange);
  transform:scaleX(0);transform-origin:left;transition:transform .3s var(--ease);
}
.nav a:not(.btn):hover::after,.nav a.is-active::after{transform:scaleX(1)}
.burger{display:none;width:44px;height:44px;background:none;border:0;cursor:pointer;position:relative}
.burger span{position:absolute;left:11px;width:22px;height:2.5px;background:#fff;border-radius:2px;transition:transform .3s var(--ease),background .3s var(--ease)}
.hdr.scrolled .burger span{background:var(--navy)}
.burger span:nth-child(1){top:19px}
.burger span:nth-child(2){top:26px}
.burger[aria-expanded="true"] span:nth-child(1){transform:translateY(3.5px) rotate(45deg)}
.burger[aria-expanded="true"] span:nth-child(2){transform:translateY(-3.5px) rotate(-45deg)}
html.menu-open{overflow:hidden}
/* El scrim vive FUERA del header: con backdrop-filter, sus hijos position:fixed
   quedan atrapados en el contenedor. */
.scrim{position:fixed;inset:0;z-index:45;background:rgba(12,34,52,.5)}

/* ==== HERO ===============================================================
   Malla low-poly generada una vez y embebida como SVG (252 triangulos entre los
   dos turquesas de marca). Es el recurso que define a la referencia.
   ====================================================================== */
/* ⚠️ 2026-09-22: banner 20% mas alto, pedido del estudio (primero fue 10%,
   subido a 20% el mismo día). Medido a 1440 (el ancho de referencia del
   resto de las capturas del proyecto): el hero mide 619px de fondo navy SIN
   este cambio -pixel exacto, no estimado, hasta donde el fondo pasa a
   blanco de .claim-. El 20% son 124px, que se suman +62 arriba y +62 abajo
   sobre el padding de siempre, en vez de escalar los clamp() -que solo
   mueven el padding, no el alto total: escalarlos un 20% solo sumaria
   ~36px, porque mas de la mitad del alto es el contenido (kicker+titular+
   bajada+botones), que no crece-. Sumar un flat en vez de tocar los clamp
   deja intacta toda la curva responsive ya afinada (el aire crece igual en
   cualquier ancho, no solo en el de referencia). */
.hero{
  position:relative;background:var(--navy);color:#fff;
  padding:calc(var(--hdr-h) + clamp(56px,8vw,92px) + 62px) 0 calc(clamp(56px,6vw,86px) + 62px);
}
/* La tira de luz del borde de abajo (2026-09-26, pedido del estudio): los
   mismos tres colores de la rayita de los titulos (.rule), pero a todo lo
   ancho y corriendose de costado, como una tira LED.
   El degrade va y vuelve (teal-neon-naranja-neon-teal) para que el final
   empalme con el principio, y mide el doble del ancho: moverlo 200% (un
   tile entero, porque con el fondo al doble cada 100% es medio tile) deja
   todo igual que al arrancar, asi que el loop no salta.
   Sin movimiento si se pidio menos movimiento: la regla global dejaria la
   animacion infinita en .01ms, que es un parpadeo. */
@keyframes hero-led{to{background-position:200% 0}}
.hero::after{
  content:'';position:absolute;left:0;right:0;bottom:0;height:4px;z-index:1;pointer-events:none;
  background:linear-gradient(90deg,var(--teal) 0%,var(--neon) 22.5%,var(--orange) 50%,var(--neon) 77.5%,var(--teal) 100%);
  background-size:200% 100%;
  animation:hero-led 8s linear infinite;
}
@media (prefers-reduced-motion:reduce){ .hero::after{animation:none} }
/* z-index 0 y no -1: con -1 la malla queda por detras del contenido del hero y
   deja de recibir el puntero, que es lo que alimenta la luz. */
.poly{position:absolute;inset:0;width:100%;height:100%;z-index:0}
/* Una sola columna centrada: el mockup (navegador + telefono) salio el
   2026-09-18 y quedo guardado en ~/archivo/intarget-2026/descartes/. Sin el,
   la malla low-poly y su luz quedan a la vista enteras. */
.hero__in{position:relative;z-index:1;text-align:center}
/* margin-bottom subio de 18px a 30px (2026-09-22, pedido del estudio): mas aire
   entre la etiqueta y el titular que tipea. */
.hero__kicker{
  font-family:'Satoshi',system-ui,sans-serif;font-weight:600;font-size:12.5px;letter-spacing:.22em;
  text-transform:uppercase;color:#fff;margin-bottom:30px;
}
/* El ancho maximo sube a 34ch porque el titular tiene que entrar en DOS
   renglones con la frase mas larga; con 19ch se partia en cuatro. El cuerpo lo
   termina de ajustar el JS (initType), que lo achica hasta que las tres frases
   entren en dos renglones. Sin JS queda el clamp, que alcanza para la primera.
   ⚠️ El clamp subio un ~8% (2026-09-22, pedido del estudio: que el titular
   ocupe un poco mas de espacio). Con las frases actuales sobra margen dentro
   de las 34ch --initType mide 2 renglones sin achicar nada, ver PROYECTO.md
   "Dos renglones, ni uno mas"-- asi que el aumento no dispara el achique. Si
   se suma una frase mas larga, el JS lo sigue resolviendo solo, pero puede
   volver a achicar mas de lo que achicaba antes: revisar la tabla de arriba. */
.hero__h1{
  font-weight:600;font-size:clamp(2.4rem,5.6vw,4.1rem);line-height:1.08;letter-spacing:-.03em;
  color:#fff;max-width:34ch;margin-inline:auto;text-wrap:balance;
}
/* Dos renglones fijos: arriba el prefijo en color, abajo el resto en blanco.
   Van como bloques para que el corte sea siempre ahi y no dependa del ancho.

   El prefijo va en --neon y NO en el --teal del logo, aunque el logo use los
   dos. Medido sobre el fondo real del hero: el neon da 6.41:1 con la malla
   apagada y 3.04:1 contra una faceta encendida --el tope de brillo de la luz
   esta calculado justo para eso, ver "El tope de contraste del encendido"--.
   El teal da 3.78:1 apagado pero se derrumba a 1.81:1 con una faceta encendida.

   El peso es 600 en los dos renglones: el que separa el prefijo es el color.
   Con 900 contra 400, como se probo antes, el salto quedaba brusco. En Satoshi
   el 600 pesa como el 700 de Lato, asi que el titular no se afino. */
.type__a,.type__b{display:block}
.type__a{color:var(--neon)}
/* Los renglones vacios tienen que seguir ocupando alto mientras se borra y se
   escribe, si no el hero se sacude aunque el min-height este puesto. */
.type__a:empty::before,.type__b:empty::before{content:'\200B'}
/* "intarget" con las letras del logo (2026-10-01): una svg por letra, ver los
   #lt-* del sprite. Las unidades son las del dibujo del logo: --lu es cuanto
   mide una en em, y cada letra trae su ancho en --w. La franja va de 371 (el
   punto de la i) a 4765 (la cola de la g) y la linea de base esta en 3721, de
   ahi el alto y el vertical-align. Con --lu=.00026em el palo de la t mide
   .72em, la altura de mayuscula de Satoshi.
   Los margenes negativos (--lm arriba y abajo) son para que la letra no agrande
   el renglon: la franja mide 1.14em y el renglon 1.08, y sin ellos el h1
   saltaba unos pixeles cada vez que el prefijo pasaba de "intarget" a
   "Creamos". El dibujo se sigue viendo entero (overflow visible).
   Va en el color del prefijo (--neon), no en los dos turquesas del logo: ver
   el contraste mas arriba. */
.lt{
  --lu:.00026em;--lm:.2em;
  display:inline-block;width:calc(var(--w) * var(--lu));height:calc(4394 * var(--lu));
  margin-block:calc(-1 * var(--lm));vertical-align:calc(-1044 * var(--lu) + var(--lm));
  fill:currentColor;overflow:visible;
}
/* Texto y tamaño cambiados el 2026-09-22: antes describia los tres servicios
   --lo que ahora dice el claim, mas abajo-- en un solo renglon largo (clamp
   chico, 1.02-1.14rem). Ahora es la frase corta que antes vivia en .claim
   ("Nos ocupamos de tu imagen / para que vos te ocupes de tu negocio."), en
   DOS renglones fijos con un <br> --no hace falta un span aparte como
   .claim__l porque aca no hay <em> que separar-- y con la letra mas grande
   (~15%) porque ahora es mas corta y funciona como bajada del titular, no
   como parrafo descriptivo. */
/* ⚠️ 2026-09-22, pedido del estudio: letra un poco mas grande (clamp subio
   ~10%, de 1.18-1.32rem a 1.3-1.46rem) y mas aire antes de los botones
   (margin-top de .hero__cta, de 34px a 46px). */
.hero__lead{margin:22px auto 0;max-width:46ch;font-size:clamp(1.3rem,2.05vw,1.46rem);color:#fff;line-height:1.5}
.hero__cta{display:flex;flex-wrap:wrap;justify-content:center;gap:14px;margin-top:46px}

/* ==== EL TITULAR QUE TIPEA ==============================================
   Tres frases, como en apartes.com.ar (alla es Typed.js; aca son 30 lineas en
   initType). Dos cuidados:

   1. El alto del h1 se reserva midiendo las TRES frases (lo hace el JS) porque
      no miden lo mismo: sin eso, el hero se sacude a cada cambio y arrastra la
      bajada y los botones.
   2. El cursor parpadea con una animacion infinita, asi que hay que apagarla a
      mano con prefers-reduced-motion: el bloque global deja la duracion en
      .01ms y parpadearia a mil por hora (la misma trampa de la cinta).
   ====================================================================== */
.type__caret{
  display:inline-block;width:.055em;min-width:3px;height:.86em;
  margin-left:.07em;vertical-align:-.05em;background:var(--neon);
  animation:caret 1.05s steps(1,end) infinite;
}
@keyframes caret{50%{opacity:0}}

/* ---- Anillo animado (sube-baja) -----------------------------------------
   Mecanismo de templates.iqonic.design/sofbox canvas-1: un circulo hueco que
   se asoma por el borde de la pantalla y flota en loop con translateY
   (alla es .banner-objects + .iq-fadebounce). La diferencia: alla el anillo
   es un borde solido traslucido; aca es un degrade de DOS paradas de la
   paleta -como los g1..g12 de imagenes/, ver README.

   Pedido del estudio (2026-09-22), dos veces. Los dos van montados en la
   seccion de ABAJO de la costura que ocupan -no en la de arriba- y suben con
   un `top` negativo (media altura propia): asi quedan mitad en cada seccion,
   sin importar cuanto mida ninguna de las dos, y pintan encima de la seccion
   de arriba donde se superponen, que es el efecto que se busca (la seccion
   de abajo va despues en el documento). Ninguno repone el "target"
   decorativo que se saco de la C el 2026-09-19 (comentario de abajo, en
   SECCIONES): son formas nuevas, sin el isotipo adentro.

   - .ring--contacto: en #contacto, del lado derecho, en la costura con
     #nosotros ("Sobre nosotros" / el formulario). Hasta el 2026-09-26 fue
     .ring--claim, en #servicios, primero en la costura con .claim y despues
     con el hero -ver el historial en git/PROYECTO.md-.
   - .ring--seam: en #proceso, del lado izquierdo, en la costura con
     #servicios ("Que hacemos" / "Como trabajamos").

   ⚠️ Mismo tamaño y mismos colores en los dos (pedido del estudio,
   2026-09-22): los dos comparten --ring-d y el degrade `ring-grad-seam` -ya
   no existe un degrade `-claim` aparte, ver el sprite en el HTML-.

   ⚠️ 2026-09-22 (mas tarde): la primera version del anillo era un <div> con
   background:conic-gradient() recortado en forma de anillo con mask-image
   -border-image no respeta border-radius, queda cuadrado en las puntas-.
   El estudio lo vio pixelado (conic-gradient + mask rasterizados, se nota
   sobre todo animando). Se cambio por un <circle> de SVG de verdad, con
   stroke en degrade. Vectorial: no hay nada que rasterizar, sale nitido en
   cualquier zoom o densidad de pantalla. El viewBox es 0 0 100 100 con
   r=42.5 y stroke-width=15 -esa proporcion, ~15% del diametro-, asi que el
   anillo entero escala con el tamaño del <svg> (--ring-d) sin tocar nada
   adentro.

   ⚠️ 2026-09-25: 25% mas finos y mas escondidos, pedido del estudio. Trazo
   15 -> 11.25 y r 42.5 -> 44.375, para que el borde de afuera siga en 50 y
   el anillo no se achique. El corrimiento hacia afuera paso de
   clamp(-140px,-10vw,-50px) -a 1440 dejaba afuera ~29% del diametro- a
   -.45 × diametro en cualquier ancho, y el mismo dia a -.4 (~40% oculto).

   No llevan overflow:hidden propio: body ya tiene overflow-x:hidden (RESET)
   y eso alcanza para recortar el lado que se pasa del viewport. Ponerlo en
   la seccion recortaria la mitad de arriba de cada anillo, que tiene que
   asomarse en la seccion anterior. */
/* ⚠️ 2026-09-25: ORBITA. Pedido del estudio (variante "D2" de una pagina de
   prueba): el anillo es un planeta, con una orbita finita alrededor y el
   cohete de la marca dando la vuelta sobre ella, cuerpo violeta y llamarada
   naranja (symbol #cohete-orbita).
   - El anillo y la orbita rebotan a contramano: cuando uno sube, el otro
     baja. Cada uno es un <g> con su animacion; el <svg> ya no se mueve.
   - Los rebotes van en unidades del viewBox (los px de un translate dentro
     de un SVG son unidades del viewBox), asi que escalan con el anillo.
   - Distancia: el borde del anillo esta en 50 y la orbita en 61. En el
     peor momento se acercan lo que suman los dos rebotes (anillo 3.75 o 5
     + orbita 2.5), asi que quedan 3.5-4.75 unidades de aire: ~15-20px a
     tamaño grande. NUNCA se tocan; si se sube un rebote, revisar esta cuenta.
   - El viewBox va de -20 a 120 (140) para que entre la orbita con el
     cohete, asi que el <svg> mide 1.4 anillos (--k) y se corre .2 anillo
     para arriba y para afuera: el anillo grueso queda donde estaba.
   - Con prefers-reduced-motion no se mueve nada: la regla global deja las
     animaciones en .01ms, que en una infinita es un parpadeo. */
@keyframes ring-flota{50%{transform:translateY(var(--ring-amp,4px))}}
@keyframes ring-contra{50%{transform:translateY(-2.5px)}}
@keyframes ring-giro{to{transform:rotate(360deg)}}
.ring{
  --k:1.4;
  position:absolute;z-index:0;pointer-events:none;display:block;overflow:visible;
  width:calc(var(--ring-d) * var(--k));aspect-ratio:1;
}
.ring__flota{animation:ring-flota var(--ring-dur,6s) var(--ease) infinite}
.ring__contra{animation:ring-contra var(--ring-dur,6s) var(--ease) infinite}
/* 32s por vuelta y cohete de 9 unidades (2026-09-26; antes 24s y 11): con
   el anillo 70% escondido se ve un tercio de cada vuelta, ~11s. */
.ring__giro{transform-origin:50px 50px;animation:ring-giro 32s linear infinite}
.ring use{--cuerpo:#6843E1;--llama:var(--orange)}
@media (prefers-reduced-motion:reduce){
  .ring__flota,.ring__contra,.ring__giro{animation:none !important}
}
/* 50% mas grande que la medida original de .ring--seam (190/22vw/320 × 1.5).
   Vertical: 30% del anillo en la seccion de arriba y 70% en la de abajo
   (pedido del 2026-09-22). Horizontal: se ve solo el 30% del anillo, el 70%
   queda afuera de la pantalla (2026-09-26; antes 50%, y antes 40%). Las dos cuentas restan (k-1)/2 porque
   el <svg> es mas grande que el anillo (ver arriba). */
/* --ring-d: ~15% mas chico el 2026-09-26 (antes clamp(285px,33vw,480px)).
   Todo lo de adentro -orbita, cohete, rebotes- escala con el. */
.ring--contacto,.ring--seam{
  --ring-d:clamp(240px,28vw,410px);
  top:calc(var(--ring-d) * -.3 - var(--ring-d) * (var(--k) - 1) / 2);
}
/* 2026-09-26: se muda de la costura hero/"Que hacemos" (era .ring--claim) a
   la de "Sobre nosotros"/contacto, pedido del estudio. Mismo lado, el derecho. */
.ring--contacto{
  --ring-amp:3.75px;
  right:calc(var(--ring-d) * -.7 - var(--ring-d) * (var(--k) - 1) / 2);
}
.serv{position:relative}
.serv>.wrap{position:relative;z-index:1}
/* En telefono no hay aire a los costados del contenido. */
@media (max-width:640px){ .ring--contacto{display:none} }

/* ==== SECCIONES Y HEADER CENTRADO ========================================
   El divisor es una rayita con degrade horizontal (ver .rule). Antes era
   linea-reticula-linea --la version Intarget del linea-circulo-linea de la
   referencia--, pero el target decorativo se saco de toda la pagina el
   2026-09-19: el isotipo ya apunta solo, y repetirlo en cada header lo gastaba.
   ====================================================================== */
.sec{padding-block:clamp(72px,9vw,116px)}
.sec--tint{background:var(--tint)}
/* Bloque oscuro de la version A: navy con una malla de dos radiales, neon arriba
   a la derecha y violeta abajo a la izquierda. */
.sec--dark{position:relative;overflow:hidden;background:var(--navy);color:var(--on-dark)}
.sec--dark::before{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(90% 90% at 96% 6%, rgba(81,228,209,.2) 0%, rgba(81,228,209,0) 58%),
    radial-gradient(90% 80% at 4% 98%, rgba(104,67,225,.4) 0%, rgba(104,67,225,0) 60%);
}
.sec--dark .head__t{color:var(--on-dark)}
.sec--dark .head__p{color:var(--on-dark-2)}
.head{text-align:center;max-width:730px;margin:0 auto clamp(46px,5.5vw,70px)}
.head__t{font-size:clamp(1.85rem,3.9vw,2.7rem);letter-spacing:-.022em}
/* Una sola rayita con degrade horizontal. Antes era linea-reticula-linea: el
   target decorativo se saco de toda la pagina el 2026-09-19. Mide lo mismo que
   median las dos lineas mas la reticula y los dos gaps (109 a 149px), asi que
   el ritmo vertical de los headers no se movio.
   Los tres colores son los de la marca: el turquesa del logo, el neon de la
   malla y el naranja del CTA. Sirve igual sobre claro que sobre los fondos
   oscuros, asi que ya no hacen falta las dos excepciones que pintaban las
   lineas de blanco en .sec--dark y en .proj. */
.rule{
  width:clamp(109px,14vw,149px);height:4px;border-radius:999px;margin:20px auto 22px; /* era 2px (2026-09-21) */
  background:linear-gradient(90deg,var(--teal) 0%,var(--neon) 45%,var(--orange) 100%);
}
.head__p{color:var(--ink-2);font-size:16.8px}

/* ==== TARJETAS DE SERVICIO =============================================== */
.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:26px}
.card{
  background:#fff;border:1px solid var(--line);border-radius:var(--r-lg);
  padding:38px 30px 34px;text-align:center;box-shadow:var(--sh-sm);
  display:flex;flex-direction:column;
  transition:transform .35s var(--ease),box-shadow .35s var(--ease),border-color .35s var(--ease);
}
/* .is-vista es el mismo hover, pero en pantallas sin cursor (celular): lo pone
   el JS con el scroll, en las tarjetas de servicio y en las de los pasos
   (initCardsVista, 2026-09-25: ahi estan los dos criterios). */
.card:hover,.card.is-vista{translate:0 -9px;scale:1.02;box-shadow:var(--sh-lg);border-color:var(--teal)}
/* ⚠️ El hover va en translate/scale, NO en transform, y la transition esta abajo del
   bloque .up (ver "LA TRAMPA DEL REVEAL" cerca del final). Con transform aca no pasaba
   NADA: .js .up.is-in, tres clases, le gana en especificidad y deja transform:none.

   El zoom leve al pasar el cursor viene del bloque "Cuadros personalizados" de mooon
   (.mn-cats__card, custom-panel.css). Alla el que escala es la foto dentro de la tarjeta,
   con overflow:hidden y scale(1.045); aca escala la tarjeta entera, que no tiene imagen, y
   ademas ya subia (9px). Por eso va a 1.02 y no a 1.045: medido, la tarjeta mide 360px, asi que
   1.045 le suma 16px de ancho (8 por lado) y el gap de 26px contra la vecina cae a 18; con 1.02
   suma 7px y el gap queda en 22.4. El will-change, como en mooon, solo
   donde hay cursor. El prefers-reduced-motion ya esta cubierto abajo, que apaga todas las
   transiciones de la pagina. */
@media (hover:hover){ .card{will-change:translate,scale} }
.card__ring{
  width:86px;height:86px;margin:0 auto 22px;border-radius:50%;
  border:1.5px solid var(--teal);display:grid;place-items:center;color:var(--teal);
  transition:background .35s var(--ease),color .35s var(--ease);
}
.card__ring svg{width:38px;height:38px}
.card:hover .card__ring,.cards .card.is-vista .card__ring{background:var(--teal);color:#fff}
.card h3{font-size:1.32rem;margin-bottom:12px}
.card p{color:var(--ink-2);font-size:16px}
/* flex:1 no es decorativo: estira la lista para que los tres "Cotizar" queden a la
   misma altura aunque una tarjeta tenga una vinieta mas larga que otra. */
.ticks{list-style:none;margin-top:22px;border-top:1px solid var(--line);padding-top:20px;text-align:left;flex:1}
.card__cta{align-self:center;margin-top:26px}
.ticks li{position:relative;padding-left:24px;font-size:15.4px;color:var(--ink-2);margin-top:10px;line-height:1.55}
.ticks li::before{
  content:'';position:absolute;left:0;top:.48em;width:9px;height:9px;border-radius:50%;
  border:2px solid var(--teal);
}

/* ==== PROCESO: CUATRO PASOS EN FILA ======================================
   Pedido sobre genemy/app-landing: el numeral grande manda y el resto cuelga
   de el. Reemplaza al radial alrededor del isotipo (ver PROYECTO.md).

   El numero va en --teal-ink y NO en el naranja de la referencia: el naranja
   sobre blanco da 2.02:1 y estos numerales son contenido (ordenan los pasos),
   asi que les corre el 3:1 de texto grande. El --teal-ink da 5.54:1.

   Van con aria-hidden porque el orden ya lo dice el <ol>: sin eso, un lector
   de pantalla anuncia "1. 01. Conversamos".
   ====================================================================== */
.steps4{list-style:none;display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(20px,2vw,26px);align-items:stretch;position:relative;z-index:1}
/* Los pasos usan .card: heredan el hover de "Que hacemos" (sube 9px, escala 1.02,
   sombra y borde turquesa) sin duplicar una linea. Solo cambian el relleno y la
   alineacion, que en la tarjeta de servicio va centrada. */
.card--step{text-align:left;padding:30px 26px 30px}
.steps4__n{
  display:block;font-weight:800;font-size:clamp(2.4rem,3.4vw,3rem);line-height:1;
  letter-spacing:-.045em;color:var(--teal-ink);margin-bottom:14px;
}
/* En caja mixta (se probaron versales el 2026-09-18 y no quedaron): 19.4px con
   -.012em son los valores medidos para minusculas en Satoshi.
   Dos renglones reservados: "Te armamos una propuesta" se parte y los otros no,
   asi que sin esto los parrafos arrancan a distinta altura y se ve.
   2.28em = 2 renglones al line-height 1.14 de los titulos. */
.steps4 h3{font-size:19.4px;letter-spacing:-.012em;margin-bottom:9px;min-height:2.28em}
.steps4 p{color:var(--ink-2);font-size:16px;line-height:1.62}

/* ==== EL PROCESO SE MONTA SOBRE PROYECTOS ================================
   Pedido sobre convertio.uicore.co/lead-capture: las tarjetas apoyan su tercio
   inferior sobre el bloque de color siguiente. Al principio la franja era
   propia de esta seccion (un ::after al pie); con el bloque oscuro de
   Proyectos abajo ya no hace falta inventarla: las tarjetas se montan sobre el
   fondo real, que es lo que hacen las dos referencias.

   El truco son tres piezas que se tienen que mover juntas:
     .proc sin padding abajo · la lista con margin-bottom negativo · Proyectos
     con ese mismo valor sumado a su padding de arriba.
   Por eso --over vive en :root y no en la seccion.
   ====================================================================== */
.proc{position:relative;padding-bottom:0}
.proc>.wrap{position:relative;z-index:1}
.steps4{margin-bottom:calc(-1 * var(--over))}

/* .ring--seam (mecanismo, tamaño y `top` en SERVICIOS, mas arriba): en la
   costura entre "Que hacemos" y "Como trabajamos". */
.ring--seam{
  --ring-amp:5px;--ring-dur:7s;
  left:calc(var(--ring-d) * -.7 - var(--ring-d) * (var(--k) - 1) / 2);
}
@media (max-width:640px){ .ring--seam{display:none} }

/* ==== PROYECTOS ==========================================================
   Sobre apartes.com.ar. Tres cosas definen el bloque:

   1. El fondo oscuro NO es el de la seccion: es .proj__bg, una capa absoluta
      que corta antes del pie (inset abajo = lo que sobresalen las imagenes +
      la fila de puntos). Si fuera background de la seccion, las imagenes no
      podrian asomarse: quedarian siempre sobre oscuro.
   2. Por eso tampoco usa .sec--dark, que lleva overflow:hidden y recortaria
      justo lo que tiene que sobresalir. Los colores de texto se copian abajo.
   3. La fila es un scroller con scroll-snap: sin JS se arrastra igual, y el
      JS solo sincroniza los puntos (ver script.js).
   ====================================================================== */
/* ⚠️ El fondo de la seccion tiene que ser EL MISMO que el de la seccion de abajo.
   Lo que asoma por debajo de la capa oscura --los ultimos ~40px de las tarjetas--
   se apoya sobre este fondo, y si no coincide con el de la seccion siguiente
   queda una franja de cien pixeles de otro color cruzando la pagina.

   Estuvo en --tint mientras abajo iba "Por que elegirnos", que era gris. Hoy
   abajo va la franja de marcas, que es BLANCA (2026-09-19), asi que este fondo
   es --paper. Si vuelve a cambiar lo de abajo, hay que cambiar esto con ello. */
.proj{
  position:relative;color:var(--on-dark);background:var(--paper);
  padding-top:calc(clamp(72px,9vw,116px) + var(--over));
  padding-bottom:clamp(30px,4vw,54px);
}
.proj__bg{
  position:absolute;z-index:0;left:0;right:0;top:0;
  bottom:var(--over);
  overflow:hidden;background:var(--navy);
}
.proj__bg::before{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(90% 90% at 96% 6%, rgba(81,228,209,.2) 0%, rgba(81,228,209,0) 58%),
    radial-gradient(90% 80% at 4% 98%, rgba(104,67,225,.4) 0%, rgba(104,67,225,0) 60%);
}
#projFx{position:absolute;inset:0;width:100%;height:100%;display:block}
.proj > .wrap,.proj__rail{position:relative;z-index:1}

/* La cinta es la del catalogo de megaclean (.marquee), traida tal cual el
   mecanismo: la pista lleva el juego DOS veces y la animacion la corre media
   vuelta, asi el empalme cae justo donde empieza la copia y no se ve el corte.
   Anda SIN JS; con JS (initProjRail, clase .is-js) la animacion CSS se apaga y
   la mueve el JS a la misma velocidad, con arrastre e inercia.

   --n es cuantas tarjetas entran a lo ancho y --dur cuanto tarda media vuelta.
   Con --n:2.75 la tarjeta mide ~510px a 1440, que es el tamaño que ya tenia.

   ⚠️ --dur DEPENDE DE CUANTAS TARJETAS HAY. Media vuelta es un juego entero,
   asi que con menos tarjetas el mismo --dur recorre menos y la cinta se ve mas
   lenta. La cuenta es ~8.6s por tarjeta: eran 43s con las cinco de despues de
   sacar el placeholder (2026-09-20), 52s con las seis de la tarde (sumada
   Mooon producto), 77s con las nueve del 2026-09-21 de noche (sumadas las
   tres de Quetza), 60s con las siete del 2026-09-22 a la tarde (Quetza se
   fusiono en una sola tarjeta), 69s con las ocho del mismo dia (entra Grupo
   Peñaflor), 77s con las nueve del 2026-09-25 (entra el video de Perfumes
   de Oriente) y son 86s con las diez de ahora (2026-09-29, entra MegaClean). El JS usa el mismo numero --vel = ancho_del_juego /
   --dur-- asi que con ajustarlo aca alcanza.

   SE INTERCALAN a proposito: nunca el mismo cliente ni el mismo tipo dos
   veces seguidas mas de lo evitable. Con 5 redes, 2 web y 3 producto en 10
   lugares la alternancia sale perfecta: las redes van en los impares y el
   resto en los pares. MegaClean (2026-09-29) entro al final y cerro el par
   pegado que quedaba en la vuelta (Mooon redes al final, Climatecnica al
   principio). El
   video de Perfumes de Oriente (2026-09-25) entro entre Grupo Peñaflor y
   Mooon redes, que eran el otro par pegado, y queda a 4 tarjetas de la otra
   de Perfumes de Oriente, lo mas lejos que se puede en 9. El orden tambien cuida que Mooon (aparece tres veces:
   sitio, redes y producto) no quede nunca al lado de si mismo -eso fue lo
   que se rompio al sacar Quetza 2/3 el 2026-09-22 a la tarde, que hacian de
   separador entre "Mooon redes" y "Mooon producto"; desde entonces cada vez
   que se suma o saca una tarjeta hay que revisar el orden entero, no solo
   agregar o cortar la lista.

   ⚠️ NO LLEVA MASCARA, y sacarla fue un pedido del estudio (2026-09-21): el
   fundido de las puntas, sobre el navy de la seccion, se leia como un sombreado
   azul encima de la primera y la ultima tarjeta. Ahora las tarjetas se cortan
   al ras contra el borde de la pantalla, que es lo que hace el overflow:hidden.

   Si alguna vez se quiere volver a fundir las puntas, eran DOS capas y la
   segunda no era decorativa: una de lados (fundido horizontal) y una de abajo
   (opaca en la franja que sobresale de la capa oscura). Se suman
   --mask-composite:add es el valor inicial--, asi que la de abajo cancelaba el
   fundido justo ahi; sin ella el fundido tambien se comia esa franja y, como
   abajo el fondo es claro, aparecia una cuña blanca en la esquina inferior de
   la primera y la ultima tarjeta. Nunca poner la de abajo sola: enmascara todo
   lo que no sea esa franja y la cinta desaparece.

   --salida es cuanto sobresalen las tarjetas: lo que la capa oscura se corta
   antes del final (--over) menos el padding de abajo de la seccion.

   --aire es el hueco de abajo para que se VEA la sombra de las tarjetas.
   ⚠️ No es un margen de diseño, es una correccion: el overflow:hidden de la
   cinta recorta al ras del borde de abajo de las tarjetas, asi que la sombra
   que .pwork dibuja hacia abajo se cortaba entera. A los costados se veia --el
   hueco entre tarjeta y tarjeta esta adentro de la caja-- pero justo abajo, que
   es el unico lado donde la tarjeta apoya sobre BLANCO (--salida), no habia
   nada y el canto quedaba pegado al fondo. El padding agranda la caja que
   recorta y el margen negativo lo devuelve, asi que la pagina no se mueve ni un
   pixel; lo unico que cambia es que la sombra tiene donde caer.
   ====================================================================== */
.proj__rail{
  --n:2.75;--g:clamp(14px,1.6vw,22px);--dur:86s;
  --salida:calc(var(--over) - clamp(30px,4vw,54px));
  --aire:clamp(34px,4vw,56px);
  container-type:inline-size;overflow:hidden;
  margin-top:clamp(30px,3.6vw,48px);
  padding-bottom:var(--aire);margin-bottom:calc(-1 * var(--aire));
}
.proj__track{list-style:none;display:flex;width:max-content;animation:proj-cinta var(--dur) linear infinite}
.proj__track li{flex:0 0 calc((100cqw - var(--g) * (var(--n) - 1)) / var(--n));margin-right:var(--g)}
@keyframes proj-cinta{to{transform:translateX(-50%)}}
@media (hover:hover){.proj__rail:hover .proj__track{animation-play-state:paused}}
.proj__rail.is-js{cursor:grab;touch-action:pan-y;user-select:none;-webkit-user-select:none}
.proj__rail.is-js .proj__track{animation:none;will-change:transform}
.proj__rail.is-dragging{cursor:grabbing}
.proj__rail.is-js img{-webkit-user-drag:none;user-drag:none;pointer-events:none}
/* ---- La tarjeta: la ficha va ENCIMA de la imagen -----------------------
   Cliente, descripcion y etiqueta, abajo a la izquierda, SIEMPRE PUESTAS, en
   todas las pantallas y sin animacion de entrada.

   ⚠️ Esto cambio el 2026-09-21, por pedido del estudio. Antes la ficha se
   destapaba al pasar el cursor --la mecanica de apartes.com.ar, que es la
   referencia del bloque: cortina que sube, las tres lineas escalonadas y zoom
   de la imagen-- y solo en tactil se mostraba siempre, porque sin cursor no hay
   hover. El efecto se veia bien pero escondia el dato: en la cinta, que ademas
   se mueve sola, el trabajo pasaba sin decir de quien era. Ahora el que mira no
   tiene que apuntar a cada tarjeta para saber que esta viendo.

   De las tres cosas que se movian queda el zoom de la imagen, como senal de que
   la tarjeta se puede abrir.

   El radio y la sombra viven en la tarjeta y no en la <img>: el overflow:hidden
   de la tarjeta es lo que recorta el zoom. */
.pwork{
  position:relative;
  border-radius:var(--r-lg);overflow:hidden;background:#0E2536;
  box-shadow:0 9px 22px rgba(6,18,28,.38); /* era 0 18px 44px: 50% mas chica (2026-09-21) */
}
.pwork__ver{
  display:block;width:100%;padding:0;border:0;background:none;
  font:inherit;color:inherit;cursor:zoom-in;
}
.proj__rail.is-dragging .pwork__ver{cursor:grabbing}
.proj__track img{
  display:block;width:100%;height:auto;aspect-ratio:5/4;object-fit:cover;
  background:#0E2536;transition:scale 1.2s cubic-bezier(.2,1,.2,1);
}

/* La ficha, en la esquina inferior izquierda de la imagen.
   ⚠️ 2026-09-22: el pie vuelve a medir LO MISMO que los costados (pedido del
   estudio: misma distancia a la izquierda y hacia abajo). Antes el pie tenia
   su propio numero, mas chico, --history: 24px→4px→14px→9px, ver el historial
   de git si hace falta la cuenta completa-- y quedaba mas pegado al borde de
   abajo que a los costados. Ahora los tres lados comparten el mismo
   `padding`, asi que la pastilla queda unos pixeles mas arriba que antes. */
.pwork{--cw:calc((100cqw - var(--g) * (var(--n) - 1)) / var(--n))}
.pwork__cap{
  position:absolute;inset:0;z-index:2;display:flex;flex-direction:column;
  justify-content:flex-end;align-items:flex-start;text-align:left;
  padding:clamp(15px,1.8vw,24px);
}
/* ⚠️ YA NO HAY CORTINA ni degrade. La cortina la quito el estudio el
   2026-09-21 (la ficha va sobre la imagen pelada) y el degrade blanco que la
   reemplazo -sumado ese mismo dia para separar la pastilla del fondo de la
   imagen- se saco el 2026-09-22, al mismo tiempo que el nombre del cliente
   dejo de mostrarse en la tarjeta (ver mas abajo): lo unico que queda arriba
   de la imagen es la pastilla de tipo, que es opaca y trae su propio color
   --no necesita nada detras para leerse, en ningun fondo--.
   Si alguna vez hace falta separar la ficha del fondo de nuevo, el degrade
   blanco era:
     height:15% y linear-gradient(0deg, rgba(255,255,255,1) 0%,
     rgba(255,255,255,.8) 30%, rgba(255,255,255,.4) 65%, rgba(255,255,255,0) 100%)
   y antes de eso, la cortina oscura era:
     height:max(19%,72px) y linear-gradient(0deg, rgba(8,20,30,.82) 0%,
     rgba(8,20,30,.74) 45%, rgba(8,20,30,.60) 80%, rgba(8,20,30,0) 100%)
   con un piso de opacidad de .56 donde habia texto (ver PROYECTO.md). */
/* ⚠️ 2026-09-22: el nombre del cliente se saco de la tarjeta (pedido del
   estudio): ahora la ficha visible es SOLO la pastilla de tipo, y el nombre
   recien aparece al abrir el popup (#lbCliT, mas abajo, que ya vivia aparte).
   Se borro .pwork__cli --queda en el historial de git si hace falta reponerlo--
   y se saco el "ClientName — " del aria-label de cada boton, para que la
   experiencia sea la misma con lector de pantalla: el nombre no se anticipa
   en ningun lado, solo se sabe al entrar a la imagen.
   El `gap` que separaba la pastilla del nombre en .pwork__cap tambien se
   saco ese mismo dia, sin nombre no tenia nada que separar. */
.pwork__tag{margin-bottom:0}

/* Lo unico que queda para el cursor es el zoom de la imagen: la ficha ya esta
   puesta, asi que el hover confirma que la tarjeta se puede abrir y nada mas. */
@media (hover:hover){
  .pwork:hover img{scale:1.07}
}
/* Con el teclado hace falta un foco propio. Antes lo hacia la ficha al
   destaparse; ahora que esta siempre, se marca con un filo. Va POR DENTRO
   (offset negativo) porque el overflow:hidden de .pwork recorta lo de afuera. */
.pwork__ver:focus-visible{
  outline:3px solid var(--neon);outline-offset:-3px;border-radius:var(--r-lg);
}

/* ---- La etiqueta de tipo de trabajo -------------------------------------
   Tres colores de la paleta, y los tres medidos contra su propio fondo. El
   color lo pone [data-tipo] (abajo), no el texto, asi que el 2026-09-21 el
   estudio alargo dos de los tres textos sin tocar esta cuenta:
     Sitio Web                     violeta #6843E1 con blanco .. 6.02:1 ✓
     Diseño para redes sociales    --teal  #3AAFA9 con navy .... 5.34:1 ✓
     Imagen de producto con IA     --orange #FCA311 con navy ... 7.03:1 ✓
   El violeta va de FONDO, no de texto: como texto sobre oscuro da 2.35:1 y por
   eso la guia de marca lo prohibe. De fondo con blanco encima, pasa.
   ⚠️ Desde que la etiqueta va ARRIBA de todo (2026-09-21) queda casi entera
   fuera de la cortina, apoyada sobre la imagen pelada. No es un problema
   --la pastilla es opaca y trae su propio color-- y de hecho es lo que
   permitio bajar la cortina: el elemento mas alto de la ficha ya no necesita
   fondo. El filo interior claro, que estaba para despegarla de la cortina,
   ahora la despega de la imagen, que es un fondo mucho menos previsible. */
.pwork__tag{
  align-self:flex-start;padding:4px 10px 3px;border-radius:999px;
  font-size:11px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  background:var(--tg);color:var(--tg-ink);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.2);
}
[data-tipo="web"]     {--tg:#6843E1;--tg-ink:#FFFFFF}
[data-tipo="redes"]   {--tg:var(--teal);--tg-ink:var(--navy)}
[data-tipo="producto"]{--tg:var(--orange);--tg-ink:var(--navy)}

/* Los titulos de esta seccion viven sobre el oscuro. */
/* ==== FILTROS DE PROYECTOS (2026-09-26) ==================================
   "Todos" = la cinta de siempre. Un tipo = .is-filtro en la cinta: el JS la
   frena y la deja en su lugar, y aca pasa a grilla quieta y centrada, con solo
   los trabajos de ese tipo y sin la copia aria-hidden. Una cinta infinita con
   un solo trabajo (hoy hay uno de web) no tendria sentido.
   Los botones solo existen con JS (.js): sin JS no harian nada. */
.proj__filtros{display:none}
.js .proj__filtros{display:flex;flex-wrap:wrap;justify-content:center;gap:10px;margin-top:clamp(-30px,-2vw,-14px)}
.proj__f{
  padding:10px 18px;border-radius:999px;border:1px solid rgba(255,255,255,.26);
  background:transparent;color:var(--on-dark-2);font:inherit;font-size:15px;font-weight:500;cursor:pointer;
  transition:background .2s var(--ease),color .2s var(--ease),border-color .2s var(--ease);
}
.proj__f:hover{border-color:var(--neon);color:var(--on-dark)}
.proj__f[aria-pressed="true"]{background:var(--neon);border-color:var(--neon);color:var(--navy)}
.proj__f:focus-visible{outline:2.5px solid var(--neon);outline-offset:3px}
.proj__rail.is-filtro{--n:3;cursor:auto}
.proj__rail.is-filtro .proj__track{
  width:min(var(--maxw),100% - 48px);margin-inline:auto;
  flex-wrap:wrap;justify-content:center;gap:var(--g);
  transform:none !important;animation:none !important;
}
.proj__rail.is-filtro .proj__track li{
  flex:0 0 calc((100% - var(--g) * (var(--n) - 1)) / var(--n));margin-right:0;
}
.proj__rail.is-filtro .pwork{--cw:calc((min(var(--maxw),100cqw - 48px) - var(--g) * (var(--n) - 1)) / var(--n))}
.proj__rail.is-filtro .proj__track li[aria-hidden="true"],
.proj__rail.is-filtro .proj__track li.is-fuera{display:none}
/* En celular los cuatro van en UN renglon: mas compactos y, si igual no
   entran (pantallas de ~360px), la fila se desliza de costado. */
@media (max-width:480px){
  .js .proj__filtros{flex-wrap:nowrap;justify-content:flex-start;gap:6px;overflow-x:auto;
    margin-inline:-24px;padding-inline:24px;scrollbar-width:none}
  .js .proj__filtros::-webkit-scrollbar{display:none}
  .proj__f{flex:none;padding:8px 13px;font-size:14px}
}
@media (max-width:1040px){ .proj__rail.is-filtro{--n:2} }
@media (max-width:640px){ .proj__rail.is-filtro{--n:1} .proj__rail.is-filtro .proj__track{width:calc(100% - 32px)} }
.proj .head__t{color:var(--on-dark)}
.proj .head__p{color:var(--on-dark-2)}

/* ==== POPUP DE PROYECTOS =================================================
   <dialog> nativo. El backdrop, el foco atrapado, el Esc y la vuelta del foco
   al boton los pone el navegador; aca solo va la pinta.

   Dos cuidados:
   1. El <dialog> cerrado es display:none, asi que para que la entrada se anime
      hay que animar el estado ABIERTO ([open]) y no una transicion: cuando el
      elemento aparece ya esta en su lugar.
   2. El alto lo manda la imagen: max-height en vh sobre la <img> y no sobre el
      dialogo, porque con object-fit:contain la caja se encoge con ella y la
      plaqueta queda siempre pegada abajo.
   ====================================================================== */
.lb{
  /* ⚠️ margin:auto NO es decorativo. Un <dialog> modal se centra porque la hoja
     del navegador le pone margin:auto, y el reset de arriba (*{margin:0}) se lo
     come: sin esta linea el popup queda pegado arriba a la izquierda y la
     imagen se sale de la pantalla. */
  margin:auto;
  border:0;padding:0;background:transparent;overflow:visible;
  /* La tercera medida es la que manda en pantallas bajas. Los trabajos son
     5:4 desde el 2026-09-21 (antes 4:3; ver PROYECTO.md), asi que atar el ANCHO a la altura de
     la ventana evita dos franjas muertas a los costados de la foto. La cuenta:
     la foto mide ancho x 0.8 y la plaqueta de abajo ronda los 110px, y todo
     junto tiene que entrar en el 94vh de la caja -> ancho <= (94vh - 110px)/.8,
     con un poco de aire por si la descripcion cae en dos renglones. */
  /* ⚠️ 2026-09-25: mas grande. Antes min(940px,92vw,calc(117vh - 140px)): el
     -140px era la plaqueta de abajo. Ahora, en pantallas apaisadas, la plaqueta
     va ENCIMA de la imagen (ver .lb__pie mas abajo), asi que la foto puede usar
     el 94vh entero -> ancho <= 94vh / .8 = 117.5vh. El tope de 1400px es por la
     version grande de cada trabajo (2000px): mas alla ya no suma detalle. */
  width:min(1400px,94vw,117vh);max-height:94vh;
  color:var(--on-dark);
}
.lb::backdrop{background:rgba(6,18,28,.78)}
.lb[open]{animation:lb-in .28s var(--ease) both}
.lb[open]::backdrop{animation:lb-fade .28s var(--ease) both}
@keyframes lb-in{from{opacity:0;transform:translateY(14px) scale(.97)}}
@keyframes lb-fade{from{opacity:0}}

.lb__caja{
  position:relative;display:flex;flex-direction:column;max-height:94vh;
  border-radius:var(--r-lg);overflow:hidden;background:#0E2536;
  box-shadow:0 30px 80px rgba(2,10,18,.55);
}
/* Columna flexible + min-height:0: si el alto no alcanza, lo que cede es la
   imagen y la plaqueta no se corta nunca. El contain es el seguro para el dia
   que entre un trabajo que no sea 5:4. */
/* ⚠️ 2026-09-25: la imagen va dentro de .lb__lupa, que es la que recorta el
   zoom. El zoom es un scale() sobre la <img> con transform-origin en el punto
   que se mira (--zx/--zy, los mueve el JS): con el mouse sigue al puntero, con
   el dedo se arrastra. El origin cambia sin transicion -si no, el paneo va
   con retraso-; solo el scale se anima. */
.lb__lupa{
  position:relative;overflow:hidden;min-height:0;aspect-ratio:5/4;
  background:#0A1B28;cursor:zoom-in;
}
.lb__img{
  display:block;width:100%;height:100%;object-fit:contain;
  transform-origin:var(--zx,50%) var(--zy,50%);
  transition:transform .3s var(--ease);
}
.lb.is-zoom .lb__lupa{cursor:zoom-out;touch-action:none}
.lb.is-zoom .lb__img{transform:scale(var(--zk,2))}
/* Trabajo en video (2026-09-25): el reel es 9:16, asi que el popup se angosta
   al ancho que le da la altura disponible, en vez de mostrar el video chiquito
   con dos franjas enormes en una caja 5:4. --vid-h es la altura del video:
   lo que deja el 94vh despues de la plaqueta (~150px, con aire), sin pasar
   el tamaño real del archivo (1280). */
.lb__vid{display:none}
.lb[data-media="video"]{--vid-h:min(calc(94vh - 150px),1280px);width:min(92vw,calc(var(--vid-h) * 9 / 16))}
.lb[data-media="video"] .lb__lupa,.lb[data-media="video"] .lb__zbtn{display:none}
.lb[data-media="video"] .lb__vid{display:block;width:100%;aspect-ratio:9/16;min-height:0;background:#0A1B28}
.lb__pie{padding:16px clamp(16px,2vw,24px) 18px;display:grid;gap:5px}
.lb__cli{
  margin:0;display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  font-size:clamp(18px,1.6vw,22px);font-weight:600;line-height:1.25;
}
/* La misma pastilla de la tarjeta, pero aca va en linea con el nombre. */
/* El popup reusa la pastilla de la tarjeta, asi que le neutraliza lo que la
   tarjeta le pone de su lado. margin:0 y no margin-top:0, porque el aire de la
   pastilla cambio de arriba a abajo cuando la etiqueta paso arriba del nombre. */
.lb__cli .pwork__tag{align-self:auto;margin:0}
.lb__desc{margin:0;color:var(--on-dark-2);font-size:clamp(14px,1.1vw,16px);line-height:1.5}
/* Pantalla apaisada: lo que limita la imagen es el alto, asi que la plaqueta
   pasa ENCIMA de la foto, abajo, sobre un degrade, y le devuelve ese alto. En
   vertical (celular) el limite es el ancho y la plaqueta abajo no le quita
   nada, asi que queda como estaba. El video la deja siempre abajo: encima
   taparia los controles. Al hacer zoom se va, para no tapar lo que se mira. */
@media (min-aspect-ratio:1/1){
  .lb:not([data-media="video"]) .lb__pie{
    position:absolute;left:0;right:0;bottom:0;padding-top:56px;pointer-events:none;
    background:linear-gradient(to top,rgba(6,18,28,.92),rgba(6,18,28,.6) 55%,rgba(6,18,28,0));
    transition:opacity .25s var(--ease);
  }
  .lb.is-zoom .lb__pie{opacity:0}
}

/* El play de la tarjeta de video: avisa que al abrirla hay un reel y no una
   imagen.
   ⚠️ 2026-09-25: el primero (navy translucido, 64px) se perdia sobre la
   portada, que es oscura: el estudio no lo veia. Ahora naranja lleno -el del
   CTA, el color que en el sitio significa "apreta aca"-, mas grande, con aro
   blanco y un pulso que sale del circulo cada 2.4s. Sin pulso si se pidio
   menos movimiento.
   Despues, el mismo dia: a la esquina de abajo a la derecha, con el mismo
   aire que la pastilla de la izquierda (el padding de .pwork__cap), y el
   triangulo 3px mas a la izquierda (margin-left 5 -> 2): centrado por su
   caja se percibia corrido a la derecha. */
.pwork__play{
  position:absolute;right:clamp(15px,1.8vw,24px);bottom:clamp(15px,1.8vw,24px);z-index:1;width:84px;height:84px;
  display:grid;place-items:center;border-radius:50%;pointer-events:none;
  background:var(--orange);color:var(--navy);border:3px solid #fff;
  box-shadow:0 10px 30px rgba(2,10,18,.5);
  transition:transform .25s var(--ease);
}
.pwork__play::after{
  content:"";position:absolute;inset:-3px;border-radius:50%;border:3px solid #fff;
  animation:play-pulso 2.4s var(--ease) infinite;
}
@keyframes play-pulso{0%{transform:scale(1);opacity:.85}70%,100%{transform:scale(1.55);opacity:0}}
.pwork__play svg{width:36px;height:36px;margin-left:2px;fill:currentColor}
.pwork__ver:hover .pwork__play{transform:scale(1.1)}
@media (prefers-reduced-motion:reduce){ .pwork__play::after{display:none} }

/* La X va sobre la imagen. Fondo propio y opaco: estas imagenes son casi todas
   blancas arriba y una X clara ahi no se ve. */
.lb__x{
  position:absolute;top:12px;right:12px;z-index:1;
  width:40px;height:40px;border:0;border-radius:50%;cursor:pointer;
  display:grid;place-items:center;
  background:rgba(17,45,66,.82);color:#fff;
  transition:background .2s var(--ease),transform .2s var(--ease);
}
.lb__x:hover{background:var(--navy);transform:rotate(90deg)}
/* La lupa, al lado de la X y con su misma pinta. Es la entrada al zoom para
   teclado y la pista en celular, donde no hay cursor que avise. */
.lb__zbtn{
  position:absolute;top:12px;right:60px;z-index:1;
  width:40px;height:40px;border:0;border-radius:50%;cursor:pointer;
  display:grid;place-items:center;
  background:rgba(17,45,66,.82);color:#fff;
  transition:background .2s var(--ease);
}
.lb__zbtn:hover{background:var(--navy)}
.lb__zbtn svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round}
/* ZOOM EN PANTALLA TACTIL (2026-09-25, pedido del estudio). En el celular la
   ventana es una franja 5:4 del ancho de la pantalla y ampliar ADENTRO de esa
   franja no tenia sentido. Con dedo, el zoom pasa el popup a pantalla completa:
   la imagen toma todo el alto (a 390x844 queda ~2.7 veces mas grande) y se
   recorre con el scroll nativo, que va con inercia y sin JS. Nada de scale().
   ⚠️ max-width/max-height:none no son de mas: el navegador le pone a todo
   <dialog> modal un max-width/height de calc(100% - 6px - 2em). */
@media (pointer:coarse){
  .lb.is-zoom{width:100vw;height:100dvh;max-width:none;max-height:none}
  .lb.is-zoom .lb__caja{height:100%;max-height:none;border-radius:0}
  .lb.is-zoom .lb__lupa{
    height:100%;flex:1 1 auto;aspect-ratio:auto;overflow:auto;
    touch-action:auto;overscroll-behavior:contain;cursor:auto;
  }
  .lb.is-zoom .lb__img{width:auto;height:100%;max-width:none;transform:none;transition:none}
  .lb.is-zoom .lb__pie{display:none}
}
.lb__zmenos,.lb.is-zoom .lb__zmas{display:none}
.lb.is-zoom .lb__zmenos{display:inline}
.lb__x svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round}

/* ==== SOBRE NOSOTROS =====================================================
   Dos columnas: el texto del estudio y los tres motivos. La izquierda es mas
   angosta a proposito (0.95fr contra 1fr): dos parrafos largos con la medida
   corta se leen mejor que estirados a la mitad exacta.

   El hilo que une los tres cohetes lo corta el circulo de cada marca, pintado
   del color del fondo: si cambia el fondo de la seccion hay que cambiar
   .nos__mark con ella.

   El cohete es el mismo remate del wordmark del logo (simbolo #rocket, sacado
   de imagenes/rocket-flat.svg). Va en --teal y no en el naranja que tenia la
   reticula: es una forma de la marca, y en naranja se leia como otro icono
   mas. Es decorativo --aria-hidden--, asi que no le aplica el minimo de
   contraste de texto; igual el turquesa lleno a 26px se ve sin esfuerzo sobre
   el --tint.
   ====================================================================== */
.nos__grid{display:grid;grid-template-columns:.95fr 1fr;gap:clamp(38px,5vw,84px);align-items:start}
.nos__txt .head__t{text-align:left}
.nos__txt p{color:var(--ink-2);font-size:17.2px;line-height:1.72;max-width:46ch}
.nos__txt p + p{margin-top:18px}

.nos__list{--sep:clamp(26px,3vw,38px);list-style:none;display:grid;gap:var(--sep)}
.nos__list li{position:relative;padding-left:64px;min-height:46px}
/* El hilo va tramo a tramo --de cada marca a la siguiente-- y no de una sola
   pieza detras de la lista: con una sola pieza habria que saber cuanto mide el
   ultimo item para cortarla ahi, y como no se sabe, sobresalia por debajo.
   El ultimo no lleva tramo. Los 22px son el centro de la marca (46/2 - 1). */
.nos__list li::before{
  content:'';position:absolute;z-index:0;left:22px;top:22px;bottom:calc(-1 * var(--sep));
  width:1.5px;background:var(--line-2);
}
.nos__list li:last-child::before{content:none}
.nos__mark{
  position:absolute;z-index:1;left:0;top:-1px;display:grid;place-items:center;
  width:46px;height:46px;border-radius:50%;background:var(--tint);color:var(--teal);
}
/* 26 y no 23: el cohete es una diagonal fina y con la caja de la reticula
   quedaba chico dentro del circulo. */
.nos__mark svg{width:26px;height:26px}
.nos__list h3{font-size:19.4px;letter-spacing:-.012em;margin-bottom:8px}
.nos__list p{color:var(--ink-2);font-size:16.2px;line-height:1.62}

/* ==== MARCAS =============================================================
   La cinta de logos es el mismo mecanismo que la de Proyecto (ver .proj__rail)
   con dos diferencias: no la agarra ningun JS --no hace falta arrastrar logos,
   asi que alcanza con la animacion CSS-- y los items no son fracciones del
   ancho sino cada logo con su medida propia.

   El margin-right en vez de gap no es capricho: con gap la pista mide dos
   juegos MAS un espacio, y el -50% de la animacion cae medio espacio corrido.
   Con el margen adentro de cada item los dos juegos miden exactamente lo mismo
   y el empalme no se ve.

   Los logos entran ya normalizados desde el archivo --cada .avif se genero a la
   medida que le toca, ver PROYECTO.md "La franja de marcas"--, porque en una
   fila de logos lo que tiene que emparejarse no es el alto sino la MANCHA: van
   de 23 a 46px de alto segun cuanta tinta tenga cada marca.
   ====================================================================== */
.marcas__rail{
  --g:clamp(38px,4.6vw,68px);--dur:55s;
  overflow:hidden;margin-top:clamp(26px,3.2vw,42px);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
}
.marcas__track{list-style:none;display:flex;align-items:center;width:max-content;animation:marcas-cinta var(--dur) linear infinite}
.marcas__track li{flex:0 0 auto;margin-right:var(--g)}
/* Siluetas negras al 55% sobre el blanco: da un gris neutro (#737373) igual para
   los dieciocho, sin que ninguna marca grite mas fuerte que otra por su color. */
.marcas__track img{opacity:.55;transition:opacity .3s var(--ease)}
@keyframes marcas-cinta{to{transform:translateX(-50%)}}
@media (hover:hover){
  .marcas__rail:hover .marcas__track{animation-play-state:paused}
  .marcas__track img:hover{opacity:.85}
}

/* ==== CONTACTO ===========================================================
   Variante elegida por el estudio el 2026-09-19 sobre ewebot.livewp.site/bento.
   Reemplaza la banda oscura a sangre con el formulario en dos columnas; la
   version anterior y la otra propuesta quedan en intarget-c/pruebas/.
   ====================================================================== */
.rule--left{margin-left:0}
/* El bloque entero es UN objeto apoyado sobre la pagina, no una banda a sangre.
   ⚠️ El fondo va en --paper y NO en el --tint que tenia la prueba: arriba esta
   "Sobre nosotros", que ya es --tint, y dos secciones grises seguidas borran el
   limite entre las dos. Sobre blanco el panel necesita quedar apoyado en algo,
   y eso lo hace la sombra. Si alguna vez el bloque de arriba deja de ser gris,
   este fondo puede volver a --tint y la sombra se puede bajar. */
.v2{position:relative;background:var(--paper);padding-block:clamp(56px,7vw,96px)}
/* Las particulas van en el blanco, DETRAS del panel: lo que se ve es el marco
   que queda alrededor --los dos costados del .wrap y el aire de arriba y de
   abajo--, asi que el panel las tapa en el medio y eso esta bien, el efecto es
   un campo alrededor de la tarjeta y no un fondo con puntos encima.

   Sin overflow:hidden no hace falta recorte: las particulas se envuelven en los
   bordes del canvas, que mide exactamente la seccion. */
#contactoFx{position:absolute;inset:0;z-index:0;width:100%;height:100%;display:block;pointer-events:none}
.v2 > .wrap{position:relative;z-index:1}

/* ⚠️ El degrade NO esta inventado: son los colores del hero, muestreados sobre
   la diagonal de la malla low-poly (2026-09-19, pedido del estudio). El hero va
   del turquesa oscuro de arriba a la izquierda al azul violaceo de abajo a la
   derecha, y el panel repite ese recorrido para que el cierre de la pagina rime
   con la apertura. Las cinco paradas son el promedio de un cuadro de 88px
   centrado en cada punto de la diagonal del hero renderizado a 1440x636:

     t     color     blanco  --on-dark-2  --neon
     0.00  #225C69    7.49       4.85      4.77   <- la mas exigente
     0.25  #194454   10.52       6.80      6.70
     0.50  #133347   13.19       8.53      8.40
     0.75  #243367   12.04       7.79      7.66
     1.00  #32357E   10.79       6.98      6.87

   Ningun texto del panel baja de 4.5:1 en ninguna parada, incluido el turquesa,
   que es la mas clara y donde cae la bajada en --on-dark-2. Antes el degrade
   terminaba en un turquesa oscuro #17534F; si se vuelve a tocar hay que rehacer
   esta tabla, y sobre todo NO poner el --teal de marca (#3AAFA9), que dejaria
   el blanco en 2.6:1.

   `to bottom right` y no un angulo en grados: asi las dos puntas caen siempre
   en las esquinas, mida lo que mida el panel. Con un angulo fijo, el turquesa
   se corre de la esquina cuando el bloque se hace alto en celular. */
.v2__panel{
  position:relative;overflow:hidden;border-radius:clamp(22px,2.4vw,34px);
  background:linear-gradient(to bottom right,#225C69 0%,#194454 25%,#133347 50%,#243367 75%,#32357E 100%);
  color:var(--on-dark);
  padding:clamp(32px,4vw,62px);box-shadow:0 30px 70px rgba(17,45,66,.18), 0 6px 18px rgba(17,45,66,.08);
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:clamp(30px,4vw,58px);
  align-items:start;
}
/* El formulario es mas alto que el texto de al lado. Se probo estirar la
   columna y mandar la ficha de datos al pie, y el hueco de 450px entre la
   bajada y los datos se leia como un error. El aire de abajo a la izquierda lo
   ocupa el isotipo, espejado y saliendose del panel: es la misma marca de agua
   que la seccion de contacto ya usa hoy, en el mismo lugar. */
.v2__mark{
  position:absolute;z-index:0;left:-9%;bottom:-16%;width:min(420px,40%);aspect-ratio:4400/4466;
  --mk-a:var(--neon);--mk-b:var(--teal);opacity:.07;pointer-events:none;transform:scaleX(-1);
}
/* Los dos radiales que iban encima --neon arriba a la derecha y violeta abajo a
   la izquierda-- salieron el 2026-09-19: caian justo al reves del degrade nuevo
   y le ensuciaban las dos puntas. El color lo lleva el degrade solo. */
.v2__left,.v2__card{position:relative;z-index:1}

.v2__t{
  font-size:clamp(1.9rem,3.5vw,2.9rem);font-weight:700;line-height:1.1;letter-spacing:-.028em;
  color:#fff;text-wrap:balance;max-width:14ch;
}
.v2__lead{margin-top:16px;color:var(--on-dark-2);font-size:16.4px;line-height:1.64;max-width:34ch}

/* Los cuatro datos en grilla de dos por dos, cada uno con su rotulo chico.
   Las versales tracked son la firma de la referencia y por eso se quedan: es
   lo que hace que el bloque se lea como una ficha de datos y no como un
   parrafo de contacto. */
.v2__data{margin-top:clamp(30px,3.6vw,46px);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(22px,2.6vw,32px) clamp(18px,2.4vw,30px)}
.v2__data > div{min-width:0}
/* Con tres datos y dos columnas, el tercero quedaria solo a la izquierda y la
   grilla se leeria incompleta. Ocupando el ancho entero no: dos arriba, uno
   abajo, y el renglon largo es justamente el que tiene el texto mas largo. */
.v2__data > .v2__wide{grid-column:1 / -1}
.v2__data dt{font-size:11.6px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--neon)}
.v2__data dd{margin:7px 0 0;font-size:17.4px;font-weight:600;line-height:1.42;color:#fff;word-break:break-word}
.v2__data a{color:inherit;text-decoration:none;box-shadow:inset 0 -1px 0 rgba(255,255,255,.34);transition:box-shadow .25s var(--ease),color .25s var(--ease)}
.v2__data a:hover{color:var(--neon);box-shadow:inset 0 -1px 0 var(--neon)}
/* ⚠️ Sin uso desde el 2026-09-19: la bajada de "Donde estamos" salio y ninguna
   celda quedo con segunda linea. Se conserva porque hay un cuarto dato
   propuesto al estudio y sin decidir, que la usaria. Si se descarta, esta
   regla se va con el. */
.v2__data .sub{display:block;margin-top:4px;font-size:14.4px;font-weight:500;color:var(--on-dark-2)}

/* La tarjeta esmerilada con la esquina cortada. El clip-path saca la cuña de
   arriba a la derecha; el border-radius sigue valiendo en las otras tres
   esquinas porque ahi el recorte no llega. El borde de 1px no dobla sobre el
   corte --el borde se pinta y despues se recorta-- y esta bien asi: el canto
   limpio es justamente lo que se ve en la referencia. */
.v2__card{
  --notch:clamp(28px,3.4vw,52px);
  background:rgba(255,255,255,.075);
  border:1px solid rgba(255,255,255,.17);
  border-radius:clamp(16px,1.9vw,26px);
  padding:clamp(26px,3vw,42px);
  -webkit-backdrop-filter:blur(16px);backdrop-filter:blur(16px);
  clip-path:polygon(0 0, calc(100% - var(--notch)) 0, 100% var(--notch), 100% 100%, 0 100%);
}
.v2__card h3{font-size:1.32rem;letter-spacing:-.016em;color:#fff;max-width:18ch}

/* ---- Campos subrayados sobre oscuro ---------------------------------
   Igual que en la variante 1, el <label> se queda arriba: la referencia usa
   solo placeholder y eso deja al que escribe sin rotulo apenas toca el campo. */
.f2{display:grid;gap:clamp(17px,2vw,23px);margin-top:clamp(22px,2.6vw,30px)}
/* Nombre y email comparten renglon: son los dos campos cortos del formulario y
   juntos le sacan una fila de alto a la tarjeta, que es lo que la desbalanceaba
   contra la columna de la izquierda. */
.f2__pair{display:grid;grid-template-columns:1fr 1fr;gap:clamp(14px,1.6vw,20px)}
.f2__row{display:grid;gap:6px;min-width:0}
.f2 label,.f2 legend{font-size:13.2px;font-weight:600;color:var(--on-dark-2);letter-spacing:.012em;transition:color .25s var(--ease)}
.f2__row:focus-within > label{color:var(--neon)}
.f2 .opt{font-weight:500;color:var(--on-dark-2)}
.f2__ctrl{position:relative}
.f2__ctrl input,.f2__ctrl textarea{
  width:100%;display:block;border:0;border-bottom:1px solid rgba(255,255,255,.3);border-radius:0;
  background:transparent;padding:10px 2px;color:#fff;
  font-family:inherit;font-size:16.2px;line-height:1.5;
}
.f2__ctrl textarea{min-height:92px;resize:vertical}
.f2__ctrl input::placeholder,.f2__ctrl textarea::placeholder{color:rgba(255,255,255,.5)}
/* Neon pleno: en la parada mas exigente del degrade da 4.77:1, muy por encima
   del 3:1 que pide un indicador de foco. */
.f2__ctrl::after{
  content:'';position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--neon);
  transform:scaleX(0);transform-origin:left;transition:transform .32s var(--ease);
}
.f2__ctrl:focus-within::after{transform:scaleX(1)}
.f2__ctrl input:focus,.f2__ctrl textarea:focus{outline:0}
.f2__ctrl input:focus-visible,.f2__ctrl textarea:focus-visible{outline:2px solid rgba(81,228,209,.55);outline-offset:6px}

/* Acá SI van pastillas: en un panel que es todo curva, el rectangulo seria el
   que desentona. Marcado en blanco con texto navy y no en naranja, porque el
   naranja es del boton: un solo acento por bloque. */
/* Dos por dos y no cuatro en fila: la tarjeta es mas angosta que la columna
   del formulario actual y con cuatro columnas "Varias cosas" parte en dos
   renglones y descuadra la fila. */
.f2__chips{position:relative;display:grid;grid-template-columns:repeat(2,1fr);gap:9px}
.f2__chips input{position:absolute;opacity:0;width:0;height:0}
.f2__chips label{
  display:block;text-align:center;padding:10px 8px;border-radius:999px;cursor:pointer;
  font-size:13.8px;font-weight:600;color:var(--on-dark-2);
  border:1px solid rgba(255,255,255,.32);
  transition:background .2s var(--ease),border-color .2s var(--ease),color .2s var(--ease);
}
.f2__chips label:hover{border-color:var(--neon);color:#fff}
.f2__chips input:checked + label{background:rgba(255,255,255,.94);border-color:transparent;color:var(--navy);font-weight:700}
.f2__chips input:focus-visible + label{outline:2px solid var(--neon);outline-offset:3px}

.f2__foot{display:flex;flex-wrap:wrap;align-items:center;gap:14px 18px;margin-top:6px}
/* --on-dark-2 y no --on-dark-3: sobre la tarjeta esmerilada --que le suma un
   7.5% de blanco al degrade-- el terciario queda al filo y el secundario no. */
.f2__foot .note{font-size:13.2px;color:var(--on-dark-2);max-width:28ch}
.form__hp{position:absolute;left:-9999px;opacity:0;pointer-events:none}

.f2__ok,.f2__err{display:none;border-radius:12px;padding:13px 16px;font-size:14.8px}
.f2__ok.show,.f2__err.show{display:block}
.f2__ok{background:rgba(81,228,209,.15);border:1px solid rgba(81,228,209,.42);color:var(--neon)}
.f2__err{background:rgba(252,163,17,.14);border:1px solid rgba(252,163,17,.44);color:var(--orange)}

@media (max-width:920px){
  .v2__panel{grid-template-columns:1fr}
  .v2__t{max-width:20ch}
  .v2__lead{max-width:46ch}
}
@media (max-width:560px){
  .v2__data{grid-template-columns:1fr}
  .f2__pair{grid-template-columns:1fr}
  .f2__chips{grid-template-columns:1fr}
  .v2 .btn--lg{width:100%}
  .f2__foot .note{max-width:none}
}

/* ==== FOOTER ============================================================= */
.ft{background:var(--navy-2);color:var(--on-dark);padding-block:clamp(46px,6vw,66px);border-top:1px solid rgba(255,255,255,.09)}
/* 2026-09-25: el pie se veia vacio. Pasa a tres columnas -marca, secciones,
   contacto-. En tablet la marca va arriba a lo ancho y las dos listas debajo;
   en celular, todo en una columna. Hubo una franja de abajo con el © y
   "Volver arriba" (.ft__base); el estudio la saco el mismo dia. */
.ft__in{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:36px;align-items:start}
/* En caja normal y no en versales espaciadas (2026-09-26): la etiqueta en
   mayusculas sobre cada columna es un recurso de plantilla. */
.ft__t{margin-bottom:4px;color:var(--on-dark);font-family:'Satoshi',system-ui,sans-serif;font-size:16.5px;font-weight:700}
.ft__contacto>span{color:var(--on-dark-2)}
.ft__redes{display:flex;gap:10px;margin-top:6px}
.ft__red{
  width:40px;height:40px;border-radius:50%;display:grid;place-items:center;
  border:1px solid rgba(255,255,255,.2);color:var(--on-dark-2);
  transition:color .2s var(--ease),border-color .2s var(--ease),background .2s var(--ease);
}
.ft__red svg{width:19px;height:19px;fill:none;stroke:currentColor;stroke-width:1.8}
.ft__red .ft__lleno{fill:currentColor;stroke:none}
a.ft__red:hover{color:var(--navy);background:var(--neon);border-color:var(--neon)}
@media (max-width:760px){
  .ft__in{grid-template-columns:1fr 1fr}
  .ft__brand{grid-column:1/-1}
}
@media (max-width:440px){ .ft__in{grid-template-columns:1fr} }
.ft__brand p{margin-top:18px;color:var(--on-dark-2);font-size:15.8px;line-height:1.6}
.ft__nav{display:flex;flex-direction:column;gap:11px;font-size:15.8px}
.ft__nav a{color:var(--on-dark-2);width:fit-content}
.ft__nav a:hover{color:var(--neon)}

/* ==== BOTONES FLOTANTES ==================================================
   Abajo a la derecha, el de subir arriba del de WhatsApp. z-index 44: por
   debajo del scrim del menu de celular (45), asi el menu abierto los tapa en
   vez de dejarlos flotando encima.

   Los colores siguen la misma cuenta que el CTA naranja del hero: fondo fuerte
   con el glifo en navy. El verde de WhatsApp es el suyo --se reconoce de
   lejos-- y el glifo va en --navy, que da 6.47:1; en blanco daria 2.11 ✗ y no
   llegaria ni al 3:1 que pide un icono. El de subir es al reves: navy con el
   cohete en --neon, 9.4:1.

   El cohete del sprite apunta en diagonal, como en el logo. Acá se gira 45
   grados para que apunte derecho hacia arriba, que es lo que el boton hace.
   ====================================================================== */
.fabs{
  position:fixed;z-index:44;right:clamp(14px,2.2vw,24px);
  bottom:calc(clamp(14px,2.2vw,24px) + env(safe-area-inset-bottom,0px));
  display:flex;flex-direction:column;gap:12px;
}
.fab{
  width:54px;height:54px;border-radius:50%;display:grid;place-items:center;
  box-shadow:0 10px 26px rgba(17,45,66,.26);
  transition:transform .25s var(--ease),box-shadow .25s var(--ease),opacity .25s var(--ease),visibility .25s;
}
.fab:hover{transform:translateY(-3px);box-shadow:0 16px 34px rgba(17,45,66,.32)}
.fab__ico{width:26px;height:26px}
.fab__ico--cohete{transform:rotate(-45deg)}
.fab--top{background:var(--navy);color:var(--neon)}
.fab--wa{background:#25D366;color:var(--navy)}
/* Sin JS se ve siempre --mejor eso que un boton que no existe--; con JS aparece
   recien cuando ya hay algo que desandar, pasado el alto del hero. */
.js .fab--top{opacity:0;visibility:hidden;transform:translateY(10px)}
.js .fab--top.is-on{opacity:1;visibility:visible;transform:none}
.js .fab--top.is-on:hover{transform:translateY(-3px)}

/* ==== REVEAL ============================================================= */
/* ⚠️ 2026-09-26: el reveal quedo SOLO en las tarjetas de "Que hacemos" y de
   "Como trabajamos", que entran escalonadas (.d1-.d3). Antes lo tenia cada
   titulo y cada bloque de la pagina, y el mismo deslizamiento repetido en
   todas las secciones se leia como plantilla. El resto de los .up ya no se
   mueve: el JS les sigue poniendo .is-in, pero ninguna regla los esconde. */
.js .cards .up,.js .steps4 .up{opacity:0;transform:translateY(22px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.js .cards .up.is-in,.js .steps4 .up.is-in{opacity:1;transform:none}

/* ==== LA TRAMPA DEL REVEAL ==============================================
   `.js .up` (dos clases) declara su propia transition y le pisaba entera la de
   `.card` (una clase): sobre las tarjetas de servicio, el box-shadow y el borde
   del hover cambiaban de golpe y el movimiento no existia, porque ademas
   `.js .up.is-in` (tres clases) fija `transform:none` y le gana a `.card:hover`.
   Por eso el hover de la tarjeta usa `translate`/`scale`, que son propiedades
   aparte y conviven con el `transform` del reveal, y por eso esta regla va ACA
   abajo y con dos clases: misma especificidad que `.js .up`, pero despues.
   Lleva tambien opacity y transform, que son los del reveal: si no se los
   devuelve, las secciones aparecen de golpe.
   ===================================================================== */
.cards .card,
.steps4 .card{
  transition:opacity .7s var(--ease),transform .7s var(--ease),
             translate .35s var(--ease),scale .35s var(--ease),
             box-shadow .35s var(--ease),border-color .35s var(--ease);
}
.d1{transition-delay:.09s}.d2{transition-delay:.18s}.d3{transition-delay:.27s}

/* ==== RESPONSIVE ========================================================= */
@media (max-width:1040px){
  /* Cuatro columnas abajo de 1040 dejan el parrafo en 4 renglones cortitos. */
  .steps4{grid-template-columns:repeat(2,1fr);gap:40px 34px}
}
@media (max-width:920px){
  /* Dos tarjetas y pico: a este ancho tres quedan chiquitas. */
  .proj__rail{--n:1.85}
  .hero__h1{max-width:none}
  .cards{grid-template-columns:1fr;max-width:520px;margin-inline:auto}
  .contact__top{grid-template-columns:1fr;gap:30px}
  /* Una cosa abajo de la otra: primero quienes somos, despues los motivos. */
  .nos__grid{grid-template-columns:1fr;gap:clamp(34px,5vw,48px)}
  .nos__txt p{max-width:none}

  /* El menu de hamburguesa arranca ACA y no en 760, que es donde estaba hasta el
     2026-09-19. Con cinco enlaces mas el CTA la fila ya no entra: abajo de ~900px
     se parten en dos renglones "Sobre nosotros" y el boton, y el header crece de
     alto. Con cuatro enlaces el limite real eran ~800px, asi que tambien estaba
     justo; ahora hay aire. */
  .burger{display:block}

  /* ==== MENU DE CELULAR (2026-09-25) ====================================
     Antes era un panel blanco con cinco enlaces chicos; el estudio lo veia
     basico. Ahora es pantalla completa, en el navy de las secciones oscuras
     con sus mismos dos brillos (neon arriba a la derecha, violeta abajo).
     - Se abre como un circulo que crece desde la hamburguesa (clip-path; el
       JS pasa el centro en --bx/--by): el target del logo y los anillos del
       sitio. Es la unica animacion del menu, mas la entrada escalonada de los
       enlaces (--i en el HTML).
     - La seccion en pantalla (is-active, la marca initHeader al scrollear)
       va en neon y con el cohete: "estas aca".
     - Abajo, lo que se hace despues de leer: el CTA y el contacto directo.
     ⚠️ El nav vive DENTRO del header, y .hdr.scrolled lleva backdrop-filter,
     que atrapa a los hijos position:fixed en la caja del header (78px). Por
     eso el JS le pone .is-menu al header mientras el menu esta abierto -y
     hasta que termina de cerrarse-, que le saca el filtro y el fondo. El
     z-index:-1 lo deja debajo del logo y la X, dentro del header. */
  .nav{
    position:fixed;inset:0;z-index:-1;height:100vh;height:100dvh;
    flex-direction:column;align-items:stretch;gap:0;overflow-y:auto;
    padding:calc(var(--hdr-h) + 22px) 24px calc(24px + env(safe-area-inset-bottom));
    background:
      radial-gradient(120% 60% at 100% 0%,rgba(81,228,209,.18),rgba(81,228,209,0) 60%),
      radial-gradient(100% 55% at 0% 100%,rgba(104,67,225,.42),rgba(104,67,225,0) 65%),
      var(--navy);
    clip-path:circle(0px at calc(100% - var(--bx,38px)) var(--by,39px));
    visibility:hidden;
    transition:clip-path .5s cubic-bezier(.7,0,.25,1),visibility 0s .5s;
  }
  .nav.open{
    clip-path:circle(150vmax at calc(100% - var(--bx,38px)) var(--by,39px));
    visibility:visible;
    transition:clip-path .6s cubic-bezier(.7,0,.25,1),visibility 0s;
  }
  /* Alineados a la derecha, del lado de la X (pedido del estudio). El
     row-reverse pone el cohete a la IZQUIERDA del texto, para que el enlace
     activo no se corra y los cinco sigan terminando en la misma linea. */
  .hdr .nav>a:not(.btn),.hdr.scrolled .nav>a:not(.btn){
    display:flex;flex-direction:row-reverse;align-items:center;gap:12px;
    width:fit-content;align-self:flex-end;
    padding-block:10px;color:#fff;
    font-size:clamp(30px,8.8vw,38px);font-weight:700;letter-spacing:-.03em;line-height:1.08;
  }
  .hdr .nav>a.is-active,.hdr.scrolled .nav>a.is-active{color:var(--neon)}
  .nav a:not(.btn)::after{display:none}
  .nav__cohete{display:none;width:.62em;height:.62em;color:var(--neon);flex:none}
  .nav>a.is-active .nav__cohete{display:block}
  /* Entrada escalonada: al abrir, cada pieza llega con 50ms de diferencia
     despues de que el circulo arranco; al cerrar se van todas juntas. */
  .nav>*{opacity:0;translate:0 16px;transition:opacity .35s var(--ease),translate .35s var(--ease)}
  .nav.open>*{opacity:1;translate:0 0;transition-delay:calc(.16s + var(--i,0) * .05s)}
  /* Alto fijo en 64px -el que tenia con 17px de letra y 16px de padding-
     para que el texto crezca a 18.5px sin que crezca el boton. */
  .hdr .nav a.btn--solid,.hdr.scrolled .nav a.btn--solid{
    margin-top:auto;height:64px;padding:0 24px;
    display:flex;align-items:center;justify-content:center;
    font-size:18.5px;line-height:1;
    background:var(--orange);border-color:var(--orange);color:var(--navy);
  }
  /* La frase de la marca ocupa el hueco entre los enlaces y el CTA (2026-09-26):
     a la derecha, como los enlaces, y empujada abajo por el margin-top:auto;
     el CTA ya no lo necesita porque la frase lo lleva pegado. */
  .nav__lema{margin-top:auto;margin-bottom:14px;text-align:right;color:var(--on-dark-2);font-size:17px;font-weight:500}
  .hdr .nav a.btn--solid,.hdr.scrolled .nav a.btn--solid{margin-top:0}
  /* El aire minimo entre el ultimo enlace y el CTA, para cuando la pantalla
     es baja y el margin-top:auto del CTA queda en cero. */
  .nav>a[href="#contacto"]:not(.btn){margin-bottom:28px}
  .nav__extra{display:flex;gap:10px;margin-top:22px}  /* era 12: sube el CTA 10px */
  .hdr .nav .nav__dato,.hdr.scrolled .nav .nav__dato{
    flex:1;display:flex;align-items:center;justify-content:center;gap:9px;
    padding:13px 10px;border:1px solid rgba(255,255,255,.24);border-radius:999px;
    color:var(--on-dark);font-size:15.5px;font-weight:500;
  }
  .nav__dato svg{width:19px;height:19px}
  /* El header mientras el menu esta abierto: sin fondo ni filtro (ver arriba)
     y con el logo y la X en blanco, aunque se haya scrolleado. */
  .hdr.is-menu{background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none;box-shadow:none;border-bottom-color:transparent}
  .hdr.is-menu .logo-img--claro{display:block}
  .hdr.is-menu .logo-img--oscuro{display:none}
  .hdr.is-menu .burger span{background:#fff}
}
/* Fuera del menu de celular, el cohete y el contacto del menu no existen. */
@media (min-width:921px){ .nav__cohete,.nav__extra,.nav__lema{display:none} }
@media (max-width:760px){
  /* Cuatro chips en un renglon necesitan ~120px cada uno; abajo de 560px no hay
     lugar y el texto se parte en dos lineas. Pasan a 2x2. */
  .chips__row{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:520px){
  /* En dos columnas a este ancho el parrafo cae en renglones de ~22 caracteres
     y se lee picado. Una sola columna, aunque el bloque quede mas alto. */
  .steps4{grid-template-columns:1fr;gap:30px}
  /* Una tarjeta y pico a la vista: con dos, en un telefono no se ve ninguna. */
  .proj__rail{--n:1.15}
  /* En una columna no hay nada que alinear y el hueco se notaria. */
  .steps4 h3{min-height:0}
  .hero__cta{flex-direction:column;align-items:stretch}
  .hero__cta .btn{width:100%}
}

/* Sin esto, el reveal deja secciones invisibles para quien pide menos movimiento. */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms !important;transition-duration:.01ms !important}
  .js .up{opacity:1;transform:none}
  /* Sin movimiento la cinta queda quieta y se recorre deslizando, y la copia
     sobra. El animation:none es obligatorio: la regla de arriba deja la
     duracion en .01ms y, al ser infinita, la pista parpadearia. */
  .proj__track{animation:none !important;transform:none !important}
  .type__caret{animation:none !important;opacity:.65}
  .proj__rail{overflow-x:auto}   /* ya no lleva mascara: ver el bloque de .proj__rail */
  .proj__track li[aria-hidden="true"]{display:none}
  /* Lo mismo para la cinta de marcas, que no tiene JS que la frene. */
  .marcas__track{animation:none !important;transform:none !important}
  .marcas__rail{overflow-x:auto;-webkit-mask-image:none;mask-image:none}
  .marcas__track li[aria-hidden="true"]{display:none}
}
