/* ---------------------------------------------------------------------------
   The audit request
   ---------------------------------------------------------------------------
   The support form's fields, a step at a time. `.ticket` supplies the inputs,
   the measure and the note; what is here is the three things that form does
   not have — somewhere to say how far along you are, options to pick from
   rather than type, and what the page does once the request has gone.

   Violet, not orange, for everything that is *this form's*: the door into it
   on the downloads page is the violet button, and the marks, the picked
   options and Send carry that through, so the page reads as the inside of the
   thing that was pressed.
   --------------------------------------------------------------------------- */

.audit {
  --audit: #7a68f0;
  --audit-wash: color-mix(in srgb, var(--violet) 14%, transparent);
  margin-top: 0;
  gap: 26px;
}

/* --- where you are -------------------------------------------------------- */

.audit-progress {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 13.5px;
  color: var(--text-dim);
}

/* A rule over each name, and the rule is the mark: lit for the step on screen
   and the ones behind it, so how far along is read off the line rather than
   counted. */
.audit-progress li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 12px;
  border-top: 2px solid var(--line);
  transition:
    border-color 240ms ease,
    color 240ms ease;
}

.audit-progress li span {
  flex: none;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  font-size: 11.5px;
  font-weight: 600;
  transition:
    background 240ms ease,
    border-color 240ms ease,
    color 240ms ease;
}

.audit-progress li.is-done,
.audit-progress li[aria-current] {
  border-top-color: var(--audit);
}

.audit-progress li[aria-current] {
  color: var(--text);
}

.audit-progress li.is-done span,
.audit-progress li[aria-current] span {
  border-color: transparent;
  background: var(--audit);
  color: #fff;
}

/* --- a step --------------------------------------------------------------- */

.audit-step {
  display: grid;
  gap: 18px;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  animation: audit-arrive 320ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

.audit-step[hidden] {
  display: none;
}

.audit-step legend {
  margin-bottom: 18px;
  padding: 0;
  font-family: var(--font-display), var(--font-ui, Geist), sans-serif;
  font-size: 24px;
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.15;
  color: var(--text);
}

@keyframes audit-arrive {
  from {
    opacity: 0;
    transform: translateX(14px);
  }
}

.audit .opt {
  margin-left: 4px;
  font-style: normal;
  font-size: 13px;
  color: var(--text-dim);
}

.audit [aria-invalid='true'] {
  border-color: var(--err);
}

/* `.btn` and `.ticket` each set a display, and an author's `display` outranks
   the `hidden` attribute's: Back stood on the first step with nowhere to go
   back to, and the whole form stood over the rocket it had been replaced by. */
.audit[hidden],
.audit [hidden] {
  display: none;
}

.audit input:focus-visible,
.audit textarea:focus-visible {
  outline-color: var(--violet);
}

.audit textarea {
  min-height: 120px;
}

/* --- options -------------------------------------------------------------- */

.audit-group {
  display: grid;
  gap: 10px;
}

.audit-caption {
  font-size: 14.5px;
  color: var(--text-soft);
}

.audit-options {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/*
 * A pill, which on this site is the shape of a thing you toggle — see `.btn`'s
 * note in `shared.css` on why the buttons are not.
 *
 * The real input stays in the label, invisible rather than removed, so the
 * keyboard, the arrow keys within a radio group and a screen reader all get
 * the native control and only the drawing is replaced.
 */
.audit .audit-option {
  position: relative;
  display: inline-flex;
  cursor: pointer;
}

.audit .audit-option input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: pointer;
}

.audit .audit-option > span {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 15px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg-panel);
  font-size: 14.5px;
  color: var(--text-soft);
  transition:
    border-color 140ms ease,
    background 140ms ease,
    color 140ms ease;
}

.audit .audit-option:hover > span {
  border-color: color-mix(in srgb, var(--violet) 45%, var(--line));
  color: var(--text);
}

.audit .audit-option input:checked + span {
  border-color: var(--audit);
  background: var(--audit-wash);
  color: var(--text);
}

