/* Component kit styles.
 *
 * Every value here resolves through an --app-* token from tokens.css. No raw
 * Open Props or Stellar name appears, so changing the styling source stays a
 * one-file change (see ADR 0002). */

/* Hidden ---------------------------------------------------------------- */

/* The `hidden` attribute has to beat the kit's own display rules.
 *
 * The UA stylesheet's [hidden] { display: none } is a single attribute
 * selector, so ANY class rule that sets display outranks it — and .ui-button
 * sets display: inline-flex. A button carrying `hidden` was therefore reported
 * as hidden to assistive technology while staying fully visible and clickable
 * to everyone else, which is the worst of both: Pong's "Leave seat" control sat
 * next to "Take a seat" at all times, and nothing anywhere errored.
 *
 * !important is the right tool here and not a shortcut. `hidden` is a
 * browser-level assertion that an element is not to be rendered in any
 * presentation; a component's own layout rule has no business overriding it. */
[hidden] {
  display: none !important;
}

/* Focus ---------------------------------------------------------------- */

/* One focus treatment for the whole kit. :focus-visible rather than :focus so
 * a mouse click does not leave a ring behind, while keyboard users always get
 * one. */
.ui-button:focus-visible,
.ui-field__input:focus-visible,
.ui-table__scroll:focus-visible,
.ui-dialog__close:focus-visible {
  outline: 2px solid var(--app-brand);
  outline-offset: 2px;
}

.ui-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Button --------------------------------------------------------------- */

/* The base is a complete medium button, not a shell that needs a modifier.
 *
 * Every padding value used to live in --sm/--md/--lg, so a button written
 * without a size class rendered with padding: 0 and its label against the
 * edges. Measured at exactly that on the landing page's own call to action.
 * ui.Button always emits a size, so this only bites hand-written markup — which
 * is precisely what owner-authored HTML and page copy are.
 *
 * font-size is set explicitly for the same class of reason: `font: inherit`
 * takes the size of whatever encloses the button, so the same button was 16px
 * in a card and 20px inside .prose. A control should not resize according to
 * the paragraph it happens to sit in.
 *
 * Order matters — `font: inherit` is a shorthand and resets size and weight, so
 * both have to come after it. */
.ui-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--app-space-2);
  font: inherit;
  font-family: var(--app-font-sans);
  font-size: var(--app-text-2);
  /* Actions read as actions. The body face is 400; at the same weight a button
     label looks like a sentence that happens to have a box around it. */
  font-weight: 550;
  line-height: 1.2;
  padding: var(--app-space-2) var(--app-space-4);
  border: 1px solid transparent;
  border-radius: var(--app-radius-1);
  cursor: pointer;
  text-decoration: none;
  /* Stops a narrow button from becoming an unhittable sliver on touch. */
  min-height: 2.5rem;
}

.ui-button:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* --md is deliberately empty: the base above IS the medium button. Repeating
 * its padding and size here would mean two places to change and two places to
 * drift apart. The class stays declared because ui.Button always emits it, and
 * a rule that says so is clearer than an absence. */
.ui-button--sm { padding: var(--app-space-1) var(--app-space-3); font-size: var(--app-text-1); min-height: 2rem; }
.ui-button--md { /* see above */ }
.ui-button--lg { padding: var(--app-space-3) var(--app-space-5); font-size: var(--app-text-3); min-height: 3rem; }

.ui-button--primary   { background: var(--app-brand);  color: var(--app-brand-on); }
/* For the one action a page is actually for, where --primary is already spent
 * on the ordinary actions around it. On this site that is the landing page's
 * contact button, sitting above a grid of Play now buttons: same variant meant
 * the same colour, and the thing the page exists for looked like one more card
 * action.
 *
 * Accent rather than an invented colour, so it resolves through the same ramp
 * as everything else and its readable foreground is computed at generation
 * time. It is also the leaf colour, which ties the button to the tree above it.
 *
 * Declared here and not in the Go kit on purpose: ui.Button's Variant type
 * lives in internal/platform, and platform changes belong upstream in the
 * template repo (ADR 0007). Hand-written markup can name the class directly,
 * which is all this needs. */
.ui-button--accent    { background: var(--app-accent); color: var(--app-accent-on); }
.ui-button--danger    { background: var(--app-danger); color: var(--app-danger-on); }
.ui-button--secondary { background: var(--app-surface-raised); color: var(--app-ink); border-color: var(--app-line); }
.ui-button--ghost     { background: transparent; color: var(--app-ink); }

.ui-button--ghost:hover:not(:disabled),
.ui-button--secondary:hover:not(:disabled) {
  background: var(--app-surface-sunken);
}

