.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.text-center {
  text-align: center;
}

.text-sm {
  font-size: var(--text-sm);
}

.mt-2 { margin-top: var(--space-2); }
.mt-4 { margin-top: var(--space-4); }
.mt-6 { margin-top: var(--space-6); }
.mt-8 { margin-top: var(--space-8); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-6 { margin-bottom: var(--space-6); }

.max-w-prose {
  max-width: 68ch;
}

.flex-wrap-gap {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

/* Scroll-reveal — gated behind .js-ready (added by main.js) so content
   stays fully visible by default if JS fails or is disabled. Opacity-only
   (no transform) so it never fights the card's own hover-lift transform. */
.js-ready .card,
.js-ready .testimonial-card,
.js-ready .cta-band {
  opacity: 0;
  transition: opacity 0.5s ease, border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
}

.js-ready .card.is-visible,
.js-ready .testimonial-card.is-visible,
.js-ready .cta-band.is-visible {
  opacity: 1;
}
