.btn {
  align-items: center;
  background-color: var(--btn-background, transparent);
  border-radius: var(--btn-border-radius, 0.5em);
  border: var(--btn-border-size, 1px) solid var(--btn-border-color, var(--color-border-interactive));
  color: var(--btn-color, var(--color-ink));
  cursor: pointer;
  display: inline-flex;
  font-size: 0.95em;
  font-weight: 500;
  gap: var(--btn-gap, 0.5em);
  justify-content: center;
  letter-spacing: -0.01em;
  padding: var(--btn-padding, 0.55em 1.1em);
  pointer-events: auto;
  text-decoration: none;
  transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease, opacity 150ms ease;

  /* Outlined (default) button: hover lifts the fill + brightens the border. */
  @media (any-hover: hover) {
    &:where(:not([disabled]):hover) {
      background-color: var(--btn-hover-background, var(--color-subtle-light));
      border-color: var(--btn-hover-border, var(--color-subtle-dark));
    }
  }

  &:where(:has(img, .icon)) {
    text-align: start;

    img, .icon {
      block-size: var(--btn-icon-size, 1.1em);
      inline-size: var(--btn-icon-size, 1.1em);
      max-inline-size: unset;
    }
  }

  &[disabled],
  &:has([disabled]),
  &[type=submit]:disabled {
    cursor: not-allowed;
    opacity: 0.5;
    pointer-events: none;
  }

  @media print {
    display: none;
  }
}

/* Submitting state — Turbo flags the enclosing form [aria-busy] for the whole
   round-trip; freeze the submit button and overlay a spinner (no JS) for
   instant "working" feedback. The spinner border picks up --btn-color so it
   stays legible on any variant. */
form[aria-busy="true"] :is(button[type="submit"], button:not([type]), input[type="submit"]).btn {
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  /* The "working" look waits 250ms: a fast round-trip swaps the button before
     anything changes, so nothing ever flashes. Only a genuinely slow response
     hides the label and fades the spinner in. */
  form[aria-busy="true"] :is(button[type="submit"], button:not([type])).btn {
    color: transparent !important;
    position: relative;
    transition: color 150ms ease 250ms;

    &::after {
      animation:
        appear 150ms ease-out 250ms both,
        spin 600ms linear infinite;
      block-size: 1.1em;
      border: 2px solid var(--btn-color, var(--color-ink));
      border-inline-end-color: transparent;
      border-radius: 50%;
      content: "";
      inline-size: 1.1em;
      inset: 0;
      margin: auto;
      position: absolute;
    }
  }

  form[aria-busy="true"] input[type="submit"].btn {
    animation: pulse 900ms ease-in-out 250ms infinite;
  }
}

@media (prefers-reduced-motion: reduce) {
  form[aria-busy="true"] :is(button[type="submit"], button:not([type]), input[type="submit"]).btn {
    opacity: 0.6;
  }
}

.btn--reversed {
  --btn-background: var(--color-ink);
  --btn-color: var(--color-bg);
  --outline-color: var(--color-ink);
}

.btn--negative {
  --btn-background: var(--color-negative);
  --btn-color: var(--color-ink-reversed);
  --outline-color: var(--color-negative);
}

.btn--positive {
  --btn-background: var(--color-positive);
  --btn-color: var(--color-ink-reversed);
  --outline-color: var(--color-positive);
}

:is(.btn--reversed, .btn--negative, .btn--positive) {
  --btn-border-color: var(--btn-background);

  /* Filled buttons keep their fill and just dim slightly on hover. */
  @media (any-hover: hover) {
    &:where(:not([disabled]):hover) {
      --btn-hover-background: var(--btn-background);
      --btn-hover-border: var(--btn-background);
      opacity: 0.85;
    }
  }
}

.btn--small {
  --btn-padding: 0.4em 0.9em;
  font-size: 0.85em;
}

.btn--large {
  --btn-padding: 0.75em 2em;
  font-size: 1.1em;
}