/* Datastar sets this attribute for the duration of a request via
 * data-indicator, so a busy button needs no bespoke JavaScript. */
.ui-button[data-loading] { cursor: progress; opacity: 0.7; }

/* Field ---------------------------------------------------------------- */

.ui-field {
  display: grid;
  gap: var(--app-space-1);
  margin-block-end: var(--app-space-4);
}

.ui-field__label {
  font-size: var(--app-text-1);
  color: var(--app-ink-dim);
}

.ui-field__required { color: var(--app-danger); margin-inline-start: 0.25ch; }

.ui-field__input {
  font: inherit;
  font-family: var(--app-font-sans);
  padding: var(--app-space-2) var(--app-space-3);
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius-0);
  background: var(--app-surface);
  color: var(--app-ink);
  min-height: 2.5rem;
}

.ui-field__input:disabled { opacity: 0.55; cursor: not-allowed; }

/* Driven by aria-invalid rather than a separate class, so the visual state
 * cannot drift out of sync with what assistive technology is told. */
.ui-field__input[aria-invalid="true"] { border-color: var(--app-danger); }

.ui-field__hint  { margin: 0; font-size: var(--app-text-1); color: var(--app-ink-dim); }
.ui-field__error { margin: 0; font-size: var(--app-text-1); color: var(--app-danger); }

/* Dialog --------------------------------------------------------------- */

.ui-dialog {
  padding: 0;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius-2);
  background: var(--app-surface-raised);
  color: var(--app-ink);
  max-width: min(40rem, calc(100vw - var(--app-space-5)));
  width: 100%;
}

.ui-dialog::backdrop { background: rgb(0 0 0 / 0.5); }

.ui-dialog__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--app-space-4);
  padding: var(--app-space-4);
  border-bottom: 1px solid var(--app-line);
}

.ui-dialog__title { margin: 0; font-size: var(--app-text-3); }

.ui-dialog__close {
  font: inherit;
  font-size: var(--app-text-3);
  line-height: 1;
  background: none;
  border: 0;
  border-radius: var(--app-radius-0);
  color: var(--app-ink-dim);
  cursor: pointer;
  min-width: 2.5rem;
  min-height: 2.5rem;
}

.ui-dialog__body { padding: var(--app-space-4); }

/* Table ---------------------------------------------------------------- */

.ui-table__scroll {
  overflow-x: auto;
  border: 1px solid var(--app-line);
  border-radius: var(--app-radius-1);
}

.ui-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--app-font-sans);
}

.ui-table caption {
  text-align: start;
  padding: var(--app-space-3) var(--app-space-4);
  color: var(--app-ink-dim);
  font-size: var(--app-text-1);
}

.ui-table__cell {
  padding: var(--app-space-2) var(--app-space-4);
  text-align: start;
  border-bottom: 1px solid var(--app-line);
}

/* Tabular figures so digits line up column-wise instead of jittering. */
.ui-table__cell--numeric {
  text-align: end;
  font-variant-numeric: tabular-nums;
}

.ui-table thead .ui-table__cell {
  background: var(--app-surface-sunken);
  font-size: var(--app-text-1);
  color: var(--app-ink-dim);
}

.ui-table tbody tr:last-child .ui-table__cell { border-bottom: 0; }

/* Toast ---------------------------------------------------------------- */

.ui-toast {
  padding: var(--app-space-3) var(--app-space-4);
  border-radius: var(--app-radius-1);
  border: 1px solid var(--app-line);
  font-size: var(--app-text-2);
}

/* An empty live region must not paint a box; it is always in the DOM so that
 * assistive technology is already observing it when text arrives. */
.ui-toast:empty { display: none; }

.ui-toast--primary   { background: var(--app-brand);  color: var(--app-brand-on);  border-color: transparent; }
.ui-toast--danger    { background: var(--app-danger); color: var(--app-danger-on); border-color: transparent; }
.ui-toast--secondary { background: var(--app-surface-raised); color: var(--app-ink); }
.ui-toast--ghost     { background: transparent; color: var(--app-ink-dim); border-color: transparent; }

/* Motion --------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .ui-button, .ui-field__input { transition: background-color 120ms ease, border-color 120ms ease; }
}

/* Multi-line control. It shares .ui-field__input so a textarea and an input
   cannot drift apart visually; only what genuinely differs is set here. */
.ui-field__input--area {
  display: block;
  width: 100%;
  resize: vertical;
  line-height: 1.5;
  /* A textarea's default inline layout leaves a phantom descender gap under
     the control, which reads as uneven spacing next to an input. */
  vertical-align: top;
}

.ui-field__input--mono {
  font-family: var(--app-font-mono);
  font-size: var(--app-text-1);
  tab-size: 2;
}
