/* Capture Request — an instrument, not a web form.
 *
 * THREE RULES DRIVE EVERYTHING HERE.
 *
 * 1. COLOUR IS RATIONED, AND IT REPORTS OUTCOMES. Red and green are never decoration
 *    and never chrome. Green appears only on a result that came back confirmed; red
 *    only on one that failed — a declined order, an error notice, a sign-in that broke.
 *    If you can see red on this page, something did not work.
 *
 *    Pisces navy carries identity and structure — masthead, the document's top edge,
 *    the ledger spine, the selected mode, the commit button, focus. Navy never reports
 *    an outcome, so it cannot be confused with one.
 *
 *    Both modes wear the same navy. An earlier revision made the card-change mode red
 *    throughout, on the reasoning that a new card is the more dangerous act; that was
 *    dropped deliberately — it left red doing two jobs at once, so a red panel meant
 *    "you are in card mode" in one place and "this failed" in another. Red now means
 *    exactly one thing.
 *
 * 2. DATA IS MONOSPACE. Every identifier a person could mistype — order numbers, POs,
 *    card digits, transaction ids — is set in a monospaced face with tabular figures.
 *    A transposed digit charges the wrong customer, and proportional type hides
 *    exactly that. This is a safety property that happens to be the type direction.
 *
 * 3. THE IDENTIFIER IS THE LARGEST THING ON THE PAGE. Rule 2 taken to its conclusion.
 *    The ledger sets each recognised order bigger than the heading above it, because
 *    the number is the one thing a person must actually read before committing.
 *
 * THE WHOLE FORM FITS ON ONE SCREEN, in both modes, with nothing entered. That is a
 * requirement, not a nicety: this form commits an irreversible act, and a commit button
 * below the fold is a commit button pressed without the orders in view.
 *
 * Card mode earns the room two ways, both in the two-column rule at the bottom of this
 * file. The card panel sits BESIDE the orders and the steps rather than under them, and
 * the message strip fills the space left under the card panel instead of taking a full
 * row of its own — so the strip finishes level with the steps box and no gap is wasted.
 * Together that is worth a bit over 250px of height.
 *
 * No webfonts, by constraint and by preference: the CSP is font-src 'self', so the
 * personality here comes from treatment — tracking, scale, tabular figures, rules —
 * rather than from a downloaded face.
 */

:root {
  /* ground + surfaces — cool, clinical, and a ground the navy belongs on */
  --paper:      #F1F4F8;
  --surface:    #FFFFFF;

  /* identity — structure only, never a state */
  --navy:       #003680;
  --navy-deep:  #002356;
  --navy-tint:  #E7EEF8;
  --brand-green:#00DE73;

  --ink:        #0E1319;
  --ink-soft:   #4E5A69;
  --ink-faint:  #8592A2;
  --rule:       #DEE4EC;
  --rule-firm:  #BDC7D4;

  /* state — outcomes only */
  --charge:     #B4231F;   /* a result that failed */
  --charge-dim: #FBEAE9;
  --ok:         #07784A;   /* confirmed, past tense */
  --ok-dim:     #E3F2EA;

  --mono: ui-monospace, "Cascadia Mono", "Cascadia Code", Consolas,
          "SF Mono", "Roboto Mono", monospace;
  --sans: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, sans-serif;

  --step: 4px;
  --lift: 0 1px 2px rgba(14, 19, 25, .04), 0 10px 28px -14px rgba(14, 19, 25, .14);
}

*, *::before, *::after { box-sizing: border-box; }

/* The `hidden` attribute must win over every layout rule below.
   The UA stylesheet's [hidden] { display: none } has the lowest possible priority, so
   ANY author `display` rule silently beats it — `.gate { display: grid }` kept the
   sign-in panel painted over the whole app after a successful sign-in, which read as
   "sign-in did nothing". Anything toggled with .hidden in JS depends on this line. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
}

.mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "zero" 1;
  letter-spacing: -.01em;
}

button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 2px;
}

/* ── the mark ───────────────────────────────────────────────────────────── */
.logo {
  display: block;
  width: 152px;
  height: auto;
}

.eyebrow {
  margin: 0;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--navy);
}

