/* ============================================================
   POCKETEER MD3 — Login / Register (CORE, shared)
   Pattern A: single responsive card with Login | Register tabs.
   Tokens come from core: css/brand.css. Self-contained — no
   dependency on the app landing CSS.
   ============================================================ */

html, body { margin: 0; padding: 0; }
body { overflow-x: hidden; }

.lgn-page {
  box-sizing: border-box;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 48px 20px;
  background: var(--bg);
  color: var(--on-surface);
  font-family: var(--font);
  position: relative;
  overflow: hidden;
}
.lgn-page::before,
.lgn-page::after {
  content: ''; position: absolute; border-radius: var(--r-avatar);
  filter: blur(20px); pointer-events: none;
}
.lgn-page::before {
  top: -200px; right: -200px; width: 600px; height: 600px;
  background: radial-gradient(circle, var(--p-90), transparent 70%);
}
.lgn-page::after {
  bottom: -200px; left: -200px; width: 500px; height: 500px;
  background: radial-gradient(circle, var(--t-90), transparent 70%);
}

.lgn-wrap { position: relative; width: 100%; max-width: 460px; }

.lgn-logo {
  display: flex; align-items: center; justify-content: center;
  gap: 10px; margin-bottom: 28px;
}
.lgn-logo .mark {
  width: 40px; height: 40px;
  display: grid; place-items: center;
}
.lgn-logo .name { font: 800 26px/1 var(--font); letter-spacing: -.03em; color: var(--on-surface); }
.lgn-logo .name b { color: var(--p-50); font-weight: 800; }

.lgn-card {
  background: var(--surface);
  border: 1px solid var(--outline-variant);
  border-radius: var(--r-xl);
  box-shadow: var(--el-3);
  overflow: hidden;
}

/* segmented tabs — the control is the shared .pkt-tabs (brand.css); it used to
   be copied here, and the copy had drifted onto --r-panel, so the login page was
   the only screen whose segmented track was a rounded rectangle instead of the
   theme's --r-tabs. The ONE delta login needs is that its two tabs split the
   card's width instead of sizing to their labels. */
.lgn-tabs-wrap { padding: 8px; background: var(--surface-1); }
.lgn-tabs { display: grid; grid-template-columns: 1fr 1fr; width: 100%; }

/* panes */
.lgn-pane { display: none; }
.lgn-card[data-tab='login'] .lgn-pane-login { display: block; }
.lgn-card[data-tab='register'] .lgn-pane-register { display: block; }

.lgn-body { padding: 20px 32px 28px; }
.lgn-h2 { font: var(--headline-m); margin: 0 0 20px !important; }

/* login method toggle (Password / Email code) */
.lgn-method { display: flex; gap: 8px; margin-bottom: 20px; }
.lgn-method a {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 11px 10px; border-radius: var(--r-btn-sm);
  border: 1px solid var(--outline-variant); background: transparent;
  color: var(--on-surface-muted); font: var(--label-l); font-size: 13px;
  text-decoration: none; cursor: pointer; transition: all .2s var(--ease-emph);
}
.lgn-method a:hover { border-color:var(--primary); }
.lgn-method a.active { background: var(--p-95); color:var(--primary-text-hover); border-color: var(--p-80); }

/* fields */
.lgn-fields { display: grid; gap: 14px; }
.lgn-field { display: flex; flex-direction: column; }
.lgn-field > label,
.lgn-field .ui-outputlabel {
  font: var(--label-l); font-size: 12px; text-transform: uppercase;
  letter-spacing: .06em; color: var(--on-surface-muted); margin-bottom: 6px;
}
.lgn-card .lgn-field input,
.lgn-card .lgn-field .ui-inputfield,
.lgn-card .lgn-field .ui-inputtext,
.lgn-card .lgn-field .ui-password,
.lgn-card .lgn-field .ui-password-input,
.lgn-card .lgn-field .ui-inputmask {
  width: 100%; font: var(--body-l);
  padding: 14px 16px; margin: 0;
  background: var(--surface-1);
  border: 1.5px solid var(--outline);
  border-radius: var(--r-field); color: var(--on-surface);
  outline: 0; box-shadow: none;
  transition: border .2s, background .2s;
}
.lgn-card .lgn-field input:focus,
.lgn-card .lgn-field .ui-inputfield:focus,
.lgn-card .lgn-field .ui-password-input:focus,
.lgn-card .lgn-field .ui-inputmask:focus {
  border-color: var(--primary); background: var(--surface);
  box-shadow: 0 0 0 var(--focus-ring-w) var(--focus-ring-color);
}
/* PF may wrap p:password in a span.ui-password with an inner
   input.ui-password-input — make that wrapper full-width. When
   p:password renders the input directly (class ui-password) the
   styled rule above already covers it. */