/* The tick a picked option grows, so "picked" is not said by colour alone. */
.audit .audit-option input[type='checkbox'] + span::before {
  content: '';
  width: 0;
  height: 9px;
  margin-right: -8px;
  opacity: 0;
  background: var(--violet);
  clip-path: polygon(8% 52%, 0 64%, 38% 100%, 100% 18%, 90% 8%, 37% 76%);
  transition:
    width 160ms ease,
    margin 160ms ease,
    opacity 160ms ease;
}

.audit .audit-option input[type='checkbox']:checked + span::before {
  width: 11px;
  margin-right: 0;
  opacity: 1;
}

.audit .audit-option input:focus-visible + span {
  outline: 2px solid var(--violet);
  outline-offset: 2px;
}

.audit .btn:focus-visible {
  outline-color: var(--violet);
}

@media (max-width: 560px) {
  /* The names go and the numbers stay: three labels do not fit a phone, and
     the legend under them already says which step this is. */
  .audit-progress {
    font-size: 0;
    gap: 6px;
  }

  .audit-progress li span {
    font-size: 11.5px;
  }

  .audit-step legend {
    font-size: 21px;
  }
}

/* ---------------------------------------------------------------------------
   Sent
   ---------------------------------------------------------------------------
   Three states on one stage, named by `data-state`:

     sending   the rocket holds with its engines lit while the request is out
     launched  the answer came back good, and it goes
     done      the tick, and the words

   A failure never reaches the second: the stage is taken away and the form
   comes back as it was left.
   --------------------------------------------------------------------------- */

.launch {
  position: relative;
  max-width: 62ch;
  min-height: 380px;
  display: grid;
  place-items: center;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--bg-panel);
  text-align: center;
}

.launch[hidden] {
  display: none;
}

.launch > * {
  grid-area: 1 / 1;
}

/* --- the sky going past ---------------------------------------------------- */

.launch-sky {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 400ms ease;
}

.launch[data-state='sending'] .launch-sky,
.launch[data-state='launched'] .launch-sky {
  opacity: 1;
}

.launch-sky i {
  position: absolute;
  top: -40px;
  width: 1.5px;
  height: 34px;
  border-radius: 2px;
  background: linear-gradient(to bottom, transparent, color-mix(in srgb, var(--text) 50%, transparent));
  animation: launch-streak 900ms linear infinite;
}

.launch-sky i:nth-child(1) { left: 9%; animation-duration: 1000ms; animation-delay: -200ms; }
.launch-sky i:nth-child(2) { left: 22%; animation-duration: 760ms; animation-delay: -640ms; height: 22px; }
.launch-sky i:nth-child(3) { left: 36%; animation-duration: 1150ms; animation-delay: -90ms; }
.launch-sky i:nth-child(4) { left: 63%; animation-duration: 840ms; animation-delay: -420ms; height: 26px; }
.launch-sky i:nth-child(5) { left: 76%; animation-duration: 1060ms; animation-delay: -760ms; }
.launch-sky i:nth-child(6) { left: 88%; animation-duration: 720ms; animation-delay: -300ms; height: 20px; }
.launch-sky i:nth-child(7) { left: 50%; animation-duration: 1300ms; animation-delay: -980ms; height: 16px; opacity: 0.5; }

.launch[data-state='launched'] .launch-sky i {
  animation-duration: 380ms;
}

@keyframes launch-streak {
  to {
    transform: translateY(460px);
  }
}

/* --- the rocket ------------------------------------------------------------ */

.launch-rocket {
  margin-bottom: 70px;
  overflow: visible;
  filter: drop-shadow(0 14px 22px rgba(74, 56, 190, 0.45));
}

/* Holding: a tremble small enough to read as thrust rather than as a wobble. */
.launch[data-state='sending'] .launch-rocket {
  animation:
    launch-settle 420ms cubic-bezier(0.2, 0.7, 0.2, 1) both,
    launch-hold 110ms linear 420ms infinite;
}

/* Going: slow off the mark and then gone — the ease is nearly all in the
   second half, which is what makes it a launch and not a slide. */
.launch[data-state='launched'] .launch-rocket {
  animation: launch-go 1000ms cubic-bezier(0.6, 0, 0.9, 0.35) forwards;
}

.launch[data-state='done'] .launch-rocket {
  visibility: hidden;
}