/* ── sign-in gate ───────────────────────────────────────────────────────── */
.gate {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: calc(var(--step) * 6);
}
.gate-inner {
  max-width: 30rem;
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--rule);
  border-top: 3px solid var(--navy);
  box-shadow: var(--lift);
  padding: calc(var(--step) * 9) calc(var(--step) * 8) calc(var(--step) * 8);
}
.gate-inner .logo { margin-bottom: calc(var(--step) * 7); }
.gate-inner .eyebrow { margin-bottom: calc(var(--step) * 3); }
.gate-inner h1 {
  margin: 0 0 calc(var(--step) * 3);
  font-size: clamp(1.45rem, 4vw, 1.8rem);
  font-weight: 650;
  letter-spacing: -.025em;
  line-height: 1.15;
}
.gate-inner .btn { margin-top: calc(var(--step) * 6); }
.gate-error {
  margin-top: calc(var(--step) * 5);
  padding: calc(var(--step) * 3) calc(var(--step) * 4);
  border-left: 3px solid var(--charge);
  background: var(--charge-dim);
  color: var(--ink);
  font-size: 14px;
}

/* ── masthead ───────────────────────────────────────────────────────────── */
.bar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: calc(var(--step) * 4);
  padding: calc(var(--step) * 3) calc(var(--step) * 7);
  background: var(--surface);
  border-bottom: 1px solid var(--rule);
}
.who {
  display: flex;
  align-items: center;
  gap: calc(var(--step) * 4);
  font-size: 13px;
  color: var(--ink-soft);
}
#whoami { font-size: 12.5px; }

/* ── sheet ──────────────────────────────────────────────────────────────── */
/* One constant width in both modes. It is wide enough for card mode's two columns, so
   switching modes never reflows the page around you. */
.sheet {
  max-width: 58rem;
  margin: 0 auto;
  padding: calc(var(--step) * 6) calc(var(--step) * 7) calc(var(--step) * 4);
}

.page-head { margin-bottom: calc(var(--step) * 5); }
.page-head .eyebrow { margin-bottom: calc(var(--step) * 2); }
.page-head h1 {
  margin: 0 0 calc(var(--step) * 1.5);
  font-size: clamp(1.5rem, 3vw, 1.85rem);
  font-weight: 650;
  letter-spacing: -.03em;
  line-height: 1.1;
}
.lede {
  margin: 0;
  max-width: 38rem;
  font-size: 14.5px;
  color: var(--ink-soft);
}

/* ── mode picker ────────────────────────────────────────────────────────── */
.modes {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  background: var(--surface);
  border: 1px solid var(--rule-firm);
  margin-bottom: calc(var(--step) * 4);
}
.mode {
  appearance: none;
  border: 0;
  border-right: 1px solid var(--rule-firm);
  background: transparent;
  padding: calc(var(--step) * 3) calc(var(--step) * 5);
  text-align: left;
  cursor: pointer;
  display: grid;
  gap: 2px;
  transition: background-color .14s ease, color .14s ease;
}
.mode:last-child { border-right: 0; }
.mode:hover { background: var(--navy-tint); }
.mode-name { font-weight: 650; font-size: 14px; letter-spacing: -.01em; }
.mode-sub  { font-size: 12.5px; color: var(--ink-faint); }

