/* ==========================================================================
   Componentes · nav, botones, chips, cards, pills
   ========================================================================== */

/* ------------------------------------------------------------------ NAV --- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  height: var(--nav-h);
  transition: background var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
/* El fondo ya no lo pinta la barra entera sino la pastilla de los links: al
   scrollear solo se refuerza un poco. */
.nav.is-stuck .nav__links {
  background: linear-gradient(180deg, rgb(255 255 255 / .94), rgb(255 255 255 / .74));
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / .95),
    inset 0 0 0 1px rgb(0 60 120 / .10),
    0 10px 28px rgb(0 40 90 / .13);
}

.nav__inner {
  position: relative;
  width: min(100% - 2 * var(--gutter), var(--container));
  height: 100%;
  margin-inline: auto;
  display: flex;
  align-items: center;
}

/* Pastilla que envuelve SOLO los tres links, centrada en la barra. */
.nav__links {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: calc(24 * var(--s));
  white-space: nowrap;
  padding: calc(10 * var(--s)) calc(44 * var(--s));
  border-radius: var(--r-pill);
  /* Efecto vidrio: el degradado de arriba hacia abajo simula la curvatura, el
     blur con saturacion levantada toma color de lo que pasa por detras, y el
     inset blanco de 1px arriba es el reflejo del borde. Los tres juntos son lo
     que lo hace leer como espejo y no como un rectangulo translucido. */
  background: linear-gradient(180deg, rgb(255 255 255 / .80), rgb(255 255 255 / .52));
  backdrop-filter: blur(18px) saturate(180%);
  -webkit-backdrop-filter: blur(18px) saturate(180%);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / .95),
    inset 0 0 0 1px rgb(0 60 120 / .07),
    0 8px 24px rgb(0 40 90 / .09);
  transition: background var(--t) var(--ease), box-shadow var(--t) var(--ease);
}

.nav__link {
  position: relative;
  padding: calc(6 * var(--s)) calc(4 * var(--s));
  font-size: var(--fs-nav);
  font-weight: 600;
  color: var(--ink-mute);
  transition: color var(--t-fast) var(--ease);
}
/* El diseño marca el link activo sólo con color y peso: sin subrayado. */
/* 18px bold no llega al umbral de "texto grande" (18.66px), así que el link
   activo usa el azul reforzado. */
.nav__link:hover { color: var(--blue-strong); }
.nav__link.is-active { color: var(--blue-strong); font-weight: 700; }

/* Arriba de todo se ve el logo completo; al scrollear queda solo el simbolo,
   que sigue siendo el enlace al inicio. Las dos imagenes van apiladas en la
   misma celda de grilla para que el cruce sea un fundido y no un salto: si se
   alternara con display, la barra cambiaria de ancho de golpe. */
.nav__brand {
  margin-left: auto;
  display: grid;
  place-items: center end;
}
.nav__brand img {
  grid-area: 1 / 1;
  height: auto;
  transition: opacity var(--t) var(--ease), transform var(--t) var(--ease-out);
}
.nav__brand-full { width: calc(198 * var(--s)); }
/* Mismo alto que el logotipo para que el cambio no mueva nada en vertical. */
.nav__brand-icon {
  width: calc(78 * var(--s));
  opacity: 0;
  transform: scale(.9);
}
.nav.is-stuck .nav__brand-full { opacity: 0; transform: scale(.94); }
.nav.is-stuck .nav__brand-icon { opacity: 1; transform: none; }

.nav__burger {
  display: none;
  position: relative;
  z-index: 2;
  width: 44px; height: 44px;
  margin-left: 16px;
  border-radius: 12px;
}
.nav__burger span {
  display: block;
  width: 22px; height: 2px;
  margin: 5px auto;
  border-radius: 2px;
  background: var(--blue);
  transition: transform var(--t) var(--ease), opacity var(--t-fast) var(--ease);
}
.nav__burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav__burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* -------------------------------------------------------------- BOTONES --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: var(--btn-h);
  padding-inline: calc(33 * var(--s));   /* botón = 177px de ancho en el diseño */
  border-radius: var(--r-pill);
  font-family: var(--font-text);
  font-size: var(--fs-btn);
  font-weight: 700;
  white-space: nowrap;
  transition: transform var(--t) var(--ease), background var(--t) var(--ease),
              color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}

