/* ------------------------------------------------------------------ */
/* -- NuHR LOADERS OVER BOOTSTRAP'S OWN -- */
/* ------------------------------------------------------------------ */
/*
 * Loaded last (after bootstrap.min.css and nuhr.css) by both
 * themes/utils/{main,auth}StyleLinks.ts, so every Bootstrap spinner and
 * placeholder already in the app turns into the NuHR loaders without its page
 * changing. Design and usage: docs/design/brand/loaders/. Colour tokens (--nu-*)
 * come from app/globals.css.
 *
 * Not scoped to a colour scheme: the N mark keeps its gradient on every scheme.
 *
 *   .spinner-border      Orbit ring; page-size ones (not -sm, not in a button)
 *                        carry the N in the middle
 *   .spinner-border      in a button, or with its own text-* colour: the ring
 *                        in that colour (white on navy buttons)
 *   .spinner-grow        Pulse: the N's strokes light in turn
 *   .placeholder         brand-tinted shimmer
 *   AG Grid overlay      Orbit ring beside "Loading..."
 *   Tagify loading       the ring alone, in a tag field fetching suggestions
 */

/* Orbit ring. The element stays still and holds the track; ::before turns. */
.spinner-border {
  position: relative;
  border: 0;
  background: none;
  animation: none;
  box-shadow: inset 0 0 0 var(--bs-spinner-border-width) color-mix(in srgb, currentColor 16%, transparent);
}

.spinner-border::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0deg, currentColor 360deg);
  -webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - var(--bs-spinner-border-width)), #000 calc(100% - var(--bs-spinner-border-width) + 0.5px));
  mask: radial-gradient(farthest-side, #0000 calc(100% - var(--bs-spinner-border-width)), #000 calc(100% - var(--bs-spinner-border-width) + 0.5px));
  animation: var(--bs-spinner-animation-speed) linear infinite nu-spin;
}

/* Outside a button, with no colour of its own (or the primary one): the brand ring. */
.spinner-border:not(.btn *):not([class*="text-"]),
.spinner-border.text-primary:not(.btn *) {
  box-shadow: inset 0 0 0 var(--bs-spinner-border-width) var(--nu-track);
}

.spinner-border:not(.btn *):not([class*="text-"])::before,
.spinner-border.text-primary:not(.btn *)::before {
  background: conic-gradient(from 0deg, rgba(6, 180, 242, 0) 0deg, rgba(6, 180, 242, 0.15) 60deg, var(--nu-g1) 160deg, var(--nu-g2) 260deg, var(--nu-g3) 360deg);
}

/* Page-size spinners are the full Orbit: the N sits in the middle. */
.spinner-border:not(.spinner-border-sm):not(.btn *)::after {
  content: "";
  position: absolute;
  inset: 27%;
  background: url("../../img/brand/loaders/nuhr-mark.svg") center / contain no-repeat;
}

/* Pulse. */
.spinner-grow {
  background: url("../../img/brand/loaders/nuhr-pulse.svg") center / contain no-repeat;
  background-color: transparent;
  border-radius: 0;
  opacity: 1;
  animation: none;
}

/* Skeleton placeholders: the brand shimmer instead of Bootstrap's glow and wave. */
.placeholder-glow .placeholder,
.placeholder-wave .placeholder {
  background: linear-gradient(90deg, var(--nu-sk-base) 25%, var(--nu-sk-hi) 50%, var(--nu-sk-base) 75%);
  background-size: 200% 100%;
  opacity: 1;
  animation: nu-shimmer 1.6s linear infinite;
}

.placeholder-wave {
  -webkit-mask-image: none;
  mask-image: none;
  animation: none;
}

/* AG Grid's own loading overlay. */
.ag-overlay-loading-center {
  align-items: center;
  gap: 10px;
}

.ag-overlay-loading-center::before {
  content: "";
  width: 20px;
  height: 20px;
  flex: none;
  border-radius: 50%;
  background: conic-gradient(from 0deg, rgba(6, 180, 242, 0) 0deg, var(--nu-g1) 150deg, var(--nu-g2) 260deg, var(--nu-g3) 360deg);
  -webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - 2.5px), #000 calc(100% - 2px));
  mask: radial-gradient(farthest-side, #0000 calc(100% - 2.5px), #000 calc(100% - 2px));
  animation: nu-spin 0.9s linear infinite;
}

/* Tagify's own loader, while a tag field fetches suggestions: the brand ring instead. */
.tagify--loading .tagify__input::after,
.tagify--loading .tagify__input:empty::after {
  border: 0;
  border-radius: 50%;
  background: conic-gradient(from 0deg, rgba(6, 180, 242, 0) 0deg, var(--nu-g1) 150deg, var(--nu-g2) 260deg, var(--nu-g3) 360deg);
  -webkit-mask: radial-gradient(farthest-side, #0000 calc(100% - 2px), #000 calc(100% - 1.5px));
  mask: radial-gradient(farthest-side, #0000 calc(100% - 2px), #000 calc(100% - 1.5px));
  animation: nu-spin 0.85s linear infinite;
}

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

@keyframes nu-shimmer {
  0% { background-position: 150% 0; }
  100% { background-position: -50% 0; }
}

@keyframes nu-breathe {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

/* Less motion: rings stop turning and breathe instead. */
@media (prefers-reduced-motion: reduce) {
  .spinner-border::before,
  .ag-overlay-loading-center::before,
  .tagify--loading .tagify__input::after {
    animation: nu-breathe 2.4s ease-in-out infinite;
  }

  .placeholder-glow .placeholder,
  .placeholder-wave .placeholder {
    animation-duration: 3.2s;
  }
}
