/* Contact page: the three-step inquiry form.
   Every field ships in the markup as one ordinary form. site.js adds
   .cform--stepped and only then does the step chrome appear, so with JS off
   the page is a single long form posting natively to /api/contact and nothing
   a visitor needs sits behind the step logic.

   Colorless Chrome holds here too: the stepper, fields and buttons are
   achromatic at rest, and Stratos Blue arrives only on focus and on a checked
   opt-in — both selection states, never decoration. */

.cform-wrap {
  max-width: 34rem;
}

/* ---------- stepper ---------- */

/* Hidden until site.js takes over: without JS there are no steps to track, and
   Back and Next have nothing to move between. The two button selectors carry
   the extra .cform to outrank .cform__btn's own display further down the file —
   equal specificity would hand the win to whichever rule came last. */
.cform__nav,
.cform__track,
.cform__count {
  display: none;
}
.cform .cform__back,
.cform .cform__next {
  display: none;
}
.cform--stepped .cform__nav {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.cform--stepped .cform__track,
.cform--stepped .cform__count {
  display: block;
}

.cform__step-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  text-align: center;
}

.cform__dot {
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 9999px;
  border: 2px solid color-mix(in oklab, var(--color-muted-foreground) 45%, transparent);
  background: transparent;
  transition: background-color 0.25s ease, border-color 0.25s ease;
}
.cform__step-item[data-state="current"] .cform__dot,
.cform__step-item[data-state="done"] .cform__dot {
  background: var(--color-foreground);
  border-color: var(--color-foreground);
}
/* The current step gets a halo rather than a second colour, which separates it
   from a completed step without spending a hue on it. */
.cform__step-item[data-state="current"] .cform__dot {
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--color-foreground) 14%, transparent);
}

.cform__step-label {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-muted-foreground);
  transition: color 0.25s ease;
}
.cform__step-item[data-state="current"] .cform__step-label {
  color: var(--color-foreground);
}

