/* ─────────────────────────────────────────────────────────────
   Chropyne — Account pages design
   Uses Forge Dashboard token vocabulary from forge-dashboard.css.
   ───────────────────────────────────────────────────────────── */

/* ── Auth shell (Login, ForgotPassword, ResetPassword, AccessDenied) ──
   The shell is centered by default. Login.razor opts into a richer
   split-screen variant via .forge-auth-shell.forge-auth-shell--split that
   grafts a hero pane on the left at >= 960 px viewports and falls back to
   the centred card below that (prevents <main>'s flex centring from
   pushing the hero off-screen on small screens). */

.forge-auth-shell {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  height: 100vh;
  padding: var(--s-6);
  padding-top: clamp(72px, 10vh, 112px); /* room for the absolute auth header bar */
  position: relative;
  overflow: hidden;
  /* Same hero gradient as the split variant — every auth page (Login,
     ForgotPassword, ResetPassword, AccessDenied) uses the same immersive
     surface so the user never sees a flat-grey "form page". */
  background:
    radial-gradient(1400px 900px at 22% 18%, oklch(var(--accent-l) calc(var(--accent-c) + 0.04) var(--accent-h) / 0.55), transparent 60%),
    radial-gradient(1100px 800px at 82% 88%, oklch(0.55 0.18 calc(var(--accent-h) + 200) / 0.55), transparent 55%),
    linear-gradient(135deg,
      oklch(var(--accent-l) var(--accent-c) var(--accent-h)) 0%,
      oklch(0.40 0.16 calc(var(--accent-h) + 30)) 50%,
      oklch(0.22 0.08 calc(var(--accent-h) + 60)) 100%);
}

/* Subtle white dot grid that reads on the gradient (light-on-dark). */
.forge-auth-shell::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image: radial-gradient(circle at 1px 1px, rgba(255, 255, 255, 0.14) 1px, transparent 0);
  background-size: 28px 28px;
  mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black 0%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black 0%, transparent 100%);
}

/* Card container — frosted-glass card so the gradient shows through.
   Uses oklch from the theme tokens so it adapts to light/dark + accent. */
.forge-auth-container {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 440px;
  background: oklch(from var(--bg-1) l c h / 0.92);
  border: 1px solid oklch(from var(--line-strong) l c h / 0.6);
  border-radius: 16px;
  box-shadow:
    0 30px 80px -20px rgba(0, 0, 0, 0.45),
    0 12px 24px -8px rgba(0, 0, 0, 0.25),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(24px) saturate(140%);
  -webkit-backdrop-filter: blur(24px) saturate(140%);
  padding: var(--s-8);
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
  animation: auth-card-in 300ms var(--ease-out) backwards;
}

@keyframes auth-card-in {
  from { opacity: 0; transform: translateY(10px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* Card header (title + subtitle) */
.forge-auth-header {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.forge-auth-title {
  margin: 0;
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--fg-1);
  font-family: var(--font-sans);
  line-height: 1.2;
}

.forge-auth-subtitle {
  margin: 0;
  font-size: 14px;
  color: var(--fg-3);
  font-family: var(--font-sans);
  line-height: 1.5;
}

/* Logotype mark above the card */
.forge-auth-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  margin-bottom: calc(-1 * var(--s-2));
}

.forge-auth-mark {
  width: 36px;
  height: 36px;
  border-radius: var(--r-sm);
  background: conic-gradient(
    from 210deg at 50% 50%,
    oklch(var(--accent-l) var(--accent-c) var(--accent-h)),
    oklch(0.7 0.12 235),
    oklch(var(--accent-l) var(--accent-c) var(--accent-h))
  );
  display: grid;
  place-items: center;
  color: white;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.02em;
  box-shadow: 0 0 18px var(--accent-glow), inset 0 0 0 1px oklch(1 0 0 / 0.15);
  flex-shrink: 0;
}

/* Form */
.forge-auth-form {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

/* Form field */
.forge-field {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.forge-field__label {
  font-size: 13px;
  font-weight: 500;
  color: var(--fg-2);
  font-family: var(--font-sans);
}

/* Input — applied to InputText rendered <input> elements */
.forge-input {
  width: 100%;
  padding: 9px var(--s-3);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  color: var(--fg-1);
  font-size: 14px;
  font-family: var(--font-sans);
  outline: none;
  transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}

.forge-input::placeholder {
  color: var(--fg-4);
}

.forge-input:hover {
  border-color: var(--line-strong);
}

.forge-input:focus {
  border-color: var(--line-accent);
  background: var(--bg-3);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Blazor validation state — tap into the classes Blazor adds */
.forge-input.valid:not([type=checkbox]) {
  border-color: var(--ok);
}

.forge-input.invalid {
  border-color: var(--bad);
  box-shadow: 0 0 0 3px oklch(from var(--bad) l c h / 0.15);
}

.forge-field__error {
  font-size: 12px;
  color: var(--bad);
  font-family: var(--font-sans);
}

/* Primary CTA button */
.forge-button--auth-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  width: 100%;
  padding: 10px var(--s-4);
  background: var(--accent);
  color: white;
  font-size: 14px;
  font-weight: 600;
  font-family: var(--font-sans);
  border: none;
  border-radius: var(--r-md);
  cursor: pointer;
  box-shadow: 0 4px 14px var(--accent-glow);
  transition:
    filter var(--t-fast) var(--ease-out),
    box-shadow var(--t-fast) var(--ease-out),
    transform var(--t-fast) var(--ease-out);
}

.forge-button--auth-primary:hover:not(:disabled) {
  filter: brightness(1.1);
  box-shadow: var(--shadow-glow);
}

.forge-button--auth-primary:active:not(:disabled) {
  transform: scale(0.98);
}

.forge-button--auth-primary:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Spinner used inside auth-primary while a sign-in / reset request is in
   flight. Pure CSS, no JS, no SVG — keeps the static-SSR login page free
   of additional asset weight. The reduced-motion guard further down
   suppresses the spin so motion-sensitive users see a static dot. */
.forge-button__spinner {
  display: inline-block;
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, 0.45);
  border-top-color: white;
  border-radius: 50%;
  animation: forge-spin 0.8s linear infinite;
  vertical-align: -2px;
  margin-right: 6px;
}

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

@media (prefers-reduced-motion: reduce) {
  .forge-button__spinner { animation: none; }
}

/* Secondary / ghost button (back links, revoke, sign out) */
.forge-button--auth-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  width: 100%;
  padding: 9px var(--s-4);
  background: var(--bg-2);
  color: var(--fg-2);
  font-size: 14px;
  font-weight: 500;
  font-family: var(--font-sans);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  cursor: pointer;
  text-decoration: none;
  transition:
    background var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out);
}

.forge-button--auth-secondary:hover:not(:disabled) {
  background: var(--bg-3);
  border-color: var(--line-strong);
  color: var(--fg-1);
}

.forge-button--auth-secondary:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Danger button (sign out all) */
.forge-button--auth-danger {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: 8px var(--s-4);
  background: oklch(from var(--bad) l c h / 0.12);
  color: var(--bad);
  font-size: 13px;
  font-weight: 500;
  font-family: var(--font-sans);
  border: 1px solid oklch(from var(--bad) l c h / 0.25);
  border-radius: var(--r-md);
  cursor: pointer;
  transition:
    background var(--t-fast),
    border-color var(--t-fast);
}

.forge-button--auth-danger:hover:not(:disabled) {
  background: oklch(from var(--bad) l c h / 0.2);
  border-color: oklch(from var(--bad) l c h / 0.4);
}

.forge-button--auth-danger:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Inline text-link button (revoke per-session) */
.forge-button--auth-link {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  padding: 4px var(--s-2);
  background: none;
  color: var(--accent);
  font-size: 12px;
  font-weight: 500;
  font-family: var(--font-sans);
  border: none;
  border-radius: var(--r-xs);
  cursor: pointer;
  transition: color var(--t-fast), background var(--t-fast);
}

.forge-button--auth-link:hover:not(:disabled) {
  background: var(--accent-soft);
}

.forge-button--auth-link:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Alert / status message */
.forge-alert {
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r-sm);
  font-size: 13px;
  font-family: var(--font-sans);
  line-height: 1.5;
}