.lgn-card .lgn-field span.ui-password { display: block; width: 100%; padding: 0; border: 0; background: transparent; }
.lgn-field .ui-message,
.lgn-field .ui-message-error {
  margin-top: 6px; font: var(--body-s); color: var(--e-40);
  background: transparent; border: 0; padding: 0;
}
.lgn-field .ui-message .ui-message-error-icon { display: none; }

.lgn-forgot { text-align: right; }
.lgn-forgot a {
  font: var(--body-s); color:var(--primary-text); font-weight: 600;
  text-decoration: none; cursor: pointer;
}
.lgn-hint {
  font: var(--body-s); color: var(--on-surface-muted);
  display: flex; align-items: flex-start; gap: 8px; padding: 4px 2px;
}
/* OWN the leading icon (the theme sizes .pi at 1rem): render it as a fixed box
   the height of the first text line (body-s = 13px*1.5 = 19.5px) and centre the
   glyph, so it sits on line 1 instead of riding above it. The .lgn-card prefix
   lifts it above the theme's icon rules. */
.lgn-card .lgn-hint > .pi {
  flex: 0 0 auto;
  display: inline-flex !important; align-items: center; justify-content: center;
  width: 16px; height: 19.5px;
  font-size: 14px !important; line-height: 1 !important;
  margin-top: 5px;
}
/* hint rows use an inline <svg> (not .pi) — nudge it onto the first text line */
.lgn-card .lgn-hint > svg { margin-top: 7px;width: 24px;}

/* primary / submit buttons — let the material-3-pocketeer theme give the
   MD3 pill look; we only size them. */
.lgn-card .lgn-submit .ui-button {
  width: 100%; justify-content: center; margin: 8px 0 0; border-radius: var(--r-btn) !important;
}
.lgn-card .lgn-submit:not(.tonal) .ui-button { box-shadow: var(--el-1); }
.lgn-card .lgn-submit:not(.tonal) .ui-button:hover { box-shadow: var(--el-btn-h); }
.lgn-card .lgn-submit.tonal .ui-button {
  background: var(--p-90); color: var(--p-20); box-shadow: none;
}

/* terms row */
.lgn-terms { margin-top: 4px; }
.lgn-terms .lgn-hint a { color:var(--primary-text); font-weight: 700; cursor: pointer; }
/* The terms link must READ as a link (the surrounding sentence is now an explicit
   instruction to click it). Class specificity beats the .lgn-page a no-underline block. */
.lgn-terms .lgn-hint a.lgn-terms-link,
.lgn-terms .lgn-hint a.lgn-terms-link:hover,
.lgn-terms .lgn-hint a.lgn-terms-link:focus {
  color:var(--primary-text); font-weight: 700;
  text-decoration: underline; text-underline-offset: 2px;
}
/* no UA/theme focus ring on the terms link + checkbox (clicking drew a blue outline) */
.lgn-terms .lgn-hint a.lgn-terms-link:focus,
.lgn-terms .lgn-hint a.lgn-terms-link:focus-visible { outline: none; }
.lgn-terms-check .ui-chkbox input:focus,
.lgn-terms-check .ui-chkbox-box:focus,
.lgn-terms-check .ui-chkbox-box:focus-visible,
.lgn-card .lgn-terms-check .ui-chkbox-box.ui-state-focus { outline: none; box-shadow: none !important; }
.lgn-terms-check { display: flex; align-items: flex-start; gap: 10px; margin-top: 12px; }
/* checkbox: fixed size, no theme margin (we own the gap) */
.lgn-terms-check .ui-chkbox { flex: 0 0 auto; margin: 0; }
/* OWN the box + checkmark instead of inheriting the PrimeFaces theme. The
   .lgn-card prefix lifts these above the theme's .ui-chkbox .ui-chkbox-box rules. */
