/* Color, tipografía, espacio y movimiento viven en `tokens.css`, que
   se enlaza antes que esta hoja y comparte con el panel de admin.
   Aquí solo quedan los estilos del sitio público. */

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
p { margin: 0; }
h1, h2, h3 { margin: 0; font-weight: 500; letter-spacing: -0.01em; }
ul { margin: 0; padding: 0; list-style: none; }
img { display: block; max-width: 100%; height: auto; }

/* ═══════════ Layout ═══════════ */
.layout {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
}

/* ═══════════ Botones ═══════════ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 13px 24px;
  border: 1px solid transparent;
  border-radius: 999px;
  font-family: var(--font);
  font-size: 15px;
  font-weight: 500;
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.btn:hover { transform: translateY(-1px); }
/* Naranja sólido: la acción principal de la página. */
.btn--primary {
  background: var(--btn-fill);
  color: #fff;
  font-weight: 700;
}
.btn--primary:hover { background: var(--btn-fill-hover); }

/* La flecha se separa un punto al pasar el cursor: refuerza que el
   botón lleva a algún sitio. */
.btn__arrow {
  width: 15px;
  height: 15px;
  flex: none;
  transition: transform var(--t-base) var(--ease);
}
.btn:hover .btn__arrow { transform: translateX(3px); }

/* «Hablemos»: naranja sólido a todo el ancho de la barra, con peso
   normal. Se diferencia de `.btn--primary` en el ancho y en que no va
   en negrita, no en el color. */
