/* Multi-page form styles — shared by every paged form (volunteer, partnership, RSVP) */

.multi-page-form {
  max-width: 42rem;
  overflow: visible;
}

form {
  overflow: visible;
}

/* Progress Container */
.progress-container {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  margin-bottom: 0;
  background: var(--bg);
  padding: 1.5rem 0;
  z-index: 1000;
  border-bottom: 1px solid var(--border);
  width: 100%;
  max-width: 42rem;
  margin-left: auto;
  margin-right: auto;
}

/* Room for the fixed progress bar above, which is out of the flow and so takes
   none of its own. It stands 143px tall here (117px under 640px, where the
   padding shrinks); with the body's 1.5rem this leaves about 2rem between its
   rule and the page's first line at both sizes. At 7.5rem it left 1px, and the
   heading's top ran under the bar. */
.multi-page-form {
  padding-top: 9.5rem;
}

.progress-bar {
  height: 4px;
  background: var(--bg-subtle);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: 1.5rem;
}

.progress-fill {
  height: 100%;
  background: var(--color-primary);
  transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

.progress-steps {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
}

.progress-step {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  opacity: 0.5;
  transition: opacity 0.3s ease;
}

.progress-step.active {
  opacity: 1;
}

.step-number {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  background: var(--bg-subtle);
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--color-body);
  transition: all 0.3s ease;
}

.progress-step.active .step-number {
  background: var(--color-primary);
  color: white;
  box-shadow: 0 4px 12px rgba(241, 36, 154, 0.3);
}

.step-label {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--fg-muted);
  text-align: center;
}

.progress-step.active .step-label {
  color: var(--color-primary);
}

/* Form Pages */
form {
  position: relative;
}

/*
 * A hidden page is invisible but still laid out, and the document scrolls to
 * the bottom of every box in it, seen or not. Left at its natural height and
 * natural place (just below the active page), each hidden page stretched the
 * scroll well past the end of the form, into hundreds of pixels of nothing.
 * Pinning it to the top of the form and clipping it to the form's height keeps
 * it inside the space the active page already takes.
 *
 * It is not display:none because the last page holds the Turnstile widget,
 * which has to render before the visitor gets there, and because the outgoing
 * page needs a box to fade out in.
 *
 * The slide is 1rem because hidden pages rest shifted by it, and a shift wider
 * than the body's 1.5rem side padding pokes out past the screen on a phone and
 * lets the whole page scroll sideways (30px did, by 6px).
 */
.form-page {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateX(1rem);
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.form-page.active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translateX(0);
  position: relative;
  height: auto;
  overflow: visible;
}

.form-page.prev {
  transform: translateX(-1rem);
}

.page-content {
  animation: fadeInUp 0.5s ease-out 0.1s both;
}