.btn--primary {
  background: var(--blue-strong);   /* texto de 15px bold: necesita 4.5:1 */
  color: #fff;
  box-shadow: 0 calc(8 * var(--s)) calc(22 * var(--s)) rgba(0, 111, 255, .26);
}
.btn--primary:hover {
  transform: translateY(calc(-2 * var(--s)));
  box-shadow: 0 calc(14 * var(--s)) calc(30 * var(--s)) rgba(0, 111, 255, .34);
}

.btn--ghost {
  color: var(--blue-strong);
  box-shadow: inset 0 0 0 calc(1.4 * var(--s)) var(--blue-soft);
}
.btn--ghost:hover {
  background: var(--blue-strong);
  color: #fff;
  box-shadow: inset 0 0 0 calc(1.4 * var(--s)) var(--blue-strong);
  transform: translateY(calc(-2 * var(--s)));
}

.btn:active { transform: translateY(0) scale(.985); }

/* ---------------------------------------------------------------- CHIPS --- */
.chip {
  display: inline-flex;
  align-items: center;
  gap: calc(8 * var(--s));
  height: var(--chip-h);
  padding-inline: calc(16 * var(--s));
  border-radius: var(--r-pill);
  background: var(--chip-bg);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--fs-chip);
  font-weight: 600;
  line-height: 1;
  /* Borde apenas marcado, como el del componente de referencia. */
  box-shadow: inset 0 0 0 1px rgb(18 26 34 / .06);
}

/* ---- Brillo que recorre la pastilla ---------------------------------------
   El componente de referencia hace el barrido SOBRE EL TEXTO, bajandole la
   opacidad. Aca no se puede: el chip mide 13.2px en peso 600, o sea que pide
   4.5:1 y esta en 4.96 — con el texto al 70% cae a 2.81. Y aclararlo tampoco
   es opcion: el margen hasta 4.5 da para ir de #606060 a #666666, un cambio
   que no se ve.
   Asi que el brillo recorre el FONDO y el texto conserva su color exacto.
   Va en un pseudo-elemento detras del contenido (por eso isolation + z-index
   negativo): encima lavaria el texto.                                        */
.chip { position: relative; isolation: isolate; overflow: hidden; }
.chip::after {
  content: '';
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  width: 42%;
  background: linear-gradient(90deg, transparent, var(--chip-sheen, rgb(255 255 255 / .95)), transparent);
  animation: chipShine 6.5s ease-in-out infinite;
  pointer-events: none;
}
@keyframes chipShine {
  0%        { transform: translateX(-160%); }
  55%, 100% { transform: translateX(360%); }
}

.chip--live {
  background: var(--chip-live-bg);
  color: var(--blue-strong);
  font-weight: 700;
  /* El fondo de este chip es casi blanco: un destello blanco no se veria. */
  --chip-sheen: rgb(0 111 255 / .14);
}
.chip__dot {
  width: calc(7 * var(--s));
  height: calc(7 * var(--s));
  border-radius: 50%;
  background: var(--blue);
  animation: chipPulse 1.9s var(--ease) infinite;
}
@keyframes chipPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(0, 111, 255, .55); }
  70%      { box-shadow: 0 0 0 calc(7 * var(--s)) rgba(0, 111, 255, 0); }
}

/* ----------------------------------------------------------- PILL GRANDE -- */
.pill {
  display: inline-flex;
  align-items: center;
  gap: calc(28 * var(--s));
  padding: calc(25 * var(--s)) calc(24 * var(--s)) calc(25 * var(--s)) calc(58 * var(--s));
  border-radius: var(--r-pill);
  background: var(--chip-bg);
  color: var(--ink);
  font-size: calc(48 * var(--s));   /* pastilla de 398px de ancho en el diseño */
  line-height: 1;
  transition: transform var(--t) var(--ease), background var(--t) var(--ease);
}
.pill:hover { transform: translateY(calc(-3 * var(--s))); background: rgba(18, 26, 34, .10); }
.pill:hover .pill__icon { transform: rotate(-45deg) scale(1.06); }

.pill__icon {
  display: grid;
  place-items: center;
  width: calc(56 * var(--s));
  height: calc(56 * var(--s));
  border-radius: 50%;
  background: var(--blue);
  transition: transform var(--t) var(--ease-out);
}
.pill__icon svg { width: 56%; height: 56%; }

