/*
 * Form layout, inputs and inline validation output, to Glacier's form spec
 * (sections 9.2 and 5.4).
 *
 * Labels sit above their input, never floating or inline -- that is Redwood's
 * rule and Glacier keeps it. Height matches the default button at 40px, the
 * focus ring is PTAG blue, and an errored field takes the danger ramp for both
 * its border and its ring.
 */

.form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.form__field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.form__field--inline {
  flex-direction: row;
  align-items: center;
  gap: var(--space-2);
}

.form__label-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}

.form__label {
  font-size: var(--text-body-sm);
  font-weight: 500;
  color: var(--text-label);
}

.form__label-link {
  font-size: var(--text-caption);
  font-weight: 500;
  text-decoration: none;
}

.form__label-link:hover {
  text-decoration: underline;
}

/* Auth screens only: the card is narrow and every field fills it. Everything
   else about this control -- height, padding, border, focus, disabled,
   placeholder -- comes from the one shared treatment further down, which the
   filter bars and the three form builders use too. */
.form__input {
  width: 100%;
}

/* Room for the reveal toggle that sits inside the password field. */
.form__input--password {
  padding-right: 3.5rem;
}

.form__input-group {
  position: relative;
  display: flex;
  align-items: center;
}

.form__reveal {
  position: absolute;
  right: var(--space-1);
  padding: var(--space-1) var(--space-2);
  color: var(--text-tertiary);
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
  font-family: inherit;
  font-size: var(--text-caption);
  font-weight: 500;
  cursor: pointer;
}

.form__reveal:hover {
  color: var(--text-primary);
  background: var(--surface-tertiary);
}

.form__hint {
  font-size: var(--text-caption);
  color: var(--text-tertiary);
}

.form__checkbox {
  width: 1rem;
  height: 1rem;
  margin: 0;
  accent-color: var(--ptag-blue);
}

.form__checkbox-label {
  font-size: var(--text-body-sm);
  color: var(--text-tertiary);
}

.form__actions {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-1);
}

/* The auth card stacks its actions full width; a form on the page shell has
   room to lay them out side by side. */
.form__actions--row,
.form--page .form__actions {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

/* --- page-shell forms ----------------------------------------------------
   `.form--page` is every form that sits in the content area rather than on
   the narrow auth card: mapping, rules, schedule and connection. What they
   share is above (a footer row -- Glacier lays a form footer out as a row,
   not the auth card's full-width stack) and the checkbox grid below.

   WIDTH IS NOT HERE, deliberately. Glacier caps a form at 720px, and the
   mapping, schedule and connection forms each say so; the rules form holds a
   four-column grid of inputs and must not be capped. Their gaps differ too.
   Each keeps its own.

   Every view that renders a page form adds this class beside its own
   modifier; spec/views/page_forms_spec.rb fails if one does not. */

/* The checkbox reads left-to-right with its label and hint, unlike every
   other field. Both classes are named on purpose: `.form--mapping
   .form__field` (mapping.css) sets `display: flex` at the same specificity
   and loads after this file, so a single-class selector here would lose to
   it and stack the checkbox above its label again. */
.form--page .form__field.form__field--check {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-1) var(--space-2);
  align-items: center;
}

.form--page .form__field--check input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  margin: 0;
  accent-color: var(--ptag-blue);
}

.form--page .form__field--check .form__hint {
  grid-column: 2;
}

.form__errors {
  padding: var(--space-3) var(--space-4);
  color: var(--status-danger-fg);
  background: var(--status-danger-bg);
  /* Glacier's toast treatment: a 3px accent bar in the semantic colour rather
     than a full-weight border on all four sides. */
  border-left: 3px solid var(--status-danger);
  border-radius: var(--radius-md);
}

.form__errors-title {
  font-size: var(--text-body-sm);
  font-weight: 600;
  color: inherit;
}

.form__errors-list {
  margin: var(--space-1) 0 0;
  padding-left: var(--space-4);
  font-size: var(--text-body-sm);
}

/* Drift uses the same banner but not the same colour. It is a reconciliation
   finding an operator settles in ACC, not a validation failure, and a red box
   above an otherwise valid form says the form is broken when it is not. Same
   reasoning as the drift pill -- see pill.css. */
.form__errors--drift {
  color: var(--status-info-fg);
  background: var(--status-info-bg);
  border-left-color: var(--status-info);
}

.form__note {
  padding: var(--space-2) var(--space-3);
  color: var(--text-tertiary);
  background: var(--surface-tertiary);
  border: 1px solid var(--border-primary);
  border-radius: var(--radius-md);
  font-size: var(--text-caption);
}

/* --- the one text field and dropdown treatment -------------------------
 *
 * Glacier 9.2 and the guide's 5.2 starter, in ONE place. Four screens were
 * each carrying their own hand-copy of these nine declarations, and the copies
 * had already drifted: two had the focus transition and two did not, only this
 * one had a disabled state, and only this one turned an errored field red --
 * so an invalid cron or mapping showed a message at the top of the form while
 * the field that caused it looked perfectly fine.
 *
 * Listed by context rather than by a shared class because these are bare
 * `f.text_field` and `select_tag` calls across four form builders; giving them
 * all a class means touching every view, and the selector list is the same
 * contract with none of that churn.
 *
 * WIDTH IS NOT HERE, deliberately. A filter-bar control is a fixed width
 * sitting inline; a form field fills its row. Each context still sets its own,
 * and this file loads before mapping.css and rules.css so theirs win.
 */
