/* ============================================================
   Helikona — Buttons & links
   One box, one type ramp, one press convention, for every
   labelled action across every Helikona surface.

   Depends on tokens.css — import that first.

   Compose three parts: `.btn` (the box) + a look (`-primary`,
   `-secondary`, `-outline`, `-ghost`, `-danger`,
   `-danger-outline`) + an optional size (`-md`, `-sm`, `-icon`).
   `.btn-quiet` stands alone — it's text, not a box.

   Three conventions run through this file. Each is load-bearing;
   none of them is a stylistic tic:

   1. Every `:hover` sits inside `@media (hover: hover)`.
      Unguarded, a touch browser fakes hover on tap and then keeps
      it, leaving the control looking permanently focused.
   2. `:active` swaps colour, not lightness, and sets
      `transition: none`. A finger covers most of a control, so a
      change in lightness is hidden underneath it while a change in
      hue still shows around the edge — and feedback that eases in
      over 180ms has already missed the press it was meant to
      confirm.
   3. The odd-numbered padding is not a typo. Every size carries a
      1px transparent border so filled and outlined buttons net the
      same box; each value is one less than the round number it
      makes up to.
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  cursor: pointer;
  border: 1px solid transparent;
  font-family: var(--font-display);
  font-weight: 600;
  border-radius: 7px;
  /* The page scale, on the base rather than on each look — a look is a
   * colour scheme, not a size, and `.btn.btn-outline` with no size class
   * should still be a button rather than a 21px sliver with the label
   * touching both edges. The size classes below still win, since they come
   * later. */
  padding: 10px 21px;
  font-size: 15px;
  transition: opacity 0.18s, background 0.18s, border-color 0.18s;
  white-space: nowrap;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.btn-primary {
  background: var(--leaf-light);
  color: var(--deep-jungle);
}
@media (hover: hover) {
  .btn-primary:hover { opacity: 0.88; }
}
.btn-primary:active:not(:disabled) {
  background: var(--press-fill);
  color: var(--press-text);
  transition: none;
}
.btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }

/* The secondary action beside a primary one — "Cancel" next to "Approve",
 * "Save" next to a rename's cancel. Outlined rather than filled, so it
 * doesn't compete with `.btn-primary` for attention in the same row. */
.btn-secondary {
  background: transparent;
  color: var(--text);
  border-color: var(--border);
}
@media (hover: hover) {
  .btn-secondary:hover { background: var(--surface-hover); }
}
.btn-secondary:active:not(:disabled) {
  background: var(--surface-active);
  transition: none;
}
.btn-secondary:disabled { opacity: 0.5; cursor: not-allowed; }

/* The section-level action — "Add contact" above a list, "Create link",
 * "Save" on a form. Branded like `.btn-primary` but outlined, so a page
 * can carry several without any of them claiming to be the one thing to
 * do. Same relationship `.icon-outline-btn` has to `.icon-solid-btn`.
 *
 * `--leaf-pale` reads as a pale green wash in light mode and a dark one
 * in dark mode, so one declaration covers both. */
/* --leaf-strong rather than --leaf-light: this look puts the brand green in
 * TEXT on a light ground, where --leaf-light measures 2.16:1 against the
 * 4.5:1 WCAG 1.4.3 asks of a label. --leaf-strong is the darker jungle green
 * in light mode and --leaf-light again in dark, so the button looks the same
 * on a dark ground and merely becomes legible on a light one. */
.btn-outline {
  background: transparent;
  border-color: var(--leaf-strong);
  color: var(--leaf-strong);
}
@media (hover: hover) {
  .btn-outline:hover { background: var(--leaf-pale); }
}
.btn-outline:active:not(:disabled) {
  background: var(--leaf-light);
  color: var(--deep-jungle);
  transition: none;
}
.btn-outline:disabled { opacity: 0.5; cursor: not-allowed; }

/* Borderless — the "Cancel" that sits beside an outline button and
 * shouldn't draw a second box around itself to say so. */
