/* ==========================================================================
   Apply form — functionality layer
   --------------------------------------------------------------------------
   Kept in a separate file on purpose. Everything here is additive and scoped
   to .apply-form / .form-* so it can sit on top of a changing styles.css
   without fighting it during a merge. Uses only existing design tokens.
   ========================================================================== */

/* Let the form column stack so status text sits under the fields. */
.apply-form {
  position: relative;
}

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

.apply-form input {
  transition: border-color 0.2s ease, background 0.2s ease;
}

.apply-form input[aria-invalid="true"] {
  border-color: #e5484d;
  background: rgba(229, 72, 77, 0.06);
}

.apply-form input[aria-invalid="true"]:focus {
  border-color: #e5484d;
}

.apply-form.is-submitting input,
.apply-form.is-success input {
  opacity: 0.55;
  pointer-events: none;
}

/* --- Submit button -------------------------------------------------------- */

/* No min-width here on purpose: the spinner state keeps the label in place and
   only makes it transparent, so the button never changes size mid-submit.
   Setting a min-width would silently widen the button in its resting state. */
.apply-form button[type="submit"] {
  position: relative;
}

.apply-form button[type="submit"][disabled] {
  cursor: not-allowed;
  transform: none;
}

.apply-form.is-submitting button[type="submit"] {
  color: transparent;
}

/* Spinner, shown only while submitting. */
.apply-form.is-submitting button[type="submit"]::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 17px;
  height: 17px;
  margin: -8.5px 0 0 -8.5px;
  border-radius: 50%;
  border: 2px solid rgba(20, 7, 0, 0.3);
  border-top-color: #140700;
  animation: form-spin 0.7s linear infinite;
}

@keyframes form-spin {
  to { transform: rotate(360deg); }
}

/* --- Status message ------------------------------------------------------- */

/* Absolutely positioned so an empty (or newly filled) status never reflows the
   apply card — the form row must not shift under the user's cursor mid-submit.
   It stays in the DOM and rendered, so the aria-live announcement still fires.
   The success state puts it back in flow, because by then the fields it would
   have overlapped are hidden. */
.form-status {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  margin: 0;
  font-size: 13.5px;
  line-height: 1.45;
  text-align: center;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}

.form-status:not(:empty) {
  opacity: 1;
  transform: translateY(0);
}

.form-status.is-error   { color: #ff8b8e; }
.form-status.is-success { color: var(--ember-hot); font-weight: 600; }

/* --- Success state -------------------------------------------------------- */

/* Replace the field row with a confirmation, matching the card's ember voice. */
.apply-form.is-success button[type="submit"] {
  display: none;
}

.apply-form.is-success input {
  display: none;
}

.apply-form.is-success .form-status {
  position: static;
  font-size: 16px;
  padding: 16px 22px;
  border-radius: 999px;
  border: 1px solid rgba(255, 106, 31, 0.35);
  background: rgba(255, 106, 31, 0.08);
}

/* --- Honeypot ------------------------------------------------------------- */

/* Off-screen rather than display:none so bots that skip hidden fields still
   fill it, but real users and screen readers never reach it. */
.form-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .form-status { transition: none; }
  .apply-form.is-submitting button[type="submit"]::after { animation: none; }
}