.launch-flame {
  transform-origin: 32px 70px;
  animation: launch-burn 90ms ease-in-out infinite alternate;
}

.launch[data-state='launched'] .launch-flame {
  animation: launch-burn-full 70ms ease-in-out infinite alternate;
}

@keyframes launch-settle {
  from {
    opacity: 0;
    transform: translateY(60px);
  }
}

@keyframes launch-hold {
  0% { transform: translate(0, 0); }
  25% { transform: translate(0.7px, -0.6px); }
  50% { transform: translate(-0.6px, 0.5px); }
  75% { transform: translate(0.5px, 0.7px); }
  100% { transform: translate(0, 0); }
}

@keyframes launch-go {
  0% { transform: translateY(0); }
  18% { transform: translateY(7px); }
  100% { transform: translateY(-460px); }
}

@keyframes launch-burn {
  from { transform: scale(0.92, 0.82); }
  to { transform: scale(1.04, 1.06); }
}

@keyframes launch-burn-full {
  from { transform: scale(1.05, 1.5); }
  to { transform: scale(1.2, 1.9); }
}

/* --- arrived ---------------------------------------------------------------- */

.launch-check {
  align-self: start;
  margin-top: 54px;
  fill: none;
  stroke: var(--ok);
  stroke-width: 3.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  visibility: hidden;
}

.launch-check circle {
  stroke-dasharray: 202;
  stroke-dashoffset: 202;
  transform: rotate(-90deg);
  transform-origin: 50% 50%;
}

.launch-check path {
  stroke-dasharray: 44;
  stroke-dashoffset: 44;
}

.launch[data-state='done'] .launch-check {
  visibility: visible;
  animation: launch-pop 520ms cubic-bezier(0.3, 1.5, 0.5, 1) 380ms both;
}

.launch[data-state='done'] .launch-check circle {
  animation: launch-draw 560ms cubic-bezier(0.6, 0, 0.3, 1) forwards;
}

.launch[data-state='done'] .launch-check path {
  animation: launch-draw 300ms cubic-bezier(0.6, 0, 0.3, 1) 460ms forwards;
}

@keyframes launch-draw {
  to {
    stroke-dashoffset: 0;
  }
}

/* The ring closes, the tick lands, and the whole mark gives once — the landing
   is what says "done" rather than "drawn". */
@keyframes launch-pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.09); }
  100% { transform: scale(1); }
}

/* --- the words --------------------------------------------------------------- */

.launch-words {
  align-self: end;
  width: 100%;
  padding: 0 28px 38px;
}

.launch-status {
  font-size: 14.5px;
  color: var(--text-soft);
}

.launch[data-state='done'] .launch-status {
  display: none;
}

.launch-thanks {
  display: none;
}

.launch[data-state='done'] .launch-thanks {
  display: grid;
  gap: 12px;
  justify-items: center;
  animation: launch-words 520ms ease 640ms both;
}

.launch-thanks h2 {
  font-size: clamp(26px, 4vw, 34px);
  outline: none;
}

.launch-thanks p {
  max-width: 46ch;
  font-size: 16px;
  color: var(--text-soft);
  overflow-wrap: anywhere;
}

.launch-thanks .launch-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 10px;
  margin-top: 6px;
  font-size: 14.5px;
  color: var(--text-dim);
}

.launch-links a {
  color: var(--violet);
  text-decoration: none;
}

.launch-links a:hover {
  text-decoration: underline;
}

@keyframes launch-words {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
}

/* Nothing moves, and nothing is missing: the stage still says sending, then
   shows the tick already drawn and the words already there. */
@media (prefers-reduced-motion: reduce) {
  .audit-step,
  .launch-sky i,
  .launch-rocket,
  .launch-flame,
  .launch[data-state] .launch-rocket,
  .launch[data-state] .launch-flame,
  .launch[data-state='done'] .launch-check,
  .launch[data-state='done'] .launch-thanks {
    animation: none;
  }

  .launch-sky {
    display: none;
  }

  .launch[data-state='launched'] .launch-rocket {
    visibility: hidden;
  }

  .launch[data-state='done'] .launch-check circle,
  .launch[data-state='done'] .launch-check path {
    animation: none;
    stroke-dashoffset: 0;
  }
}
