/* ============================================================
   TRILLIONS — buyer identity surfaces
   ------------------------------------------------------------
   Sign in, register, verify and reset, plus the invitation-only
   supplier quotation page. These carry the slim identity header
   rather than the site navigation: someone here arrived from an
   email or a sign-in link, not from browsing.

   Loads after tokens.css. buyer-identity.js writes
   #identityMessage.className as "identity-status ok" or
   "identity-status error"; both states are styled below, and the
   element stays invisible until one of them is set.
   ============================================================ */

[hidden] {
  display: none !important;
}

body.identity-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
}

.identity-header {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.identity-nav {
  display: flex;
  align-items: center;
  gap: var(--s5);
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding: var(--s3) var(--page-margin);
  min-height: 60px;
}

.identity-links {
  display: flex;
  gap: var(--s4);
  margin-inline-start: auto;
}

/* Last in the bar, at the reading edge. On a page with no account links beside
   it the auto margin is the switcher's own; where there are links they take it
   and the switcher follows them. */
.identity-lang {
  margin-inline-start: auto;
}

.identity-links + .identity-lang {
  margin-inline-start: 0;
}

.identity-links a {
  font-size: 13px;
  font-weight: 500;
  color: var(--mute);
  text-decoration: none;
}

.identity-links a:hover {
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.identity-main {
  flex: 1;
  padding-block: var(--s8);
}

/* One column, centred. Every identity page is now the card and nothing else —
   the panel beside it explained the workspace to somebody who was already on
   their way into it, which is a thing to read rather than a thing to do. Sign
   in had this on its own; it is the shell now. */
.identity-shell {
  display: grid;
  grid-template-columns: minmax(0, 420px);
  justify-content: center;
  gap: var(--s7);
  align-items: start;
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--page-margin);
}

.identity-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r4);
  padding: var(--s6);
}

/* The sign-in, registration and password pages carry no intro block, so their
   card heading is the page heading and is marked up as `h1`; the pages that do
   have an `.identity-intro` above keep `h2` here, under that page's `h1`. Both
   are the same object in the card, so both take the same type. */
.identity-card :is(h1, h2) {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.identity-card > p {
  margin-block-start: 6px;
  font-size: 13px;
  color: var(--mute);
}

/* The label above the heading.

   Removed by the same commit, and with no `.eyebrow` rule anywhere else in the
   two stylesheets these pages load, "Platform bootstrap" and "Invitation-only
   quotation" render as ordinary body text rather than the label they are.

   Only what is actually broken is restored here: `.identity-intro h1` and its
   lead paragraph went too, but h1 still has a rule in tokens.css and the
   paragraph reads correctly at the body size, so re-adding those would change
   how the pages look rather than repair them. */
.identity-intro .eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-block-end: var(--s3);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mute);
}

.identity-intro .eyebrow::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* The short points under an intro heading, and the result lines a run writes
   back.

   These rules were deleted on 4 August with the identity pages that used them,
   but two pages outside that set still carry the class, and both lost their
   layout silently: the spans are inline with nothing between them, so the text
   renders as one run of words. On /supplier-quotation.html that is the
   reference, quantity and deadline of the request a supplier was invited to
   quote — read as `ReferenceQuantityDeadline`. On /admin/bootstrap.html it is
   the page an operator opens when a deployment is already broken.

   `li` is matched beside `span` because the same class carries the migration
   and reset result lists, which are real lists; the marker is turned off so
   they take the square below rather than a bullet and a square. */
.identity-points {
  display: grid;
  gap: var(--s3);
  margin-block-start: var(--s6);
  padding-block-start: var(--s5);
  padding-inline-start: 0;
  border-top: 1px solid var(--line);
  list-style: none;
}

.identity-points span,
.identity-points li {
  display: grid;
  grid-template-columns: 14px minmax(0, 1fr);
  gap: var(--s3);
  font-size: 13px;
  color: var(--mute);
}

.identity-points span::before,
.identity-points li::before {
  content: "";
  width: 9px;
  height: 9px;
  margin-block-start: 5px;
  border-radius: 2px;
  background: var(--ink);
}

.identity-form {
  display: grid;
  gap: var(--s4);
  margin-block-start: var(--s5);
}

.identity-form label {
  display: grid;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-2);
}

/* A grid makes an item of every child, and of every run of text between them —
   so "Website" and its "— optional" became two rows, one under the other, with
   the gap of a field between them. The two are one line of label, so they are
   one element; this only says what the marker looks like inside it. */
.identity-form .opt {
  font-weight: 400;
  color: var(--mute);
}

/* Text controls only. A radio or a checkbox brings its own shape — the
   .choice card draws its own dot, and .identity-check its own box — and a
   42px-tall full-width border around either is the wrong control entirely.
   The sign-up's first question is radios, so this is load-bearing. */
.identity-form input:not([type="radio"]):not([type="checkbox"]),
.identity-form select,
.identity-form textarea {
  width: 100%;
  height: 42px;
  padding-inline: 13px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r2);
  background: var(--surface);
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink);
  transition: border-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
  /* Typed values resolve their own direction; see .input in tokens.css. */
  unicode-bidi: plaintext;
}

.identity-form textarea {
  height: auto;
  min-height: 96px;
  padding-block: 11px;
  line-height: 1.55;
  resize: vertical;
}

.identity-form input:not([type="radio"]):not([type="checkbox"]):hover,
.identity-form select:hover,
.identity-form textarea:hover {
  border-color: var(--mute-2);
}

.identity-form input:not([type="radio"]):not([type="checkbox"]):focus,
.identity-form select:focus,
.identity-form textarea:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(15, 23, 42, 0.09);
}