.lgn-card .lgn-terms-check .ui-chkbox-box {
  box-sizing: border-box;
  width: 18px !important; min-width: 18px; height: 18px !important; margin-top: 1px;
  /* radius/tick kept identical to the global native-control block (core-components.css),
     which reads the --r-check role token — NOT the generic --r-xs scale step, or this
     PF widget and the native checkboxes would round differently per theme */
  border: 2px solid var(--outline) !important; border-radius: var(--r-check) !important;
  background: var(--surface-1) !important; position: relative;
  transition: background .15s, border-color .15s;
}
.lgn-card .lgn-terms-check .ui-chkbox-box.ui-state-hover { border-color:var(--primary) !important; }
/* Disabled = terms not yet read: still invite the click (the row opens the terms). */
.lgn-card .lgn-terms-check .ui-chkbox-box.ui-state-disabled { opacity: .45; cursor: pointer; }
/* hide the theme's primeicon glyph; draw our own SVG check when active.
   The mark comes from --check-mark (the whole url() is the token, because
   var() cannot be used inside a data URI) so a theme with a light primary
   can restate it in dark ink instead of white. */
.lgn-card .lgn-terms-check .ui-chkbox-icon { display: none !important; }
.lgn-card .lgn-terms-check .ui-chkbox-box.ui-state-active {
  border-color: var(--primary) !important;
  background: var(--primary) var(--check-mark) center / 13px 13px no-repeat !important;
}
/* label takes the rest of the row and wraps cleanly beside the box */
.lgn-terms-check .ui-outputlabel { flex: 1; margin: 0; text-transform: none; letter-spacing: 0; font: var(--body-s); line-height: 1.45; color: var(--on-surface); }

/* footer line — the "no dead end" cross-link */
.lgn-foot {
  border-top: 1px solid var(--outline-variant);
  padding: 16px 32px; text-align: center;
  font: var(--body-s); color: var(--on-surface-muted);
  background: var(--surface-1);
}
.lgn-foot a { color:var(--primary-text); font-weight: 700; cursor: pointer; text-decoration: none; }
.lgn-foot .lgn-foot-register { display: none; }
.lgn-card[data-tab='register'] .lgn-foot .lgn-foot-login { display: none; }
.lgn-card[data-tab='register'] .lgn-foot .lgn-foot-register { display: inline; }

/* No underline on any login button/link in any state (overrides the
   PrimeFaces theme's a:hover underline). */
.lgn-page a,
.lgn-page a:hover,
.lgn-page a:focus,
.lgn-page .ui-commandlink,
.lgn-page .ui-commandlink:hover,
.lgn-page .ui-commandlink:focus,
.lgn-page .ui-button,
.lgn-page .ui-button:hover,
.lgn-page .lgn-tab,
.lgn-page .lgn-tab:hover { text-decoration: none; }

/* ===== terms-of-use dialog — MD3 (desktop = centered modal) ===== */
.terms-of-use-dialog.ui-dialog {
  border: 0; border-radius: var(--r-xl); padding: 0;
  box-shadow: var(--el-3); overflow: hidden;
  background: var(--surface);
  /* PF sets an explicit inline height on the dialog/content (auto-resize) —
     force auto so the modal sizes to its content, not the viewport. */
  height: auto !important;
  max-height: 70vh;
}
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar {
  position: relative;
  background: var(--surface-1); border: 0;
  border-bottom: 1px solid var(--outline-variant);
  padding: 18px 24px; border-radius: 0;
}
.terms-of-use-dialog.ui-dialog .ui-dialog-title {
  font: var(--headline-s); color: var(--on-surface);
}
/* hide the jQuery-UI maximize icon entirely; redraw close as a clean X */
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar-maximize { display: none; }
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar-icon {
  position: relative; width: 34px; height: 34px;
  border-radius: var(--r-pill); color: transparent;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background .2s;
}
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar-icon .ui-icon {
  display: none;
}
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar-close::before,
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar-close::after {
  content: ''; position: absolute;
  width: 16px; height: 2px; border-radius: var(--r-hairline);
  background: var(--on-surface-muted);
}
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar-close::before { transform: rotate(45deg); }
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar-close::after { transform: rotate(-45deg); }
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar-close:hover {
  background: var(--surface-2);
}
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar-close:hover::before,
.terms-of-use-dialog.ui-dialog .ui-dialog-titlebar-close:hover::after {
  background: var(--on-surface);
}
.terms-of-use-dialog.ui-dialog .ui-dialog-content {
  background: var(--surface); padding: 16px 20px 20px;
  height: auto !important; max-height: 58vh; overflow: auto;
}
/* the dialog content is wrapped in nested ui-outputpanel / .p-3 —
   strip their padding/margin so there is no superfluous frame */