.forge-alert--success {
  background: oklch(from var(--ok) l c h / 0.1);
  border: 1px solid oklch(from var(--ok) l c h / 0.25);
  color: var(--ok);
}

.forge-alert--error {
  background: oklch(from var(--bad) l c h / 0.1);
  border: 1px solid oklch(from var(--bad) l c h / 0.25);
  color: var(--bad);
}

/* Manage-page variant — used on /account/manage/* pages where the alert
   sits between the page header and a form. Adds vertical rhythm so the
   banner doesn't visually butt against the first form label. */
.forge-alert--manage {
  display: flex;
  align-items: center;
  gap: var(--s-2, 8px);
  margin: var(--s-4, 16px) 0 var(--s-5, 20px);
  padding: var(--s-3, 12px) var(--s-4, 16px);
  font-size: 14px;
}
.forge-alert--manage svg { flex-shrink: 0; }

/* Auth footer links */
.forge-auth-links {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--s-4);
}

.forge-auth-links li a {
  font-size: 13px;
  color: var(--fg-3);
  text-decoration: none;
  transition: color var(--t-fast);
}

.forge-auth-links li a:hover {
  color: var(--accent);
}

/* Social login divider label */
.forge-auth-divider {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: 12px;
  color: var(--fg-4);
  font-family: var(--font-sans);
}

.forge-auth-divider::before,
.forge-auth-divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* Access denied icon block */
.forge-auth-icon-block {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: var(--r-lg);
  background: oklch(from var(--bad) l c h / 0.1);
  border: 1px solid oklch(from var(--bad) l c h / 0.2);
  font-size: 26px;
  align-self: flex-start;
}

/* Confirmation block (forgot-password sent state) */
.forge-auth-confirm-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: var(--r-lg);
  background: oklch(from var(--ok) l c h / 0.1);
  border: 1px solid oklch(from var(--ok) l c h / 0.2);
  font-size: 26px;
  align-self: flex-start;
}

/* The .forge-button--auth-* classes are designed for the LOGIN card where
   width: 100% fills the form box. On the Manage pages they're embedded in a
   regular content area and the full-width treatment looks like a touch target
   the size of the page. Constrain them to natural width when used outside
   the auth shell. */
.forge-manage-actions .forge-button--auth-primary,
.forge-manage-actions .forge-button--auth-secondary,
.forge-manage-actions .forge-button--auth-danger,
.forge-manage-actions .forge-auth-logout-form,
.forge-manage-actions form {
  width: auto;
  align-self: flex-start;
}

.forge-manage-actions .forge-button--auth-primary,
.forge-manage-actions .forge-button--auth-secondary,
.forge-manage-actions .forge-button--auth-danger {
  display: inline-flex;
  width: auto;
  min-width: 0;
  padding-left: var(--s-4);
  padding-right: var(--s-4);
}

/* The logout form on /account/manage is wrapped in a <form> with class
   forge-auth-logout-form. Ensure both the form AND the button shrink to
   content width on the manage pages. */
.forge-manage-actions .forge-auth-logout-form {
  display: inline-flex;
}
.forge-manage-actions .forge-auth-logout-form .forge-button--auth-secondary {
  width: auto;
}

/* ── Manage section layout ── */

/* Full-page layout: left sidebar + right content */
.forge-manage-layout {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: var(--s-6);
  padding: var(--s-6);
  min-height: 100%;
  align-items: start;
}

@media (max-width: 700px) {
  .forge-manage-layout {
    grid-template-columns: 1fr;
  }
}

.forge-manage-sidebar {
  background: var(--surface-elevated);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-2);
  position: sticky;
  top: var(--s-4);
}

.forge-manage-content {
  background: var(--surface-elevated);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-6);
  display: flex;
  flex-direction: column;
  gap: var(--s-6);
}

/* Manage nav */
.forge-manage-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.forge-manage-nav a {
  display: flex;
  align-items: center;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  font-size: 13px;
  font-weight: 500;
  color: var(--fg-2);
  text-decoration: none;
  border: 1px solid transparent;
  transition:
    background var(--t-fast),
    border-color var(--t-fast),
    color var(--t-fast);
}

.forge-manage-nav a:hover {
  background: var(--bg-3);
  border-color: var(--line);
  color: var(--fg-1);
}

.forge-manage-nav a.active {
  background: var(--accent-soft);
  border-color: var(--line-accent);
  color: var(--fg-1);
}

/* Manage page section heading */
.forge-manage-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--fg-1);
  font-family: var(--font-sans);
}

/* Profile definition list */
.forge-profile-list {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: var(--s-1) var(--s-4);
  margin: 0;
  font-family: var(--font-sans);
}

.forge-profile-list dt {
  font-size: 13px;
  font-weight: 500;
  color: var(--fg-3);
  padding: var(--s-2) 0;
  display: flex;
  align-items: center;
}

.forge-profile-list dd {
  font-size: 14px;
  color: var(--fg-1);
  margin: 0;
  padding: var(--s-2) 0;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
  border-bottom: 1px solid var(--line);
}

.forge-profile-list dt {
  border-bottom: 1px solid var(--line);
}

.forge-profile-list dd:last-child,
.forge-profile-list dt:nth-last-child(2) {
  border-bottom: 0;
}

/* Badges (role pill, unconfirmed, success/warning) */
.forge-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 500;
  font-family: var(--font-mono);
  letter-spacing: 0.02em;
  background: var(--bg-3);
  color: var(--fg-2);
  border: 1px solid var(--line);
}

.forge-badge--success {
  background: oklch(from var(--ok) l c h / 0.12);
  border-color: oklch(from var(--ok) l c h / 0.25);
  color: var(--ok);
}

