// Spinner Component

.pf-c-spinner {
  --pf-c-spinner--diameter: var(--pf-global--icon--FontSize--xl);
  --pf-c-spinner--Width: var(--pf-c-spinner--diameter);
  --pf-c-spinner--Height: var(--pf-c-spinner--diameter);
  --pf-c-spinner--Color: var(--pf-global--primary-color--100);

  // sizes
  --pf-c-spinner--m-sm--diameter: var(--pf-global--icon--FontSize--sm);
  --pf-c-spinner--m-md--diameter: var(--pf-global--icon--FontSize--md);
  --pf-c-spinner--m-lg--diameter: var(--pf-global--icon--FontSize--lg);
  --pf-c-spinner--m-xl--diameter: var(--pf-global--icon--FontSize--xl);

  width: var(--pf-c-spinner--Width);
  height: var(--pf-c-spinner--Height);
  overflow: hidden;

  // Modifiers change the variables for size variations
  &.pf-m-sm {
    --pf-c-spinner--diameter: var(--pf-c-spinner--m-sm--diameter);
  }

  &.pf-m-md {
    --pf-c-spinner--diameter: var(--pf-c-spinner--m-md--diameter);
  }

  &.pf-m-lg {
    --pf-c-spinner--diameter: var(--pf-c-spinner--m-lg--diameter);
  }

  &.pf-m-xl {
    --pf-c-spinner--diameter: var(--pf-c-spinner--m-xl--diameter);
  }
}

// stylelint-disable selector-no-qualifying-type
span.pf-c-spinner {
  --pf-c-spinner--AnimationDuration: 1.5s;
  --pf-c-spinner--AnimationTimingFunction: cubic-bezier(.77, .005, .315, 1);

  // These conceptual variables are used to size the stroke width, which is accomplished using various properties in the clipper:after and the ball animations
  --pf-c-spinner--stroke-width-multiplier: .1;
  --pf-c-spinner--stroke-width: calc(var(--pf-c-spinner--diameter) * var(--pf-c-spinner--stroke-width-multiplier));

  // Clipper variables
  --pf-c-spinner__clipper--Width: var(--pf-c-spinner--diameter);
  --pf-c-spinner__clipper--Height: var(--pf-c-spinner--diameter);

  // Clipper:after (circle) values
  --pf-c-spinner__clipper--after--BoxShadowColor: var(--pf-c-spinner--Color);
  --pf-c-spinner__clipper--after--Width: var(--pf-c-spinner--diameter);
  --pf-c-spinner__clipper--after--Height: var(--pf-c-spinner--diameter);

  // This creates the stroke and needs to match the spinner__ball:after Height and Width
  --pf-c-spinner__clipper--after--BoxShadowSpreadRadius: var(--pf-c-spinner--stroke-width);

  // Lead ball variables
  --pf-c-spinner__lead-ball--after--BackgroundColor: var(--pf-c-spinner--Color);

  // These sizes need to match the stroke width, i.e. clipper:after BoxShadowSpreadRadius
  --pf-c-spinner__ball--after--Width: var(--pf-c-spinner--stroke-width);
  --pf-c-spinner__ball--after--Height: var(--pf-c-spinner--stroke-width);

  // Tail ball variables
  --pf-c-spinner__tail-ball--after--BackgroundColor: var(--pf-c-spinner--Color);

  position: relative;
  display: inline-block;
  text-align: left;
  animation: pf-animation-spinner-parent calc(var(--pf-c-spinner--AnimationDuration) * 2) var(--pf-c-spinner--AnimationTimingFunction) infinite;
}
// stylelint-enable

// Rotate the parent 360deg as the basic line animation happens, repeat that twice, and another rotation overall. This adds up to 3 complete rotations.
@keyframes pf-animation-spinner-parent {
  0% {
    transform: rotate(0deg);
  }

  50% {
    transform: rotate(-540deg);
  }

  100% {
    transform: rotate(-1080deg);
  }
}

// Clipper is a rotating rectangle clipped to one quarter the size of the spinner, starting in the upper right
.pf-c-spinner__clipper {
  position: absolute;
  width: var(--pf-c-spinner__clipper--Width);
  height: var(--pf-c-spinner__clipper--Height);
  clip-path: inset(0 0 50% 50%);
  animation: pf-animation-spinner__clipper var(--pf-c-spinner--AnimationDuration) linear infinite;
}

@keyframes pf-animation-spinner__clipper {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(-270deg);
  }
}

// The :after of the Clipper is a rotating semicircle that has the part that you see moving around (inset box shadow), growing and shrinking because it is moving into and out of the Clipper box
.pf-c-spinner__clipper::after {
  position: absolute;
  width: var(--pf-c-spinner__clipper--after--Width);
  height: var(--pf-c-spinner__clipper--after--Height);
  clip-path: inset(0 0 0 50%);
  content: "";
  border-radius: 50%;
  box-shadow: inset 0 0 0 var(--pf-c-spinner__clipper--after--BoxShadowSpreadRadius) var(--pf-c-spinner__clipper--after--BoxShadowColor);
  animation: pf-animation-spinner__clipper-after var(--pf-c-spinner--AnimationDuration) linear infinite;
}