.terms-of-use-dialog .ui-dialog-content > .ui-outputpanel,
.terms-of-use-dialog .ui-dialog-content .ui-outputpanel,
.terms-of-use-dialog .ui-dialog-content .p-3 { padding: 0; margin: 0; }
/* dialog is not resizable — kill any stray handles */
.terms-of-use-dialog .ui-resizable-handle { display: none; }
.terms-of-use-dialog .ui-dialog-content h2 { font: var(--headline-s); color: var(--on-surface); margin: 0 0 8px; }

.terms-of-use-dialog .tos-accordion-panel,
.terms-of-use-dialog .tos-accordion-panel.ui-accordion { border: 0; background: transparent; }
.terms-of-use-dialog .tos-accordion-panel .ui-accordion-header {
  margin-top: 10px; border: 1px solid var(--outline-variant);
  border-radius: var(--r-lg); background: var(--surface-1);
}
.terms-of-use-dialog .tos-accordion-panel .ui-accordion-header > a {
  padding: 16px 18px; font: var(--title-m); color: var(--on-surface); text-decoration: none;
}
.terms-of-use-dialog .tos-accordion-panel .ui-accordion-header.ui-state-active {
  background: var(--p-95); border-color: var(--outline-variant); border-bottom-color: transparent;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
/* hover feedback (login-md3 had none -> base theme made it transparent/near-invisible) */
.terms-of-use-dialog .tos-accordion-panel .ui-accordion-header:not(.ui-state-active):hover {
  border-color:var(--primary); background: var(--surface-2);
}
.terms-of-use-dialog .tos-accordion-panel .ui-accordion-header.ui-state-active:hover {
  background: var(--p-90); border-color: var(--outline-variant); border-bottom-color: transparent;
}
.terms-of-use-dialog .tos-accordion-panel .ui-accordion-content {
  border: 1px solid var(--outline-variant); border-top: 0;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  background: var(--surface); padding: 18px 20px;
  color: var(--on-surface-muted); font: var(--body-m); line-height: 1.7;
}
/* The PF theme :first-child / -last rules force the small 8px ($borderRadius) corner, which made
   the first header's top "shrink" once the active tab was collapsed. Pin both ends to --r-lg so
   every closed header is a uniform pill (last header skips it while active = content attached). */
.terms-of-use-dialog .tos-accordion-panel .ui-accordion-header:first-child {
  border-top: 1px solid var(--outline-variant);
  border-top-left-radius: var(--r-lg);
  border-top-right-radius: var(--r-lg);
}
.terms-of-use-dialog .tos-accordion-panel .ui-accordion-header.ui-accordion-header-last:not(.ui-state-active) {
  border-bottom-left-radius: var(--r-lg);
  border-bottom-right-radius: var(--r-lg);
}

/* ============================================================
   MOBILE (<= 600px) — per design, login is a full-screen stacked
   layout (no card chrome / blobs) and dialogs become bottom sheets.
   ============================================================ */
@media (max-width: 600px) {
  /* login: full-bleed stacked, no elevated card */
  .lgn-page { padding: 24px 16px; align-items: start; }
  .lgn-page::before, .lgn-page::after { display: none; }
  .lgn-wrap { max-width: none; }
  .lgn-logo { margin: 8px 0 24px; }
  .lgn-logo .name { font-size: 20px; }
  .lgn-card {
    border: 0; box-shadow: none; border-radius: 0; background: transparent;
  }
  .lgn-tabs-wrap { background: transparent; padding: 0 0 8px; }
  .lgn-body { padding: 20px 2px 8px; }
  /* the card is transparent here, so the fields sit straight on --bg and their --surface-1
     fill melts into it — use the plain surface (white) so the fields read as fields */
  .lgn-card .lgn-field input,
  .lgn-card .lgn-field .ui-inputfield,
  .lgn-card .lgn-field .ui-inputtext,
  .lgn-card .lgn-field .ui-password-input,
  .lgn-card .lgn-field .ui-inputmask {
    background: var(--surface);
  }
  .lgn-foot {
    background: transparent; border-top: 1px solid var(--outline-variant);
    padding: 16px 2px 0; margin-top: 8px;
  }

  /* terms-of-use dialog: bottom sheet (slide up from bottom) */
  .terms-of-use-dialog.ui-dialog {
    position: fixed !important;
    left: 0 !important; right: 0 !important; bottom: 0 !important;
    top: auto !important;
    width: 100% !important; max-width: 100% !important;
    max-height: 88vh;
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    animation: lgn-sheet-up .5s var(--ease-emph) both;
  }
  .terms-of-use-dialog.ui-dialog .ui-dialog-content { max-height: calc(88vh - 60px); }
  @keyframes lgn-sheet-up {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
  }
  .terms-of-use-dialog.ui-dialog .ui-dialog-titlebar {
    border-radius: var(--r-xl) var(--r-xl) 0 0;
    padding-top: 28px;
  }
  .terms-of-use-dialog.ui-dialog .ui-dialog-titlebar::before {
    content: ''; position: absolute; top: 10px; left: 50%;
    transform: translateX(-50%);
    width: 40px; height: 4px; border-radius: var(--r-pill);
    background: var(--outline);
  }
  .terms-of-use-dialog.ui-dialog .ui-dialog-content {
    max-height: calc(88vh - 64px); overflow: auto;
  }
}

/* ============================================================
   INVALID FIELD STATE (login / register / forgot / 2FA panes).
   Duplicated from core css/core-components.css on purpose: login.xhtml
   is a standalone view that loads ONLY brand.css + login-md3.css +
   password-policy.css — core-components.css is never on this page, so
   the shared invalid-state layer cannot reach it. Same tokens, same
   contract; keep the two blocks in sync.

   Beats:
     - `.lgn-card .lgn-field input`  (0,3,1, no !important)  -> !important
     - `.lgn-card .lgn-field input:focus` (0,3,1, no !important) -> !important
     - theme.css shared/_pf-bridge.scss
       `input.ui-inputfield:focus{border-color:var(--primary)!important;
        box-shadow:...!important}` — highest matching specificity (0,2,1)
       WITH !important, so the focus rules below reach (0,4,1) or more
       and win on SPECIFICITY (important-vs-important compares it).
   Only border-COLOUR is forced; the width stays --error-border-w, which
   is what the resting field already uses, so nothing re-measures.
   ============================================================ */
.lgn-card .lgn-field input.ui-state-error,
.lgn-card .lgn-field .ui-inputfield.ui-state-error,
.lgn-card .lgn-field .ui-inputtext.ui-state-error,
.lgn-card .lgn-field .ui-password.ui-state-error,
.lgn-card .lgn-field .ui-password-input.ui-state-error,
.lgn-card .lgn-field .ui-inputmask.ui-state-error{
  border-color: var(--error-border) !important;
  border-width: var(--error-border-w);
}
/* focus while invalid: red border stays, ring goes error-tinted */
.lgn-card .lgn-field input.ui-state-error:focus,
.lgn-card .lgn-field .ui-inputfield.ui-state-error:focus,
.lgn-card .lgn-field .ui-password-input.ui-state-error:focus,
.lgn-card .lgn-field .ui-inputmask.ui-state-error:focus,
.lgn-card .lgn-field .ui-inputfield.ui-state-error.ui-state-focus{
  border-color: var(--error-border) !important;
  box-shadow: 0 0 0 var(--focus-ring-w) var(--error-ring) !important;
}
/* the span.ui-password wrapper is border-less here (see the rule above),
   so this only colours a box that is actually drawn */
.lgn-card .lgn-field .ui-password:has(> .ui-state-error),
.lgn-card .lgn-field .ui-inputnumber:has(> .ui-state-error),
.lgn-card .lgn-field .ui-calendar:has(> .ui-state-error){
  border-color: var(--error-border) !important;
}
/* label red — every login field uses p:outputLabel, which carries PF's
   own ui-state-error hook. Kept in its OWN rule: one unsupported
   selector invalidates a whole comma list, so it must not be grouped
   with the :has() fallback below. */
.lgn-field .ui-outputlabel.ui-state-error{
  color: var(--error-text) !important;
}
/* fallback for a hand-written <label>, which PRECEDES the input — a
   sibling combinator cannot reach backwards, :has() on .lgn-field can */
.lgn-field:has(.ui-state-error) > label,
.lgn-field:has(> .ui-message-error) > label{
  color: var(--error-text) !important;
}

/* ============================================================
   NATIVE biometric sign-in (bridge.js renders the DOM — class-
   tagged markup only, no injected CSS; native wrappers only).
   Styled here so it follows the active theme tokens. The rules
   are inert in normal browsers: the elements are never created.
   ============================================================ */

/* fingerprint trigger under the password form */
.qnb-bio-trigger { margin: 18px 0 2px; display: flex; flex-direction: column; align-items: center; gap: 8px; }
.qnb-bio-fab {
  width: 64px; height: 64px; border-radius: var(--r-avatar);
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--outline-variant); background: var(--surface-1);
  color: var(--p-40); cursor: pointer;
  transition: box-shadow .2s, background .15s;
}
.qnb-bio-fab:hover { box-shadow: var(--el-1); }
.qnb-bio-hint { font: var(--body-s); text-align: center; color: var(--on-surface-muted); }