.forge-badge--warning {
  background: oklch(from var(--warn) l c h / 0.12);
  border-color: oklch(from var(--warn) l c h / 0.25);
  color: var(--warn);
}

/* Page action row — scoped to account pages only.
   Originally this rule used a bare `.forge-page__actions` selector; because
   account-pages.css is loaded globally (App.razor), the border-top + padding
   bled into EVERY page that used .forge-page__actions, including the dashboard
   `Cards / Table + New todo` toolbar (visible thin line above the tab pill).
   Scoped to .auth-shell so account forms keep their separator and dashboard
   pages render flush with the page header (no extra rule). */
.auth-shell .forge-page__actions {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding-top: var(--s-2);
}

/* Inline form field group (for manage forms) */
.forge-form-field {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.forge-form-field label {
  font-size: 13px;
  font-weight: 500;
  color: var(--fg-2);
  font-family: var(--font-sans);
}

/* Manage forms use the same input style */
.forge-form-field input,
.forge-form-field .forge-input {
  width: 100%;
  padding: 9px var(--s-3);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  color: var(--fg-1);
  font-size: 14px;
  font-family: var(--font-sans);
  outline: none;
  transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}

.forge-form-field input:hover {
  border-color: var(--line-strong);
}

.forge-form-field input:focus {
  border-color: var(--line-accent);
  background: var(--bg-3);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.forge-form-field input.valid:not([type=checkbox]) {
  border-color: var(--ok);
}

.forge-form-field input.invalid {
  border-color: var(--bad);
}

.forge-form-field .validation-message {
  font-size: 12px;
  color: var(--bad);
}

/* Manage form submit wrapper */
.forge-manage-form {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

.forge-manage-form-actions {
  padding-top: var(--s-2);
}

/* Sessions list */
.forge-sessions__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.forge-sessions__item {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-4);
  padding: var(--s-4);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color var(--t-fast);
}

.forge-sessions__item:hover {
  border-color: var(--line-strong);
}

.forge-sessions__info {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  min-width: 0;
}

.forge-sessions__device {
  font-size: 14px;
  font-weight: 500;
  color: var(--fg-1);
  font-family: var(--font-sans);
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
}

.forge-sessions__meta {
  font-size: 12px;
  color: var(--fg-3);
  font-family: var(--font-mono);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-4);
}

.forge-sessions__actions {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding-top: var(--s-2);
  border-top: 1px solid var(--line);
}

/* Two-factor / enable-authenticator placeholder area */
.forge-placeholder {
  padding: var(--s-6);
  background: var(--bg-2);
  border: 1px dashed var(--line-strong);
  border-radius: var(--r-md);
  color: var(--fg-3);
  font-size: 14px;
  font-family: var(--font-sans);
  text-align: center;
}

/* Instructional list inside enable-authenticator */
.forge-auth-steps {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding-left: var(--s-5);
  margin: 0;
  color: var(--fg-2);
  font-size: 14px;
  font-family: var(--font-sans);
}

.forge-auth-steps li {
  line-height: 1.6;
}

/* Info block (passkeys, two-factor explanation) */
.forge-info-block {
  font-size: 14px;
  color: var(--fg-2);
  font-family: var(--font-sans);
  line-height: 1.6;
  margin: 0;
}

/* Social login grid */
.forge-social-grid {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  flex-wrap: wrap;
}

/* AuthLayout — full-bleed immersive container for the auth flow pages
   (Login, ForgotPassword, ResetPassword, AccessDenied). The whole layout
   pins to 100vh, the top header bar is positioned ABOVE the body without
   adding height (z-index above shell decorations) and renders with a
   transparent background so the hero gradient extends edge-to-edge.
   Result: no scroll, no visual seam between top bar and body. The shell
   provides its own gradient via the split-screen variant.

   Why no `min-height: 100vh` + flex layout (the original): the form pane
   was scrollable on short viewports because the body was forced to fit
   below the topbar, then the auth-shell inside it added 100vh on top.
   Switching to a fixed-height shell lets `.forge-auth-shell--split` fill
   the viewport with no overflow. */
.forge-auth-layout {
    position: relative;
    min-height: 100vh;
    height: 100vh;
    overflow: hidden;
    background: var(--bg-1, #fff);
    color: var(--fg-1, var(--text-t1, #111));
}

/* Phase Q.1 (2026-05-27) — accent-tinted ambient gradient mounted on the
   LAYOUT (which persists across SPA navigation between auth pages: Login ↔
   Register ↔ ForgotPassword ↔ ResetPassword ↔ Kiosk), not on the per-page
   .forge-auth-shell--split. Without this, the gradient mounted/unmounted
   on every page swap and the user saw a brief "background flash" — the
   flat --bg-1 colour showed through during the tail end of the old shell's
   unmount + the head of the new shell's mount.

   Keeping the per-page shell gradient AS WELL is intentional defence in
   depth — pages that use auth-shell--split outside AuthLayout (rare, but
   nothing prevents it) keep their visual identity. The two gradients are
   the same colour, so stacking is invisible to the eye. */
.forge-auth-layout::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    background:
        radial-gradient(900px 600px at 80% 20%, oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.18), transparent 60%),
        radial-gradient(700px 500px at 18% 90%, oklch(0.7 0.12 235 / 0.10), transparent 55%);
}

/* Dot grid mounted on the layout for the same reason as the gradient
   above — keeps the texture consistent across page navigation. */
.forge-auth-layout::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    background-image: radial-gradient(circle at 1px 1px, var(--grid-line) 1px, transparent 0);
    background-size: 32px 32px;
    mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black 0%, transparent 100%);
    -webkit-mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black 0%, transparent 100%);
    opacity: 0.55;
}

/* The layout's header bar + body need to render ABOVE the gradient/grid
   pseudo-elements. Without this, the ::before / ::after overlap the
   form card content because they have the same z-index as the body. */
.forge-auth-layout > * {
    position: relative;
    z-index: 1;
}
.forge-auth-header-bar {
    position: absolute;
    inset: 0 0 auto 0;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-4, 16px);
    padding: 12px 24px;
    border-bottom: 0;
    background: transparent;
    pointer-events: none; /* let cursor reach body decorations behind controls — children re-enable */
}
.forge-auth-header-bar > * { pointer-events: auto; }
/* Brand block — theme-aware via the token vocabulary. Brand mark uses
   the accent gradient so it tracks the user's accent picker choice. */