.cform__track {
  margin-top: 0.875rem;
  height: 2px;
  border-radius: 9999px;
  background: color-mix(in oklab, var(--color-border) 90%, transparent);
  overflow: hidden;
}
.cform__bar {
  display: block;
  height: 100%;
  width: var(--cform-progress, 33.333%);
  background: var(--color-foreground);
  transition: width 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

.cform__count {
  margin-top: 1rem;
  text-align: center;
  font-size: 0.75rem;
  color: var(--color-muted-foreground);
}

/* ---------- card ---------- */

.cform__card {
  /* Stratos Blue proper, the brand hue from brand-assets/Colors/Colors.txt.
     Used as tint, border and ring only — never as type. The -ink variant is the
     darkened/lightened pair the design system requires wherever the blue has to
     read as a glyph, which here is the single confirmation checkmark. */
  --cform-accent: #417ced;
  --cform-accent-ink: #1e4fb8; /* AA on paper */
  margin-top: 1.5rem;
  padding: 1.5rem;
  border: 1px solid var(--color-border);
  border-radius: 0.75rem;
  background: var(--color-card);
}
.dark .cform__card {
  --cform-accent-ink: #7aa5f5; /* 5.6:1 on Carbon Black */
}
@media (min-width: 768px) {
  .cform__card { padding: 2rem; }
}

.cform__step {
  border: 0;
  margin: 0;
  padding: 0;
  min-width: 0; /* fieldset defaults to min-content and would blow out the layout */
}
/* Unstepped, the three steps read as one long form and need separating. */
.cform__step + .cform__step {
  margin-top: 2.5rem;
}
.cform--stepped .cform__step + .cform__step {
  margin-top: 0;
}

.cform__legend {
  padding: 0;
  font-size: 1.375rem;
  font-weight: 600;
  line-height: 1.25;
  text-wrap: balance;
  color: var(--color-foreground);
}
.cform__lede {
  margin-top: 0.375rem;
  font-size: 0.875rem;
  line-height: 1.6;
  color: var(--color-muted-foreground);
}

.cform__fields {
  display: flex;
  flex-direction: column;
  gap: 1.125rem;
  margin-top: 1.75rem;
}

/* ---------- fields ---------- */

.cform__field {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.cform__label {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--color-foreground);
}
.cform__optional {
  font-weight: 400;
  color: var(--color-muted-foreground);
}

.cform__input,
.cform__select,
.cform__textarea {
  width: 100%;
  font: inherit;
  font-size: 0.875rem;
  color: var(--color-foreground);
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: 0.5rem;
  padding: 0 0.75rem;
  height: 2.5rem;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.cform__textarea {
  height: auto;
  min-height: 9.5rem;
  padding: 0.625rem 0.75rem;
  line-height: 1.6;
  resize: vertical;
}
.cform__input::placeholder,
.cform__textarea::placeholder {
  color: color-mix(in oklab, var(--color-muted-foreground) 80%, transparent);
}
.cform__input:focus-visible,
.cform__select:focus-visible,
.cform__textarea:focus-visible {
  outline: none;
  border-color: var(--cform-accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--cform-accent) 22%, transparent);
}
/* Only once a submit has been attempted — :invalid on its own would mark every
   required field red before the visitor has typed a character. */
.cform__card[data-validated] .cform__input:invalid,
.cform__card[data-validated] .cform__select:invalid,
.cform__card[data-validated] .cform__textarea:invalid {
  border-color: var(--color-destructive);
}
/* The enhanced select's own border is invisible, so the red has to move to the
   trigger drawn over it. */
.cform__card[data-validated] .cselect:has(.cform__select:invalid) .cselect__trigger {
  border-color: var(--color-destructive);
}

/* Native select chrome varies too much between platforms to leave alone; the
   chevron is a real element, so it inherits currentColor in both themes. */
.cform__selectwrap {
  position: relative;
  display: block;
}
.cform__select {
  appearance: none;
  padding-right: 2.25rem;
}
.cform__chevron {
  position: absolute;
  right: 0.75rem;
  top: 50%;
  transform: translateY(-50%);
  width: 1rem;
  height: 1rem;
  pointer-events: none;
  color: var(--color-muted-foreground);
  transition: transform 0.2s ease;
}

/* ---------- custom select ---------- */

/* A listbox drawn over the native control, which stays in the DOM and stays the
   source of truth: it is what FormData reads, what constraint validation
   checks, and what a visitor with JS off is left with. Nothing below exists
   until site.js decides the enhancement is on. */
.cselect .cform__select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  pointer-events: none;
  /* Not display:none: reportValidity() needs a rendered box to hang its bubble
     on, and an unrendered control silently reports nothing at all. */
}

.cselect__trigger {
  display: flex;
  align-items: center;
  width: 100%;
  height: 2.5rem;
  padding: 0 2.25rem 0 0.75rem;
  font: inherit;
  font-size: 0.875rem;
  text-align: left;
  color: var(--color-foreground);
  background: var(--color-background);
  border: 1px solid var(--color-border);
  border-radius: 0.5rem;
  cursor: pointer;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.cselect__trigger:focus-visible {
  outline: none;
  border-color: var(--cform-accent);
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--cform-accent) 22%, transparent);
}
.cselect[data-open='true'] .cselect__trigger {
  border-color: var(--cform-accent);
}
.cselect[data-open='true'] .cform__chevron {
  transform: translateY(-50%) rotate(180deg);
}

