/* @ofself/shell — .ofself-btn: the workhorse button. Flat and square — a grid
 * cell, never an island: no radius, no shadow, hover is an ink wash. Three
 * voices (outline · solid · quiet) × two tones (neutral · danger) × two sizes
 * (md · sm). The outline/solid skins ARE the old ConfirmDialog pair, promoted
 * to the canonical house button. */

@layer ofself.tokens, ofself.components;

@layer ofself.components {

.ofself-btn {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-family: var(--ofself-font-sans);
  font-size: var(--ofself-text-sm);
  padding: 8px 16px;
  border: 1px solid transparent;
  border-radius: 0;
  background: none;
  color: var(--shell-ink);
  cursor: pointer;
  transition: background var(--dur-fade, 0.4s) ease, border-color var(--dur-fade, 0.4s) ease, color var(--dur-fade, 0.4s) ease;
}
/* sm — compact, for dense rows and toolbars */
.ofself-btn--sm { padding: 4px 10px; gap: 5px; }

/* icon slots inherit the label's ink; the glyph sizes itself */
.ofself-btn__leading,
.ofself-btn__trailing { display: inline-flex; align-items: center; }

/* ── outline (default) — the seam-bordered cell; ink wash on hover ── */
.ofself-btn--outline { border-color: var(--border-medium, rgb(var(--shell-ink-rgb) / 0.14)); }
.ofself-btn--outline:hover:not(:disabled) { background: var(--ofself-control-hover, rgb(var(--shell-ink-rgb) / 0.05)); }
.ofself-btn--outline.ofself-btn--danger { border-color: var(--ofself-danger, #b0524a); color: var(--ofself-danger, #b0524a); }
.ofself-btn--outline.ofself-btn--danger:hover:not(:disabled) {
  background: var(--ofself-danger, #b0524a);
  color: var(--text-on-accent, #fff);
}

/* ── solid — the accent-filled primary ── */
.ofself-btn--solid { background: var(--accent); border-color: var(--accent); color: var(--text-on-accent, #fff); }
.ofself-btn--solid:hover:not(:disabled) { background: var(--accent-secondary, var(--accent)); }
.ofself-btn--solid.ofself-btn--danger { background: var(--ofself-danger, #b0524a); border-color: var(--ofself-danger, #b0524a); }
.ofself-btn--solid.ofself-btn--danger:hover:not(:disabled) { background: var(--ofself-danger-strong, #953f38); }

/* ── quiet — borderless text; the wash is the only hover chrome ── */
.ofself-btn--quiet { color: var(--text-secondary); }
.ofself-btn--quiet:hover:not(:disabled) { background: var(--ofself-control-hover, rgb(var(--shell-ink-rgb) / 0.05)); color: var(--shell-ink); }
.ofself-btn--quiet.ofself-btn--danger { color: var(--ofself-danger, #b0524a); }
.ofself-btn--quiet.ofself-btn--danger:hover:not(:disabled) {
  background: color-mix(in srgb, var(--ofself-danger, #b0524a) 10%, transparent);
  color: var(--ofself-danger, #b0524a);
}

/* disabled — fades like every other control on the grid */
.ofself-btn:disabled { cursor: not-allowed; }
.ofself-btn:disabled:not(.is-busy) { opacity: 0.3; }

/* busy — the in-flight state: label dims, a pulsing ellipsis appends. No
   spinner; progress reads as breath, not chrome. */
.ofself-btn.is-busy { cursor: progress; }
.ofself-btn.is-busy .ofself-btn__label { opacity: 0.55; }
.ofself-btn.is-busy .ofself-btn__label::after {
  content: '…';
  margin-inline-start: 0.35em;
  animation: ofself-btn-busy 1.1s ease-in-out infinite;
}
@keyframes ofself-btn-busy {
  0%, 100% { opacity: 0.25; }
  50% { opacity: 0.9; }
}
@media (prefers-reduced-motion: reduce) {
  .ofself-btn.is-busy .ofself-btn__label::after { animation: none; }
}

/* The house ring must be restated here: buttons ride portaled surfaces (Modal,
   menus at <body>), OUTSIDE the .shell subtree, so reset.css's :focus-visible
   default never reaches them (tokens do — they live on :root). */
.ofself-btn:focus-visible { outline: var(--focus-ring); outline-offset: var(--focus-ring-offset); }

} /* @layer ofself.components */