.forge-auth-header-bar__brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    font-weight: 600;
    color: var(--fg-1);
}
.forge-auth-header-bar__brand .brand-mark {
    width: 32px;
    height: 32px;
    border-radius: 9px;
    background: linear-gradient(140deg,
        oklch(var(--accent-l) var(--accent-c) var(--accent-h)),
        oklch(calc(var(--accent-l) - 0.18) var(--accent-c) calc(var(--accent-h) + 30)));
    border: 1px solid oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.4);
    color: white;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    font-size: 14px;
    letter-spacing: -0.04em;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.4),
        0 4px 12px oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.32);
}
.forge-auth-header-bar__controls {
    display: inline-flex;
    align-items: center;
    gap: var(--s-3, 12px);
    flex-wrap: wrap;
}
.forge-auth-header-bar__group {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px;
    background: var(--bg-2);
    border-radius: var(--radius-md, 8px);
    border: 1px solid var(--line);
}
.forge-auth-header-bar__chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    height: 28px;
    padding: 0 10px;
    font-size: 12px;
    font-weight: 500;
    color: var(--fg-2);
    background: transparent;
    border: 0;
    border-radius: var(--radius-sm, 6px);
    text-decoration: none;
    cursor: pointer;
    transition: color var(--t-fast, 140ms) var(--ease-out, ease-out),
                background var(--t-fast, 140ms) var(--ease-out, ease-out);
}
.forge-auth-header-bar__chip:hover {
    color: var(--fg-1);
    background: var(--bg-3);
}
.forge-auth-header-bar__chip:focus-visible {
    outline: 2px solid oklch(var(--accent-l) var(--accent-c) var(--accent-h));
    outline-offset: 2px;
}
.forge-auth-header-bar__chip.is-active,
[data-theme="light"] .forge-auth-header-bar__chip[data-theme-target="light"],
[data-theme="dark"] .forge-auth-header-bar__chip[data-theme-target="dark"] {
    color: var(--fg-1);
    background: var(--surface-elevated, var(--bg-1));
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.10), inset 0 0 0 1px var(--line);
}

/* Standalone tweaks chip — opens a JS-driven popover. Sized like a
   single-button group so it visually balances with the language and
   theme groups without needing a wrapper. */
.forge-auth-header-bar__chip--tweaks {
    width: 36px;
    height: 32px;
    padding: 0;
    background: var(--bg-2);
    border: 1px solid var(--line);
    border-radius: var(--radius-md, 8px);
    color: var(--fg-2);
}
.forge-auth-header-bar__chip--tweaks:hover {
    color: var(--fg-1);
    background: var(--bg-3);
}
.forge-auth-header-bar__chip--tweaks svg {
    width: 14px;
    height: 14px;
}
.forge-auth-layout__body {
    position: relative;
    z-index: 1;
    height: 100vh;
    width: 100%;
    display: flex;
    align-items: stretch;
    justify-content: stretch;
}
/* Logout form in MainLayout — strip default browser margin so the form
   doesn't add an unwanted block of padding under the sign-out button. */
.forge-auth-logout-form {
    margin: 0;
    width: 100%;
}

/* ── Auth tweaks popover ────────────────────────────────────────────
   Lightweight, JS-driven preferences panel that opens from the auth
   layout's customize chip. Lives in the layout DOM (always rendered),
   shown / hidden via the `data-open` attribute the inline-onclick
   handler flips. Each accent swatch is a plain `<a>` link to
   /Tweaks/Accent — the redirect writes a cookie and reloads, the new
   request reads the cookie and uses the matching `--accent-h/c/l`
   token bundle when generating the gradient. */
.forge-auth-tweaks {
    position: absolute;
    top: 56px;
    right: 24px;
    z-index: 6;
    min-width: 220px;
    padding: 14px;
    background: var(--surface-elevated, var(--bg-2));
    border: 1px solid var(--line);
    border-radius: 14px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.18);
    color: var(--fg-1);
    opacity: 0;
    transform: translateY(-6px);
    pointer-events: none;
    transition: opacity 160ms ease-out, transform 160ms ease-out;
}
.forge-auth-tweaks[data-open="true"] {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}
.forge-auth-tweaks__title {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--fg-3);
    margin-bottom: 10px;
}
.forge-auth-tweaks__row {
    display: flex;
    gap: 8px;
}
.forge-auth-tweaks__swatch {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1px solid var(--line-strong, var(--line));
    cursor: pointer;
    transition: transform 140ms ease-out, box-shadow 140ms ease-out;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
}
.forge-auth-tweaks__swatch:hover {
    transform: scale(1.08);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.20);
}
.forge-auth-tweaks__swatch[data-accent="blue"]   { background: oklch(0.62 0.18 235); }
.forge-auth-tweaks__swatch[data-accent="teal"]   { background: oklch(0.65 0.14 195); }
.forge-auth-tweaks__swatch[data-accent="violet"] { background: oklch(0.55 0.20 295); }
.forge-auth-tweaks__swatch[data-accent="amber"]  { background: oklch(0.75 0.15  75); }
.forge-auth-tweaks__swatch[data-accent="rose"]   { background: oklch(0.65 0.18  10); }

/* ── Login split-screen variant ─────────────────────────────────────
   Adobe-grade hero / form split. The hero pane is decorative — uses the
   accent gradient + dot grid + a couple of layered glass cards for depth.
   The form pane keeps the existing .forge-auth-container card so every
   other auth page (forgot-password, reset-password) renders identically.

   Behaviour:
     • >= 960 px → side-by-side (hero left, form right).
     • <  960 px → form-only; hero collapses (display: none) so the
                   centred card fills the viewport.
   The CSS keeps the hero in the DOM for screen readers; aria-hidden on
   the visual decorations means assistive tech only reads the welcome
   copy. */

/* Immersive split — the shell IS the layout body. Form pane on the LEFT,
   hero pane on the RIGHT; both centred horizontally on the screen so the
   visual weight reads balanced from edge to edge. Below 960 px the hero
   collapses and the form pane fills the viewport. The background uses
   the more subtle "ambient glow on dot-grid" treatment from the original
   single-card auth shell — the earlier saturated gradient was too loud
   for an utility surface. */
.forge-auth-shell.forge-auth-shell--split {
  display: grid;
  grid-template-columns: 1fr;
  align-items: stretch;
  justify-content: stretch;
  padding: 0;
  width: 100%;
  height: 100vh;
  min-height: 0;
  position: relative;
  overflow: hidden;
  background: var(--bg-1);
}

/* Layered ambient surface — accent radial glow + secondary cool glow
   (offset to the bottom-right) on top of a dot-grid that fades into the
   centre. The accent glow shifts hue with `[data-accent="…"]` because
   --accent-l/c/h come straight from forge-tokens.css, so the surface
   tracks the user's accent choice. */
.forge-auth-shell.forge-auth-shell--split::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(900px 600px at 80% 20%, oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.18), transparent 60%),
    radial-gradient(700px 500px at 18% 90%, oklch(0.7 0.12 235 / 0.10), transparent 55%);
}

.forge-auth-shell.forge-auth-shell--split::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image: radial-gradient(circle at 1px 1px, var(--grid-line) 1px, transparent 0);
  background-size: 32px 32px;
  mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black 0%, transparent 100%);
  -webkit-mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black 0%, transparent 100%);
  opacity: 0.55;
}

/* Subtle dot grid spans the entire shell — covers BOTH panes so the
   transition from hero-half to form-half feels continuous. The mask
   fades the dots out where the form card sits so the dots don't
   show through the translucent glass. */
