/* ============================================================================
   Layout primitives + animation utilities.
   Compose pages from these — avoid bespoke margins / magic numbers.
   ============================================================================ */

/* ---- Container: centered, capped, responsive gutter --------------------- */
.container {
  width: 100%;
  max-width: var(--max-w);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--narrow { max-width: 880px; }
.container--prose  { max-width: var(--max-w-prose); }

/* ---- Section: vertical rhythm ------------------------------------------- */
.section { padding-block: var(--section-pad); }
.section--tight { padding-block: clamp(40px, 6vw, 80px); }

/* ---- Stack: vertical flow with consistent gap -------------------------- */
.stack { display: flex; flex-direction: column; gap: var(--gap, var(--space-4)); }
.stack--sm { --gap: var(--space-2); }
.stack--lg { --gap: var(--space-6); }

/* ---- Cluster: horizontal wrap with gap --------------------------------- */
.cluster {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: var(--gap, var(--space-3));
}

/* ---- Auto-grid: responsive equal columns ------------------------------- */
.grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
}

/* ---- Split: 2-column feature layout (collapses on mobile) -------------- */
.split {
  display: grid;
  gap: var(--space-7);
  align-items: center;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; gap: var(--space-9); }
  .split--reverse > :first-child { order: 2; }
}

/* ---- Bento: mosaic of unequal cells ------------------------------------ */
.bento {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
}
@media (min-width: 760px) {
  .bento {
    grid-template-columns: repeat(6, 1fr);
    grid-auto-rows: minmax(180px, auto);
  }
  .bento__cell--hero  { grid-column: span 4; grid-row: span 2; }
  .bento__cell--tall  { grid-column: span 2; grid-row: span 2; }
  .bento__cell--wide  { grid-column: span 4; }
  .bento__cell        { grid-column: span 2; }
}

/* ============================================================================
   Animation utilities — transform/opacity only (GPU), custom easing.
   ============================================================================ */

/* Reveal on scroll: JS toggles .in-view via IntersectionObserver */
.reveal {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity var(--dur-reveal) var(--ease-glide),
    transform var(--dur-reveal) var(--ease-glide);
  transition-delay: calc(var(--i, 0) * 80ms);
  will-change: transform, opacity;
}
.reveal.in-view { opacity: 1; transform: none; }

/* Ambient slow float (for hero art) */
@keyframes float-y { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
.anim-float { animation: float-y 6s var(--ease-in-out) infinite; }

/* Slow gradient drift (for hero backdrops) */
@keyframes drift { 0% { background-position: 0% 50%; } 100% { background-position: 200% 50%; } }
.anim-drift { background-size: 200% 200%; animation: drift 16s linear infinite; }

/* Arrow nudge on hover (apply to a child .arrow inside a hover target) */
.arrow { display: inline-block; transition: transform var(--dur-fast) var(--ease-out); }
:where(a, button):hover > .arrow { transform: translateX(3px); }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  .anim-float, .anim-drift { animation: none; }
  *, *::before, *::after { transition-duration: 0.001ms !important; }
}