.btn-ghost {
  background: transparent;
  color: var(--text-muted);
}
@media (hover: hover) {
  .btn-ghost:hover { background: var(--surface-hover); color: var(--text); }
}
.btn-ghost:active:not(:disabled) {
  background: var(--surface-active);
  transition: none;
}
.btn-ghost:disabled { opacity: 0.5; cursor: not-allowed; }

/* Delete's confirm pair. */
.btn-danger,
.btn-danger-outline {
  border-color: var(--action-text);
  color: var(--action-text);
  background: transparent;
}
.btn-danger {
  background: var(--action-text);
  color: var(--surface);
}
@media (hover: hover) {
  .btn-danger:hover { filter: brightness(1.1); }
  .btn-danger-outline:hover { background: var(--action-bg); }
}
/* Both go the same way on press — the outline fills to match the solid,
 * and the solid deepens to the rust the outline borrows its colour from
 * — so the pair reads as one control being worked. */
.btn-danger:active:not(:disabled) {
  background: var(--iron-oxide);
  border-color: var(--iron-oxide);
  filter: none;
  transition: none;
}
.btn-danger-outline:active:not(:disabled) {
  background: var(--action-text);
  color: var(--surface);
  transition: none;
}
.btn-danger:disabled,
.btn-danger-outline:disabled { opacity: 0.5; cursor: not-allowed; }

/* The smallest action there is — "change", "remove", sitting inside a
 * line of body text. Not a `.btn`: a box here would outrank the sentence
 * it annotates. Dotted underline going solid is the press, since there's
 * no fill to swap.
 *
 * Body font rather than `.btn`'s display face, because it's set in a
 * run of body text and has to match what surrounds it. */