// The Clipper:after moves rotates 270deg in relation to its parent (so that it appears to grow and then shrink)
@keyframes pf-animation-spinner__clipper-after {
  0% {
    transform: rotate(90deg);
  }

  100% {
    transform: rotate(-180deg);
  }
}

// The Lead ball is at the front of the stroke to round out the leading end
.pf-c-spinner__lead-ball {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  animation: pf-animation-spinner__lead-ball var(--pf-c-spinner--AnimationDuration) linear infinite;

  &::after {
    position: absolute;
    top: calc(50% - (var(--pf-c-spinner__ball--after--Height) / 2));
    right: 0;
    width: var(--pf-c-spinner__ball--after--Width);
    height: var(--pf-c-spinner__ball--after--Height);
    content: "";
    background-color: var(--pf-c-spinner__lead-ball--after--BackgroundColor);
    border-radius: 50%;
    transform-origin: top right;
  }
}

// The Lead ball rotates to match the line that grows and shrinks - first following the Clipper:after and then the Clipper itself.
@keyframes pf-animation-spinner__lead-ball {
  0% {
    transform: rotate(0deg);
  }

  34% {
    transform: rotate(-180deg);
  }

  100% {
    transform: rotate(-360deg);
  }
}

// The tail ball is at the end of the stroke to round out the tail end
.pf-c-spinner__tail-ball {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  animation: pf-animation-spinner__tail-ball var(--pf-c-spinner--AnimationDuration) linear infinite;

  &::after {
    position: absolute;
    top: calc(50% - (var(--pf-c-spinner__ball--after--Height) / 2));
    right: 0;
    width: var(--pf-c-spinner__ball--after--Width);
    height: var(--pf-c-spinner__ball--after--Height);
    content: "";
    background-color: var(--pf-c-spinner__tail-ball--after--BackgroundColor);
    border-radius: 50%;
    transform-origin: top right;
  }
}

// The Tail ball rotates to match the tail end of the line that grows and shrinks - first following the Clipper and then the Clipper:after
@keyframes pf-animation-spinner__tail-ball {
  0% {
    transform: rotate(0deg);
  }

  67.5% {
    transform: rotate(-180deg);
  }

  100% {
    transform: rotate(-360deg);
  }
}

// stylelint-disable selector-no-qualifying-type
svg.pf-c-spinner {
  --pf-c-spinner--diameter: var(--pf-global--icon--FontSize--xl);
  --pf-c-spinner--AnimationDuration: 1.4s;
  --pf-c-spinner--AnimationTimingFunction: linear;
  --pf-c-spinner--stroke-width: 10;

  // path
  --pf-c-spinner__path--Stroke: var(--pf-c-spinner--Color);
  --pf-c-spinner__path--StrokeWidth: var(--pf-c-spinner--stroke-width);
  --pf-c-spinner__path--AnimationTimingFunction: ease-in-out;

  // size modifiers
  --pf-c-spinner--m-sm--diameter: var(--pf-global--icon--FontSize--sm);
  --pf-c-spinner--m-md--diameter: var(--pf-global--icon--FontSize--md);
  --pf-c-spinner--m-lg--diameter: var(--pf-global--icon--FontSize--lg);
  --pf-c-spinner--m-xl--diameter: var(--pf-global--icon--FontSize--xl);

  animation: pf-c-spinner-animation-rotate calc(var(--pf-c-spinner--AnimationDuration) * 2) var(--pf-c-spinner--AnimationTimingFunction) infinite;

  // Modifiers change the variables for size variations
  &.pf-m-sm {
    --pf-c-spinner--diameter: var(--pf-c-spinner--m-sm--diameter);
  }

  &.pf-m-md {
    --pf-c-spinner--diameter: var(--pf-c-spinner--m-md--diameter);
  }

  &.pf-m-lg {
    --pf-c-spinner--diameter: var(--pf-c-spinner--m-lg--diameter);
  }

  &.pf-m-xl {
    --pf-c-spinner--diameter: var(--pf-c-spinner--m-xl--diameter);
  }
}
// stylelint-enable

.pf-c-spinner__path {
  width: 100%;
  height: 100%;
  transform-origin: 50% 50%;
  animation: pf-c-spinner-animation-dash var(--pf-c-spinner--AnimationDuration) var(--pf-c-spinner__path--AnimationTimingFunction) infinite;
  stroke: var(--pf-c-spinner--Color);
  stroke-linecap: round;
  stroke-dasharray: 283;
  stroke-dashoffset: 280;
  stroke-width: var(--pf-c-spinner--stroke-width);
}

@keyframes pf-c-spinner-animation-rotate {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

@keyframes pf-c-spinner-animation-dash {
  0% {
    stroke-dashoffset: 280;
    transform: rotate(0);
  }

  15% {
    stroke-width: calc(var(--pf-c-spinner__path--StrokeWidth) - 4);
  }

  40% {
    stroke-dashoffset: 150;
    stroke-dasharray: 220;
  }

  100% {
    stroke-dashoffset: 280;
    transform: rotate(720deg);
  }
}