@keyframes fadeInUp {
  from {
    opacity: 0;
    transform: translateY(15px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/*
 * Banner above the heading on a welcome page.
 *
 * `height: auto` lets the file keep its own proportions, so nothing is cropped
 * — give the <img> real width/height attributes and the browser reserves the
 * right space before it loads. `max-height` is the guard: a portrait image
 * swapped in later gets cropped to a sane band rather than filling the screen
 * and pushing the heading out of view.
 */
.page-hero {
  display: block;
  width: 100%;
  height: auto;
  max-height: 22rem;
  object-fit: cover;
  border-radius: var(--radius);
  margin-bottom: 1.5rem;
  background: var(--bg-subtle);
}

/* A heading that is nothing but the banner: the image already carries the
   spacing below it, so the h1 must not add a second gap on top of it. */
.page-content h1:has(> .page-hero) {
  margin: 0;
  line-height: 0;
}

.page-content h1,
.page-content h2 {
  margin-bottom: 0.5rem;
  color: var(--color-headline);
}

/* A page of separate questions with a rule between each, so one question's
   choices don't read as the start of the next. Only between questions: the
   write-ins nested inside a group aren't direct children, and the captcha at
   the foot isn't a question.
   The rule hangs under a question rather than over the next one, because a
   fieldset draws its top border through the middle of its legend. */
.page-content--divided > :is(.field, .field-group) {
  margin-bottom: 1.25rem;
}

.page-content--divided > :is(.field, .field-group):has(+ :is(.field, .field-group)) {
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--border);
}

.page-subtitle {
  margin: 0 0 1.5rem;
  font-size: 1rem;
  font-weight: 500;
  color: var(--color-primary);
}

.page-intro {
  background: var(--bg-subtle);
  border-left: 4px solid var(--color-primary);
  padding: 1.25rem;
  border-radius: var(--radius);
  margin-bottom: 1.5rem;
  line-height: 1.6;
}

.page-intro p {
  margin: 0 0 1rem;
  color: var(--color-body);
  font-size: 0.95rem;
}

.page-intro p:last-child {
  margin-bottom: 0;
}

/*
 * Links inside the intro block.
 *
 * The global rule in styles.css sets `text-decoration: none`, which leaves
 * colour as the only thing marking a link. In this block colour was losing
 * badly: `.crusader-highlight` renders non-clickable words as bold pink pills,
 * so decorative text was louder than the one thing here you can actually click,
 * and the roles link read as ordinary prose.
 *
 * Colour could not have carried it anyway. --color-primary is 3.59:1 against
 * this block's background, under the 4.5:1 that text this size needs, and only
 * 2.97:1 against the body text beside it — under the 3:1 that colour alone
 * would have to clear to distinguish a link at all. The underline is what marks
 * it; --color-primary-strong is what makes it legible.
 */
.page-intro a {
  color: var(--color-primary-strong);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 2px;
}

.page-intro a:hover,
.page-intro a:focus-visible {
  color: var(--color-secondary);
  text-decoration-thickness: 3px;
}

/*
 * inline-block is load-bearing: a parent's underline is drawn straight through
 * its descendants and a child cannot opt out of it, but it stops at an
 * inline-block. Without this the arrow gets underlined too and reads as a typo.
 */
.page-intro a .link-arrow {
  display: inline-block;
  margin-left: 0.25rem;
  text-decoration: none;
  transition: transform 0.15s ease;
}

.page-intro a:hover .link-arrow,
.page-intro a:focus-visible .link-arrow {
  transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
  .page-intro a .link-arrow {
    transition: none;
  }
}

/* Form Navigation */
.form-navigation {
  display: flex;
  gap: 1rem;
  margin-top: 2rem;
  justify-content: flex-end;
}

.btn-nav {
  padding: 0.75rem 1.75rem;
  font-family: var(--font-secondary);
  font-size: 0.95rem;
  font-weight: 600;
  color: #fff;
  background: var(--color-primary);
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  transition: all 0.2s ease;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
}

.btn-nav:hover:not(:disabled) {
  background: var(--color-secondary);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(26, 89, 171, 0.3);
}

.btn-nav:active:not(:disabled) {
  transform: translateY(0);
}

.btn-nav:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn-prev {
  background: var(--border);
  color: var(--color-body);
}

.btn-prev:hover:not(:disabled) {
  background: #c0c0c0;
}

/*
 * Next and Submit are blue until the step they gate is actually complete, then
 * brand pink. `.is-ready` is put on and taken off by syncReadyState().
 *
 * These sit after .btn-nav deliberately: same specificity, later wins, so the
 * blue is what a nav button starts as. Previous keeps its own grey — it is
 * always available and has no readiness to report.
 */
.btn-next,
.btn-submit {
  background: var(--color-secondary);
}

.btn-next.is-ready,
.btn-submit.is-ready {
  background: var(--color-primary);
}

/*
 * Hover deepens whichever state the button is in rather than swapping its hue.
 * The shared .btn-nav:hover turned every nav button blue, which was invisible
 * when blue meant nothing and would now say the exact opposite of the truth:
 * a finished page's button going blue under the cursor reads as "no longer
 * ready" at the moment the visitor reaches for it.
 */
.btn-next:hover:not(:disabled),
.btn-submit:hover:not(:disabled) {
  background: var(--color-secondary-strong);
  box-shadow: 0 4px 12px rgba(26, 89, 171, 0.3);
}

.btn-next.is-ready:hover:not(:disabled),
.btn-submit.is-ready:hover:not(:disabled) {
  background: var(--color-primary-strong);
  box-shadow: 0 4px 12px rgba(241, 36, 154, 0.3);
}

/* Responsiveness */
@media (max-width: 640px) {
  .multi-page-form {
    padding-top: 8rem;
  }

  .progress-container {
    padding: 1rem 0;
  }

  .progress-steps {
    gap: 0.5rem;
  }

  .step-number {
    width: 2rem;
    height: 2rem;
    font-size: 0.75rem;
  }

  .step-label {
    font-size: 0.65rem;
  }

  /* Previous and Next stay on one row rather than stacking.

     Two full-width buttons pushed the primary action a whole button-height
     down the page, and stacking them then forced a choice about order that
     has no good answer: plain `column` puts Back above the action everyone
     wants, and the `column-reverse` this replaces put Next *above* Previous,
     a visual order contradicting both the DOM and the tab order. Side by side
     is the arrangement that needs no such trade. */
  .form-navigation {
    gap: 0.75rem;
  }

  .btn-nav {
    /* min-width:0 overrides the automatic minimum size of a flex item, which
       is its content width — without it a long label ("Submit Application" is
       the one that tests this) props the row open past the viewport instead
       of wrapping, and the whole page scrolls sideways. */
    flex: 1 1 auto;
    min-width: 0;
    justify-content: center;
    padding: 0.75rem 1rem;
    font-size: 0.9rem;
  }

  /* The secondary action holds its natural width and never splits its label —
     "← Previous" broken across two lines reads as a rendering fault rather
     than a button. The primary one absorbs whatever is left, and is the one
     allowed to wrap if the screen is narrow enough to require it. */
  .btn-prev {
    flex: 0 0 auto;
    white-space: nowrap;
  }

  .page-intro {
    padding: 1rem;
  }

  .page-content h1,
  .page-content h2 {
    font-size: 1.75rem;
  }
}

/* Dark mode support */
@media (prefers-color-scheme: dark) {
  .page-intro {
    background: rgba(255, 255, 255, 0.05);
    border-left-color: var(--color-primary);
  }

  .progress-bar {
    background: rgba(255, 255, 255, 0.1);
  }

  .step-number {
    background: rgba(255, 255, 255, 0.1);
  }
}