.forge-auth-shell.forge-auth-shell--split::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background-image: radial-gradient(circle at 1px 1px, rgba(255, 255, 255, 0.14) 1px, transparent 0);
  background-size: 28px 28px;
  mask-image: radial-gradient(ellipse 90% 70% at 30% 55%, black 0%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 90% 70% at 30% 55%, black 0%, transparent 75%);
}

/* Hero pane — text + value-prop bullets vertically centred so they sit
   level with the form card on the left. Hidden on narrow viewports
   (the form alone fills the screen). */
.forge-auth-hero {
  display: none;
  position: relative;
  z-index: 1;
  padding: clamp(var(--s-8), 6vw, var(--s-10));
  padding-top: clamp(96px, 12vh, 128px); /* clear the absolute auth top bar */
  color: var(--fg-1);
  isolation: isolate;
  background: transparent;
}

@media (min-width: 960px) {
  /* Two-column grid — both halves equal so the visual axis runs through
     the centre of the viewport; form sits left, hero sits right. */
  .forge-auth-shell.forge-auth-shell--split {
    grid-template-columns: 1fr 1fr;
  }
  .forge-auth-hero {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    min-height: 100vh;
    /* Pull the hero copy a bit toward the centre of the screen — the
       block stays inside the right-half pane but its left edge is closer
       to the page's vertical axis, balancing the form card on the left. */
    padding-left: clamp(var(--s-6), 4vw, var(--s-8));
  }
}

/* Soft bloom anchored in the hero pane — concentric radial gradients
   give a "morning sun" diffuse light without any extra DOM. Tracks the
   accent through the same CSS custom-property surface used by the
   theme. */
.forge-auth-hero::after {
  content: "";
  position: absolute;
  right: -6%;
  top: 50%;
  transform: translateY(-50%);
  width: 70%;
  height: 60%;
  pointer-events: none;
  background:
    radial-gradient(closest-side,
        oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.18),
        transparent 70%),
    radial-gradient(closest-side,
        oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.10) 25%,
        transparent 55%),
    radial-gradient(closest-side,
        oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.06) 45%,
        transparent 75%);
  filter: blur(0.5px);
  opacity: 0.9;
}

/* Floating orb — small bright sphere anchoring the bloom. Theme-aware
   via the accent OKLCH so it shifts hue with [data-accent]. */
.forge-auth-hero__lead::before {
  content: "";
  position: absolute;
  right: 6%;
  top: -64px;
  width: 88px;
  height: 88px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 30%,
        oklch(var(--accent-l) var(--accent-c) var(--accent-h)) 0%,
        oklch(calc(var(--accent-l) - 0.18) var(--accent-c) var(--accent-h) / 0.4) 60%,
        transparent 80%);
  box-shadow:
    0 0 60px oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.35),
    0 0 22px oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.5),
    inset -6px -10px 22px rgba(0, 0, 0, 0.18);
  pointer-events: none;
  animation: forge-auth-orb-float 6s ease-in-out infinite alternate;
}

@keyframes forge-auth-orb-float {
  0%   { transform: translate(0, 0) scale(1); }
  100% { transform: translate(-10px, -6px) scale(1.04); }
}

@media (prefers-reduced-motion: reduce) {
  .forge-auth-hero__lead::before { animation: none; }
}

/* Hero typography — theme-aware via OKLCH tokens. The light theme reads
   on a near-white shell (var(--bg-1)) with the soft accent glow; dark
   theme reads on a deep neutral. Both pull from --fg-1/--fg-2/--fg-3
   so the contrast stays WCAG-correct in either mode. The pre-2026-05-05
   version used `color: white` which dissolved on the light theme — fixed. */
.forge-auth-hero__lead {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  max-width: 560px;
  z-index: 2;
  padding-bottom: var(--s-6);
}

.forge-auth-hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  align-self: flex-start;
  padding: 5px 12px;
  border-radius: 999px;
  background: oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.12);
  border: 1px solid oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.30);
  color: oklch(var(--accent-l) var(--accent-c) var(--accent-h));
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.forge-auth-hero__title {
  margin: 0;
  font-size: clamp(36px, 4.4vw, 56px);
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: var(--fg-1);
  font-family: var(--font-display, var(--font-sans));
}

.forge-auth-hero__subtitle {
  margin: 0;
  font-size: 16px;
  line-height: 1.6;
  color: var(--fg-3);
  max-width: 48ch;
}

/* Footer trust bar — feature bullets reminder of value props. The icon
   chip uses the accent-soft token so it tints with the user's accent. */
.forge-auth-hero__footer {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}

.forge-auth-hero__bullets {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.forge-auth-hero__bullet {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--fg-2);
  font-size: 14px;
}

.forge-auth-hero__bullet svg {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  padding: 4px;
  border-radius: 999px;
  background: oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.14);
  color: oklch(var(--accent-l) var(--accent-c) var(--accent-h));
}

/* Form pane — sits on the LEFT under the split layout. Justified to the
   END so the card hugs the vertical centre of the screen (right edge
   of the form pane = page horizontal axis). The card uses a frosted
   glass treatment so the ambient gradient peeks through softly. */
.forge-auth-shell.forge-auth-shell--split .forge-auth-formpane {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: clamp(var(--s-8), 5vw, var(--s-10));
  padding-top: clamp(96px, 12vh, 128px); /* mirror hero topbar gap */
  background: transparent;
  position: relative;
  z-index: 1;
}

.forge-auth-shell.forge-auth-shell--split .forge-auth-container {
  width: 100%;
  max-width: 440px;
  background: oklch(from var(--bg-1) l c h / 0.86);
  border: 1px solid oklch(from var(--line) l c h / 0.7);
  border-radius: 18px;
  box-shadow:
    0 30px 80px -20px rgba(0, 0, 0, 0.35),
    0 12px 24px -8px rgba(0, 0, 0, 0.18),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
  backdrop-filter: blur(24px) saturate(140%);
  -webkit-backdrop-filter: blur(24px) saturate(140%);
}

/* Smooth swap between Login and ForgotPassword — both pages render the
   same shell and form-pane structure, so toggling between them feels
   like the form is the only thing that changes. The card animates in
   with the existing `auth-card-in` keyframes; we add a parallel slide
   on the hero text below. */
.forge-auth-shell.forge-auth-shell--split .forge-auth-container {
  animation: auth-card-swap 360ms var(--ease-out) backwards;
}