.cselect__value {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* Matches the placeholder tone the text inputs use, so an unanswered select and
   an unanswered input read as the same state. */
.cselect__value--empty {
  color: color-mix(in oklab, var(--color-muted-foreground) 80%, transparent);
  /* At rest the label is sitting in this exact spot, so the placeholder waits
     until the label has moved out of the way — the same bargain the inputs
     strike with their examples, which only appear once the field is focused. */
  opacity: 0;
  transition: opacity 0.18s ease;
}
.cselect:focus-within .cselect__value--empty,
.cselect[data-open='true'] .cselect__value--empty {
  opacity: 1;
}

.cselect__panel {
  position: absolute;
  z-index: 30;
  top: calc(100% + 0.375rem);
  left: 0;
  right: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  max-height: 17rem;
  overflow-y: auto;
  background: var(--color-card);
  border: 1px solid var(--color-border);
  border-radius: 0.5rem;
  box-shadow: 0 12px 32px -12px rgb(0 0 0 / 0.35), 0 2px 6px rgb(0 0 0 / 0.06);
}
/* Flipped when the panel would run past the bottom of the viewport. */
.cselect[data-drop='up'] .cselect__panel {
  top: auto;
  bottom: calc(100% + 0.375rem);
}

.cselect__option {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  padding: 0.5625rem 0.75rem;
  cursor: pointer;
}
.cselect__option + .cselect__option {
  border-top: 1px solid color-mix(in oklab, var(--color-border) 70%, transparent);
}
/* Hover and keyboard land on the same state deliberately — the pointer and the
   arrow keys are moving one highlight, not two. */
.cselect__option[data-active='true'] {
  background: color-mix(in oklab, var(--color-foreground) 6%, transparent);
}
.cselect__option[aria-selected='true'] {
  background: color-mix(in oklab, var(--cform-accent) 12%, transparent);
}
.cselect__option[aria-selected='true'] .cselect__optitle {
  color: var(--cform-accent-ink);
}

.cselect__optitle {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-foreground);
}
.cselect__optdesc {
  font-size: 0.75rem;
  line-height: 1.45;
  color: var(--color-muted-foreground);
}

.cform__note {
  font-size: 0.75rem;
  line-height: 1.6;
  color: var(--color-muted-foreground);
}
.cform__note--caution {
  padding: 0.625rem 0.75rem;
  border: 1px dashed var(--color-border);
  border-radius: 0.5rem;
  background: color-mix(in oklab, var(--color-foreground) 3%, transparent);
}

/* ---------- branching step two ---------- */

/* One branch per answer to "What is this about". site.js shows the one that
   applies and disables the rest; with JS off there is nothing to switch, so all
   three stand open at once and each needs a heading naming the answer it
   belongs to. That heading is pure JS-off scaffolding, which is why
   .cform--stepped — a class only site.js ever adds — takes it back down. */
.cform__branch {
  display: flex;
  flex-direction: column;
  gap: 1.125rem;
}
.cform__branch[hidden] {
  display: none;
}
.cform__branch-head {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-muted-foreground);
}
.cform--stepped .cform__branch-head {
  display: none;
}
/* Switching answers replaces the whole lower half of the step, which is a large
   enough change to be worth announcing. Keyed on display rather than a class:
   an element leaving display:none restarts its animations. */
.cform--stepped .cform__branch {
  animation: cform-branch-in 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes cform-branch-in {
  from {
    opacity: 0;
    transform: translateY(0.375rem);
  }
}

/* ---------- single-choice rows ---------- */

/* Two or three short answers, so they run as pills on one line rather than
   stacking into cards the way the opt-ins do. Same accent, same selection
   grammar — this is a choice, not decoration. */
.cform__radios {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.cform__radio {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.875rem;
  border: 1px solid var(--color-border);
  border-radius: 9999px;
  font-size: 0.8125rem;
  color: var(--color-foreground);
  cursor: pointer;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}
.cform__radio:hover {
  border-color: color-mix(in oklab, var(--cform-accent) 35%, var(--color-border));
}
.cform__radio:has(input:checked) {
  border-color: color-mix(in oklab, var(--cform-accent) 45%, var(--color-border));
  background: color-mix(in oklab, var(--cform-accent) 8%, transparent);
}
.cform__radio:has(input:focus-visible) {
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--cform-accent) 22%, transparent);
}
.cform__radio input {
  margin: 0;
  width: 0.875rem;
  height: 0.875rem;
  flex: none;
  accent-color: var(--cform-accent);
}

