/* ============================================================================
 * auth.css — the standalone account & password pages (Phase 2 Task 11b).
 *
 * Pixel source: project/auth/auth-screens.jsx — AuthShell + CardHead +
 * TextField + PwField + ReqList + SubmitBtn, across the three screens:
 *   - ClaimAccount  (invite / set initial password)   -> activate.html
 *   - ResetRequest  (forgot / request a reset link)    -> forgot.html
 *   - ResetChoose   (reset with token / new password)  -> reset.html
 *
 * Like login.css these are STANDALONE surfaces OUTSIDE the portal shell, but
 * token- and font-pure via the Phase-1 --tp-* system. The field metrics match
 * the login page exactly (46px control / 11px radius / brand focus ring) so
 * every auth surface reads as one family.
 *
 * D-085: no inline JS/handlers, no inline style="" — the show/hide toggles,
 * the live requirement checklist, the password-match indicator and the submit
 * busy face all live in static/js/auth.js, bound through data-au-* hooks.
 * element.style writes by JS are allowed; this stylesheet supplies every
 * static rule. Token-pure: the only literal is the on-ink #FFFFFF the design
 * system already allowlists for text on solid fills.
 * ========================================================================= */

/* ---- centered-card shell (AuthShell device="desktop") ---------------------- */
.au-page {
  min-height: 100vh;
  min-height: 100dvh;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Device chrome, BOTH axes (2026-08-10 — the viewport-fit=cover rollout).
   *
   * These five templates own their own <head> and now declare
   * `viewport-fit=cover` like base.html does, so the layout viewport extends
   * under the Island / rounded corners / home indicator and nothing above this
   * page absorbs the insets for it — there is no portal topbar out here.
   *
   * THIS rule is the >=768px half of that. At those widths .au-shell is a
   * centred 440px column floating inside this padded page box, so the page's
   * own padding IS the right inset site: the tablet band (768-1023.98px) is
   * where an installed counter iPad's home indicator actually is (D-170), and
   * 48px of designed padding does not by itself reserve a band it knows
   * nothing about. Below 768 the card goes edge-to-edge and this padding drops
   * to 0, which is why the phone override re-homes the insets onto the ROWS
   * (see the media block at the bottom of this file) rather than pulling the
   * full-bleed card off the glass.
   *
   * Two operators, one per axis (design-delta #92(a)): calc() vertically so the
   * designed 48px survives on top of the reserved band, max() horizontally
   * because a landscape notch inset already IS the clearance. Every inset is 0
   * in an ordinary browser tab, so the designed 48/24 is byte-for-byte what
   * desktop renders. Swept by tests/test_device_chrome.py. */
  padding: calc(48px + var(--tp-safe-top)) max(24px, var(--tp-safe-right))
    calc(48px + var(--tp-safe-bottom)) max(24px, var(--tp-safe-left));
  background: var(--tp-bg);
  font-family: var(--tp-font-ui);
  color: var(--tp-ink);
}

.au-shell {
  width: 100%;
  max-width: 440px;
  display: flex;
  flex-direction: column;
}

/* ---- brand mark above the card (BrandMark size 34) ------------------------- */
.au-brand {
  display: flex;
  justify-content: center;
  padding: 0 0 30px;
}

.au-shell.is-muted .au-brand {
  /* Expired/used/invalid: desaturate the whole lockup so the triangle reads as
     deliberately inactive, not just low-contrast (D-153 "1C" muted rule). */
  filter: grayscale(1);
  opacity: 0.5;
}

/* The mark is the Stacks wordmark lockup (.st-authlock / brand.css, D-153) —
   .au-brand above only centers it (desktop) / left-aligns it (phone).
   TODO(dark-mode): dark-set lockup. */

/* ---- the card ------------------------------------------------------------- */
.au-card {
  background: var(--tp-surface);
  border: 1px solid var(--tp-hairline);
  border-radius: 18px;
  overflow: hidden;
  box-shadow: var(--tp-shadow-hero);
}

/* The 4px top accent bar — the bundle's brand gradient #2456E6 -> #6E9BF5.
 * The brand stop is the token; the lighter stop is a one-off ramp endpoint the
 * design system owns no token for (allowlisted in tests/styleguide/conftest.py,
 * same precedent as the login hero's dark stops). */
.au-card-accent {
  height: 4px;
  background: linear-gradient(90deg, var(--tp-brand) 0%, #6E9BF5 100%);
}

.au-shell.is-muted .au-card-accent {
  background: var(--tp-hairline);
}

.au-card-body {
  padding: 34px 36px 36px;
}

/* ---- card head (CardHead: tinted icon tile + title + sub) ------------------ */
.au-head {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 22px;
}

.au-head-icon {
  width: 52px;
  height: 52px;
  border-radius: 14px;
  display: grid;
  place-items: center;
  font-size: 25px;
}

.au-head-icon--brand {
  background: var(--tp-brand-soft);
  color: var(--tp-brand);
}

.au-head-icon--ok {
  background: var(--tp-ok-soft);
  color: var(--tp-ok);
}

.au-head-icon--muted {
  background: var(--tp-hairline-2);
  color: var(--tp-muted);
}

.au-head-text {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.au-title {
  margin: 0;
  font-size: 24px;
  font-weight: 780;
  letter-spacing: -0.02em;
  color: var(--tp-ink);
  line-height: 1.1;
}

.au-sub {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--tp-muted);
}

/* ---- "setting up <email>" verified banner (ClaimAccount main) -------------- */
.au-target {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 13px;
  margin-bottom: 18px;
  background: var(--tp-brand-soft);
  border-radius: 11px;
}

.au-target-icon {
  color: var(--tp-brand);
  font-size: 16px;
  flex-shrink: 0;
}

.au-target-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.au-target-eyebrow {
  font-size: 11px;
  font-weight: 600;
  color: var(--tp-brand);
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.au-target-email {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--tp-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.au-target-badge {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 700;
  color: var(--tp-ok);
  background: var(--tp-ok-soft);
  border-radius: var(--tp-radius-pill);
  padding: 3px 9px;
  flex-shrink: 0;
}

/* ---- error banner (rate-limit / server error; mirrors lg-error in login.css) */
.au-error {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0;
  padding: 11px 13px;
  border-radius: var(--tp-radius-control);
  background: var(--tp-danger-soft);
  color: var(--tp-danger);
  border: 1px solid var(--tp-danger);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.4;
}

.au-error i {
  margin-top: 1px;
  flex-shrink: 0;
}

/* ---- the form ------------------------------------------------------------- */
.au-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.au-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.au-field-label {
  display: flex;
  align-items: center;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--tp-ink-2);
}

/* The wrapper carries the border + focus ring; it holds the leading glyph, the
 * input, and (for password fields) the Show/Hide toggle — mirrors the bundle's
 * TextField/PwField span. */
.au-control {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 48px;
  padding: 0 13px;
  border-radius: 11px;
  background: var(--tp-surface);
  border: 1px solid var(--tp-hairline);
  transition: border 0.15s, box-shadow 0.15s;
}

.au-control:focus-within {
  border-color: var(--tp-brand);
  box-shadow: 0 0 0 3px var(--tp-brand-soft);
}

.au-control-icon {
  color: var(--tp-muted);
  font-size: 16px;
  flex-shrink: 0;
}

.au-input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-size: 14.5px;
  color: var(--tp-ink);
  font-family: var(--tp-font-ui);
}

.au-input::placeholder {
  color: var(--tp-muted);
}

/* Show/Hide password toggle, anchored at the trailing edge of the control. */
.au-show-toggle {
  border: none;
  background: transparent;
  color: var(--tp-muted);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  font-family: var(--tp-font-ui);
  padding: 0;
  white-space: nowrap;
  flex-shrink: 0;
}

/* ---- password-match indicator on the confirm field's label ----------------- */
.au-match {
  margin-left: auto;
  display: none;
  align-items: center;
  gap: 4px;
  font-weight: 600;
}

.au-match--ok {
  color: var(--tp-ok);
}

.au-match--bad {
  color: var(--tp-danger);
}

.au-field[data-au-match="ok"] .au-match--ok {
  display: inline-flex;
}

.au-field[data-au-match="bad"] .au-match--bad {
  display: inline-flex;
}

/* When the confirm field doesn't match, the control reads as an error. */
.au-field[data-au-match="bad"] .au-control {
  border-color: var(--tp-danger);
  box-shadow: 0 0 0 3px var(--tp-danger-soft);
}

/* ---- password requirement checklist (ReqList) ------------------------------ */
.au-reqs {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 13px 14px;
  background: var(--tp-bg);
  border: 1px solid var(--tp-hairline-2);
  border-radius: 11px;
}

.au-req {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--tp-ink-2);
  transition: color 0.15s;
}

/* Empty field: every rule reads as a hint, not a failure. */
.au-reqs[data-au-state="empty"] .au-req {
  color: var(--tp-muted);
}

.au-req.is-ok {
  color: var(--tp-ok);
}

.au-req-dot {
  width: 17px;
  height: 17px;
  border-radius: var(--tp-radius-pill);
  flex-shrink: 0;
  display: grid;
  place-items: center;
  background: var(--tp-hairline-2);
  color: var(--tp-muted);
  font-size: 11px;
  transition: background 0.15s, color 0.15s;
}

.au-req.is-ok .au-req-dot {
  background: var(--tp-ok-soft);
  color: var(--tp-ok);
}

/* The check glyph shows only once the rule passes; otherwise a small dot. */
.au-req-check {
  display: none;
}

.au-req-empty-dot {
  width: 4px;
  height: 4px;
  border-radius: var(--tp-radius-pill);
  background: var(--tp-muted);
}

.au-req.is-ok .au-req-check {
  display: inline-block;
}

.au-req.is-ok .au-req-empty-dot {
  display: none;
}

/* ---- submit button (SubmitBtn: idle -> working -> done) -------------------- */
.au-submit {
  height: 50px;
  border-radius: 12px;
  border: 1px solid var(--tp-ink);
  background: var(--tp-ink);
  color: #FFFFFF;
  font-size: 15px;
  font-weight: 650;
  font-family: var(--tp-font-ui);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  white-space: nowrap;
  transition: background 0.2s;
}

/* Disabled (requirements not yet met): hairline fill, muted label, no border. */
.au-submit:disabled {
  background: var(--tp-hairline);
  border-color: var(--tp-hairline);
  color: var(--tp-muted);
  cursor: default;
}

.au-submit-face {
  display: none;
  align-items: center;
  gap: 10px;
}

.au-submit[data-au-state="idle"] .au-submit-face--idle,
.au-submit[data-au-state="working"] .au-submit-face--working,
.au-submit[data-au-state="done"] .au-submit-face--done {
  display: inline-flex;
}

/* The done state goes brand-ok green (the bundle's success fill). */
.au-submit[data-au-state="done"] {
  background: var(--tp-ok);
  border-color: var(--tp-ok);
  color: #FFFFFF;
}

.au-spin {
  width: 15px;
  height: 15px;
  border-radius: var(--tp-radius-pill);
  border: 2px solid var(--tp-spinner-track-on-fill);
  border-top-color: #FFFFFF;
  animation: au-spin var(--tp-spin-dur) linear infinite;
  flex-shrink: 0;
}

@keyframes au-spin {
  to { transform: rotate(360deg); }
}

/* ---- OR divider + Microsoft link (ClaimAccount footer options) ------------- */
.au-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 2px 0;
}