@keyframes auth-card-swap {
  from { opacity: 0; transform: translateY(8px) scale(0.985); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

@media (max-width: 959.98px) {
  /* Mobile / portrait — pinned 100vh, tight gaps so the form card,
     hero block and bullets all fit on a single phone screen without
     scroll. */
  .forge-auth-shell.forge-auth-shell--split {
    height: 100vh;
    height: 100dvh; /* dynamic viewport, accounts for mobile URL bar */
  }
  .forge-auth-shell.forge-auth-shell--split .forge-auth-formpane {
    min-height: 100vh;
    min-height: 100dvh;
    justify-content: center;
    flex-direction: column;
    align-items: center;
    gap: var(--s-3);
    padding: clamp(56px, 8vh, 88px) var(--s-4) var(--s-4);
  }
  /* Compact card on mobile so the form fits with the orb + bullets. */
  .forge-auth-shell.forge-auth-shell--split .forge-auth-container {
    padding: var(--s-5) var(--s-5);
    gap: var(--s-4);
  }
}

/* Mobile-only intro block above the form card. Renders only on
   < 960 px viewports. On desktop the hero pane covers the same role
   on the right side. */
.forge-auth-formpane__hero {
  display: none;
  text-align: center;
  max-width: 460px;
  position: relative;
}

@media (max-width: 959.98px) {
  .forge-auth-formpane__hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s-3, 12px);
    padding-bottom: var(--s-6, 24px);
    margin-bottom: var(--s-5, 20px);
  }
  .forge-auth-formpane__hero .forge-auth-mobile-orb {
    display: block;
    margin-bottom: var(--s-3, 12px);
  }
  .forge-auth-formpane__hero h1 {
    margin: 0;
    font-size: clamp(24px, 6.5vw, 32px);
    font-weight: 700;
    letter-spacing: -0.025em;
    color: var(--fg-1);
    line-height: 1.15;
  }
  .forge-auth-formpane__hero p {
    margin: 0;
    font-size: 14px;
    line-height: 1.5;
    color: var(--fg-3);
    max-width: 38ch;
  }
  /* Mobile bullets — render below the form card. Compact icon row,
     wrapped where needed so all three value-props are visible on
     smaller screens. */
  .forge-auth-formpane__bullets {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0;
    padding: 0;
    list-style: none;
    width: 100%;
    max-width: 360px;
  }
  .forge-auth-formpane__bullets li {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    line-height: 1.3;
    color: var(--fg-3);
  }
  .forge-auth-formpane__bullets li svg {
    flex-shrink: 0;
    width: 14px;
    height: 14px;
    padding: 3px;
    border-radius: 999px;
    background: oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.14);
    color: oklch(var(--accent-l) var(--accent-c) var(--accent-h));
  }
}
.forge-auth-formpane__bullets {
  display: none; /* desktop hides — hero pane on the right has its own bullets */
}

/* Mobile decoration above the form — a stack of two concentric accent
   rings + a small bright core dot. Reads as a stylised "core" anchored
   above the greeting, much more interesting than the previous lone
   ball. The rings rotate at different rates; the core pulses gently. */
.forge-auth-mobile-orb {
  display: none;
  position: relative;
  width: 84px;
  height: 84px;
}
.forge-auth-mobile-orb::before,
.forge-auth-mobile-orb::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
}
.forge-auth-mobile-orb::before {
  border: 1px dashed oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.5);
  animation: forge-auth-mobile-orb-spin 24s linear infinite;
}
.forge-auth-mobile-orb::after {
  inset: 22%;
  border: 1px solid oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.7);
  animation: forge-auth-mobile-orb-spin 16s linear infinite reverse;
}
.forge-auth-mobile-orb > span {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 30%,
        oklch(var(--accent-l) var(--accent-c) var(--accent-h)) 0%,
        oklch(calc(var(--accent-l) - 0.18) var(--accent-c) var(--accent-h) / 0.5) 60%,
        transparent 80%);
  box-shadow:
    0 0 24px oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.55),
    0 0 12px oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.7);
  animation: forge-auth-mobile-orb-pulse 4s ease-in-out infinite;
}

@keyframes forge-auth-mobile-orb-spin {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
@keyframes forge-auth-mobile-orb-pulse {
  0%, 100% { transform: translate(-50%, -50%) scale(1); }
  50%      { transform: translate(-50%, -50%) scale(1.18); }
}

@media (prefers-reduced-motion: reduce) {
  .forge-auth-mobile-orb::before,
  .forge-auth-mobile-orb::after,
  .forge-auth-mobile-orb > span { animation: none; }
}

/* Mobile auth shell — improved background. The desktop split shell
   already has gradients but they're keyed to the right pane. On
   mobile the form pane spans the full viewport, so we paint richer
   ambient layers directly on the formpane: an accent radial bloom
   anchored top-right + secondary cool bloom bottom-left + dot grid
   masked into a soft ellipse. The combination matches the desktop
   atmosphere without the split-pane scaffolding. */
@media (max-width: 959.98px) {
  .forge-auth-formpane {
    position: relative;
    isolation: isolate;
  }
  .forge-auth-formpane::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background:
      radial-gradient(70% 60% at 80% 0%,
          oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.18),
          transparent 60%),
      radial-gradient(60% 50% at 10% 100%,
          oklch(0.7 0.12 235 / 0.1),
          transparent 60%);
  }
  .forge-auth-formpane::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image: radial-gradient(circle at 1px 1px,
        color-mix(in oklab, var(--fg-1, currentColor) 6%, transparent) 1px,
        transparent 0);
    background-size: 28px 28px;
    -webkit-mask-image: radial-gradient(ellipse 90% 70% at 50% 30%, black 0%, transparent 80%);
            mask-image: radial-gradient(ellipse 90% 70% at 50% 30%, black 0%, transparent 80%);
    opacity: 0.5;
  }
}

/* Add the inner span the .forge-auth-mobile-orb expects (Login.razor
   wires this: <span class="forge-auth-mobile-orb"> inside formpane__hero).
   The mobile-orb selector itself styles the wrapper; we need the inner
   span for the bright core. Defensive default in case Login wasn't
   updated yet — plain selector (no nested span) falls back to the
   pre-redesign single-glow look. */
.forge-auth-mobile-orb:not(:has(> span))::after {
  inset: 0;
  border: 0;
  background:
    radial-gradient(circle at 30% 30%,
        oklch(var(--accent-l) var(--accent-c) var(--accent-h)) 0%,
        oklch(calc(var(--accent-l) - 0.18) var(--accent-c) var(--accent-h) / 0.4) 60%,
        transparent 80%);
  animation: none;
}

/* prefers-reduced-motion — disable the rotating glass card so motion-
   sensitive users don't get a parallax shimmer when the page first paints
   under InteractiveServer hot-reload. */
@media (prefers-reduced-motion: reduce) {
  .forge-auth-hero::after { transform: none; }
  .forge-auth-container { animation: none; }
}

