/* admin-controls.css — buttons, chips, badges and pills under KasirBiru.
 *
 * Overrides pkg/webui's components.css / badges.css / datatable.css for the
 * backoffice only. Colour and radius already arrived through gen/admin-theme.css;
 * this file adds the things the mockup expresses as BEHAVIOUR — press feedback,
 * a hover lift, and a loading state — plus the pill typography.
 *
 * Every duration and curve here is a token from motion-bo. The mockup states the
 * contract in prose next to a live demo: press feedback is 120 ms, enter is
 * ease-out and never ease-in, and exit is faster than enter. */

/* ---- press feedback ------------------------------------------------------
 * 120 ms, scale .97. The single cheapest thing in the whole redesign: it is the
 * difference between a button that acknowledges a tap and one that appears not
 * to have noticed on a slow connection. */
.btn {
  position: relative;
  transition: background-color var(--sn-motion-duration-short) var(--sn-motion-ease),
              border-color var(--sn-motion-duration-short) var(--sn-motion-ease),
              color var(--sn-motion-duration-short) var(--sn-motion-ease),
              box-shadow var(--sn-motion-duration-short) var(--sn-motion-ease),
              transform var(--sn-motion-duration-press) var(--sn-motion-ease-out);
}
.btn:active:not(:disabled) { transform: scale(0.97); }
.btn-icon:active:not(:disabled) { transform: scale(0.92); }

/* The primary button lifts on hover instead of only darkening. The glow is the
 * button's own colour at low alpha, so it stays correct in both schemes without
 * a second declaration. */
.btn-primary:hover:not(:disabled) {
  background: color-mix(in srgb, var(--sn-primary) 86%, var(--sn-on-surface));
  box-shadow: 0 8px 20px color-mix(in srgb, var(--sn-primary) 26%, transparent);
}

.btn-outlined {
  border-color: var(--sn-outline-variant);
  background: var(--sn-surface);
  color: var(--sn-on-surface);
}
.btn-outlined:hover:not(:disabled) {
  border-color: var(--sn-primary);
  color: var(--sn-primary-text);
}

/* ---- loading state -------------------------------------------------------
 * The mockup demonstrates a button that spins and then draws a tick. That demo
 * drives itself from a setTimeout; here the truth is on the wire, so the state
 * is htmx's own .htmx-request class — set for exactly as long as the request is
 * in flight, with no JavaScript of ours involved.
 *
 * The label stays in place and fades rather than being replaced, because
 * swapping it for a spinner reflows the button mid-press and the row jumps. */
.btn.htmx-request {
  pointer-events: none;
  color: transparent;
}
.btn.htmx-request::after {
  content: "";
  position: absolute;
  width: 1rem;
  height: 1rem;
  border: 2px solid currentColor;
  border-radius: var(--sn-shape-corner-full);
  border-block-start-color: transparent;
  color: var(--sn-on-primary);
  animation: bo-spin 0.75s linear infinite;
}
.btn-outlined.htmx-request::after,
.btn-text.htmx-request::after,
.btn-icon.htmx-request::after,
.btn-danger.htmx-request::after { color: var(--sn-primary-text); }

/* ---- chips, badges, pills ------------------------------------------------
 * The mockup's tags are heavier and tighter than Sneat's: 700 weight, a little
 * letter-spacing, and a fully-round end cap. They are read at a glance in a
 * column of forty rows, not as prose. */
.chip,
.badge,
.status-pill {
  font-size: var(--sn-type-overline-size);
  font-weight: 700;
  letter-spacing: 0.03em;
  border-radius: var(--sn-shape-corner-full);
  white-space: nowrap;
}

/* Tonal, not filled. A row of saturated chips forty deep is a colour chart; the
 * container pairs carry the same meaning at a fraction of the shout, and each
 * `on-*-container on *-container` pair is gated at 4.5:1 exactly as the filled
 * pair was. The filled forms stay available for the one-off case (a single
 * chip in a card header) via the .chip-solid modifier below. */
.chip-success { background: var(--sn-success-container); color: var(--sn-on-success-container); }
.chip-info    { background: var(--sn-info-container);    color: var(--sn-on-info-container); }
.chip-warning { background: var(--sn-warning-container); color: var(--sn-on-warning-container); }
.chip-error   { background: var(--sn-error-container);   color: var(--sn-on-error-container); }

.chip-solid.chip-success { background: var(--sn-success); color: var(--sn-on-success); }
.chip-solid.chip-info    { background: var(--sn-info);    color: var(--sn-on-info); }
.chip-solid.chip-warning { background: var(--sn-warning); color: var(--sn-on-warning); }
.chip-solid.chip-error   { background: var(--sn-error);   color: var(--sn-on-error); }

/* The 7th role. KasirBiru carries a premium purple Sneat never had; it marks the
 * paid tiers in the package table and the upgrade offer. */
.chip-prem {
  background: var(--sn-prem-container);
  color: var(--sn-on-prem-container);
}
.badge-prem {
  background: var(--sn-prem-container);
  color: var(--sn-on-prem-container);
}

/* A live indicator: the dot pulses, the text does not. Used where a shift or a
 * device is currently open. */
.dot-live {
  display: inline-block;
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: var(--sn-shape-corner-full);
  background: currentColor;
  animation: bo-pulse 1.6s ease-out infinite;
}

/* ---- filter chip strip --------------------------------------------------- */
.filters .chip,
.filters .badge {
  transition: background-color var(--sn-motion-duration-short) var(--sn-motion-ease),
              transform var(--sn-motion-duration-press) var(--sn-motion-ease-out);
}
.filters .chip:active,
.filters .badge:active { transform: scale(0.95); }

/* ---- toggle rows ---------------------------------------------------------
 * Deliberately `>` and not a descendant selector. app.css already owns
 * `.toggle-list label`, and TestToggleRowWraps finds that rule with a regex that
 * returns the FIRST match across the linked sheets — whose concatenation order
 * is map iteration, i.e. random. A second rule spelled identically would make
 * that gate pass or fail depending on the run. The child combinator matches the
 * same elements and cannot be mistaken for the rule the gate is watching. */
.toggle-list > label {
  transition: background-color var(--sn-motion-duration-short) var(--sn-motion-ease);
}