/* "Who is signing in?" profile picker — swapped in for the form via
   .qnb-bio-mode on the login pane (a pure class toggle, so PF ajax
   re-renders of the form panel cannot resurrect it while hidden) */
.qnb-bio { display: none; }
.qnb-bio-mode .qnb-bio { display: flex; flex-direction: column; gap: 16px; margin-top: 4px; }
.qnb-bio-mode [id$=":login-panel"] { display: none; }
.qnb-bio-mode .qnb-bio-trigger { display: none; }
.qnb-bio-mode .lgn-h2 { display: none; }

.qnb-bio-title { margin: 0; font: var(--headline-m); color: var(--on-surface); }

/* profile cards — 4 visible, the rest behind a real scroll */
.qnb-bio-scrollwrap { position: relative; }
.qnb-bio-scroll {
  display: flex; flex-direction: column; gap: 12px;
  /* inner padding so the .recent ring (1px OUTSIDE the border box) is not
     clipped by overflow and cards keep a small gap to the container edge */
  padding: 4px;
  /* 4 cards (44px avatar + 2x14 padding + 2x1 border = 74px) + 3 gaps + 2x4 padding */
  max-height: 340px; overflow-y: auto;
  scrollbar-width: none;
}
.qnb-bio-scroll::-webkit-scrollbar { display: none; }