/* ────────────────────────────────────────────────────────────────────
   Auth shell — top-tier enhancements (matches dashboard hero language).

   The base auth shell already has a radial-glow + dot-grid background +
   one bright orb on the hero pane. These additions push it to match
   the visual richness of the new dashboard hero:

     • Three drift orbs in the hero pane (large / medium / small) on
       18 s / 14 s / 16 s ease-in-out loops, accent-OKLCH tinted so
       they flip hue with [data-accent]. They sit BEHIND the hero copy
       (z-index: 0) so the bloom + orbs read as a layered atmosphere.
     • Conic-gradient halo on the form card — a soft accent wash anchored
       at 30 % / 110 % that wraps around the form's bottom-left corner
       (40 px blur, opacity 0.4, behind the card via z-index: -1). Reads
       as "this is where you land" without competing with the inputs.
     • Entrance cascade — the auth-container card rises in over 540 ms
       (already there from auth-card-in); now its child fields are also
       staggered: title / status / form rows / divider / social buttons /
       links each on their own beat (40 ms apart). The combined effect
       is a Linear / Adobe Spectrum-grade entrance that signals the
       page is alive without distracting from the form input.

   prefers-reduced-motion stops every animation at the final state.
   ──────────────────────────────────────────────────────────────────── */

.forge-auth-hero__visual {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  overflow: hidden;
}

.forge-auth-hero__orb {
  position: absolute;
  border-radius: 999px;
  background: radial-gradient(circle at 30% 30%,
      oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.55),
      oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.12) 60%,
      transparent 80%);
  filter: blur(40px);
  opacity: 0.6;
  will-change: transform;
}
.forge-auth-hero__orb--lg {
  width: 360px; height: 360px;
  top: -100px; right: -80px;
  animation: forge-auth-orb-drift 18s ease-in-out infinite;
}
.forge-auth-hero__orb--md {
  width: 220px; height: 220px;
  top: 220px; right: 180px;
  animation: forge-auth-orb-drift 14s ease-in-out infinite reverse;
  opacity: 0.45;
}
.forge-auth-hero__orb--sm {
  width: 120px; height: 120px;
  bottom: 80px; right: 320px;
  animation: forge-auth-orb-drift 16s ease-in-out infinite;
  animation-delay: -5s;
  opacity: 0.5;
}

@keyframes forge-auth-orb-drift {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(-28px, 18px, 0); }
}

/* Conic halo behind the auth container — warmer accent wash anchored
   at the bottom-left so it reads as a soft glow seeping up under the
   form. opacity stays low so it doesn't compete with the inputs. */
.forge-auth-container::before {
  content: "";
  position: absolute;
  inset: -4px;
  pointer-events: none;
  background:
    conic-gradient(
      from 200deg at 30% 110%,
      transparent 0deg,
      oklch(var(--accent-l) var(--accent-c) var(--accent-h) / 0.18) 60deg,
      transparent 130deg
    );
  filter: blur(40px);
  opacity: 0.6;
  z-index: -1;
}

/* Form-card entrance cascade — each child rises into place 40 ms after
   the previous one. The card itself already animates via auth-card-in
   in the existing CSS; this adds a per-row beat on top so the
   greeting + inputs settle in sequence. */
@keyframes forge-auth-row-in {
  0%   { opacity: 0; transform: translateY(8px); }
  100% { opacity: 1; transform: translateY(0); }
}
.forge-auth-container > .forge-auth-header,
.forge-auth-container > .forge-auth-form,
.forge-auth-container > .forge-auth-divider,
.forge-auth-container > .forge-auth-links,
.forge-auth-container > [class*="StatusMessage"] {
  animation: forge-auth-row-in 480ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
.forge-auth-container > .forge-auth-header { animation-delay: 200ms; }
.forge-auth-container > .forge-auth-form   { animation-delay: 280ms; }
.forge-auth-container > .forge-auth-divider { animation-delay: 360ms; }
.forge-auth-container > .forge-auth-links  { animation-delay: 440ms; }

/* When the auth shell is up, freeze the layered radial bloom so the
   ambient gradient + orb motion don't compete for attention with the
   user's typing. The drift orbs stay alive (calmer pace) but the
   bloom anchored bright spot stops pulsing. */
.forge-auth-hero__lead::before { /* pre-existing single orb — keep it,
                                    but slow the drift so it doesn't
                                    race the new big orbs around it. */
  animation-duration: 9s;
}

@media (prefers-reduced-motion: reduce) {
  .forge-auth-hero__orb,
  .forge-auth-container > .forge-auth-header,
  .forge-auth-container > .forge-auth-form,
  .forge-auth-container > .forge-auth-divider,
  .forge-auth-container > .forge-auth-links {
    animation: none !important;
  }
}

@media (max-width: 960px) {
  /* Mobile — drop the multi-orb decoration; the existing single-orb
     bloom is enough on small viewports and the additional orbs would
     read busy on a phone. */
  .forge-auth-hero__visual { display: none; }
}

/* ────────────────────────────────────────────────────────────────────
   Stay-signed-in row — checkbox + label, full-width tap target.
   Used by Login.razor in both transports: a plain <input type="checkbox"
   name="rememberMe"> for the Server-mode HTML form, and Blazor's
   <InputCheckbox @bind-Value="Input.RememberMe"> for Token-mode
   EditForm. Both render as the same `<input type="checkbox">` element
   so this CSS matches either path.

   Custom-styled box because the native checkbox is too small and
   visually inconsistent across OS / browser. The faux box mirrors
   the active accent on focus + checked, and the entire label is the
   click target so users hit it easily on touch.
   ──────────────────────────────────────────────────────────────────── */

.forge-auth-remember {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
  font-size: 13px;
  color: var(--fg-2, var(--text-t2));
  padding: 6px 0;
}
.forge-auth-remember > input[type="checkbox"] {
  /* Hide the native control but keep it accessible — keyboard / screen
     readers operate on it; we paint a styled square in its place via
     the sibling. */
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  margin: 0;
  flex-shrink: 0;
  border: 1.5px solid color-mix(in oklab, var(--fg-1, currentColor) 22%, transparent);
  border-radius: 5px;
  background: color-mix(in oklab, var(--fg-1, currentColor) 4%, transparent);
  cursor: pointer;
  display: inline-grid;
  place-content: center;
  transition: background 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}
.forge-auth-remember > input[type="checkbox"]::before {
  content: "";
  width: 10px;
  height: 10px;
  background: var(--accent);
  clip-path: polygon(14% 44%, 0 60%, 40% 100%, 100% 20%, 86% 6%, 39% 70%);
  transform: scale(0);
  transform-origin: center;
  transition: transform 160ms cubic-bezier(0.22, 1, 0.36, 1);
}
.forge-auth-remember > input[type="checkbox"]:checked {
  border-color: var(--accent);
  background: color-mix(in oklab, var(--accent) 14%, transparent);
}
.forge-auth-remember > input[type="checkbox"]:checked::before {
  transform: scale(1);
}
.forge-auth-remember > input[type="checkbox"]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in oklab, var(--accent) 30%, transparent);
}
.forge-auth-remember:hover > input[type="checkbox"] {
  border-color: color-mix(in oklab, var(--accent) 50%, transparent);
}
.forge-auth-remember__label {
  line-height: 1.4;
}