.pill--light {
  gap: 0;
  padding: calc(24 * var(--s)) calc(48 * var(--s));
  background: #fff;
  color: var(--ink);
  font-size: calc(40 * var(--s));
}
.pill--light:hover { background: #fff; transform: translateY(calc(-3 * var(--s))) scale(1.015); }

/* ---------------------------------------------------------------- CARDS --- */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--r-card);
  background: var(--card);
  box-shadow: var(--shadow-card);
  /* Las tres van juntas a propósito: este shorthand tiene la misma especificidad
     que el de [data-reveal] y se declara después, así que lo pisa. Si acá sólo
     pusiéramos box-shadow, las cards entrarían de golpe (sin fundido ni
     desplazamiento) y perderían el escalonado de data-reveal-delay. */
  transition:
    opacity calc(var(--t-reveal) * 0.7) var(--ease-out) var(--reveal-delay, 0ms),
    transform var(--t-reveal) var(--ease-out) var(--reveal-delay, 0ms),
    box-shadow var(--t) var(--ease-out);
}
/* La card NO se mueve: el hover sólo eleva la sombra y hace crecer el mockup
   de adentro. Antes subía 6px y a pedido se saca ese desplazamiento. */
.card:hover { box-shadow: var(--shadow-lift); }

.card__media {
  overflow: hidden;
  flex: 0 0 auto;
}
.card__media img {
  width: 100%;
  transition: transform var(--t-slow) var(--ease-out);
}
.card:hover .card__media img { transform: scale(1.035); }

/* En el diseño el mockup de la 2ª card ancla a la derecha y arranca 30px más
   abajo, para que los dos títulos de la fila queden alineados. */
.card__media--right {
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;
  padding-top: calc(27 * var(--s));
}
.card__media--right img { width: 88%; }

/* El texto crece en hover con scale, NO con font-size: el font-size cambiaría el
   alto del contenido y con él el de la card, y eso volvería a mover el grid
   entero. El transform no toca el layout.
   El origen es el borde izquierdo para que el texto crezca "hacia afuera" desde
   su alineación, sin despegarse del margen; y en vertical desde el centro, así
   el título no se come el hueco que lo separa del párrafo.

   Se escala el bloque ENTERO (.card__body), no el título y el párrafo por
   separado. Con piezas separadas el título de dos líneas no puede crecer nada:
   entre su última línea y el párrafo hay sólo 5.8px, así que al agrandarse se lo
   come (con escala 1.18 el solape medido era de 1.6px). Escalando el contenedor,
   ese hueco crece en la misma proporción y el solape es imposible.

   El origen es arriba-izquierda porque ahí no hay lugar: arriba está el mockup a
   pocos px y a la izquierda el margen de la card. El crecimiento se va entonces
   hacia abajo y hacia la derecha, que es donde queda aire (~24px de margen
   inferior).

   El techo NO es estético sino geométrico: la card tiene overflow:hidden, así que
   pasado cierto punto el texto se recorta. Medido con el ancho real de los glifos
   (dejando 10px sin usar contra el borde), el máximo por viewport es 1.18 a
   1750px · 1.15 a 1201 · 1.11 a 1024 · 1.04 a 900. El cuello de botella siempre
   es el párrafo de "Integraciones y automatización", que es el más largo. Por eso
   la escala es una variable que baja por breakpoint. */
.card { --card-zoom: 1.05; }
.card__body {
  /* Crece hacia ARRIBA: con el origen abajo, la ultima linea de texto queda
     clavada y el bloque se estira hacia el mockup, que es donde el crecimiento
     no se lee como que el texto se escapa de la tarjeta.
     Medido a 1440: 8px de aire hasta el mockup y 23px hasta el borde inferior,
     con 12-14px de crecimiento. Por eso el zoom baja de 1.12 a 1.05: con 1.12
     el titulo se metia ~6px dentro del mockup. */
  transform-origin: left bottom;
  transition: transform var(--t) var(--ease-out);
}
.card:hover .card__body { transform: scale(var(--card-zoom)); }

.card__title {
  margin: calc(12 * var(--s)) calc(55 * var(--s)) 0;
  font-size: var(--fs-card-title);
  line-height: 1.2;
  /* 24px sólo al ancho de diseño; abajo escala y deja de ser "texto grande" */
  color: var(--blue-strong);
}
.card__text {
  margin: calc(10 * var(--s)) calc(55 * var(--s)) calc(29 * var(--s));
  font-size: var(--fs-card-text);
  line-height: var(--lh-card-text);
  font-weight: 500;
  color: var(--ink);
}
/* En las cards anchas el texto no ocupa todo el ancho: corta en 2 líneas */
.card--wide .card__text { max-width: calc(430 * var(--s)); }