/* ---------- opt-in checkboxes ---------- */

.cform__checks {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.cform__check {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.875rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: 0.625rem;
  cursor: pointer;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}
.cform__check:hover {
  border-color: color-mix(in oklab, var(--cform-accent) 35%, var(--color-border));
}
.cform__check:has(input:checked) {
  border-color: color-mix(in oklab, var(--cform-accent) 45%, var(--color-border));
  background: color-mix(in oklab, var(--cform-accent) 8%, transparent);
}
.cform__check:has(input:focus-visible) {
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--cform-accent) 22%, transparent);
}
.cform__check input {
  margin: 0.125rem 0 0;
  width: 1rem;
  height: 1rem;
  flex: none;
  accent-color: var(--cform-accent);
}
.cform__check-title {
  display: block;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--color-foreground);
}
/* A consent line is one sentence and no more, so it skips the title/body pair
   the opt-in cards are built from and reads at body weight. */
.cform__check-line {
  display: block;
  font-size: 0.8125rem;
  line-height: 1.55;
  color: var(--color-foreground);
}
.cform__check-body {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.75rem;
  line-height: 1.55;
  color: var(--color-muted-foreground);
}

/* ---------- footer row ---------- */

.cform__actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 2rem;
}
.cform--stepped .cform__back,
.cform--stepped .cform__next {
  display: inline-flex;
}
/* Outranks the two rules above, which are what put Back and Next on screen in
   the first place; without it [hidden] loses and every button shows at once. */
.cform--stepped .cform__actions .cform__btn[hidden] {
  display: none;
}
/* Keeps the lone button hard right on step one, where Back is not yet shown. */
.cform__actions > :only-child {
  margin-left: auto;
}

.cform__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  height: 2.5rem;
  padding: 0 1.25rem;
  border-radius: 9999px;
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease;
}
.cform__btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--cform-accent) 30%, transparent);
}
.cform__btn svg {
  width: 0.875rem;
  height: 0.875rem;
}
.cform__btn--primary {
  border: 1px solid transparent;
  background: var(--color-primary);
  color: var(--color-primary-foreground);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.05);
}
.cform__btn--primary:hover {
  background: color-mix(in oklab, var(--color-primary) 90%, transparent);
}
.cform__btn--ghost {
  border: 1px solid var(--color-border);
  background: var(--color-background);
  color: var(--color-foreground);
}
.cform__btn--ghost:hover {
  box-shadow: 0 1px 3px rgb(0 0 0 / 0.06);
}
.cform__btn[disabled] {
  pointer-events: none;
  opacity: 0.6;
}

.cform__status {
  margin-top: 1rem;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--color-destructive);
}
.cform__status:empty {
  display: none;
}

/* ---------- sent ---------- */

.cform__done {
  text-align: center;
  padding: 1rem 0 0.5rem;
}
.cform__done-mark {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  margin: 0 auto;
  border-radius: 9999px;
  border: 1px solid color-mix(in oklab, var(--cform-accent) 45%, var(--color-border));
  background: color-mix(in oklab, var(--cform-accent) 10%, transparent);
  color: var(--cform-accent-ink);
}
.cform__done-mark svg {
  width: 1.25rem;
  height: 1.25rem;
}
.cform__done-title {
  margin-top: 1.25rem;
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--color-foreground);
}
.cform__done-body {
  margin-top: 0.5rem;
  font-size: 0.875rem;
  line-height: 1.65;
  color: var(--color-muted-foreground);
}

/* The honeypot sits off-screen rather than display:none, which some bots skip. */
.cform__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* ---------- floating labels ---------- */