.form__input,
.dashboard__filters input[type="text"],
.dashboard__filters input[type="email"],
.dashboard__filters input[type="date"],
.dashboard__filters select,
.form--mapping input[type="text"],
.form--mapping input[type="email"],
.form--mapping input[type="url"],
.form--mapping input[type="number"],
.form--mapping textarea,
.form--mapping select,
.form--schedule input[type="text"],
.form--schedule select,
.form--rules input[type="text"],
.form--rules select,
.rules__form-table input[type="text"],
.rules__form-table select {
  height: 40px;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--input-border);
  border-radius: var(--radius-sm);
  background: var(--input-bg);
  color: var(--input-text);
  font-family: var(--font-sans);
  font-size: var(--text-body-sm);
  line-height: 1.4;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.form__input::placeholder,
.dashboard__filters input::placeholder,
.form--mapping input::placeholder,
.form--schedule input::placeholder,
.form--rules input::placeholder,
.rules__form-table input::placeholder {
  color: var(--text-tertiary);
}

.form__input:focus,
.dashboard__filters input[type="text"]:focus,
.dashboard__filters input[type="email"]:focus,
.dashboard__filters input[type="date"]:focus,
.dashboard__filters select:focus,
.form--mapping input[type="text"]:focus,
.form--mapping input[type="email"]:focus,
.form--mapping input[type="url"]:focus,
.form--mapping input[type="number"]:focus,
.form--mapping textarea:focus,
.form--mapping select:focus,
.form--schedule input[type="text"]:focus,
.form--schedule select:focus,
.form--rules input[type="text"]:focus,
.form--rules select:focus,
.rules__form-table input[type="text"]:focus,
.rules__form-table select:focus {
  outline: none;
  border-color: var(--ptag-blue);
  box-shadow: var(--focus-ring);
}

/* Glacier 9.2: "Disabled: background --neutral-100, text --neutral-500,
   cursor not-allowed." Three of the four copies had no disabled state at all,
   so a disabled control fell back to the browser's own grey -- which in dark
   mode is a light grey box. */
.form__input:disabled,
.dashboard__filters input:disabled,
.dashboard__filters select:disabled,
.form--mapping input:disabled,
.form--mapping select:disabled,
.form--schedule input:disabled,
.form--schedule select:disabled,
.form--rules input:disabled,
.form--rules select:disabled,
.rules__form-table input:disabled,
.rules__form-table select:disabled {
  background: var(--surface-tertiary);
  color: var(--text-muted);
  cursor: not-allowed;
}

/* Rails wraps an errored input -- and its label -- in a `div.field_with_errors`.
   That extra block element sits between .form__input-group and the input,
   which knocks the absolutely positioned reveal button out of the field.
   `display: contents` removes the wrapper from layout entirely while keeping
   it as a styling hook. Guarded by a spec in spec/requests/devise_screens_spec.rb. */
.field_with_errors {
  display: contents;
}

.field_with_errors .form__label {
  color: var(--status-danger);
}

/* Matched on the element, not on `.form__input`. Rails wraps whatever the form
   builder rendered, and only the auth screens give their inputs that class --
   so scoping the red border to it meant the mapping, rules and schedule forms
   reported an error at the top of the form and left the offending field
   looking untouched. Glacier 9.2 asks for the border AND the ring. */
.field_with_errors .form__input,
.field_with_errors input[type="text"],
.field_with_errors input[type="date"],
.field_with_errors input[type="email"],
.field_with_errors input[type="password"],
.field_with_errors select,
.field_with_errors textarea {
  border-color: var(--status-danger);
}

.field_with_errors .form__input:focus,
.field_with_errors input:focus,
.field_with_errors select:focus,
.field_with_errors textarea:focus {
  border-color: var(--status-danger);
  box-shadow: var(--focus-ring-danger);
}

/* --- required fields -----------------------------------------------------
 *
 * The implementation guide's 5.4.3: "Required fields show `*` after label text
 * in --status-danger."
 *
 * A pseudo-element rather than markup in the label, so the marker cannot drift
 * out of step with the field's own `required` attribute -- and so it is
 * decoration, not content. The input already carries `required`, which is what
 * assistive technology announces; this is the visual half of the same fact.
 */
.form__label--required::after,
.form__field--required > label::after,
/* Rails wraps an errored field's label in `.field_with_errors`, which breaks a
   child combinator -- so the marker would vanish at exactly the moment the
   form is being re-read most carefully. */
.form__field--required > .field_with_errors > label::after {
  content: " *";
  color: var(--status-danger);
  font-weight: 600;
}

/* Generate / Copy under a secret field (Configure -> Systems -> a connection).
   Small secondary and ghost buttons in a row, the toolbar pattern. */
.form__secret-tools {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-1);
}
