/* =================================================================
   BASE — reset, elementos, tipografía y utilidades
   -----------------------------------------------------------------
   Depende de tokens.css. Sin valores a mano.
   ================================================================= */

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-h);
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-body);
  color: var(--color-text);
  background: var(--color-bg);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

img, svg, iframe { display: block; max-width: 100%; }
img { height: auto; object-fit: cover; }
a { color: inherit; text-decoration: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; }

::selection { background: var(--color-accent); color: var(--color-white); }
:focus-visible { outline: var(--border-medium) solid var(--color-accent); outline-offset: 3px; }

/* ---------- Grano global ----------
   Unifica material fotográfico de calidad dispar. Es identidad del
   sistema, no un adorno: sin esto, una foto de celular al lado de un
   render se ve como dos sitios distintos. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: var(--z-grain);
  opacity: var(--grain-opacity);
  background-image: var(--grain-svg);
  background-size: var(--grain-size) var(--grain-size);
}

/* ---------- Salto al contenido ---------- */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: var(--z-skip);
  background: var(--color-primary);
  color: var(--color-text-inverse);
  padding: 0.75rem 1.25rem;
  font-size: var(--text-sm);
}
.skip-link:focus { left: 8px; top: 8px; }

/* ---------- Contenedor ---------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* =================================================================
   TIPOGRAFÍA
   -----------------------------------------------------------------
   Chivo 900/700 arriba, apretada y en mayúsculas.
   Public Sans abajo, neutra y aireada.
   El contraste es de rol, no de estilo. Ver CLAUDE.md.
   ================================================================= */

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--weight-black);
  line-height: var(--leading-display);
  letter-spacing: var(--track-tight);
  text-wrap: balance;
}

h1 {
  font-size: var(--text-hero);
  text-transform: uppercase;
  letter-spacing: var(--track-hero);
}
h2 { font-size: var(--text-2xl); }
h3 {
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  letter-spacing: var(--track-snug);
}

/* El acento en un título se marca con <em>, nunca con color suelto */
h1 em, h2 em { font-style: normal; color: var(--color-accent); }

p { color: var(--color-text-muted); max-width: var(--measure); }

.lead {
  font-size: var(--text-lg);
  line-height: var(--leading-normal);
  color: var(--color-primary-light);
  max-width: var(--measure-lead);
}

/* ---------- Etiqueta en mayúsculas ----------
   La firma del sistema. Aparece en toda sección, tarjeta y ficha.
   El filete de 24px a la izquierda es parte de la marca. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  margin-bottom: 0.9rem;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  letter-spacing: var(--track-widest);
  text-transform: uppercase;
  color: var(--color-accent-ink);
}
.eyebrow::before {
  content: '';
  flex: 0 0 auto;
  width: 24px;
  height: 2px;
  background: currentColor;
}
/* Sobre foto o fondo muy oscuro el ladrillo pierde contraste. La misma
   corrección tiene que llegar cuando ".light" está en el .sec-head que
   envuelve al eyebrow y no en el eyebrow mismo (ver .sec-head.light). */
.eyebrow.light,
.sec-head.light .eyebrow { color: var(--ink-inv-2); }
.eyebrow.sm { margin-bottom: 0.3rem; }

/* ---------- Encabezado de sección ---------- */
.sec-head {
  max-width: 640px;
  margin-bottom: var(--space-lg);
}
.sec-head.center {
  margin-left: auto;
  margin-right: auto;
  text-align: center;
}
.sec-head.center .eyebrow,
.center-eyebrow { justify-content: center; }
.sec-head h2 { margin-bottom: 0.8rem; }
.sec-sub { font-size: var(--text-base); }
.sec-head.light h2 { color: var(--color-text-inverse); }
.sec-head.light .sec-sub { color: var(--ink-inv-3); }
.sec-head.center .sec-sub { margin-inline: auto; }

/* ---------- Nota al pie de bloque ---------- */
.nota {
  font-size: var(--label-lg);
  font-style: italic;
  color: var(--color-text-muted);
}

/* =================================================================
   UTILIDADES DE ANIMACIÓN
   -----------------------------------------------------------------
   El escalonado usa --i (índice) en vez de nth-child. En el boceto
   los delays estaban atados a cantidades exactas (6 sectores, 5
   pasos); con contenido que sale de JSON la cantidad es variable y
   esas reglas fallaban en silencio. Ahora el render escribe
   style="--i:3" y el sistema no se entera de cuántos hay.
   ================================================================= */

.reveal {
  opacity: 0;
  transform: translateY(26px);
  animation: revealUp var(--dur-reveal) var(--ease-out) forwards;
  animation-delay: calc(var(--i, 0) * 0.12s);
}
@keyframes revealUp { to { opacity: 1; transform: none; } }

.scroll-reveal {
  opacity: 0;
  transform: translateY(28px);
  transition:
    opacity var(--dur-slower) var(--ease-out),
    transform var(--dur-slower) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 0.06s);
}
.scroll-reveal.visible { opacity: 1; transform: none; }
.scroll-reveal.from-left  { transform: translateX(-26px); }
.scroll-reveal.from-right { transform: translateX(26px); }
.scroll-reveal.from-left.visible,
.scroll-reveal.from-right.visible { transform: none; }

/* ---------- Motion reducido ----------
   Las duraciones ya se anulan en tokens.css. Acá solo queda lo que
   no es una duración. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-delay: 0ms !important;
  }
  .reveal, .scroll-reveal { opacity: 1 !important; transform: none !important; }
}
