#particle-container {
    position: fixed;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 9999;
  }

  .particle {
    position: absolute;
    left: 0;
    top: 0;
    border-radius: 50%;
    mix-blend-mode: screen;
    will-change: transform;
    opacity: var(--opa, 0.60);
    filter: blur(var(--blur, 0px));
  }

  /* Swirl overlay (Aether/Nether) */
  .particle::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: var(--swirlBg, none);
    opacity: var(--swirlO, 0);
    mix-blend-mode: overlay;
    animation: spin var(--swirlDur, 14s) linear infinite;
    pointer-events: none;
  }

  /* Grain overlay (all) */
  .particle::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background-image:
      repeating-linear-gradient(0deg, rgba(255,255,255,0.06) 0px, rgba(255,255,255,0.06) 1px, rgba(0,0,0,0) 1px, rgba(0,0,0,0) 4px),
      repeating-linear-gradient(90deg, rgba(255,255,255,0.05) 0px, rgba(255,255,255,0.05) 1px, rgba(0,0,0,0) 1px, rgba(0,0,0,0) 5px);
    opacity: var(--grainO, 0.10);
    mix-blend-mode: overlay;
    pointer-events: none;
  }

  /* Light trail */
  .particle-trail {
    opacity: 0.12 !important;
    filter: blur(2.2px) !important;
  }

  @keyframes spin { to { transform: rotate(360deg); } }

  /* Freeze the existing swirl while its page cannot be seen. */
  #particle-container.sn-octa-paused .particle::before {
    animation-play-state: paused;
  }