.btn--cta {
  width: 100%;
  background: var(--btn-fill);
  color: #fff;
  font-weight: 500;
}
.btn--cta:hover { background: var(--btn-fill-hover); }
.btn--light { background: #fff; color: var(--text); }
.btn--outline { border-color: rgba(255, 255, 255, 0.4); color: #fff; }
.btn--outline:hover { border-color: #fff; background: rgba(255, 255, 255, 0.1); }

/* ═══════════ Sidebar ═══════════ */
.sidebar {
  position: sticky;
  top: 0;
  align-self: start;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 32px;
  padding: 28px 32px 24px;
  overflow: hidden;
}

.avatar {
  position: relative;
  width: 72px;
  height: 72px;
  border-radius: 50%;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--border);
  display: grid;
  place-items: center;
  margin-bottom: 24px;
  /* El doble clic abre el panel de administración (script.js). Sin esto
     el gesto dejaría el logo resaltado en azul. */
  user-select: none;
  -webkit-user-select: none;
}
/* El logo es una marca negra sobre blanco: se muestra completo y con aire,
   no recortado como una fotografía. */
.avatar img {
  width: 78%;
  height: 78%;
  object-fit: contain;
}

.intro__title {
  font-family: var(--display);
  font-size: clamp(26px, 2.1vw, 32px);
  font-weight: 600;
  line-height: 1.16;
  letter-spacing: -0.03em;
  margin-bottom: 16px;
  /* Evita que la última palabra caiga sola en una línea. */
  text-wrap: balance;
}
.intro__bio {
  font-size: 15px;
  line-height: 1.55;
  color: var(--text-muted);
  margin-bottom: 26px;
  max-width: 318px;
}

.sidebar__bottom { display: flex; flex-direction: column; gap: 26px; }

.sidenav { display: flex; flex-direction: column; gap: 9px; }
.sidenav__link {
  display: flex;
  align-items: center;
  gap: 9px;
  width: fit-content;
  font-size: 16px;
  color: var(--text-faint);
  transition: color 0.18s ease;
}
/* El salto de inactivo a activo tiene que verse: gris medio → negro
   con peso. Antes los tres estados quedaban casi indistinguibles. */
.sidenav__link:hover { color: var(--text); }
.sidenav__link.is-active { color: var(--text); font-weight: 500; }
.sidenav__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  /* Entra creciendo desde el centro, no apareciendo de golpe. */
  transform: scale(0.4);
  transition: opacity var(--t-base) var(--ease),
              transform var(--t-slow) var(--ease-out);
}
.sidenav__link.is-active .sidenav__dot { opacity: 1; transform: scale(1); }

/* Tira de logos */
/* El desvanecido a los lados es simétrico y más largo por la derecha:
   con el corte anterior al 88% el último chip aparecía tajado en seco
   y parecía un fallo de maquetación, no un degradado. */
.clients {
  overflow: hidden;
  /* Aire arriba y abajo para que el chip tenga adónde subir en hover:
     con `overflow: hidden` y sin holgura, esos 2px quedaban fuera de la
     caja y el logo aparecía cortado por el borde superior. El margen
     negativo devuelve el espacio y deja la tira donde estaba. */
  padding: 6px 0;
  margin: -6px 0;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 80%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 10%, #000 80%, transparent);
}
.clients__track {
  display: flex;
  gap: 10px;
  animation: marquee 28s linear infinite;
  width: max-content;
}
.clients:hover .clients__track { animation-play-state: paused; }
@keyframes marquee {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .clients__track { animation: none; }
  .clients { overflow-x: auto; }
}
/* A todo color. El `title` de cada uno dice de qué proyecto se trata,
   que antes había que adivinar. */
.chip {
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 11px;
  display: grid;
  place-items: center;
  font-size: 11px;
  font-weight: 600;
  color: #fff;
  letter-spacing: 0.02em;
  cursor: default;
  transition: transform var(--t-base) var(--ease);
}
.chip:hover { transform: translateY(-2px); }
.chip--1 { background: #1e3a8a; }
.chip--2 { background: #7c3aed; }
.chip--3 { background: #ea580c; }
.chip--4 { background: #0f766e; }
.chip--5 { background: #be123c; }
.chip--6 { background: #334155; }
.chip--7 { background: #15803d; }
.chip--8 { background: #0369a1; }
.chip--9 { background: #a16207; }
.chip--10 { background: #4d7c0f; }
/* Chips con logo real: fondo blanco para que la marca se lea. */
.chip--img {
  background: #fff;
  border: 1px solid var(--border);
  padding: 7px;
}
.chip--img img { width: 100%; height: 100%; object-fit: contain; }

.sidebar__footer {
  display: flex;
  align-items: center;
  gap: 26px;
  font-size: 13px;
  color: var(--text-faint);
}
.sidebar__footer a { transition: color 0.18s ease; }
.sidebar__footer a:hover { color: var(--text); }

/* ═══════════ Columna derecha ═══════════ */
.content {
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  padding: var(--gap) var(--gap) var(--gap) 0;
  min-width: 0;
}
.stack { display: flex; flex-direction: column; gap: var(--gap); }
.pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
}

/* ═══════════ Tarjetas de proyecto ═══════════ */
.card {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  color: #fff;
  display: flex;
  flex-direction: column;
  min-height: 420px;
}
.card--wide {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.95fr);
  align-items: center;
  min-height: 480px;
}
.card__body { padding: 44px 40px; display: flex; flex-direction: column; align-items: flex-start; }
.card--wide .card__body { padding: 48px 8px 48px 44px; }

.card__logo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--display);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: auto;
  padding-bottom: 40px;
}
.card__logo-mark { display: block; width: 24px; color: #fff; }
.card__logo-mark svg { display: block; width: 100%; height: auto; }
.card__logo-sub { font-weight: 500; opacity: 0.75; }
.card__title {
  font-family: var(--display);
  font-size: clamp(23px, 2vw, 31px);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: -0.025em;
  max-width: 20ch;
  margin-bottom: 22px;
}
.tags { display: flex; flex-wrap: wrap; gap: 8px; }
.tags li {
  padding: 6px 12px;
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.16);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.card__link {
  margin-top: 38px;
  font-size: 15px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.45);
  padding-bottom: 2px;
  transition: border-color 0.18s ease;
}
.card__link:hover { border-color: #fff; }

/* Dos acciones: leer el caso o abrir el sitio en vivo */
.card__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 12px 26px;
  margin-top: 38px;
}
.card__actions .card__link { margin-top: 0; }
.card__link--site {
  color: rgba(255, 255, 255, 0.78);
  border-bottom-color: transparent;
}
.card__link--site:hover {
  color: #fff;
  border-bottom-color: rgba(255, 255, 255, 0.45);
}
.card__soon {
  margin-top: 30px;
  font-size: 15px;
  color: rgba(255, 255, 255, 0.82);
}

/* Aliados Contables — colores de marca reales del sitio */
.card--aliados { background: linear-gradient(150deg, #24407a, #1b2f5e 58%, #12203f); }
.card--aliados.card--wide { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr); }
.card--aliados .tags li { background: rgba(232, 132, 43, 0.22); }
.card--aliados .card__link:not(.card__link--site) { border-color: rgba(232, 132, 43, 0.65); color: #f5a24f; }
.card--aliados .card__link:not(.card__link--site):hover { border-color: #e8842b; }
.card--aliados .card__link--site:hover { border-bottom-color: rgba(232, 132, 43, 0.65); }

.card--teal   { background: linear-gradient(150deg, #14b8a6, #0f766e 62%, #115e59); }
.card--indigo { background: linear-gradient(150deg, #4f46e5, #312e81 65%, #1e1b4b); }
/* SenderMTB: tierra outdoor, tomado del sitio real. */
.card--amber  { background: linear-gradient(150deg, #8a6034, #5c3f24 62%, #2e2117); }
.card--amber .tags li { background: rgba(208, 154, 99, 0.24); }
.card--amber .card__link:not(.card__link--site) { border-color: rgba(208, 154, 99, 0.65); color: #e0b184; }
.card--amber .card__link:not(.card__link--site):hover { border-color: #e0b184; }
.card--amber .card__link--site:hover { border-bottom-color: rgba(208, 154, 99, 0.65); }
.card--rose   { background: linear-gradient(150deg, #fb7185, #be123c 66%, #881337); }
.card--violet { background: linear-gradient(150deg, #a855f7, #7e22ce 64%, #4c1d95); }
.card--slate  { background: linear-gradient(150deg, #475569, #1e293b 66%, #0f172a); }
.card--green  { background: linear-gradient(150deg, #4ade80, #15803d 62%, #14532d); }
/* NZ Bikefitter: azul noche casi negro con acento celeste, como el sitio real. */
.card--nz     { background: linear-gradient(150deg, #1c2b3d, #101a26 58%, #070c12); }
.card--nz .tags li { background: rgba(96, 165, 250, 0.2); }
.card--nz .card__link:not(.card__link--site) { border-color: rgba(96, 165, 250, 0.6); color: #60a5fa; }
.card--nz .card__link:not(.card__link--site):hover { border-color: #60a5fa; }
.card--nz .card__link--site:hover { border-bottom-color: rgba(96, 165, 250, 0.6); }
.card__logo--nz { display: block; letter-spacing: 0.06em; line-height: 1; }
.card__logo--nz span {
  display: block;
  margin-top: 5px;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.36em;
  text-transform: uppercase;
  opacity: 0.6;
}

/* Mockups (reemplazables por imágenes) */
.shot { position: relative; }
.shot--wide {
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  padding: 40px 34px;
}
.shot--flush {
  margin: 0 26px;
  height: 190px;
  border-radius: 12px 12px 0 0;
  background: #fbfbfa;
  overflow: hidden;
  box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.05), 0 22px 46px rgba(0, 0, 0, 0.22);
}
.card:not(.card--wide) .shot--flush { margin-top: auto; }
.shot--flush img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}

.phone {
  flex: none;
  width: 158px;
  aspect-ratio: 9 / 18.5;
  border-radius: 26px;
  background: #101114;
  padding: 6px;
  box-shadow: 0 24px 48px rgba(0, 0, 0, 0.3);
}
.phone span {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 21px;
  background: linear-gradient(170deg, rgba(255, 255, 255, 0.95), rgba(255, 255, 255, 0.72));
}
.phone--a { transform: translateY(-14px) rotate(-2deg); }
.phone--b { transform: translateY(26px) rotate(3deg); }

/* Maqueta de sitio web (Aliados Contables) */
.site {
  width: 100%;
  max-width: 430px;
  border-radius: 12px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 26px 54px rgba(0, 0, 0, 0.34);
  font-size: 0;
}
.site__bar {
  display: flex;
  gap: 5px;
  padding: 9px 12px;
  background: #eceef2;
}
.site__bar i { width: 7px; height: 7px; border-radius: 50%; background: #c3c8d2; }
.site__nav {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 11px 14px;
  background: #1b2f5e;
}
.site__nav b { width: 42px; height: 9px; border-radius: 3px; background: #fff; }
.site__nav u { width: 22px; height: 5px; border-radius: 3px; background: rgba(255, 255, 255, 0.5); }
.site__nav u:first-of-type { background: rgba(255, 255, 255, 0.9); }
.site__nav s { width: 46px; height: 14px; border-radius: 999px; background: #e8842b; margin-left: auto; }
.site__hero {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  padding: 16px 14px 18px;
  align-items: center;
}
.site__copy { display: flex; flex-direction: column; gap: 6px; }
.site__copy em { width: 54px; height: 4px; border-radius: 2px; background: #e8842b; }
.site__copy h4 { height: 11px; border-radius: 3px; background: #1b2f5e; }
.site__copy h4.is-short { width: 62%; }
.site__copy p { height: 5px; border-radius: 3px; background: #cdd3de; margin-top: 2px; }
.site__copy p.is-short { width: 74%; }
.site__copy s { width: 74px; height: 15px; border-radius: 999px; background: #e8842b; margin-top: 6px; }
.site__media {
  aspect-ratio: 4 / 3;
  border-radius: 8px;
  background: linear-gradient(140deg, #dbe3f0, #b9c6dd 60%, #96a7c6);
}
.site__stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  padding: 12px 14px;
  background: #1b2f5e;
}
.site__stats span { height: 9px; border-radius: 3px; background: #e8842b; opacity: 0.9; }

/* Captura real dentro de una tarjeta de proyecto */
.shot__frame {
  margin: 0;
  width: 100%;
  max-width: 440px;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 26px 54px rgba(0, 0, 0, 0.4);
}
.shot__frame img { width: 100%; display: block; }

.browser { padding: 14px 16px; display: flex; flex-direction: column; gap: 11px; }
.browser span {
  display: block;
  height: 12px;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.09);
}
.browser span:first-child { width: 46%; background: rgba(0, 0, 0, 0.16); height: 16px; }
.browser span:nth-child(2) { width: 88%; }
.browser span:nth-child(3) { width: 70%; }

/* ═══════════ Paneles claros ═══════════ */
.panel {
  background: var(--panel);
  border-radius: var(--radius);
  padding: 44px 44px 48px;
}
/* `display: grid` le gana a [hidden]: hay que devolvérselo explícitamente. */
[hidden] { display: none !important; }
.panel--split {
  display: grid;
  grid-template-columns: minmax(0, 0.34fr) minmax(0, 1fr);
  gap: 40px;
  align-items: start;
}
.panel__title {
  font-family: var(--display);
  font-size: clamp(26px, 2.2vw, 34px);
  font-weight: 600;
  line-height: 1.14;
  letter-spacing: -0.03em;
}
.panel:not(.panel--split) .panel__title { margin-bottom: 34px; }
.panel__lead {
  margin-top: 14px;
  font-size: 15px;
  color: var(--text-muted);
  line-height: 1.55;
}
.panel__aside { position: sticky; top: 22px; }

/* Acerca de */
.about {
  display: grid;
  grid-template-columns: minmax(0, 0.42fr) minmax(0, 1fr);
  gap: 40px;
  align-items: start;
}
.about__photo {
  position: relative;
  margin: 0;
  aspect-ratio: 3 / 4;
  border-radius: 16px;
  overflow: hidden;
  background: linear-gradient(168deg, #eff6ff, #dbeafe 55%, #c7dcf7);
  display: grid;
  place-items: center;
}
/* Multiply funde el fondo blanco del recorte con el degradado del marco.
   El degradado es claro a propósito: uno más oscuro tiñe la piel de azul. */
.about__photo img { mix-blend-mode: multiply; }
.about__photo-fallback {
  font-size: 13px;
  font-weight: 500;
  color: rgba(0, 0, 0, 0.4);
}
/* Solo se ve si la imagen falta (onerror la elimina del DOM). */
.about__photo:has(img) .about__photo-fallback { display: none; }
.about__photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* La foto ya viene recortada: se muestra completa, sin recortar la cabeza. */
  object-fit: contain;
  object-position: center bottom;
}

/* Filas reutilizables */
.rows { display: flex; flex-direction: column; }
.row { padding: 22px 0; border-bottom: 1px solid var(--border); }
.row:first-child { padding-top: 0; }
.row:last-child { border-bottom: 0; padding-bottom: 0; }
.row h3 {
  font-family: var(--display);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.015em;
  margin-bottom: 7px;
}
.row p { font-size: 15px; line-height: 1.55; color: var(--text-muted); }
.row--icon { display: grid; grid-template-columns: 44px minmax(0, 1fr); gap: 16px; }
.ico {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  display: grid;
  place-items: center;
  font-size: 19px;
  color: #fff;
}
.ico--blue { background: #2563eb; }
.ico--orange { background: #ea580c; }
.ico--pink { background: #db2777; }
.ico--cyan { background: #0891b2; }
.ico--dark { background: #18181b; }
.ico--green { background: #059669; }
.ico--violet { background: #7c3aed; }
.ico--lime { background: #65a30d; }

/* Experiencia */
.cv-card {
  display: block;
  position: relative;
  margin-top: 30px;
  padding: 18px 20px 20px;
  border-radius: 14px;
  background: #fff;
  box-shadow: 0 10px 26px rgba(0, 0, 0, 0.06);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.cv-card:hover { transform: translateY(-2px); box-shadow: 0 16px 34px rgba(0, 0, 0, 0.1); }
.cv-card__name {
  font-family: var(--display);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  text-align: center;
  margin-bottom: 4px;
}
.cv-card__meta {
  font-size: 10px;
  color: var(--text-faint);
  text-align: center;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.cv-card__label {
  display: block;
  margin: 14px 0 10px;
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.cv-card__cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 15px;
}
.cv-card__arrow {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: var(--text);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: 12px;
}

.jobs { display: flex; flex-direction: column; gap: 12px; }
.job {
  background: #fff;
  border-radius: 14px;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
}
.job__head {
  width: 100%;
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) auto auto;
  gap: 14px;
  align-items: center;
  padding: 14px 18px;
  background: none;
  border: 0;
  font: inherit;
  text-align: left;
  color: inherit;
  cursor: pointer;
}
.job__logo {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
}
/* Logos que ya traen su propio fondo: llenan el cuadrado, sin marco blanco. */
.job__logo--full { overflow: hidden; }
.job__logo--full img { width: 100%; height: 100%; object-fit: cover; }
.job__logo--a { background: #0f766e; }
.job__logo--b { background: #1d4ed8; }
.job__logo--c { background: #b45309; }
/* Logos reales: fondo blanco con borde suave, la marca respira dentro. */
.job__logo--img {
  background: #fff;
  border: 1px solid var(--border);
  padding: 5px;
}
.job__logo--img img { width: 100%; height: 100%; object-fit: contain; }
.job__body h3 { font-size: 16px; font-weight: 600; letter-spacing: -0.015em; }
.job__body p { font-size: 14px; color: var(--text-muted); }
.job__years { font-size: 14px; color: var(--text-muted); white-space: nowrap; }
.job__plus {
  font-size: 17px;
  color: var(--text-faint);
  transition: transform 0.2s ease;
}
.job__head[aria-expanded="true"] .job__plus { transform: rotate(45deg); }
.job__detail {
  padding: 0 18px 18px 72px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-muted);
}
.job__detail p + p { margin-top: 10px; }

/* ═══════════ CTA final ═══════════ */
/* ═══════════ Página de caso de estudio ═══════════ */
.case-body { background: #0d1b3e; }

.layout--case { background: #0d1b3e; }

.sidebar--case {
  background: #0d1b3e;
  color: #fff;
  justify-content: space-between;
  padding: 26px 34px 30px;
}
.case-side__top { display: flex; flex-direction: column; }

.back {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  font-size: 17px;
  margin-bottom: 34px;
  transition: background 0.18s ease;
}
.back:hover { background: rgba(255, 255, 255, 0.2); }

.case-side__logo {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-bottom: 24px;
}
.case-side__mark { display: block; width: 22px; color: #fff; }
.case-side__mark svg { display: block; width: 100%; height: auto; }

.case-side__title {
  font-size: clamp(26px, 2.2vw, 33px);
  font-weight: 600;
  line-height: 1.16;
  letter-spacing: -0.03em;
  margin-bottom: 20px;
}
.case-side__text {
  font-size: 14.5px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.66);
  margin-bottom: 14px;
}
.tags--case { margin-top: 12px; }
.tags--case li { background: rgba(255, 255, 255, 0.13); }

.case-meta { margin: 30px 0 0; display: flex; flex-direction: column; gap: 11px; }
.case-meta > div { display: flex; gap: 14px; align-items: baseline; }
.case-meta dt {
  width: 96px;
  flex: none;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.45);
}
.case-meta dd { margin: 0; font-size: 13.5px; color: #fff; }
.case-meta a { border-bottom: 1px solid rgba(255, 255, 255, 0.35); }
.case-meta a:hover { border-color: #fff; }

/* Variante NZ Bikefitter: azul noche casi negro con acento celeste */
.case-body--nz, .case-body--nz .layout--case, .case-body--nz .sidebar--case {
  background: #0a1017;
}
.case-body--nz .case-meta a { border-bottom-color: rgba(96, 165, 250, 0.5); }
.case-body--nz .case-meta a:hover { border-bottom-color: #60a5fa; border-color: #60a5fa; }
.case-side__logo--nz {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1;
}
.case-side__logo--nz span {
  display: block;
  margin-top: 6px;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.38em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}
/* Se escopan al body para ganarle a las reglas base, que vienen después. */
.case-body--nz .case-callout {
  background: #101a26;
  border: 1px solid rgba(96, 165, 250, 0.18);
}
.case-body--nz .case-callout strong { color: #60a5fa; }
.case-body--nz .result__num { color: #2563eb; }

/* Variante SenderMTB: tierra y outdoor */
.case-body--sender, .case-body--sender .layout--case, .case-body--sender .sidebar--case {
  background: #1f1a15;
}
.case-body--sender .case-meta a { border-bottom-color: rgba(184, 124, 74, 0.55); }
.case-body--sender .case-meta a:hover { border-bottom-color: #b87c4a; border-color: #b87c4a; }
.case-body--sender .case-callout {
  background: #2b231b;
  border: 1px solid rgba(184, 124, 74, 0.22);
}
.case-body--sender .case-callout strong { color: #d09a63; }
.case-body--sender .result__num { color: #a86a38; }

/* Variante VIDI: azul profundo con acento magenta y teal de la marca */
.case-body--vidi, .case-body--vidi .layout--case, .case-body--vidi .sidebar--case {
  background: #10202b;
}
.case-body--vidi .case-side__logo {
  font-size: 30px;
  font-weight: 700;
  letter-spacing: 0.1em;
}
.case-body--vidi .case-meta a { border-bottom-color: rgba(214, 31, 105, 0.55); }
.case-body--vidi .case-meta a:hover { border-bottom-color: #e84d8c; border-color: #e84d8c; }
.case-body--vidi .tags--case li { background: rgba(47, 138, 149, 0.3); }
.case-body--vidi .case-callout {
  background: #16303f;
  border: 1px solid rgba(47, 138, 149, 0.28);
}
.case-body--vidi .case-callout strong { color: #ff5fa2; }
.case-body--vidi .result__num { color: #d61f69; }

/* Variante Cuidapp: verde clínico sereno, tomado de la interfaz */
.case-body--cuidapp, .case-body--cuidapp .layout--case, .case-body--cuidapp .sidebar--case {
  background: #14261f;
}
.case-body--cuidapp .case-meta a { border-bottom-color: rgba(62, 122, 107, 0.55); }
.case-body--cuidapp .case-meta a:hover { border-bottom-color: #6bb39c; border-color: #6bb39c; }
.case-body--cuidapp .tags--case li { background: rgba(62, 122, 107, 0.32); }
.case-body--cuidapp .case-callout {
  background: #1d3830;
  border: 1px solid rgba(62, 122, 107, 0.26);
}
.case-body--cuidapp .case-callout strong { color: #6bb39c; }
.case-body--cuidapp .result__num { color: #3e7a6b; }

/* Variante FinPlus: azul noche del logo con acentos violeta y ámbar */
.case-body--finplus, .case-body--finplus .layout--case, .case-body--finplus .sidebar--case {
  background: #0d1330;
}
.case-body--finplus .case-meta a { border-bottom-color: rgba(240, 185, 89, 0.5); }
.case-body--finplus .case-meta a:hover { border-bottom-color: #f0b959; border-color: #f0b959; }
.case-body--finplus .tags--case li { background: rgba(88, 79, 216, 0.4); }
.case-body--finplus .case-callout {
  background: #151d45;
  border: 1px solid rgba(88, 79, 216, 0.35);
}
.case-body--finplus .case-callout strong { color: #f0b959; }
.case-body--finplus .result__num { color: #584fd8; }

/* Variante 820 Lab: negro taller con el naranja de la marca */
.case-body--820, .case-body--820 .layout--case, .case-body--820 .sidebar--case {
  background: #141210;
}
.case-body--820 .case-side__logo {
  font-size: 28px;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.case-body--820 .case-meta a { border-bottom-color: rgba(240, 90, 12, 0.55); }
.case-body--820 .case-meta a:hover { border-bottom-color: #f05a0c; border-color: #f05a0c; }
.case-body--820 .tags--case li { background: rgba(240, 90, 12, 0.26); }
.case-body--820 .case-callout {
  background: #241d18;
  border: 1px solid rgba(240, 90, 12, 0.3);
}
.case-body--820 .case-callout strong { color: #ff7a2f; }
.case-body--820 .result__num { color: #f05a0c; }

/* Columna derecha */
.case {
  background: #fff;
  border-radius: var(--radius);
  margin: var(--gap) var(--gap) var(--gap) 0;
  padding: 48px clamp(24px, 5vw, 64px) 72px;
  min-width: 0;
}

.case-hero {
  max-width: var(--case-media);
  margin: 0 auto 56px;
  aspect-ratio: 16 / 11;
  border-radius: 16px;
  background: linear-gradient(180deg, #eef4ff, #c5d8f8 60%, #a9c3f0);
  display: grid;
  place-items: center;
  overflow: hidden;
}
/* Con imagen real manda la captura, no el marco de relleno. */
.case-hero:has(img) {
  aspect-ratio: auto;
  background: none;
}
.case-hero__ph, .case-shot figcaption {
  font-size: 13px;
  color: rgba(0, 0, 0, 0.38);
}
.case-hero img, .case-shot img { border-radius: 16px; width: 100%; }

/* El contenido va centrado en la columna, con las imágenes más anchas
   que el texto (igual que la referencia). */
.case-block {
  max-width: 62ch;
  margin: 0 auto 52px;
}
.case-block .eyebrow {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 14px;
}
.case-block h2 {
  font-size: clamp(23px, 2.1vw, 30px);
  font-weight: 600;
  line-height: 1.24;
  letter-spacing: -0.025em;
  margin-bottom: 16px;
}
.case-block p {
  font-size: 16px;
  line-height: 1.68;
  color: var(--text-muted);
  margin-bottom: 14px;
}

.case-callout {
  background: #1b2f5e;
  color: #fff;
  border-radius: 16px;
  padding: 40px 44px;
  max-width: var(--case-media);
  margin: 0 auto 52px;
  text-align: center;
}
.case-callout p {
  font-size: clamp(18px, 1.8vw, 24px);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.02em;
  max-width: 34ch;
  margin: 0 auto;
}
.case-callout strong { font-weight: 600; color: #f5a24f; }

.case-shot {
  max-width: var(--case-media);
  margin: 0 auto 52px;
  padding: 26px;
  border-radius: 16px;
  background: var(--panel);
  display: grid;
  gap: 16px;
  justify-items: center;
}
.case-shot::before {
  content: "";
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 10px;
  background: linear-gradient(150deg, #ffffff, #dfe6f3);
  box-shadow: 0 14px 32px rgba(0, 0, 0, 0.1);
}
.case-shot:has(img)::before { display: none; }
.case-shot img {
  width: 100%;
  border-radius: 10px;
  box-shadow: 0 14px 32px rgba(0, 0, 0, 0.14);
}

/* Dos capturas lado a lado */
.case-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  max-width: var(--case-media);
  margin: 0 auto 52px;
}
.case-pair .case-shot { margin-bottom: 0; padding: 18px; }
@media (max-width: 760px) {
  .case-pair { grid-template-columns: 1fr; }
}

.case-results {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  max-width: var(--case-media);
  margin: 0 auto 52px;
}
.result {
  padding: 26px 22px;
  border-radius: 14px;
  background: var(--panel);
}
.result__num {
  font-size: 32px;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: #1b2f5e;
  margin-bottom: 6px;
}
.result__label { font-size: 14px; line-height: 1.5; color: var(--text-muted); }

.case-next {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  max-width: var(--case-media);
  margin: 0 auto;
  padding-top: 30px;
  border-top: 1px solid var(--border);
  font-size: 15px;
  font-weight: 500;
}
.case-next a { color: var(--text-muted); transition: color 0.18s ease; }
.case-next a:hover { color: var(--text); }

@media (max-width: 980px) {
  .sidebar--case {
    height: auto;
    min-height: 100dvh;
  }
  .case { margin: 16px; padding: 30px 22px 44px; }
  .case-results { grid-template-columns: 1fr; }
  .case-callout { padding: 30px 24px; }
}

/* ═══════════ Menú móvil ═══════════ */
.sidebar-toggle {
  display: none;
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 60;
  width: 44px;
  height: 44px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  border: 1px solid var(--border);
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(8px);
  cursor: pointer;
}
.sidebar-toggle span {
  width: 17px;
  height: 2px;
  border-radius: 2px;
  background: var(--text);
}
.scrim {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(0, 0, 0, 0.4);
}

/* ═══════════ Responsive ═══════════ */
@media (max-width: 1180px) {
  :root { --sidebar-w: 340px; }
  .card__body { padding: 36px 32px; }
  .card--wide .card__body { padding: 40px 4px 40px 34px; }
  .panel { padding: 36px; }
}

@media (max-width: 980px) {
  .layout { grid-template-columns: 1fr; }
  .sidebar-toggle { display: flex; }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 50;
    width: min(88vw, 360px);
    height: 100dvh;
    background: var(--bg);
    border-right: 1px solid var(--border);
    overflow-y: auto;
    transform: translateX(-100%);
    transition: transform 0.28s ease;
    /* En escritorio el contenido se reparte contra el alto de la
       pantalla. Aquí el panel se desplaza, así que se agrupa arriba y
       el pie va detrás: repartido, quedaba pegado al borde inferior y
       la barra del navegador lo tapaba. */
    justify-content: flex-start;
    gap: 26px;
    /* Sitio para el botón de cerrar, que flota en la esquina. */
    padding: 24px 24px calc(24px + env(safe-area-inset-bottom));
    /* El menú se recorre entero; que el logo o los enlaces no se
       aplasten cuando la pantalla es corta. */
    overscroll-behavior: contain;
  }
  .sidebar > * { flex: none; }
  .sidebar.is-open { transform: translateX(0); }

  /* La tira de logos se sale del panel: su máscara la hace sangrar y
     el ancho del carrusel no conoce el relleno del contenedor. */
  .sidebar .clients {
    margin-inline: -24px;
    padding-inline: 24px;
  }

  /* El correo es lo más largo del pie y arrastraba la fila fuera del
     panel. Pasa a su propia línea y se recorta si aún no cabe. */
  .sidebar__footer {
    flex-wrap: wrap;
    gap: 10px 18px;
    margin-top: auto;
    padding-top: 8px;
  }
  .sidebar__footer a[href^='mailto:'] {
    flex-basis: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .content { padding: 16px; gap: 16px; }
  /* Aliados se nombra aparte porque su proporción propia lleva dos
     clases y ganaría a esta regla, dejándola en dos columnas
     estrujadas mientras el resto ya se apila. */
  .card--wide,
  .card--aliados.card--wide { grid-template-columns: 1fr; min-height: 0; }
  .card--wide .card__body { padding: 34px 28px 0; }
  .shot--wide { padding: 32px 24px 0; }
  .phone { width: 136px; }
  .pair { grid-template-columns: 1fr; }
  .panel--split, .about { grid-template-columns: 1fr; gap: 26px; }
  .panel__aside { position: static; }
}

@media (max-width: 560px) {
  .panel { padding: 28px 22px 32px; }
  .card__body { padding: 30px 24px; }
  .card--wide .card__body { padding: 30px 24px 0; }
  .job__head { grid-template-columns: 36px minmax(0, 1fr) auto; row-gap: 4px; }
  .job__years { grid-column: 2 / 3; }
  .job__plus { grid-row: 1 / 3; grid-column: 3 / 4; }
  .job__detail { padding-left: 24px; }
}

/* ═══════════════════════════════════════════════════════════════
   Contacto
   ═══════════════════════════════════════════════════════════════ */
/* Mismo panel hueso que el resto de secciones: el formulario debe
   parecer parte de la página, no un bloque pegado de otro sitio.
   El relleno vertical es menor que en los demás paneles porque el
   formulario ya trae su propio aire entre campos. */
#contacto { padding: 38px 44px 40px; }

/* La columna del texto ocupa la mitad: con menos, el titular partía
   en tres líneas y pesaba demasiado para lo que dice. */
.contact {
  display: grid;
  grid-template-columns: minmax(0, 0.5fr) minmax(0, 1fr);
  gap: 44px;
  align-items: start;
}

/* El titular usa `.panel__title` como el resto de secciones. Aquí
   solo se anula el margen inferior, pensado para cuando el título va
   sobre el contenido y no al lado. */
.contact__intro .panel__title { margin-bottom: 0; }
.contact__intro .panel__lead { max-width: 36ch; }

/* ── Formulario ── */
.cform { display: flex; flex-direction: column; gap: 14px; }
.cform__row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }

.cfield { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.cfield__label {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.cfield__hint {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-faint);
}

.cfield__input {
  width: 100%;
  padding: 13px 16px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  transition: border-color var(--t-base) var(--ease),
              box-shadow var(--t-base) var(--ease);
}
.cfield__input::placeholder { color: var(--text-faint); }
.cfield__input:hover { border-color: var(--text-faint); }
.cfield__input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}
.cfield__input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ── Desplegable propio ──
   El <select> nativo abre una lista que pinta el sistema operativo y
   que no acepta CSS: de ahí que el control sea un botón más una lista
   propia. El valor viaja en un input oculto. */
.picker { position: relative; }

.picker__button {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  text-align: left;
  cursor: pointer;
}
.picker__value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker__arrow {
  width: 12px;
  flex: none;
  color: var(--text-muted);
  transition: transform var(--t-base) var(--ease);
}
.picker.is-open .picker__arrow { transform: rotate(180deg); }
.picker.is-open .picker__button {
  border-color: var(--accent);
  box-shadow: var(--ring);
}

.picker__list {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 20;
  max-height: 260px;
  overflow-y: auto;
  padding: 6px;
  background: #fff;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-3);
  animation: pickerIn var(--t-fast) var(--ease-out);
}
.picker__list:focus { outline: none; }

@keyframes pickerIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}

.picker__option {
  padding: 10px 12px;
  border-radius: var(--radius-xs);
  font-size: 15px;
  color: var(--text);
  cursor: pointer;
  /* El resaltado sigue al ratón y al teclado por igual: el estado lo
     lleva `.is-active`, no `:hover`. */
  transition: background var(--t-fast) var(--ease);
}
.picker__option.is-active { background: var(--panel); }
.picker__option[aria-selected='true'] {
  color: var(--accent-ink);
  font-weight: 600;
}
/* Marca de elegido, para no depender solo del color. */
.picker__option[aria-selected='true']::after {
  content: '✓';
  float: right;
  font-weight: 700;
}

/* 104px basta para tres líneas: con 130 el bloque quedaba vacío por
   abajo antes de que nadie escribiera. Se puede estirar a mano. */
.cfield__area { resize: vertical; min-height: 104px; line-height: 1.6; }

.cfield__input.is-invalid {
  border-color: var(--danger);
  background: var(--danger-soft);
}
.cfield__error { font-size: 13px; color: var(--danger); }

/* Trampa antibots: fuera de la vista sin usar `display:none`, que
   algunos bots detectan y saltan. */
.cform__trap {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.cform__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
.cform__note { font-size: 13px; color: var(--text-muted); }
.cform__note a {
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.cform__note a:hover { color: var(--text); }

/* Este botón no hereda el ancho completo del de la barra lateral. */
.cform__send { width: auto; flex: none; }

.cform__result {
  padding: 13px 18px;
  border-radius: var(--radius-sm);
  font-size: 14px;
}
.cform__result--ok {
  background: color-mix(in srgb, var(--success) 14%, transparent);
  color: var(--success);
}
.cform__result--error {
  background: var(--danger-soft);
  color: var(--danger);
}

@media (max-width: 980px) {
  .contact { grid-template-columns: 1fr; gap: 32px; }
  .contact__intro .panel__lead { max-width: none; }
}

@media (max-width: 560px) {
  .cform__row { grid-template-columns: 1fr; }
  .cform__foot { flex-direction: column; align-items: stretch; }
  .cform__send { width: 100%; }
  .cform__note { order: 2; text-align: center; }
}

/* ═══════════════════════════════════════════════════════════════
   Entrada al hacer scroll
   ═══════════════════════════════════════════════════════════════
   La clase `.reveal` la añade script.js, nunca el HTML: si el script
   fallara, el contenido se vería igual en lugar de quedar invisible.
   Solo se anima la primera vez que el bloque entra en pantalla.
   ═══════════════════════════════════════════════════════════════ */
/* El movimiento no es uniforme: las tarjetas de proyecto son la pieza
   protagonista y entran con más peso, mientras que los bloques de texto
   solo acompañan la lectura. Animar todo igual convierte la entrada en
   ruido de fondo que se deja de percibir. */
.reveal {
  opacity: 0;
  transform: translateY(20px);
  /* Más lento que las transiciones de interfaz: 240ms se percibiría
     como un tirón en un bloque de este tamaño. */
  transition: opacity 520ms var(--ease-out),
              transform 520ms var(--ease-out);
  /* Avisa al navegador de qué va a cambiar, para que lo mueva en la
     GPU y no reconstruya la página en cada fotograma. */
  will-change: opacity, transform;
}
.reveal.is-in {
  opacity: 1;
  transform: none;
  /* Terminada la entrada, la pista de `will-change` sobra y solo
     consumiría memoria de vídeo. */
  will-change: auto;
}

/* ── Capa 1: la tarjeta se asienta ──────────────────────────────
   Recorrido más largo que el resto para darle peso, pero SIN escala.
   Una tarjeta de ancho completo escalada queda con los bordes
   desalineados respecto a las vecinas ya asentadas, y eso se lee como
   un fallo de maquetación —«esta card es más angosta»— en vez de como
   movimiento. La sensación de asentarse la aporta el contenido interno,
   donde ningún borde compite con nada. Nada supera los 750ms: si el
   scroll adelanta a la animación, la animación estorba. */
.card.reveal {
  transform: translateY(34px);
  transition: opacity 700ms var(--ease-out),
              transform 700ms var(--ease-out);
}

/* ── Capa 2: el contenido se arma dentro de la tarjeta ──────────
   El cuerpo entra en cascada arrancando después de la tarjeta, que es
   lo que separa «un bloque apareciendo» de «una composición armándose».
   El escalonado total no pasa de ~280ms acumulados: más que eso y el
   último elemento se siente rezagado, no coreografiado. */
.card.reveal .card__logo,
.card.reveal .card__title,
.card.reveal .tags,
.card.reveal .card__actions,
.card.reveal .card__body > .card__link,
.card.reveal .card__soon {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 460ms var(--ease-out),
              transform 460ms var(--ease-out);
}
.card.reveal.is-in .card__logo,
.card.reveal.is-in .card__title,
.card.reveal.is-in .tags,
.card.reveal.is-in .card__actions,
.card.reveal.is-in .card__body > .card__link,
.card.reveal.is-in .card__soon {
  opacity: 1;
  transform: none;
}
.card.reveal.is-in .card__logo   { transition-delay: 120ms; }
.card.reveal.is-in .card__title  { transition-delay: 190ms; }
.card.reveal.is-in .tags         { transition-delay: 260ms; }
.card.reveal.is-in .card__actions,
.card.reveal.is-in .card__body > .card__link,
.card.reveal.is-in .card__soon   { transition-delay: 330ms; }

/* ── Capa 3: el mockup como contrapunto ─────────────────────────
   La imagen entra en dirección distinta al texto y con un punto de
   zoom: dos direcciones cruzadas dan profundidad sin que nada se
   desplace mucho. En las tarjetas anchas viene desde la derecha,
   donde vive; en las de par, desde abajo. */
.card.reveal .shot {
  opacity: 0;
  transform: translateY(22px) scale(1.03);
  transition: opacity 640ms var(--ease-out),
              transform 640ms var(--ease-out);
}
.card--wide.reveal .shot { transform: translateX(26px) scale(1.03); }
.card.reveal.is-in .shot {
  opacity: 1;
  transform: none;
  transition-delay: 160ms;
}

/* ── Capa 4: los bloques de texto, más contenidos ───────────────
   Aquí el gesto se apaga a propósito: el movimiento fuerte queda
   reservado para el portafolio. */
.panel.reveal { transform: translateY(20px); }

/* Dentro de un panel, las filas entran escalonadas en lugar de todas
   a la vez, que es lo que hace que un listado largo se lea como una
   secuencia y no como un muro que aparece de golpe. */
.panel.reveal .row,
.panel.reveal .job {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 440ms var(--ease-out),
              transform 440ms var(--ease-out);
}
.panel.reveal.is-in .row,
.panel.reveal.is-in .job { opacity: 1; transform: none; }
.panel.reveal.is-in .row:nth-child(1),
.panel.reveal.is-in .job:nth-child(1) { transition-delay: 100ms; }
.panel.reveal.is-in .row:nth-child(2),
.panel.reveal.is-in .job:nth-child(2) { transition-delay: 170ms; }
.panel.reveal.is-in .row:nth-child(3),
.panel.reveal.is-in .job:nth-child(3) { transition-delay: 240ms; }
.panel.reveal.is-in .row:nth-child(4),
.panel.reveal.is-in .job:nth-child(4) { transition-delay: 310ms; }
.panel.reveal.is-in .row:nth-child(n + 5),
.panel.reveal.is-in .job:nth-child(n + 5) { transition-delay: 360ms; }

/* Las dos tarjetas de un par entran escalonadas: a la vez parecería
   un solo bloque saltando, no dos piezas. */
.pair > .reveal:nth-child(2) { transition-delay: 110ms; }
/* El retraso del par se suma al del contenido interno, para que la
   segunda tarjeta mantenga su propia cascada en orden. */
.pair > .reveal:nth-child(2).is-in .card__logo   { transition-delay: 230ms; }
.pair > .reveal:nth-child(2).is-in .card__title  { transition-delay: 300ms; }
.pair > .reveal:nth-child(2).is-in .tags         { transition-delay: 370ms; }
.pair > .reveal:nth-child(2).is-in .card__actions,
.pair > .reveal:nth-child(2).is-in .card__body > .card__link,
.pair > .reveal:nth-child(2).is-in .card__soon   { transition-delay: 440ms; }
.pair > .reveal:nth-child(2).is-in .shot         { transition-delay: 270ms; }

@media (prefers-reduced-motion: reduce) {
  /* Sin movimiento no hay entrada: el contenido está desde el inicio.
     El JS ni siquiera añade `.reveal`, pero esto lo cubre por si la
     preferencia cambia con la página ya abierta. Los delays también se
     anulan: si no, dejarían huecos vacíos sin nada que los explique. */
  .reveal,
  .reveal .card__logo,
  .reveal .card__title,
  .reveal .tags,
  .reveal .card__actions,
  .reveal .card__link,
  .reveal .card__soon,
  .reveal .shot,
  .reveal .row,
  .reveal .job {
    opacity: 1;
    transform: none;
    transition: none;
    transition-delay: 0s;
  }
}