/* The label starts sitting inside the control, where a placeholder would be,
   and rises onto the top border once the field is focused or filled. The whole
   state machine is :placeholder-shown, which is why every control carries
   placeholder=" ": an empty placeholder attribute does not match it, and real
   placeholder text would sit under the resting label. The examples those
   placeholders used to hold are parked on data-ph and restored on focus by
   site.js, once the label has floated clear of them.

   The label follows its control in the DOM because CSS has no previous-sibling
   combinator. Order is presentational only — `for` still does the associating,
   so the accessible name is unchanged. */
.cform__field--float {
  position: relative;
}

.cform__field--float .cform__label {
  position: absolute;
  left: 0.5rem;
  top: 0;
  z-index: 1;
  padding: 0 0.25rem;
  /* Matches the control's own fill, not the card's: the label crosses the top
     border, and this is the colour on both sides of it. */
  background: var(--color-background);
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--color-muted-foreground);
  cursor: text;
  /* Scale rather than font-size: it animates on the compositor, and it keeps
     the resting label the same size as the text that replaces it. */
  transform: translateY(0.6875rem) scale(1);
  transform-origin: left center;
  transition: transform 0.18s ease, color 0.18s ease;
}

.cform__field--float .cform__input:focus + .cform__label,
.cform__field--float .cform__input:not(:placeholder-shown) + .cform__label,
.cform__field--float .cform__input:-webkit-autofill + .cform__label,
.cform__field--float .cform__textarea:focus + .cform__label,
.cform__field--float .cform__textarea:not(:placeholder-shown) + .cform__label,
/* An unenhanced select always shows text — either a value or its own "Select
   one" — so there is nowhere for its label to rest and it stays up. The
   enhanced one can hold its placeholder back, so it floats on the same terms as
   an input: open, focused, or answered. */
.cform__field--float .cform__selectwrap:not(.cselect) + .cform__label,
.cform__field--float .cselect:focus-within + .cform__label,
.cform__field--float .cselect[data-open='true'] + .cform__label,
.cform__field--float .cselect[data-filled='true'] + .cform__label {
  transform: translateY(-0.5rem) scale(0.8);
  font-weight: 500;
  color: var(--color-foreground);
}

.cform__field--float .cform__input:focus + .cform__label,
.cform__field--float .cform__textarea:focus + .cform__label {
  color: var(--cform-accent-ink);
}
/* The select sits inside the chevron wrapper rather than beside the label, so
   no sibling combinator reaches from one to the other; :has() on the wrapper
   closes that gap. Kept in its own rule on purpose: an engine without :has()
   throws out the whole selector list, and this one is the only selector that
   can afford to be lost. */
.cform__field--float .cselect[data-open='true'] + .cform__label {
  color: var(--cform-accent-ink);
}
.cform__field--float .cform__selectwrap:has(.cform__select:focus-visible) + .cform__label,
.cform__field--float .cform__selectwrap:has(.cselect__trigger:focus-visible) + .cform__label {
  color: var(--cform-accent-ink);
}

/* The textarea is taller than one line, so its resting label would land in the
   middle of the box rather than on the first line of text. */
.cform__field--float .cform__textarea + .cform__label {
  transform: translateY(0.75rem) scale(1);
}
.cform__field--float .cform__textarea:focus + .cform__label,
.cform__field--float .cform__textarea:not(:placeholder-shown) + .cform__label {
  transform: translateY(-0.5rem) scale(0.8);
}

/* "(optional)" rides along at the same scale; it only needs its own colour back
   once the label above has taken the foreground one. */
.cform__field--float .cform__label .cform__optional {
  color: var(--color-muted-foreground);
}

@media (prefers-reduced-motion: reduce) {
  .cform__bar,
  .cform__dot,
  .cform__check,
  .cform__radio,
  .cform__btn,
  .cform__input,
  .cform__select,
  .cform__textarea { transition-duration: 0.01ms; }
  .cform__field--float .cform__label { transition-duration: 0.01ms; }
  .cform--stepped .cform__branch { animation: none; }
}
