/* Texture utilities: dot field, grain, hero glow (docs/02 Texture). */

.dots {
  position: relative;
  isolation: isolate;
}

.dots::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: radial-gradient(var(--dot) 1px, transparent 1.2px);
  background-size: var(--dot-grid) var(--dot-grid);
  opacity: var(--dot-opacity);
  mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, black 30%, transparent 100%);
}

.dots--small::before {
  background-size: var(--dot-grid-small) var(--dot-grid-small);
}

.dots--behind-text::before {
  opacity: var(--dot-opacity-text);
}

.dots--even::before {
  mask-image: none;
}

/* The grain covers the whole page, not the viewport: a fixed layer ends at the first screen in a
   full-page capture and showed there as a hard line across the gradient (DECISIONS 152). */
.grain {
  position: relative;
}

.grain::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2147483000;
  pointer-events: none;
  background: url("/assets/img/grain.webp") repeat;
  background-size: 256px 256px;
  opacity: var(--grain-opacity);
}

/* Glow bands: put .glow--top first and .glow--end last in a .glow-page body. They sit behind the
   content, so their long fades run under the next section instead of stopping at an edge, and
   panels with their own background cover them. */
.glow-page {
  position: relative;
  isolation: isolate;
}

.glow {
  position: absolute;
  left: 0;
  right: 0;
  z-index: -2;
  height: var(--glow-reach);
  max-height: 100%; /* a short page does not grow to fit the band */
  pointer-events: none;
}

.glow--top {
  top: 0;
  background: var(--hero-gradient);
  animation: glow-up var(--d-hero) var(--ease-enter) backwards;
}

.glow--end {
  bottom: 0;
  background: var(--end-gradient);
}

@keyframes glow-up {
  from { opacity: 0; }
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .glow--top {
    animation-duration: var(--d-enter);
  }
}

/* Wide screens: the margins outside the content column hold the dot field (docs/02 Layout). */
.margin-dots::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: radial-gradient(var(--dot) 1px, transparent 1.2px);
  background-size: var(--dot-grid) var(--dot-grid);
  opacity: var(--dot-opacity);
  mask-image: linear-gradient(90deg, black, transparent calc(50% - var(--content-max) / 2 + 48px), transparent calc(50% + var(--content-max) / 2 - 48px), black);
}