/* ════════════════════════════════════════════════════════════════════════════
   Account · Manage subpages — card sections, recovery codes, TOTP setup, etc.

   These rules align /account/manage/* layout with the rest of the design
   system. The Razor markup uses BEM-style classes (`forge-manage-card__title`,
   `forge-manage-card__body`) but the original CSS only styled the layout
   wrappers — leaving section titles, body paragraphs, code chips and the
   sign-out footer with default browser margins. This block fills the gap.
   ════════════════════════════════════════════════════════════════════════════ */

/* Card container — used by every /account/manage subpage. Multiple cards on one
   page get the same vertical rhythm; the first card sits directly under the page
   header. */
.forge-manage-card {
  background: var(--surface-s1, var(--bg-2));
  border: 1px solid var(--line);
  border-radius: var(--radius-2, 12px);
  padding: var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  margin-block-end: var(--s-5);
  font-family: var(--font-sans);
}
.forge-manage-card:last-child {
  margin-block-end: 0;
}

.forge-manage-card__title {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--fg-1);
  letter-spacing: -0.01em;
}

.forge-manage-card__body {
  margin: 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--fg-2);
}

.forge-manage-card__heading {
  margin: var(--s-4) 0 var(--s-2);
  font-size: 14px;
  font-weight: 600;
  color: var(--fg-1);
  letter-spacing: -0.005em;
}
.forge-manage-card__heading:first-child {
  margin-top: 0;
}

.forge-manage-card__warning {
  margin: 0;
  padding: var(--s-3);
  border-radius: var(--radius-1, 8px);
  background: oklch(from var(--warn) l c h / 0.10);
  border: 1px solid oklch(from var(--warn) l c h / 0.25);
  color: var(--warn);
  font-size: 13px;
  line-height: 1.5;
}
.forge-manage-card__warning strong {
  font-weight: 600;
  margin-inline-end: var(--s-1);
}

.forge-manage-card--success {
  background: oklch(from var(--ok) l c h / 0.06);
  border-color: oklch(from var(--ok) l c h / 0.25);
}

/* Split layout for QR + manual-key blocks on the 2FA setup page. The QR sits
   left, the manual key + paste hint sits right. Stacks at narrow widths. */
.forge-manage-card--split {
  flex-direction: row;
  align-items: flex-start;
  gap: var(--s-5);
}
@media (max-width: 640px) {
  .forge-manage-card--split {
    flex-direction: column;
  }
}

.forge-manage-card__qr {
  flex: 0 0 auto;
}
.forge-manage-card__details {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  min-width: 0;
}

/* QR container — keeps the SVG square + bordered for scanability contrast. */
.forge-qr {
  display: inline-block;
  padding: var(--s-3);
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-1, 8px);
  line-height: 0;
}
.forge-qr svg {
  display: block;
  width: 200px;
  height: 200px;
}

/* Inline monospace key for manual entry. */
.forge-key-display {
  display: inline-block;
  padding: var(--s-2) var(--s-3);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-1, 8px);
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.04em;
  color: var(--fg-1);
  user-select: all;
  word-break: break-all;
}

/* Numbered step list on the 2FA setup page. The default browser indent puts
   the marker about 40 px in — tighten so it aligns flush with the page header
   text on the left rather than dangling under it. */
.forge-manage-steps {
  margin: 0 0 var(--s-4);
  padding-inline-start: var(--s-5);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  font-size: 14px;
  line-height: 1.5;
  color: var(--fg-2);
}
.forge-manage-steps li {
  padding-inline-start: var(--s-1);
}
.forge-manage-steps li::marker {
  color: var(--fg-3);
  font-weight: 600;
}

/* Recovery codes — 4-column grid of monospace chips, generous spacing for
   easy copy-paste. */
.forge-recovery-codes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--s-2);
  margin: var(--s-2) 0;
}
.forge-recovery-codes__item {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-2);
  background: var(--bg-3);
  border: 1px solid var(--line);
  border-radius: var(--radius-1, 8px);
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.05em;
  color: var(--fg-1);
  user-select: all;
}

/* Empty / loading placeholders — match the card visual language but flatter. */
.forge-manage-empty,
.forge-manage-skeleton {
  padding: var(--s-4);
  background: var(--bg-2);
  border: 1px dashed var(--line);
  border-radius: var(--radius-2, 12px);
  color: var(--fg-3);
  font-size: 14px;
  text-align: center;
  font-family: var(--font-sans);
  margin-block-end: var(--s-5);
}

/* Sessions / passkeys list — the existing rule was display:none-ish (see the
   forge-sessions-list animation in app.css); fill in the actual layout. */
.forge-sessions-list {
  list-style: none;
  margin: 0 0 var(--s-5);
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  font-family: var(--font-sans);
}
.forge-sessions-list__item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-1, 8px);
}
.forge-sessions-list__main {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  min-width: 0;
}
.forge-sessions-list__main strong {
  font-size: 14px;
  font-weight: 600;
  color: var(--fg-1);
}
.forge-sessions-list__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-1);
  font-size: 12px;
  color: var(--fg-3);
}

/* /account/manage profile page — give the sign-out footer breathing room
   from the profile <dl>. Without this rule the form sits flush under the
   2FA badge row. */
.forge-manage-actions {
  margin-block-start: var(--s-5);
  padding-block-start: var(--s-4);
  border-block-start: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
}

/* The page-fade-in animation in app.css uses display:none — guard the
   manage-card / sessions-list against the initial hidden state. */
.forge-manage-card,
.forge-recovery-codes,
.forge-manage-empty,
.forge-manage-skeleton {
  opacity: 1;
}


/* ────────────────────────────────────────────────────────────────────────
   Kiosk page form chrome — re-uses the same forge-auth-* surfaces as
   /account/login (split shell with mobile orb decoration), only the form
   body differs: a camera-viewfinder placeholder above a badge-ID input.
   The whole page lives inside the AuthLayout so the topbar (language /
   theme / tweaks chips) is the same as on the standard login page.
   ──────────────────────────────────────────────────────────────────────── */
.forge-kiosk-form {
  gap: var(--s-3);
}
.forge-kiosk-form__camera {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 140px;
  padding: var(--s-4);
  border: 2px dashed var(--line-strong);
  border-radius: var(--r-md);
  background:
    radial-gradient(ellipse at center, var(--accent-soft) 0%, transparent 70%),
    var(--surface-s2);
  color: var(--text-t2);
  font-size: var(--typography-scale-sm);
  text-align: center;
  /* Subtle scan-line animation hints "this is a camera viewfinder" without
     needing actual camera permission. Killed under prefers-reduced-motion. */
  position: relative;
  overflow: hidden;
}
.forge-kiosk-form__camera::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent, var(--accent-base, var(--accent)) 50%, transparent);
  opacity: 0.18;
  animation: forge-kiosk-scan 2.4s linear infinite;
  pointer-events: none;
}
@keyframes forge-kiosk-scan {
  from { transform: translateY(-100%); }
  to   { transform: translateY(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .forge-kiosk-form__camera::before { animation: none; opacity: 0.08; }
}