.au-divider-line {
  flex: 1;
  height: 1px;
  background: var(--tp-hairline);
}

.au-divider-text {
  font-size: 11.5px;
  color: var(--tp-muted);
  font-weight: 500;
}

.au-ms {
  height: 46px;
  border-radius: 12px;
  border: 1px solid var(--tp-hairline);
  background: var(--tp-surface);
  color: var(--tp-ink-2);
  font-size: 13.5px;
  font-weight: 600;
  font-family: var(--tp-font-ui);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  text-decoration: none;
}

.au-ms:hover {
  background: var(--tp-bg);
}

.au-ms-glyph {
  display: grid;
  grid-template-columns: 7px 7px;
  gap: 2px;
}

.au-ms-sq {
  width: 7px;
  height: 7px;
  border-radius: 1px;
}

.au-ms-sq--r { background: #F25022; }
.au-ms-sq--g { background: #7FBA00; }
.au-ms-sq--b { background: #00A4EF; }
.au-ms-sq--y { background: #FFB900; }

/* ---- secondary button (expired states: "Return to sign in") ---------------- */
.au-btn-secondary {
  height: 50px;
  border-radius: 12px;
  border: 1px solid var(--tp-hairline);
  background: var(--tp-surface);
  color: var(--tp-ink);
  font-size: 15px;
  font-weight: 650;
  font-family: var(--tp-font-ui);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  text-decoration: none;
}

.au-btn-secondary:hover {
  background: var(--tp-bg);
}

.au-btn-primary {
  height: 50px;
  border-radius: 12px;
  border: 1px solid var(--tp-ink);
  background: var(--tp-ink);
  color: #FFFFFF;
  font-size: 15px;
  font-weight: 650;
  font-family: var(--tp-font-ui);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  text-decoration: none;
}

.au-btn-primary:hover {
  opacity: 0.92;
}

/* ---- success state (Password set / Password updated) ----------------------- */
.au-success {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 18px;
  padding: 12px 0 6px;
}

.au-success-mark {
  position: relative;
  width: 64px;
  height: 64px;
}

.au-success-ring {
  position: absolute;
  inset: 0;
  border-radius: var(--tp-radius-pill);
  border: 2px solid var(--tp-ok);
  animation: au-ripple 1100ms ease-out infinite;
}

@keyframes au-ripple {
  0% { transform: scale(0.8); opacity: 0.8; }
  100% { transform: scale(1.8); opacity: 0; }
}

.au-success-disc {
  width: 64px;
  height: 64px;
  border-radius: var(--tp-radius-pill);
  background: var(--tp-ok-soft);
  color: var(--tp-ok);
  display: grid;
  place-items: center;
  font-size: 32px;
}

.au-success-text {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.au-success-title {
  margin: 0;
  font-size: 23px;
  font-weight: 780;
  letter-spacing: -0.02em;
  color: var(--tp-ink);
}

.au-success-sub {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--tp-muted);
  max-width: 320px;
}

/* ---- info note (ResetRequest "sent": ask your manager) --------------------- */
.au-note {
  display: flex;
  gap: 11px;
  padding: 13px 14px;
  background: var(--tp-bg);
  border: 1px solid var(--tp-hairline-2);
  border-radius: 11px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--tp-ink-2);
}

.au-note-icon {
  color: var(--tp-muted);
  font-size: 16px;
  flex-shrink: 0;
  margin-top: 1px;
}

/* ---- footer line under the card (TextLink / fine print) -------------------- */
.au-footer {
  text-align: center;
  padding: 20px 0 0;
  font-size: 12.5px;
  color: var(--tp-muted);
}

.au-textlink {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  background: transparent;
  color: var(--tp-brand);
  font-size: 13.5px;
  font-weight: 600;
  font-family: var(--tp-font-ui);
  text-decoration: none;
  cursor: pointer;
  padding: 4px;
}

.au-textlink:hover {
  text-decoration: underline;
}

@media (prefers-reduced-motion: reduce) {
  .au-spin { animation: none; }
  .au-success-ring { animation: none; opacity: 0; }
}

/* ---- responsive: edge-to-edge card on phone (AuthShell device="mobile") ----- */
/* Device chrome on phone: the page box drops to `padding: 0` here so the card
 * can run edge-to-edge, which means EVERY inset this surface owes is owed by
 * one of the rows below. That is the audit's own shape — "background surfaces
 * still run edge to edge; only content and controls pull in" — and it is what
 * .lg-hero / .lg-panel and .ob-top / .ob-stage already do on their own
 * standalone pages. Padding .au-page instead would letterbox the white card
 * inside a --tp-bg band, i.e. re-create the exact look viewport-fit=cover
 * exists to remove. */
@media (max-width: 767.98px) {
  .au-page {
    padding: 0;
    min-height: 100dvh;
  }

  .au-shell {
    max-width: 100%;
    flex: 1;
  }

  /* TOP row of the page: with `.au-page` at `padding: 0` this row starts at the
   * device edge, so the Stacks lockup began at y 26 and ran ~43px — the whole
   * mark inside the 59px Island band, the same defect finding 3 recorded for
   * `.lg-hero` and finding 5 for `.ob-top`. calc(), so the designed 26px of air
   * survives ON TOP of the reserved band: measured 85 = 26 + 59. */
  .au-brand {
    justify-content: flex-start;
    padding: calc(26px + var(--tp-safe-top)) max(22px, var(--tp-safe-right))
      18px max(22px, var(--tp-safe-left));
  }

  .au-card {
    flex: 1;
    border-radius: 0;
    border-left: none;
    border-right: none;
    box-shadow: none;
  }

  /* Sides only. The card's white wash keeps running to the glass (it is the
   * padded box, not the painted one) and only the fields/copy pull in. */
  .au-card-body {
    padding: 26px max(22px, var(--tp-safe-right)) 30px max(22px, var(--tp-safe-left));
  }

  /* The BOTTOM row is whichever of the two comes last, so each states its own
   * case rather than both reserving the band:
   *
   *   - no footer (the success / expired states, and set_pin's keypad) — the
   *     card is :last-child, is `flex: 1`, and therefore ends ON the glass. It
   *     takes a BARE inset on the WRAPPER, the .tp-popover-card / .tp-sheet-card
   *     / .ins-sheet shape (design-delta #92(c)): the wash still reaches the
   *     edge, and .au-card-body's own 30px is the internal padding that stacks
   *     on top of it.
   *   - footer present — the <p> below the card is the last row, and takes
   *     calc() so its designed 26px survives the reserved band.
   *
   * Scoped to `.au-shell >` because .au-card is also the direct child in the
   * muted/expired shells, and :last-child is the whole point of the rule. */
  .au-shell > .au-card:last-child {
    padding-bottom: var(--tp-safe-bottom);
  }

  .au-footer {
    padding: 18px max(22px, var(--tp-safe-right))
      calc(26px + var(--tp-safe-bottom)) max(22px, var(--tp-safe-left));
  }
}

/* ============================================================================
 * Session-expired card (.se-*) — ps-pages.jsx PageSession
 *
 * A standalone centered card used ONLY by auth/session_expired.html. Shares
 * .au-page for the full-viewport centering + background; the card is narrower
 * (380px, matching the bundle) and uses a different internal layout (WU mark
 * inside the card at the top, textAlign center, no top accent bar).
 *
 * Token-pure: the only literals are the on-ink #FFFFFF (allowlisted for
 * text on solid fills) and the brand gradient lighter stop #6E9BF5 (the same
 * allowlisted ramp endpoint already in .au-card-accent).
 * ========================================================================= */

/* ---- centered card -------------------------------------------------------- */
.se-card {
  width: 100%;
  max-width: 380px;
  background: var(--tp-surface);
  border: 1px solid var(--tp-hairline);
  border-radius: 16px;
  box-shadow: var(--tp-shadow-hero);
  padding: 34px 32px 26px;
  text-align: center;
}

/* ---- WU brand mark (inside the card — matches PageSession layout) ---------- */
/* The card logo is the Stacks wordmark lockup (.st-authlock / brand.css, D-153) —
   this wrapper only centers it above the copy. */
.se-logo {
  display: flex;
  justify-content: center;
  margin: 0 auto 18px;
}

/* ---- title ----------------------------------------------------------------- */
.se-title {
  margin: 0 0 6px;
  font-size: 17px;
  font-weight: 700;
  color: var(--tp-ink);
  letter-spacing: -0.01em;
}

/* ---- body copy ------------------------------------------------------------- */
.se-copy {
  margin: 0 0 22px;
  font-size: 12.5px;
  color: var(--tp-ink-2);
  line-height: 1.55;
  text-wrap: pretty;
}

/* ---- primary Sign in button (ink fill — same rule as .au-btn-primary) ------ */
.se-btn {
  height: 46px;
  border-radius: 9px;
  background: var(--tp-ink);
  color: #FFFFFF; /* on-ink text (allowlisted) */
  border: none;
  font-size: 13px;
  font-weight: 600;
  font-family: var(--tp-font-ui);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  text-decoration: none;
  transition: opacity 0.15s;
}

.se-btn:hover {
  opacity: 0.88;
}

/* ---- "You'll return to …" hint line --------------------------------------- */
.se-return {
  margin: 14px 0 0;
  font-size: 11px;
  color: var(--tp-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---- mono version footer -------------------------------------------------- */
.se-footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin-top: 22px;
  padding-top: 14px;
  border-top: 1px solid var(--tp-hairline-2);
  font-family: var(--tp-font-mono);
  font-size: 9.5px;
  color: var(--tp-muted);
}

.se-footer-sep {
  opacity: 0.6;
}

/* ---- responsive: edge-to-edge on phone ------------------------------------ */
@media (max-width: 767.98px) {
  .se-card {
    max-width: 100%;
    border-radius: 0;
    border-left: none;
    border-right: none;
    box-shadow: none;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    justify-content: center;
    /* This card IS the page below 768 — 100dvh tall inside a .au-page whose own
     * padding has dropped to 0 — so all four of its edges are device edges and
     * it owns all four insets itself. The base `34px 32px 26px` is restated
     * here rather than patched per-side, because a shorthand is what renders
     * and pinning it whole is what stops a future tidy silently wiping a term
     * (INSET_ZERO_METRICS). Content is vertically centred, so the top/bottom
     * terms are what keep a long copy block off the Island and the gesture bar
     * as the viewport shortens. */
    padding: calc(34px + var(--tp-safe-top)) max(32px, var(--tp-safe-right))
      calc(26px + var(--tp-safe-bottom)) max(32px, var(--tp-safe-left));
  }
}
