/* ============================================================
   utilities.css — small, limited utility layer
   ============================================================ */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.text-center { text-align: center; }
.mx-auto { margin-inline: auto; }

.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }
.mt-7 { margin-top: var(--space-7); }

.stack {
  display: flex;
  flex-direction: column;
}
.stack--3 { gap: var(--space-3); }
.stack--4 { gap: var(--space-4); }
.stack--5 { gap: var(--space-5); }

.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  align-items: center;
}

.max-readable { max-width: var(--content-readable); }

.body-lock {
  overflow: hidden;
}

/* Entrance reveal — only applied when JS is active (html.js). Without
   JS the content is always visible (no hidden initial state), so
   no-JS, print, and reduced-motion never hide content. */
@media (prefers-reduced-motion: no-preference) {
  html.js .reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 600ms var(--ease), transform 600ms var(--ease);
  }
  html.js .reveal[data-shown="true"] {
    opacity: 1;
    transform: none;
  }
}

/* Reduced motion: neutralise optional motion */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