/* --------------------------------------------------------- TARJETA CASO --- */
.work-card {
  position: relative;
  flex: 0 0 auto;
  width: calc(356 * var(--s));
  height: calc(458 * var(--s));
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: calc(32 * var(--s));
  border-radius: var(--r-card);
  background: var(--blue-card);
  overflow: hidden;
  transition: transform var(--t-case) var(--ease-out), background var(--t-case) var(--ease);
}
.work-card:hover { background: #0B6FF2; transform: translateY(calc(-8 * var(--s))); }

.work-card > img {
  /* width fija en vez de max-width: los logos recortados tienen lienzos mas
     chicos que el tope, y con max-width se quedaban en su tamano intrinseco
     (Winefor a 91px contra los 129px del resto). object-fit: contain evita
     deformacion si max-height llega a recortar la caja. */
  width: 62%;
  max-height: calc(120 * var(--s));
  object-fit: contain;
  transition: transform var(--t-case) var(--ease-out);
}
.work-card:hover > img { transform: scale(1.05); }

.work-card__cta {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(34 * var(--s));
  display: inline-flex;
  align-items: center;
  gap: calc(14 * var(--s));
  color: #fff;
  /* 19px bold entra en "texto grande" (≥18.66px): 3.89:1 sobre la tarjeta
     azul cumple el mínimo de 3:1. A 17px habría necesitado 4.5:1. */
  font-size: calc(19 * var(--s));
  font-weight: 700;
}
.work-card__cta span {
  display: inline-block;
  transition: transform var(--t-case) var(--ease-out);
}
.work-card:hover .work-card__cta span { transform: translateX(calc(8 * var(--s))); }

/* Hover con la captura del proyecto. Sólo las tarjetas marcadas .has-shot; el
   resto conserva el hover plano hasta que tengan su imagen. */
.work-card > .work-card__shot {
  position: absolute;
  inset: 0;
  /* Gana en especificidad a `.work-card > img`, que la limitaría al 62%. */
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.06);
  transition: opacity var(--t-case) var(--ease-out), transform var(--t-case) var(--ease-out);
}
.work-card:hover > .work-card__shot { opacity: 1; transform: scale(1); }

/* Velo azul sobre la captura: el collage es claro y tanto el logo como
   "Ver caso" son blancos. Sin esto el texto se pierde en las zonas claras. */
.work-card.has-shot::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Alfas medidos, no elegidos a ojo: sobre este collage el blanco da 1.27:1
     sin velo. Con estos valores "Ver caso" (19px bold) llega a 4.8 y el logo
     del centro a 3.2, contra el 3:1 que pide AA para texto grande y gráficos. */
  background: linear-gradient(180deg,
    rgba(0, 84, 208, .34) 0%,
    rgba(0, 74, 192, .58) 55%,
    rgba(0, 58, 160, .76) 100%);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-case) var(--ease-out);
}
.work-card.has-shot:hover::after { opacity: 1; }

/* Logo y CTA por encima de la captura y del velo. */
.work-card > img:not(.work-card__shot) { position: relative; z-index: 2; }
.work-card__cta { z-index: 2; }

/* Clasificación de la empresa, sobre el logo y sólo en hover.
   Va en absolute a propósito: si fuera un item más del flex, el logo se
   correría hacia abajo al aparecer, y en la referencia se queda quieto.
   --tag-lift = medio logo + aire; se ajusta por tarjeta si el logo es más
   alto o más bajo que el de Ligier (100px). */
.work-card__tag {
  --tag-lift: calc(62 * var(--s));
  position: absolute;
  left: 50%;
  bottom: calc(50% + var(--tag-lift));
  transform: translate(-50%, 6px);
  z-index: 2;
  padding: calc(5 * var(--s)) calc(15 * var(--s));
  border-radius: 999px;
  /* Pill opaco y --blue-strong: con el azul de marca sobre blanco al 94% el
     texto daba 4.13:1 y a 15px bold hace falta 4.5. Así da 5.27. */
  background: #fff;
  color: var(--blue-strong);
  font-size: calc(15 * var(--s));
  font-weight: 700;
  line-height: 1.3;
  white-space: nowrap;
  opacity: 0;
  transition: opacity var(--t-case) var(--ease-out), transform var(--t-case) var(--ease-out);
}
.work-card:hover .work-card__tag { opacity: 1; transform: translate(-50%, 0); }

