/*
    THE UPLOAD BUTTON'S OWN STYLESHEET.

    Everything Components/Shared/FileUploadButton.razor needs and nothing else.

    A LABEL STYLED AS A BUTTON, with the real input laid over it at zero opacity. The input keeps
    its place in the tab order and receives the click directly, so nothing has to be re-dispatched;
    the label carries the focus ring because the input it sits on is invisible. It is what the
    product offers instead of the native file button, whose words belong to the user agent, and
    instead of MudFileUpload's own activator.

    WHAT IT DOES NOT OWN. .sv-btn and .sv-checkbox are utilities and stay in utilities.css. This
    file composes the first and never mentions the second.
*/

/* WHAT IS LEFT AFTER .sv-btn. The label wears .sv-btn in the markup, so the shape, the height, the
   border, the type and the hover all come from the button vocabulary and are not repeated here.

   This block used to restate that whole recipe with a padding of its own and NO min-height, which
   is the one declaration .sv-btn exists to make: a control's height is the control's, never its
   contents'. So an upload button carrying a 20px Material icon stood taller than the primary
   action next to it, and did so at all ten upload sites. Reported as buttons being different
   sizes.

   Positioning is the one thing genuinely its own: the real <input> is laid over the label at zero
   opacity and needs a positioned ancestor to fill. */
.sv-upload {
  position: relative;
}

.sv-upload--block {
  display: flex;
  width: 100%;
}

.sv-upload__input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.sv-upload:focus-within {
  outline: 2px solid var(--sv-accent);
  outline-offset: 1px;
}

.sv-upload[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

.sv-upload[aria-disabled="true"] .sv-upload__input {
  cursor: not-allowed;
}

/* Busy is not disabled, and it must not look like it.

   A control the user has just handed work to is the one moment they most need to be able to read
   it, so the dimming that says "nothing to do here" is undone and the cursor says "wait" instead of
   "no". Both selectors carry the same class-plus-attribute weight, so this one is written with the
   extra class to win outright rather than by sitting further down the file. */
.sv-upload.sv-upload--busy[aria-disabled="true"] {
  opacity: 1;
  cursor: progress;
}

.sv-upload.sv-upload--busy[aria-disabled="true"] .sv-upload__input {
  cursor: progress;
}

/* Sized to the icon it replaces, so the button does not resize when work starts.
   The ring is the border colour and the moving arc is the accent - amber is the only chromatic
   colour in the system, and a spinner is a shape rather than text, so it takes the fill token. */
.sv-upload__spinner {
  flex: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid var(--sv-border-strong);
  border-top-color: var(--sv-accent-fill);
  animation: sv-upload-spin 700ms linear infinite;
}

@keyframes sv-upload-spin {
  to {
    transform: rotate(360deg);
  }
}

/* Rotation is the kind of motion that makes some people ill, so it comes off - but the control
   still has to look alive, or a reduced-motion user reads a stalled button. A slow opacity breath
   carries the same "working" without anything moving across the screen. */
@media (prefers-reduced-motion: reduce) {
  .sv-upload__spinner {
    animation: sv-upload-breathe 1600ms ease-in-out infinite;
    border-color: var(--sv-accent-fill);
  }
}

@keyframes sv-upload-breathe {
  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.35;
  }
}
