:root {
  --grain: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.72' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='2.2' intercept='-0.6'/%3E%3CfeFuncG type='linear' slope='2.2' intercept='-0.6'/%3E%3CfeFuncB type='linear' slope='2.2' intercept='-0.6'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Keep modal grain inside the dialog rather than over its backdrop. */
dialog { contain: paint; }

/* Match the landing's film grain across pages and native modal dialogs. */
body::after, dialog::after {
  content: "";
  position: fixed;
  inset: -50%;
  z-index: 301;
  pointer-events: none;
  opacity: 0.55;
  background-image: var(--grain);
  mix-blend-mode: overlay;
  animation: grain-shift 0.8s steps(4) infinite;
}

/* The second pass keeps the texture visible on dark backgrounds. */
body::before, dialog::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 300;
  pointer-events: none;
  opacity: 0.07;
  background-image: var(--grain);
}

@keyframes grain-shift {
  0% { transform: translate(0, 0); }
  25% { transform: translate(-3%, 2%); }
  50% { transform: translate(2%, -3%); }
  75% { transform: translate(-2%, -2%); }
  100% { transform: translate(0, 0); }
}

.motion-paused body::after, .motion-paused dialog::after { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  body::after, dialog::after { animation: none; transform: none; }
}
