/* forms.css — Sneat's form aesthetic: OUTLINED + COMFORTABLE, everywhere.
 *
 * From plugins/vuetify/defaults.ts, where Sneat sets `variant: 'outlined'` and
 * `density: 'comfortable'` globally. One field style across the product; a
 * filled input next to an outlined one reads as a bug, not a choice.
 */

.field {
  display: flex;
  flex-direction: column;
  gap: 0.375rem;
  margin-bottom: 1rem;
}

.field label {
  font-size: var(--sn-type-body-2-size);
  font-weight: 500;
  color: var(--sn-on-surface);
}

.input,
.select,
.textarea {
  width: 100%;
  min-height: var(--sn-admin-input-height);
  padding: 0.5rem 0.875rem;
  font-family: inherit;
  font-size: var(--sn-type-body-1-size);
  line-height: var(--sn-type-body-1-line);
  color: var(--sn-on-surface);
  background: var(--sn-surface);
  /* A REAL border, not Sneat's 0.12-alpha hairline.
   *
   * Sneat draws this as its ink at 12% opacity — about 1.3:1 against white,
   * where WCAG 1.4.11 requires 3:1 for a UI component boundary. The boundary of
   * a text field is how you know a text field is there. `--sn-outline` is a
   * gated 3:1 grey; the decorative `--sn-outline-variant` hairline is still used
   * for dividers, which carry no such duty. */
  border: 1px solid var(--sn-outline);
  border-radius: var(--sn-shape-corner-medium);
  transition: border-color var(--sn-motion-duration-short) ease,
              box-shadow var(--sn-motion-duration-short) ease;
}

.input:hover,
.select:hover,
.textarea:hover { border-color: var(--sn-on-surface-variant); }

.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--sn-primary);
  box-shadow: 0 0 0 1px var(--sn-primary);
}

.input:disabled,
.select:disabled,
.textarea:disabled {
  opacity: var(--sn-state-disabled);
  cursor: not-allowed;
  background: var(--sn-surface-container);
}

.input::placeholder,
.textarea::placeholder { color: var(--sn-on-surface-variant); }

.textarea { min-height: 6rem; resize: vertical; }

.select {
  appearance: none;
  padding-inline-end: 2rem;
  /* The chevron is drawn with a CSS gradient rather than a background-image, so
   * there is no data: URI to argue with the CSP about. */
  background-image:
    linear-gradient(45deg, transparent 50%, var(--sn-on-surface-variant) 50%),
    linear-gradient(135deg, var(--sn-on-surface-variant) 50%, transparent 50%);
  background-position:
    calc(100% - 1rem) calc(50% + 2px),
    calc(100% - 0.7rem) calc(50% + 2px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

/* Invalid. Colour is never the only signal — the message below carries the same
 * information, associated by aria-describedby, because a colourblind cashier and
 * a screen-reader user must both be able to tell what went wrong. */
.input[aria-invalid="true"],
.select[aria-invalid="true"],
.textarea[aria-invalid="true"] { border-color: var(--sn-error); }

.field-error {
  color: var(--sn-error-text);
  font-size: var(--sn-type-caption-size);
}

.field-hint {
  color: var(--sn-on-surface-variant);
  font-size: var(--sn-type-caption-size);
}

/* ---- input group (icon inside the field) --------------------------------- */
/* StaffRoles.dc.html puts an icon inside the border on every field. The wrapper
 * carries the border and the focus ring, not the <input> — so the whole box is
 * the visible focus target and clicking the icon focuses the field. :focus-within
 * does that with no JS, which matters because our CSP forbids inline handlers.
 *
 * The metrics are deliberately the SHIPPED ones (--sn-admin-input-height, 38px),
 * not the mockup's eyeballed 46px. A field that is 8px taller here than on every
 * other form in the product is not a design, it is a mockup that was never
 * measured against the tokens. */
.input-group {
  display: flex;
  align-items: center;
  gap: 0.5625rem;
  width: 100%;
  min-height: var(--sn-admin-input-height);
  padding: 0 0.8125rem;
  background: var(--sn-surface);
  border: 1px solid var(--sn-outline);
  border-radius: var(--sn-shape-corner-medium);
  color: var(--sn-on-surface-variant);
  transition: border-color var(--sn-motion-duration-short) ease,
              box-shadow var(--sn-motion-duration-short) ease;
}
.input-group:hover { border-color: var(--sn-on-surface-variant); }
.input-group:focus-within {
  border-color: var(--sn-primary);
  box-shadow: 0 0 0 1px var(--sn-primary);
}
.input-group .icon { flex: none; }
/* The bare <input> inside has no border of its own — the group draws it.
 *
 * Do NOT "simplify" the :not() chain away. The app bundles style bare inputs via
 * `input:not([type="checkbox"]):not([type="radio"])` — specificity (0,2,1) — and
 * load AFTER this file, so a plain `.input-group input` at (0,1,1) loses and the
 * inner field keeps its own border, padding, radius and 38px min-height: a box
 * inside the box. Matching the :not() chain here wins at (0,3,1) on specificity,
 * which holds no matter what order the stylesheets end up in. */
.input-group input:not([type="checkbox"]):not([type="radio"]) {
  flex: 1;
  min-width: 0;
  max-width: none;
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  outline: none;
  background: transparent;
  font: inherit;
  font-size: var(--sn-type-body-1-size);
  color: var(--sn-on-surface);
}
/* Same reason: a bare `input:focus` ties this rule on specificity and wins on
 * order, drawing a SECOND ring inside :focus-within's. The group owns the ring. */
.input-group input:not([type="checkbox"]):not([type="radio"]):focus {
  border: 0;
  box-shadow: none;
}
.input-group input::placeholder { color: var(--sn-on-surface-variant); }
.input-group:has(input[aria-invalid="true"]) { border-color: var(--sn-error); }

/* ---- inline invite/create form ------------------------------------------- */
/* A row of fields with the submit button on the same baseline, inside a flush
 * card's body. The button is `align-self: end` so it lines up with the INPUTS,
 * not with the labels above them.
 *
 * auto-fit rather than the mockup's fixed repeat(4,1fr): the mockup hardcodes
 * four columns and then rewrites them at two breakpoints. One auto-fit track
 * definition does the same job at every width, including widths nobody tested. */
.invite-form {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 1rem;
  align-items: end;
  padding: 0 var(--sn-admin-card-padding) var(--sn-admin-card-padding);
}
.invite-form .field { margin-bottom: 0; }

/* ---- checkbox / radio ---------------------------------------------------- */
.check {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  cursor: pointer;
}
.check input {
  width: 1.125rem;
  height: 1.125rem;
  accent-color: var(--sn-primary);
  cursor: pointer;
}

/* ---- form actions -------------------------------------------------------- */
.form-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 1.5rem;
}
.form-actions-end { justify-content: flex-end; }