/* Both modes select in navy. See rule 1. */
.mode.is-on { background: var(--navy); color: #fff; }
.mode.is-on .mode-sub { color: rgba(255, 255, 255, .70); }
.mode.is-on:hover { background: var(--navy); }

/* ── the document ───────────────────────────────────────────────────────── */
/* A grid with no named areas on purpose: items flow in DOM order, so a hidden card
   panel or notice is removed outright instead of leaving an empty row and its gaps. */
.doc {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: calc(var(--step) * 6);
  background: var(--surface);
  border: 1px solid var(--rule);
  border-top: 3px solid var(--navy);
  box-shadow: var(--lift);
  padding: calc(var(--step) * 5) calc(var(--step) * 7);
}
/* The one place brand green appears outside the mark: a short segment on the top edge,
   the width of the cross in the logo. */
.doc::before {
  content: "";
  position: absolute;
  top: -3px; left: 0;
  width: 52px; height: 3px;
  background: var(--brand-green);
}

/* ── fields ─────────────────────────────────────────────────────────────── */
.field { display: grid; gap: calc(var(--step) * 1.5); align-content: start; }
.field + .field { margin-top: calc(var(--step) * 4); }

label {
  font-size: 11.5px;
  font-weight: 650;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.hint { margin: 0; font-size: 13px; color: var(--ink-faint); }

textarea, input[type="text"], input:not([type]), select {
  width: 100%;
  padding: calc(var(--step) * 2.5) calc(var(--step) * 3);
  border: 1px solid var(--rule-firm);
  border-radius: 0;
  background: var(--surface);
  font-family: var(--mono);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
  transition: border-color .14s ease, box-shadow .14s ease;
}
textarea { resize: vertical; min-height: 3.4rem; line-height: 1.55; }
textarea:focus, input:focus, select:focus {
  border-color: var(--navy);
  box-shadow: 0 0 0 3px var(--navy-tint);
  outline: none;
}
::placeholder { color: var(--ink-faint); opacity: 1; }

/* ── THE LOCKED ORDERS BOX — the signature ──────────────────────────────
   The same box you typed into, after you commit. It REPLACES the textarea rather than
   overlaying it, because a textarea cannot colour individual lines of its own value —
   so the box stays the same size, in the same place, in the same face, and the numbers
   you approved are the numbers that turn green. Nothing migrates to another part of the
   page to report back.

   The numbered spine is the ledger that used to have its own section. The numbers are a
   CSS counter: the identifiers are the content, their position is a fact about the
   rendering. */
.orders-view {
  position: relative;
  counter-reset: oline;
  list-style: none;
  margin: 0;
  padding: calc(var(--step) * 1.5) calc(var(--step) * 3);
  border: 1px solid var(--rule-firm);
  background: var(--surface);
}
.orders-view::before {
  content: "";
  position: absolute;
  left: 1.6rem; top: calc(var(--step) * 3); bottom: calc(var(--step) * 3);
  width: 1px;
  background: var(--rule);
}

.oline {
  position: relative;
  display: grid;
  grid-template-columns: 1.625rem auto 1fr auto;
  align-items: baseline;
  gap: calc(var(--step) * 3);
  padding: calc(var(--step) * 2) 0;
}
.oline + .oline { border-top: 1px solid var(--rule); }
.oline::before {
  counter-increment: oline;
  content: counter(oline, decimal-leading-zero);
  align-self: center;
  width: 1.625rem;
  padding: 3px 0;
  background: var(--navy-tint);
  color: var(--navy);
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 600;
  text-align: center;
}
.oline-kind {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
/* Rule 3: the number a person must actually read. */
.oline-id {
  font-family: var(--mono);
  font-size: 18px;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "zero" 1;
  font-weight: 600;
  letter-spacing: -.02em;
  color: var(--ink-faint);
  transition: color .2s ease;
}
.oline-state {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}

/* Queued: legible but plainly not started. */
.oline.is-wait .oline-id { color: var(--ink-faint); }

.oline.is-working .oline-id { color: var(--ink); }
.oline.is-working .oline-state { color: var(--navy); }
.oline.is-working::before { background: var(--navy); color: #fff; }

/* A wash as well as coloured type: this is the moment the person is waiting for, and it
   should be readable from across a desk. */
.oline.is-ok { background: linear-gradient(90deg, var(--ok-dim), transparent 55%); }
.oline.is-ok .oline-id { color: var(--ok); }
.oline.is-ok .oline-state { color: var(--ok); }
.oline.is-ok::before { background: var(--ok); color: #fff; }

.oline.is-bad { background: linear-gradient(90deg, var(--charge-dim), transparent 55%); }
.oline.is-bad .oline-id { color: var(--charge); }
.oline.is-bad .oline-state { color: var(--charge); }
.oline.is-bad::before { background: var(--charge); color: #fff; }

/* A dry run is neither — saying it failed trains people to ignore the word. */
.oline.is-dry .oline-id { color: var(--ink); }
.oline.is-dry .oline-state { color: var(--ink-soft); }

.orders-note {
  margin: calc(var(--step) * 1.5) 0 0;
  min-height: 1.1rem;
  font-size: 12.5px;
  color: var(--ink-faint);
}
.orders-note.is-bad { color: var(--charge); }

/* ── the side column ────────────────────────────────────────────────────
   In card mode this is the right-hand column: the card panel at its natural height with
   the message strip filling whatever is left, so the strip finishes exactly level with
   the steps box beside it and the blank space under the card panel is put to work.

   In capture mode there is no second column and no card panel, so this collapses to
   nothing more than a wrapper around the strip. */
.side {
  display: flex;
  flex-direction: column;
  gap: calc(var(--step) * 4);
  min-height: 0;
}

/* ── card panel ─────────────────────────────────────────────────────────── */
.card-panel {
  margin: 0;
  padding: calc(var(--step) * 4);
  background: var(--navy-tint);
  border: 1px solid var(--rule-firm);
  border-left: 3px solid var(--navy);
  align-content: start;
}
.card-head h2 {
  margin: 0 0 calc(var(--step) * 1.5);
  font-size: 14.5px;
  font-weight: 650;
  letter-spacing: -.01em;
}
.card-panel .hint { color: var(--ink-soft); }
/* The card number takes the full width; expiry and code share the row under it. This
   holds up in the narrow side column AND full width, so it is the only card layout. */
.card-grid {
  margin-top: calc(var(--step) * 4);
  display: grid;
  grid-template-columns: 1fr 6.25rem;
  gap: calc(var(--step) * 3) calc(var(--step) * 4);
  align-items: end;
}
/* Placed by name, not by position: the card number spans the row, expiry and code share
   the one under it. */
.card-grid .field:first-child { grid-column: 1 / -1; }
.card-grid .field-exp { grid-column: 1; }
.card-grid .field-cvv { grid-column: 2; }
.card-grid .field + .field { margin-top: 0; }
.exp { display: flex; align-items: center; gap: calc(var(--step) * 1.5); }
.exp select { padding-inline: calc(var(--step) * 2); }
.exp-sep { color: var(--ink-faint); }

/* ── live step progress ─────────────────────────────────────────────────
   The bot publishes each step as it takes it and this renders what arrived. A step is
   ticked ONLY because the pipeline said so — there is no timer here and no estimate.

   The bar at the top is a real fraction (steps closed / steps planned). The bar under
   the active step is indeterminate on purpose: the bot cannot know how long the gateway
   will take, and a bar that pretends to would be a lie told in animation. */
.progress {
  margin: 0;
  padding: calc(var(--step) * 3.5);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--navy);
}
.progress-head {
  display: flex;
  align-items: baseline;
  gap: calc(var(--step) * 2);
}
.progress-label {
  font-size: 11.5px; font-weight: 650; letter-spacing: .11em;
  text-transform: uppercase; color: var(--navy);
}
#progress-what { font-size: 13.5px; font-weight: 600; }
.progress-count {
  margin-left: auto;
  font-size: 11.5px;
  color: var(--ink-soft);
}

.progress-track {
  margin-top: calc(var(--step) * 2.5);
  height: 3px;
  background: var(--rule);
  overflow: hidden;
}
.progress-fill {
  display: block;
  height: 100%;
  width: 0;
  background: var(--navy);
  transition: width .3s ease;
}

.psteps {
  list-style: none;
  margin: calc(var(--step) * 2.5) 0 0;
  padding: 0;
  display: grid;
}
.pstep {
  display: grid;
  grid-template-columns: 1.25rem minmax(0, 1fr);
  align-items: baseline;
  gap: calc(var(--step) * 2);
  padding: calc(var(--step) * 0.75) 0;
  font-size: 13.5px;
  line-height: 1.4;
  color: var(--ink-faint);
}
/* The status glyph. Drawn from content so it needs no icon font and no inline SVG. */
.pstep-mark {
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.35;
  text-align: center;
  color: var(--rule-firm);
}
.pstep-body { min-width: 0; }
.pstep-note {
  display: block;
  margin-top: 1px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-faint);
  overflow-wrap: anywhere;
}

.pstep.is-done { color: var(--ink); }
.pstep.is-done .pstep-mark { color: var(--ok); font-weight: 700; }

.pstep.is-now { color: var(--ink); font-weight: 600; }
.pstep.is-now .pstep-mark { color: var(--navy); }

.pstep.is-fail { color: var(--ink); }
.pstep.is-fail .pstep-mark { color: var(--charge); font-weight: 700; }
.pstep.is-fail .pstep-note { color: var(--charge); }

/* The indeterminate bar on the step actually running right now. */
.pstep-bar {
  display: none;
  margin-top: calc(var(--step) * 1.5);
  height: 2px;
  background: var(--navy-tint);
  overflow: hidden;
}
.pstep.is-now .pstep-bar { display: block; }
.pstep-bar::after {
  content: "";
  display: block;
  height: 100%;
  width: 40%;
  background: var(--navy);
  animation: pstep-sweep 1.1s ease-in-out infinite;
}
@keyframes pstep-sweep {
  from { transform: translateX(-100%); }
  to   { transform: translateX(250%); }
}

/* ── notice ─────────────────────────────────────────────────────────────── */
.notice {
  margin: 0;
  padding: calc(var(--step) * 3) calc(var(--step) * 4);
  border-left: 3px solid var(--charge);
  background: var(--charge-dim);
  font-size: 13.5px;
  /* One line per order, so the reasons stay separate and readable. */
  white-space: pre-line;
}
.notice.is-quiet {
  border-left-color: var(--rule-firm);
  background: var(--paper);
  color: var(--ink-soft);
}

/* ── commit ─────────────────────────────────────────────────────────────── */
.commit {
  margin: 0;
  padding-top: calc(var(--step) * 4);
  border-top: 1px solid var(--rule);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: calc(var(--step) * 2) calc(var(--step) * 5);
}
.commit-note { margin: 0; font-size: 13px; color: var(--ink-faint); }

.btn {
  appearance: none;
  border: 1px solid var(--navy);
  background: transparent;
  color: var(--navy);
  padding: calc(var(--step) * 2.5) calc(var(--step) * 6);
  border-radius: 0;
  font-size: 14px;
  font-weight: 650;
  letter-spacing: -.005em;
  cursor: pointer;
  transition: background-color .14s ease, color .14s ease, border-color .14s ease;
}
.btn:hover:not(:disabled) { background: var(--navy); color: #fff; }
.btn-primary { background: var(--navy); color: #fff; }
.btn-primary:hover:not(:disabled) {
  background: var(--navy-deep);
  border-color: var(--navy-deep);
}
.btn:disabled { opacity: .34; cursor: not-allowed; }

.btn-link {
  border: 0;
  padding: 0;
  font-weight: 500;
  font-size: 13px;
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.btn-link:hover { background: transparent; color: var(--navy); }

.foot {
  margin-top: calc(var(--step) * 3);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-faint);
  max-width: 40rem;
}

.muted { color: var(--ink-soft); }

/* ── card mode, wide: the card panel goes BESIDE the ledger ──────────────
   This is what buys the height that keeps the commit button above the fold. Below this
   width the single-column flow above applies and the page may scroll — a phone has no
   second column to give. */
@media (min-width: 60rem) {
  body.mode-card #form {
    grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
    column-gap: calc(var(--step) * 7);
    align-items: start;
  }
  body.mode-card #form > .field-orders { grid-column: 1; grid-row: 1; }
  body.mode-card #form > #progress     { grid-column: 1; grid-row: 2; }
  /* Spanning both rows is what makes the column as tall as the orders box plus the
     steps box, and the flex child below is what makes the strip reach the bottom of it. */
  body.mode-card #form > .side         { grid-column: 2; grid-row: 1 / span 2; }
  body.mode-card #form > .side > #notice {
    flex: 1 1 auto;
    /* min-height:0 lets it shrink inside the flex column; without it a long result
       would push the column taller and put the page back into scroll. */
    min-height: 0;
    overflow-y: auto;
  }
  /* No explicit row: auto-placement puts this after the block above. */
  body.mode-card #form > .commit       { grid-column: 1 / -1; }
}

/* ── narrow ─────────────────────────────────────────────────────────────── */
@media (max-width: 40rem) {
  .sheet { padding-inline: calc(var(--step) * 4); }
  .modes { grid-template-columns: 1fr; }
  .mode { border-right: 0; border-bottom: 1px solid var(--rule-firm); }
  .mode:last-child { border-bottom: 0; }
  .bar { padding-inline: calc(var(--step) * 4); }
  .doc { padding: calc(var(--step) * 5) calc(var(--step) * 4); }
  .gate-inner { padding: calc(var(--step) * 7) calc(var(--step) * 5); }
  .logo { width: 136px; }
  /* The identifier stays big — it is the thing being checked. The row number and the
     kind label are what give way. */
  .oline { grid-template-columns: 1.375rem auto 1fr; gap: calc(var(--step) * 2.5); }
  .oline::before { width: 1.375rem; }
  .oline-state { grid-column: 2 / -1; }
  .orders-view::before { left: 1.4rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    transition-duration: .001ms !important;
  }
  /* A sweep frozen mid-travel reads as a hung page. Show a solid bar instead — the
     step is still marked as running, just without the movement. */
  .pstep-bar::after { width: 100%; animation: none !important; }
}
