/* styles/login.css — sign-in page and the shared field / input treatment. Order in VulnerabilityCore.html is the cascade order. */

/* ============================================================ login */
.login {
  position: relative; /* anchors the top-left .login-brand */
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  min-height: 100vh;
  width: 100%;
  /* Flex child of .app — without min-width:0 it refuses to shrink below its
     content's min-content, overflowing the viewport on phones. */
  min-width: 0;
}
.login-aside {
  position: relative;
  overflow: hidden;
  background: var(--bg-panel);
  border-right: 1px solid var(--line);
  padding: 48px 52px;
  display: flex;
  flex-direction: column;
}
.app[data-theme="dark"] .login-aside {
  background: linear-gradient(160deg, #0c1219, #080b10);
}
.login-aside-grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 44px 44px;
  opacity: 0.5;
  mask-image: radial-gradient(circle at 30% 30%, #000, transparent 75%);
}
.login-aside-scan {
  position: absolute;
  left: 0;
  right: 0;
  height: 180px;
  background: linear-gradient(
    180deg,
    transparent,
    var(--accent-soft),
    transparent
  );
  opacity: 0.5;
  animation: scan 7s linear infinite;
}
@keyframes scan {
  0% {
    top: -180px;
  }
  100% {
    top: 100%;
  }
}
.login-aside-top,
.login-aside-mid {
  position: relative;
  z-index: 1;
}
.login-aside-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.login-poc {
  font: 600 10px/1 var(--font-mono);
  letter-spacing: 0.1em;
  color: var(--text-faint);
  border: 1px solid var(--line-2);
  padding: 5px 9px;
  border-radius: 20px;
  white-space: nowrap;
}
.login-aside-mid {
  margin: auto 0;
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.login-steps {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.login-step {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
  opacity: 0;
  animation: rise 0.6s cubic-bezier(0.2, 0.7, 0.3, 1) forwards;
}
@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.login-step-num {
  font: 600 12px/1 var(--font-mono);
  color: var(--accent);
  width: 22px;
}
.login-step-ic {
  color: var(--text-dim);
}
.login-step-tx {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.login-step-tx strong {
  font: 600 14px/1 var(--font);
  color: var(--text);
}
.login-step-tx span {
  font: 13px/1.3 var(--font);
  color: var(--text-dim);
}
.login-tag {
  font: 700 40px/1.05 var(--font-display);
  letter-spacing: -0.02em;
  color: var(--text);
  margin: 8px 0 0;
}
.login-sub {
  font: 15px/1.5 var(--font);
  color: var(--text-dim);
  max-width: 42ch;
  margin: 0;
  text-wrap: pretty;
}
.login-main {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 48px;
  gap: 18px;
}
/* CyMobility wordmark pinned to the top-left corner of the login page. It sits
   above the aside's grid/scan decoration, so it needs its own stacking level.
   Both theme assets are ~15:1 wordmarks, so one width sizes them alike. */
.login-brand {
  position: absolute;
  top: 30px;
  left: 52px;
  z-index: 3;
  display: block;
  /* 250px ≈ 16px of letterforms at the ~15:1 wordmark ratio — a step up from the
     sidebar footer's 150px, which suits a login page, without going hero-sized. */
  width: 250px;
  max-width: 42vw;
  height: auto;
  object-fit: contain;
  object-position: left center;
  opacity: 0.95;
}
.app[data-theme="light"] .login-brand {
  opacity: 1;
}
/* vulnerability.core wordmark heading the sign-in section. Same per-theme SVG
   lockup the sidebar uses — pre-cropped to its ink bounds (viewBox 80 700
   1360 200, ratio 6.8), so height alone sizes it. .login-main already centres
   its children, which puts the wordmark on the card's — and so the heading's —
   centre line. */
.login-wordmark {
  display: block;
  /* The SVG's ink fills only ~56% of its 200-unit viewBox, so 40px of box gives
     ~22px of actual lettering — in line with the card's 24px h2 rather than
     towering over it. Width follows at ~272px. */
  height: 40px;
  width: auto;
  /* Sits just above the 380px card; the cap only guards against overflow, it
     must stay clear of the natural width or the fixed height would squash it. */
  max-width: 400px;
  /* Extra breathing room under the wordmark lifts it clear of the card's
     "Analyst access" eyebrow, so it reads as the section's own heading. */
  margin-bottom: 36px;
}
.login-card {
  width: 100%;
  max-width: 380px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
/* Purple sign-in button (scoped to the login card so other accent
   buttons keep the theme's default styling). */
.login-card .btn-accent {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
}
.login-card .btn-accent:hover {
  background: var(--accent);
}
.login-card-head {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-bottom: 6px;
}
.login-eyebrow,
.eyebrow {
  /* block, so the 11px/1 above actually governs the box. As an inline span it
     took the parent's line-height instead and struck a 21px line box for an 11px
     label — ~10px of accidental leading at the very top of every page head.
     Safe for the login card: there the eyebrow is a flex item of
     .login-card-head, where display is already blockified and the 5px gap owns
     the spacing. */
  display: block;
  font: 600 11px/1 var(--font);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}
.login-card-head h2 {
  font: 700 24px/1.1 var(--font-display);
  margin: 2px 0 0;
  color: var(--text);
}
.login-card-head p {
  font: 13.5px/1.4 var(--font);
  color: var(--text-dim);
  margin: 0;
}
.field {
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.field-lab {
  font: 600 12px/1 var(--font);
  color: var(--text-dim);
}
.field-wrap {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 0 12px;
  height: 44px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  background: var(--surface);
  transition: 0.14s;
}
/* --accent is #49299a in BOTH themes, and on the dark canvas that is very nearly
   the canvas: as a focus bar it measures 1.51:1, as a row rail 1.82:1, as the
   selected tab 1.73:1. Dark is what the app boots in, so every cue built on it was
   invisible for most users. Dark borrows --accent-3, the brand's own lighter step
   already declared beside it; light, where raw --accent is 8.4:1 on the focus fill
   and 10.2:1 as a rail, is left byte-identical. ONE token, because the field bar,
   the table rail, the focus rings and the taxonomy tab all had the same bug and
   should not each re-derive an answer. */
.app {
  --focus: var(--accent);
}
.app[data-theme="dark"] {
  --focus: var(--accent-3);
}

/* The ground. --surface (the field), --bg-panel (the form panel) and .card's fill
   are ALL #ffffff in the light theme, so an admin field, the panel behind it and
   the card behind that were three coincident whites separated by one hairline.
   Dropping the field to --bg recesses it below its panel in BOTH themes - the same
   token and the same call .admintbl th already makes one card lower, so the form
   and the table it writes into recess alike. Login is deliberately not included:
   its fields sit directly ON --bg, and this would erase them.
   This rule and the focus rule below are both (0,0,2,0) - filing this one down into
   the admin section would make it win over focus and a focused field would stop
   lifting. Source order is the only thing holding them apart. */
.admin-form .field-wrap,
.jira-panel .field-wrap,
.rev-grid .field-wrap {
  background: var(--bg);
}
/* A read-only field that looks editable is a small lie told 44px tall. */
.field-wrap input[readonly] {
  color: var(--text-dim);
  cursor: default;
}

/* Focus must ADD definition, never subtract it. The old rule set border-color to
   transparent, so in the light theme focusing a field DELETED the only edge it had
   and left a 1.2:1 lavender wash - the focused field read as less defined than the
   unfocused ones beside it, which is exactly backwards. It was also the odd one
   out: .search, .cmt-input, .asm-due-input and .evi-drop already agree on an
   --accent-line border plus a 3px --accent-soft halo.
   Both halves of the fix are needed and each carries a different theme. The border
   and halo are the LIGHT signal - they measure under 1.3:1 on the dark ground. The
   dark signal is the fill step from --bg up to --sidebar-hover plus the inset bar,
   which is why that bar stays and why its ink is --focus rather than raw --accent. */
.field-wrap:focus-within {
  border-color: var(--accent-line);
  background: var(--sidebar-hover);
  box-shadow:
    inset 3px 0 0 var(--focus),
    0 0 0 3px var(--accent-soft);
}

/* Everything on Administration that is not a text field - the tab bar, the row
   delete buttons, Save/Test/Disconnect, the checkboxes, the confirm dialog's Cancel
   and Delete - had no authored focus style at all and fell back to the UA ring,
   which is a coin-flip on a filled indigo button. Scoped to the admin card and the
   confirm dialog rather than added to .btn, which is on eleven other screens. */
.admin-card :focus-visible,
.usm-narrow :focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}
/* The wrap already shows focus for what is inside it; a second ring drawn inside
   the first reads as a rendering fault rather than as emphasis. */
.admin-card .field-wrap input:focus-visible,
.admin-card .field-wrap select:focus-visible {
  outline: none;
}
.field-ic {
  color: var(--text-faint);
}
.field-wrap input {
  flex: 1;
  border: none;
  background: none;
  outline: none;
  color: var(--text);
  font: 14px/1 var(--font);
}
.field-wrap input::placeholder {
  color: var(--text-faint);
}
/* Hide the browser's built-in password reveal/clear controls (Edge/IE add an
   eye icon via ::-ms-reveal) so only our own "Show"/"Hide" toggle appears. */
input[type="password"]::-ms-reveal,
input[type="password"]::-ms-clear {
  display: none;
}
.field-toggle {
  background: none;
  border: none;
  color: var(--text-dim);
  font: 600 12px/1 var(--font);
  cursor: pointer;
  padding: 4px;
  /* Never let the input squeeze this: it was collapsing to "Sh" in a narrow field. */
  flex: none;
  white-space: nowrap;
}
.field-toggle:hover {
  color: var(--accent);
}
/* checkPasswordStrength() is pure, synchronous, and already returns the exact
   sentence an admin needs. The only place it was ever shown was the red .login-err
   box at the FOOT of the form — three grid rows below the field it is about, after
   a failed submit, and dressed identically to a rejection that came back from the
   server. This is where the same sentence goes while they are still typing. The red
   box keeps its real job, which is reporting what the SERVER said. */
.field-note {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  font: 11.5px/1.4 var(--font);
  color: var(--text-faint);
}
.field-note .ic {
  margin-top: 1px;
}
/* Amber, not red: a half-typed password is not an error, it is a password that is
   not finished — the same call .admin-verify makes about "Awaiting OTP". The mix
   toward --text is that chip's recipe too, and for its reason: raw --st-prog and
   --st-done measure under 3:1 on the light ground at this size. */
.field-note.is-bad {
  color: color-mix(in oklab, var(--st-prog) 72%, var(--text));
}
.field-note.is-ok {
  color: color-mix(in oklab, var(--st-done) 72%, var(--text));
}
.login-err {
  display: flex;
  align-items: center;
  gap: 8px;
  font: 13px/1.3 var(--font);
  color: var(--sev-critical);
  background: color-mix(in oklab, var(--sev-critical) 12%, transparent);
  padding: 10px 12px;
  border-radius: var(--radius-sm);
}
/* SBOM generation's error: the cause in bold on its own line, then what to do. The words are in
   the text colour, not red: dark mode's Critical is 2.7:1 on its own tint, which cannot be read.
   The tint and the icon say it is an error; the words have to be read. */
.gen-err {
  align-items: flex-start;
  color: var(--text);
}
.gen-err > svg {
  flex: none;
  margin-top: 2px;
  color: var(--sev-critical);
}
.gen-err-title {
  display: block;
  font-weight: 600;
  margin-bottom: 2px;
}
/* Not an error: why this browser was signed out (the account signed in on another device).
   Accent tint, words in the text colour like .gen-err. */
.login-note {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font: 13px/1.4 var(--font);
  color: var(--text);
  background: color-mix(in oklab, var(--accent) 12%, transparent);
  padding: 10px 12px;
  border-radius: var(--radius-sm);
}
.login-note > svg {
  flex: none;
  margin-top: 1px;
  color: var(--accent);
}
.login-card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 2px;
}
.login-hint {
  align-self: center;
  font: 12px/1 var(--font);
  color: var(--text-faint);
}
.login-link {
  font: 600 12.5px/1 var(--font);
  color: var(--accent);
  text-decoration: none;
  white-space: nowrap;
}
.login-hint {
  white-space: nowrap;
}
.login-legal {
  white-space: nowrap;
}
.login-legal {
  font: 11.5px/1 var(--font);
  color: var(--text-faint);
}