/* flat cards: hairline border, NO elevation — device-verified; a drop shadow
   under the rounded corners read as dirt on the warm bg (owner feedback) */
.qnb-bio-acc {
  flex: 0 0 auto; /* a flex-column child must not shrink into the scroll box */
  display: flex; align-items: center; gap: 14px;
  width: 100%; padding: 14px 16px; box-sizing: border-box; text-align: left;
  background: var(--surface); border: 1px solid var(--outline-variant);
  border-radius: var(--r-lg); box-shadow: none;
  font-family: var(--font); color: var(--on-surface); cursor: pointer;
  transition: box-shadow .2s, border-color .2s, background .15s;
}
.qnb-bio-acc:hover { box-shadow: var(--el-1); }
/* the most recently used profile: crisp 2px primary ring (border + snug
   0-blur ring), deliberately without any drop shadow */
.qnb-bio-acc.recent { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary); }
.qnb-bio-acc.recent:hover { box-shadow: 0 0 0 1px var(--primary); }

/* colour-coded initials avatar (deterministic per username, see bridge.js) */
.qnb-av {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: 14px;
  display: flex; align-items: center; justify-content: center;
  font: 700 15px/1 var(--font); letter-spacing: .02em;
}
.qnb-av-0 { background: #F3E8C8; color: #6B5410; }
.qnb-av-1 { background: #E4DEF3; color: #4F4370; }
.qnb-av-2 { background: #D9EDE4; color: #2E6B54; }
.qnb-av-3 { background: #F4DCE2; color: #8A4457; }
.qnb-av-4 { background: #DAE7F2; color: #33587A; }
.qnb-av-5 { background: #F6E3D4; color: #8A5A32; }
[data-theme="dark"] .qnb-av-0 { background: #3A2F0E; color: #F5C860; }
[data-theme="dark"] .qnb-av-1 { background: #322B4A; color: #C9BEEF; }
[data-theme="dark"] .qnb-av-2 { background: #1E3A30; color: #9AD8BF; }
[data-theme="dark"] .qnb-av-3 { background: #422730; color: #EBB5C4; }
[data-theme="dark"] .qnb-av-4 { background: #22364A; color: #A7CBE8; }
[data-theme="dark"] .qnb-av-5 { background: #46311F; color: #EDC49E; }

.qnb-acc-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.qnb-acc-name {
  font: 700 16px/1.2 var(--font); color: var(--on-surface);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.qnb-role {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: var(--r-pill);
  font: 700 10px/1.2 var(--font); letter-spacing: .08em; text-transform: uppercase;
  background: var(--surface-1); border: 1px solid var(--outline-variant);
  color: var(--on-surface-muted);
}
.qnb-role.admin { background: var(--p-90); border-color: transparent; color: var(--p-40); }
.qnb-role svg { flex: 0 0 auto; }

.qnb-acc-go {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: var(--r-avatar);
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-1); border: 1px solid var(--outline-variant);
  color: var(--on-surface-muted);
}
.qnb-bio-acc.recent .qnb-acc-go { background: var(--primary); border-color: transparent; color: var(--on-primary); }

/* bottom fade + "N more profiles" pill — shown only while cards sit
   below the fold (.qnb-scrollable is toggled from scroll geometry) */
.qnb-bio-fade {
  position: absolute; left: 0; right: 0; bottom: 0; height: 64px;
  background: linear-gradient(to bottom, transparent, var(--surface));
  pointer-events: none; opacity: 0; transition: opacity .2s;
}
.qnb-bio-more {
  position: absolute; left: 50%; bottom: 8px; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border: 0; border-radius: var(--r-pill);
  background: var(--on-surface); color: var(--surface); /* inverse chip in both themes */
  font: 700 12px/1 var(--font); white-space: nowrap; cursor: pointer;
  opacity: 0; pointer-events: none; transition: opacity .2s;
}
.qnb-scrollable .qnb-bio-fade { opacity: 1; }
.qnb-scrollable .qnb-bio-more { opacity: 1; pointer-events: auto; }

/* ILI divider + password sign-in */
.qnb-bio-divider {
  display: flex; align-items: center; gap: 12px; margin: 4px 0;
  font: 700 11px/1 var(--font); letter-spacing: .14em;
  color: var(--on-surface-subtle);
}
.qnb-bio-divider::before,
.qnb-bio-divider::after { content: ''; flex: 1; height: 1px; background: var(--outline-variant); }

.qnb-bio-back {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 14px 16px; box-sizing: border-box;
  background: var(--surface); border: 1px solid var(--outline-variant);
  border-radius: var(--r-btn); box-shadow: none; /* flat, like the cards above */
  font: 700 15px/1.2 var(--font); color: var(--on-surface); cursor: pointer;
  transition: box-shadow .2s, background .15s;
}
.qnb-bio-back:hover { box-shadow: var(--el-1); }
.qnb-bio-back svg { flex: 0 0 auto; color: var(--p-40); }

.qnb-bio-empty { margin: 2px 0; font: var(--body-s); text-align: center; color: var(--on-surface-muted); }
.qnb-bio-msg { margin: 0; font: 600 13px/1.4 var(--font); text-align: center; color: var(--error-text); }