/* ------------------------------------------------------------
   The first question

   Sign-up asks what you are here to do before it asks anything
   else, because the two answers want different forms and the
   person is the only one who knows which. The .choice card is the
   shared one, so the question reads the same here as it does
   inside the two journeys.
   ------------------------------------------------------------ */

.identity-roles {
  display: grid;
  gap: var(--s2);
  border: 0;
  margin: 0;
  padding: 0;
}

.identity-roles legend {
  padding: 0;
  margin-block-end: var(--s2);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-2);
}

/* .identity-form label is (0,1,1) and sets display: grid, which outranks the
   shared .choice's own flex row and stacks the dot above the words. Restated at
   matching weight rather than reordered, because the grid is right for every
   other label on the form. The same applies to the terms checkbox below. */
.identity-form .choice,
.identity-form .identity-check {
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

.identity-roles .choice {
  padding: var(--s3);
  gap: var(--s3);
}

.identity-roles .choice span {
  display: grid;
  gap: 3px;
}

.identity-roles .choice small {
  color: var(--mute);
}

/* The company block. Revealed by one of the two answers, so it is
   a section of the form rather than a second form: same labels,
   same fields.

   Its own surface rather than a rule above it. A rule separates two
   runs of fields; it does not say where the second one ends, and the
   terms checkbox below read as the last line of the company. The
   answers about the person and the answers about the company are
   different subjects, and a supplier is the only one who sees both. */
.identity-company {
  display: grid;
  gap: var(--s4);
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--r3);
  background: var(--wash);
}

/* Last line of the block and not a field: what the account is for, said
   where a supplier is deciding whether to make one. */
.identity-company .hint:last-child {
  margin: 0;
}

.identity-company .t-lab {
  margin: 0;
}

.identity-company[hidden] {
  display: none;
}

.identity-check {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-size: 13px;
  font-weight: 400;
  color: var(--ink-3);
}

.identity-check input {
  appearance: none;
  width: 19px;
  height: 19px;
  flex: none;
  margin: 1px 0 0;
  border: 1.5px solid var(--line-strong);
  border-radius: 5px;
  background: var(--surface);
  cursor: pointer;
}

.identity-check input:checked {
  background: var(--ink);
  border-color: var(--ink);
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='19' height='19' fill='none' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M5 9.8l3 3 6-6.5'/></svg>");
}

.identity-check a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

.identity-status {
  display: none;
  margin-block-start: var(--s4);
  padding: var(--s3) var(--s4);
  border-radius: var(--r3);
  border: 1px solid;
  font-size: 13px;
  line-height: 1.55;
}

.identity-status.ok {
  display: block;
  background: var(--ok-bg);
  border-color: var(--ok-line);
  color: var(--ok);
}

.identity-status.error {
  display: block;
  background: var(--miss-bg);
  border-color: var(--miss-line);
  color: var(--miss);
}

.identity-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4);
  margin-block-start: var(--s5);
  padding-block-start: var(--s4);
  border-top: 1px solid var(--line);
}

.identity-actions a {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--line-strong);
}

.identity-actions a:hover {
  text-decoration-color: var(--ink);
}

.identity-muted {
  font-size: 12.5px;
  color: var(--mute);
}

.identity-foot {
  padding: var(--s5) var(--page-margin);
  border-top: 1px solid var(--line);
  background: var(--surface);
}

.identity-foot p {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  font-size: 11.5px;
  line-height: 1.65;
  color: var(--mute);
}

@media (max-width: 980px) {
  .identity-shell {
    grid-template-columns: 1fr;
    gap: var(--s6);
  }

  .identity-main {
    padding-block: var(--s6);
  }
}

@media (max-width: 620px) {
  .identity-card {
    padding: var(--s5) var(--s4);
  }
}

/* ------------------------------------------------------------
   Invitation-only quotation page
   A supplier reaches this from a one-time link in an email. There
   is no navigation, because there is nowhere else to go.
   ------------------------------------------------------------ */

.quote-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s4);
  margin-block-start: var(--s5);
}

.quote-grid label {
  display: grid;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-2);
}

.quote-grid input,
.quote-grid select,
.quote-grid textarea {
  width: 100%;
  height: 42px;
  padding-inline: 13px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r2);
  background: var(--surface);
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink);
  /* Typed values resolve their own direction; see .input in tokens.css. */
  unicode-bidi: plaintext;
}

.quote-grid textarea {
  height: auto;
  min-height: 88px;
  padding-block: 11px;
  line-height: 1.55;
  resize: vertical;
}

.quote-grid input:focus,
.quote-grid select:focus,
.quote-grid textarea:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px rgba(15, 23, 42, 0.09);
}

.quote-grid .field-full {
  grid-column: 1 / -1;
}

@media (max-width: 620px) {
  .quote-grid {
    grid-template-columns: 1fr;
  }
}

/* The message a single field is wrong, sitting under that field rather than
   with the form-wide status at the bottom of the card. Created by
   buyer-identity.js only once there is something to say, so a clean form
   carries no empty elements and no reserved space.

   It borrows the miss colours the form-wide error already uses, without its
   panel: a box around one line under one input reads as a second field. The
   input beside it is marked through aria-invalid, which is also what colours
   its border below — so the state is announced and shown from one source. */
.identity-field-error {
  margin-block-start: var(--s2);
  margin-block-end: 0;
  color: var(--miss);
  font-size: 12px;
  line-height: 1.5;
}

.identity-field-error[hidden] {
  display: none;
}

.identity-form input[aria-invalid="true"],
.identity-form textarea[aria-invalid="true"],
.identity-form select[aria-invalid="true"] {
  border-color: var(--miss);
}
