/*
 * buttons.css
 * Chip layout (inline-flex, gap, nowrap) comes from chip.css.
 *
 * Tones come from tones.css (.primary, .info, .danger, etc.) — this file
 * only knows about the .btn shape, variants, and states.
 */

.btn {
  /* Box — was the `btn` Uno shortcut. Chip layout comes from chip.css. */
  /* Vertical padding is shared with .field — see --control-padding-block. */
  padding:       var(--control-padding-block) var(--space-xl);
  border-radius: var(--btn-radius);
  font-size:     var(--text-md);
  line-height:   1.25rem;
  cursor:        pointer;
  transition:    background-color var(--motion-base), border-color var(--motion-base),
                 color var(--motion-base), box-shadow var(--motion-base),
                 filter var(--motion-base);

  /* Skin. --fill is the effective background; chip.css derives readable
     text from it. See the auto-contrast note there. */
  --tone-fill:    var(--bg-mix, var(--color-primary));
  background:     var(--fill, var(--tone-fill));
  color:          var(--on-fill, white);
  border:         var(--border-width) solid transparent;
  font-family:    var(--font-primary);
  font-weight:    var(--btn-font-weight);
  text-transform: var(--btn-text-transform);
  letter-spacing: var(--btn-letter-spacing);
  box-shadow:     var(--shadow-sm);
}

.btn:hover { filter: brightness(1.05); }

/* Focus ring: focus.css. It is not written here on purpose — a ring in
   box-shadow was erased by `.btn.outlined { box-shadow: none }` below. */

.btn:disabled,
.btn.disabled {
  opacity: 0.6;
  cursor:  not-allowed;
}

/*
 * ── Variants — read --bg-mix, restructure ───────────────────────
 *
 * .raised / .outlined / .ghost are Treatment classes: the README says
 * they compose onto anything, and surface.css honors all three. A button
 * has to honor all three too, or the claim is false — this is the same
 * rule as "a tone consumer takes all seven tones or it's a bug".
 *
 * ── Why three of them do not paint the tone directly ──────────────
 *
 * .outlined, .link and a toned .ghost render the tone as TEXT on a
 * surface, which is not the job a tone is tuned for. Painting --bg-mix
 * straight on failed AA across most of the grid — .btn.outlined was under
 * 4.5:1 on 34 of the 72 tone x theme pairs, as low as 1.19:1. So they read
 * --tone-ink, the tone through the legibility window (tones.css), and the
 * border takes the same color: a boundary at 1.99:1 is the variant not
 * being drawn at all.
 *
 * --btn-ink is the resolved answer as a NORMAL property, so the ::after
 * spinner below inherits it — --tone-ink is registered `inherits: false`
 * and a pseudo-element would compute nothing from its own absent tone.
 *
 * Untoned, .outlined and .link keep the brand accent through the same
 * window; .ghost keeps --ink-soft, because a ghost button's text IS the
 * button and a neutral one is the common case (see below).
 */
.btn:is(.outlined, .link) {
  --accent-ink: oklch(from var(--color-primary)
                  clamp(var(--tone-l-min), l, var(--tone-l-max)) c h);
  --btn-ink:    var(--tone-ink, var(--accent-ink));
}
.btn.ghost {
  --btn-ink: var(--tone-ink, var(--ink-soft));
}

.btn.outlined {
  background:   var(--surface);
  color:        var(--btn-ink);
  border-color: var(--btn-ink);
  box-shadow:   none;
}

/* Same fill, lifted. The elevation is the whole variant. */
.btn.raised {
  box-shadow: var(--shadow-md);
}

/*
 * No fill, no border — the low-emphasis button. Toolbar actions, row
 * actions, "Cancel" beside a primary.
 *
 * Untoned it takes --ink-soft rather than the brand accent. A ghost
 * button's text IS the button, and --ink-soft is 7.3:1 where the raw
 * accent on --surface is 3.96:1; a neutral ghost is the common case
 * anyway. A tone class opts into the tone deliberately, exactly like
 * .field-hint and .tile-delta — and gets it through the window above.
 */
.btn.ghost {
  background:   transparent;
  color:        var(--btn-ink);
  border-color: transparent;
  box-shadow:   none;
}
.btn.ghost:hover {
  background: color-mix(in srgb, var(--bg-mix, var(--ink)) 8%, transparent);
  /* The brightness filter is for solid fills; on transparent it does nothing
     but wash out the label. */
  filter: none;
}

.btn.link {
  background:    transparent;
  color:         var(--btn-ink);
  box-shadow:    none;
  padding-left:  0;
  padding-right: 0;
}
.btn.link:hover {
  text-decoration: underline;
  filter:          none;
}

/*
 * ── Loading ─────────────────────────────────────────────────────
 * Hides the label with `color: transparent` rather than removing it, so
 * the button keeps its width (no layout jump) and screen readers still
 * have something to read. Draw the spinner with ::after so no extra
 * markup is needed.
 *
 *   <button class="btn primary loading" aria-busy="true" disabled>Save</button>
 *
 * aria-busy is the part that actually communicates the state; the class
 * only draws it. Keep `disabled` so the control is genuinely inert —
 * pointer-events alone still allows keyboard activation.
 */
.btn.loading {
  position:       relative;
  color:          transparent;
  pointer-events: none;
}
.btn.loading::after {
  content:       "";
  position:      absolute;
  inset:         0;
  margin:        auto;
  inline-size:   1em;
  block-size:    1em;
  border:        2px solid color-mix(in srgb, var(--on-fill, white) 30%, transparent);
  border-block-start-color: var(--on-fill, white);
  border-radius: 50%;
  animation:     fjs-spin var(--motion-spin) linear infinite;
}
/* Outlined and link buttons draw their spinner in the tone, not on it —
   the same --btn-ink their label takes, so a spinner cannot be the one
   thing on the button drawn at 1.99:1. */
.btn.loading:is(.outlined, .link)::after {
  border-color: color-mix(in srgb, var(--btn-ink) 30%, transparent);
  border-block-start-color: var(--btn-ink);
}

/*
 * ── Square button — equal padding, square via aspect-ratio ────────
 *
 * The icon-only button.
 *
 *   <button class="btn square" aria-label="Delete invoice">
 *     <svg aria-hidden="true">…</svg>
 *   </button>
 *
 * The name is `.square`, not `.icon`, since v0.10. `.icon` now means "this
 * element IS an icon" (icon.css) — the Icon vocabulary term — and one
 * class cannot mean both "a button shaped for an icon" and "an icon", or
 * `<button class="btn icon">` would try to size the button itself to
 * 1.15em. `.square` also happens to describe what the class does, which
 * `.icon` never did.
 *
 * The child sizing that used to live here is in icon.css, where it is one
 * rule for the whole package instead of three drifting copies.
 *
 * `aria-label` on the button is not optional: with no text content there
 * is nothing else to announce.
 */
.btn.square {
  padding:      0.45em;   /* equal on all sides; scales with font-size */
  aspect-ratio: 1;
  gap:          0;
}
