/* THE AUTOSAVE STATE, EVERYWHERE IT APPEARS.
 *
 * One stylesheet for the one controller (static/js/nx_autosave.js), loaded by
 * both shells so a migrated form looks the same on the Navy pages and on the
 * legacy shell. It styles a STATE, not a widget: three words that appear beside
 * a field the reader has just changed, and get out of the way again.
 *
 * QUIET IS THE POINT. "Saved" fades to nothing after a couple of seconds — the
 * page itself already shows the new number, and a permanent badge on every
 * field a player touches is noise, not reassurance. "Could not save" does NOT
 * fade: it is the one state the reader has to act on, and it carries a real
 * button.
 *
 * It is never colour alone. Each state has its own word, and the failed state
 * additionally marks the field it belongs to.
 */

/* THE STATUS NEVER COMPETES WITH THE CONTROL FOR SPACE. Most of these forms are
 * flex rows — a stepper, a number box, a maximum — and a nowrap message dropped
 * into one squeezes the number box until it is a sliver. "Could not save —
 * retry" did exactly that to the technology recorder's field, which is the one
 * moment a reader most needs to see the value they typed.
 *
 * So the status takes its own line: `flex-basis: 100%` inside a flex form (and
 * `flex-wrap` on the form to allow it), `order` last so it sits under the row
 * rather than jumping ahead of it. Both declarations are inert on a form that
 * is not a flex container, which is why they can live here rather than being
 * repeated per surface. */
form.is-autosave { flex-wrap: wrap; }

.nx-save {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 1 0 100%;
  order: 99;
  font-size: 0.78rem;
  line-height: 1.3;
  /* Empty is the resting state and must occupy nothing: a reserved gap would
   * push every recorder's layout around for a message that is not there. */
  min-height: 1em;
  transition: opacity 320ms ease;
}
.nx-save:empty { display: none; }

.nx-save.is-saving { color: var(--nx-muted, #6b7280); }
.nx-save.is-saved { color: var(--nx-olive-text, #4d6b2f); }
.nx-save.is-failed { color: var(--nx-danger-text, #a3341f); }
.nx-save.is-settled { opacity: 0; }

/* The word `retry` in "Could not save — retry", made actionable. A real
 * <button>: reachable by keyboard, announced as a button, and the only control
 * this state needs. */
.nx-save-retry {
  appearance: none;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  font: inherit;
  border-radius: 999px;
  padding: 1px 9px;
  cursor: pointer;
}
.nx-save-retry:hover { background: var(--nx-danger-tint, rgba(163, 52, 31, 0.08)); }
.nx-save-retry:focus-visible { outline: 2px solid var(--nx-focus, #2f6feb); outline-offset: 2px; }

/* THE FIELD ITSELF SAYS SO TOO. A status line the reader has scrolled past
 * cannot be the only record that their number is not stored. */
form.is-unsaved input,
form.is-unsaved select,
form.is-unsaved textarea {
  border-color: var(--nx-danger, #a3341f);
}

/* A VALUE WE REFUSED TO SEND. Nothing was attempted and nothing failed, so
 * there is no message — the box marks itself and the status goes quiet, which
 * is the honest pair for a number still being typed. */
form.is-autosave [aria-invalid="true"] {
  border-color: var(--nx-danger, #a3341f);
  outline: none;
}

@media (prefers-reduced-motion: reduce) {
  .nx-save { transition: none; }
}