.btn-quiet {
  padding: 0;
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: 12px;
  color: var(--text-muted);
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  transition: color 0.18s;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
@media (hover: hover) {
  .btn-quiet:hover { color: var(--text); text-decoration-style: solid; }
}
/* Same wash `.link:active` uses, for the same reason: there's no fill to
 * swap, and the dotted-to-solid change alone is a hair's width of feedback
 * on a control this small. Colour-agnostic, so the danger cut below keeps
 * its own without redeclaring the press. */
.btn-quiet:active:not(:disabled) {
  text-decoration-style: solid;
  background: var(--surface-active);
  border-radius: 3px;
  box-shadow: 0 0 0 3px var(--surface-active);
  transition: none;
}
.btn-quiet:disabled { opacity: 0.5; cursor: not-allowed; }

/* The destructive cut — the "remove" that unlinks one record from
 * another. */
.btn-quiet-danger { color: var(--action-text); }
@media (hover: hover) {
  .btn-quiet-danger:hover { color: var(--action-text); }
}

/* A `<button>` that reads as a link — an in-row action that opens a panel
 * in place rather than navigating ("Note", "Copy link", "Close"). Pair it
 * with `.link`, which supplies the colour and the press; all this does is
 * strip the button chrome from around it. */
.btn-link {
  padding: 0;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.btn-link:disabled { opacity: 0.5; cursor: not-allowed; }

/* Sizes. Declared after every look above so they win on padding without
 * needing `!important` or a doubled class.
 *
 * `-md` is the form scale: the buttons that sit under a field, where the
 * default 15px/22px is too big for the input it follows. `-sm` is the
 * tight scale — an approve/cancel card, an inline rename, an in-row
 * action. */
.btn-md { padding: 8px 16px; font-size: 14px; }
.btn-sm { padding: 5px 11px; font-size: 13px; }

/* Icon-only, at either scale — squares the padding so the glyph sits in a
 * square box rather than a wide one. Callers must supply an accessible
 * name; the glyph alone is not one. */
.btn-icon { padding: 5px; }
.btn-icon.btn-md { padding: 8px; }

/* Thumb-sized, whatever the look. Everything in a delete confirm takes
 * it: it sits under a "can't be undone" warning, so the tap that commits
 * shouldn't be a small one — and nor should the tap that backs out. */
.btn-tall { min-height: 44px; }

/* Mid-submit: you've taken the action and the server hasn't come back yet.
 * Not the same as `:disabled`, which says you can't take it — plenty of
 * these buttons stay clickable while pending. */
.btn[data-pending] { opacity: 0.5; cursor: wait; }

/* ── Keyboard focus ────────────────────────────────────────────────
 * WCAG 2.4.7 Focus Visible. Every control in this file, in one rule.
 *
 * `:focus-visible` rather than `:focus`, so a mouse press doesn't leave a
 * ring behind — that is the reason the ring was so often deleted from
 * stylesheets in the first place, and `:focus-visible` is the fix for it
 * rather than an excuse to ship nothing.
 *
 * The ring sits OUTSIDE the control on a 2px offset, so it is read against
 * the page rather than against a fill it might match. That is what lets one
 * colour serve all six looks: on `.btn-primary` a ring drawn on the button
 * itself would be leaf-on-leaf, but two pixels out it lands on the page and
 * measures 5.8:1 in light and 8.6:1 in dark.
 *
 * `outline` rather than `box-shadow` — it follows the border radius on its
 * own, it survives a forced-colours / high-contrast mode where a shadow is
 * discarded, and it never participates in layout. */
.btn:focus-visible,
.btn-quiet:focus-visible,
.btn-link:focus-visible,
.icon-outline-btn:focus-visible,
.icon-solid-btn:focus-visible,
.link:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* ── Icon-only page actions ────────────────────────────────────────
 * For a toolbar or section header where labelled buttons would crowd the
 * heading. 36px, growing to 44px below `sm` so the tap target stays
 * comfortable on a phone (the glyph stays the same size, centred).
 * Solid outranks outline, the same pairing the labelled buttons use. */
.icon-outline-btn,
.icon-solid-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  width: 36px;
  border-radius: 4px;
  border: 1px solid var(--leaf-strong);
  cursor: pointer;
  transition: background 0.18s, color 0.18s;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}
/* --leaf-strong for the same reason `.btn-outline` takes it: the glyph is
 * the only thing in this control, so it has to carry the contrast alone. */
.icon-outline-btn {
  color: var(--leaf-strong);
  background-color: transparent;
}
@media (hover: hover) {
  /* --leaf-pale rather than a hardcoded leaf tint, so this matches
   * `.btn-outline:hover` and the package holds no literal brand hex. */
  .icon-outline-btn:hover {
    background: var(--leaf-pale);
  }
}
/* These are the primary tap target on every heading row, and a lone glyph
 * gives no other sign it registered — so this one fills rather than
 * washes. */
.icon-outline-btn:active {
  background: var(--leaf-light);
  color: var(--deep-jungle);
  transition: none;
}
.icon-solid-btn {
  color: var(--deep-jungle);
  background-color: var(--leaf-light);
}
@media (hover: hover) {
  .icon-solid-btn:hover {
    filter: brightness(1.08);
  }
}
/* Already filled, so a press has to go the other way — the same swap
 * `.btn-primary:active` makes, and the same token pair. */
.icon-solid-btn:active {
  background-color: var(--press-fill);
  color: var(--press-text);
  filter: none;
  transition: none;
}
@media (max-width: 639px) {
  .icon-outline-btn,
  .icon-solid-btn {
    height: 44px;
    width: 44px;
  }
}

/* ── Text links ────────────────────────────────────────────────────
 * Every tappable run of text that isn't a button: breadcrumbs, jump
 * strips, secondary in-cell references, pagination arrows. */
.link {
  color: var(--link);
  /* The platform's own grey tap box lags the touch and squares off
   * against the wash below; we're supplying the press state ourselves. */
  -webkit-tap-highlight-color: transparent;
  /* Skips the legacy 300ms double-tap-zoom wait. */
  touch-action: manipulation;
}

/* Underline *and* wash. The underline alone says nothing on a link that
 * already carries one, and a wash alone is easy to miss behind a finger
 * on a single word.
 *
 * `box-shadow` spreads the wash past the tight text box rather than
 * padding, which would shove the line around at the moment of the tap. */
.link:active {
  text-decoration: underline;
  text-underline-offset: 3px;
  background: var(--surface-active);
  border-radius: 3px;
  box-shadow: 0 0 0 3px var(--surface-active);
  transition: none;
}