/* ================================================================= INTRO ===
   Pantalla de carga y vuelo diagonal del isotipo hasta el hueco del logotipo
   del nav. Portado del loader del sitio 2025 (React): mismos tiempos, mismas
   curvas; lo que cambia es la paleta (allá era un telón azul con el logo
   blanco, acá es el fondo claro del sitio con el logo azul).

   El overlay sólo existe si el script del <head> habilitó el intro
   (html.intro-on). Sin JS, o con prefers-reduced-motion, la clase nunca se
   agrega: queda en display:none y la página se ve normal desde el primer frame.
   ========================================================================== */
.intro { display: none; }

html.intro-on .intro {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 900;            /* nav = 100, skip-link = 200 */
  pointer-events: auto;    /* se traga los clicks mientras dura */
}

/* El disco arranca cubriendo todo y se cierra sobre el centro. Al ser del color
   del fondo, lo que se revela es el contenido, no un cambio de color. */
.intro__disc {
  position: fixed;
  inset: 0;
  background: var(--bg-top);
  clip-path: circle(150% at 50% 50%);
  transition: clip-path var(--intro-t-disc) var(--intro-ease-disc);
  will-change: clip-path;
}
.intro.is-out .intro__disc { clip-path: circle(0% at 50% 50%); }

.intro__layer { position: fixed; inset: 0; }

/* El centrado vive en el ancla y el movimiento en el mover: así dx/dy salen en
   px reales, sin quedar afectados por el scale. */
.intro__anchor {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* 164px es el tamaño que tenía el logo del loader viejo (caja de 180px con la
   imagen en object-fit:contain). No usa --s a propósito: en el sitio viejo el
   logo del loader medía lo mismo en todos los viewports. */
.intro__mover {
  --intro-w: min(164px, 44vw);
  position: relative;
  width: var(--intro-w);
  height: calc(var(--intro-w) * 108 / 211);
  transition: transform var(--intro-t-move) var(--intro-ease-move);
  will-change: transform;
}

.intro__mark {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 220ms ease;
}
.intro.is-still .intro__mark { opacity: 1; }

/* El gif va como background y no como <img> para que NO se descargue cuando el
   intro no corre: display:none no frena un <img src>, sí frena un background.
   Está dibujado sobre un lienzo de 520x271 con márgenes propios, así que estas
   cuatro medidas lo encajan sobre el isotipo del SVG y el crossfade no mueve un
   píxel. Salen de las cajas de tinta reales: gif 472x220 dentro de 520x271,
   svg 211.292x98.312 dentro del viewBox 211x108.

   El gif se recoloreó al copiarlo del sitio 2025: allá era #0069DB y se pintaba
   de blanco por CSS, acá va en el azul del sitio. Se editó su paleta (tenía un
   único color plano, sin antialiasing) en vez de usar un filter, para que el
   crossfade con el SVG no cambie de tono. Si alguna vez se vuelve a copiar el
   original, hay que repetir ese recoloreo a var(--blue). */
.intro__gif {
  position: absolute;
  left:   calc(var(--intro-w) * -0.0453);
  top:    calc(var(--intro-w) * -0.0368);
  width:  calc(var(--intro-w) *  1.1032);
  height: calc(var(--intro-w) *  0.5749);
  transition: opacity 180ms ease;
}
html.intro-on .intro__gif {
  background: url(../assets/logos/mangoo-loading.gif) center / contain no-repeat;
}
.intro.is-nogif .intro__gif { opacity: 0; }

/* Mientras dura el intro, el logotipo del nav se dibuja SIN el isotipo: ese
   hueco es el que viene a llenar el volador (igual que el sitio viejo, que
   componía el logo con tres imágenes y dejaba la del medio en opacity:0).
   La banda va de 48.93% a 69.45% del ancho de la imagen, que es donde cae el
   "oo": la "g" termina en x=578.99 y el punto arranca en x=793.15 del viewBox. */
html.intro-on .nav__brand-full {
  -webkit-mask-image: linear-gradient(90deg, #000 0 48.93%, transparent 48.93% 69.45%, #000 69.45% 100%);
          mask-image: linear-gradient(90deg, #000 0 48.93%, transparent 48.93% 69.45%, #000 69.45% 100%);
}
html.intro-on.intro-brand-open .nav__brand-full {
  -webkit-mask-image: none;
          mask-image: none;
}
