/* ============================================================
   朔光与墨 · 统一认证 — 登录页样式（2026-10 右栏极简重做版）
   设计基调：极简现代 / 大留白 / 细描边 / 灰阶 + 单一墨色强调
   主题：跟随系统 prefers-color-scheme 自动切换深浅
   注意：以下选择器与 JS 强耦合，重命名前先核对：
   - .auth-tabs / .auth-tabs-slider（data-active 驱动滑块；app.js 以 display:flex 显隐）
   - .auth-message / #lockedBox / .auth-qr-scanned / .auth-qr-mask（app.js 以 display:flex 显隐）
   - #attemptWarning / #lockTimer（app.js 以 display:block 显隐）
   - .auth-pw-toggle + .pw-eye/.pw-eye-off（密码可见性）
   - .auth-btn > .auth-btn-text / .auth-btn-spinner（加载态，spinner 显隐由内联样式控制，CSS 不得设 display）
   - .is-hidden（视图切换，含 forgotView 内嵌套的 step1/step2 表单）
   - .otp-input 系列结构由 app.js createOtpInput / form-enhance.js 动态生成
   - .auth-oauth-btn.is-loading（OAuth 跳转 loading）
   - .auth-input-wrap.is-invalid（行内校验）、.auth-message--success（成功消息）
   - .auth-qr-countdown.is-warning、.auth-qr-box.is-opened
   ============================================================ */

:root {
  color-scheme: light;

  /* 表面 */
  --bg-body: oklch(0.988 0.002 260);
  --bg-form-side: oklch(0.995 0.001 260);
  --bg-subtle: oklch(0.962 0.002 260);
  --bg-input: oklch(1 0 0);
  --bg-slider: oklch(1 0 0);

  /* 描边 */
  --border-color: oklch(0.918 0.004 260);
  --border-strong: oklch(0.855 0.005 260);

  /* 文字 */
  --text-primary: oklch(0.215 0.012 260);
  --text-secondary: oklch(0.47 0.01 260);
  --text-muted: oklch(0.60 0.008 260);

  /* 强调：墨黑（深色主题反转为近白），按钮文字/对勾等用 --accent-contrast */
  --accent: oklch(0.225 0.012 260);
  --accent-hover: oklch(0.30 0.014 260);
  --accent-contrast: oklch(0.995 0 0);

  /* 语义色 */
  --error: oklch(0.55 0.19 25);
  --error-bg: oklch(0.965 0.018 25);
  --error-border: oklch(0.90 0.045 25);
  --locked: oklch(0.58 0.14 65);
  --locked-bg: oklch(0.965 0.02 65);
  --locked-border: oklch(0.90 0.05 65);
  --success: oklch(0.55 0.15 150);
  --warning: oklch(0.62 0.13 70);
  --info: oklch(0.55 0.11 240);

  /* 品牌图（左侧不动） */
  --brand-overlay: oklch(0.12 0.02 260 / 0.55);
  --brand-text: oklch(0.98 0.005 260);

  --radius-sm: 8px;
  --radius-md: 10px;
  --radius-lg: 14px;

  --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
  --font-serif: var(--font-sans);

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --transition-fast: 0.15s var(--ease-out);
  --transition-normal: 0.25s var(--ease-out);

  /* 阴影：聚焦用 4px 光环，滑块/按钮用轻投影 */
  --shadow-focus: 0 0 0 4px oklch(0.225 0.012 260 / 0.12);
  --shadow-focus-error: 0 0 0 4px oklch(0.55 0.19 25 / 0.14);
  --shadow-slider: 0 1px 2px oklch(0 0 0 / 0.10), 0 0 0 1px oklch(0 0 0 / 0.04);
  --shadow-btn: 0 1px 2px oklch(0 0 0 / 0.10);
  --shadow-btn-hover: 0 4px 14px oklch(0 0 0 / 0.16);
}

/* ====== 基础重置 ====== */
*, *::before, *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* hidden 属性优先级最高：防止自定义 display 规则压过它 */
[hidden] {
  display: none !important;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body {
  font-family: var(--font-sans);
  background: var(--bg-body);
  color: var(--text-primary);
  min-height: 100vh;
  overflow-x: hidden;
}

button {
  font-family: inherit;
}

/* 供屏幕阅读器之外隐藏的同步域（如找回密码隐藏验证码输入框） */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ====== 页面骨架：左侧品牌卡 + 右侧表单 ====== */
.auth-page {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.auth-brand-side {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 近满栏圆角卡片：图片+遮罩整体裁剪出圆角并浮起 */
.auth-brand-bg {
  position: absolute;
  inset: 40px;
  z-index: 0;
  border-radius: 24px;
  overflow: hidden;
  box-shadow:
    0 24px 60px oklch(0 0 0 / 0.16),
    0 4px 16px oklch(0 0 0 / 0.08);
}

.auth-brand-bg-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

.auth-brand-bg-overlay {
  position: absolute;
  inset: 0;
  background: var(--brand-overlay);
  backdrop-filter: blur(1px);
  -webkit-backdrop-filter: blur(1px);
}

.auth-brand-content {
  position: relative;
  z-index: 1;
  text-align: center;
  padding: 48px;
  animation: brandEnter 0.8s var(--ease-out) forwards;
  opacity: 0;
}

@keyframes brandEnter {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}

.auth-brand-logo {
  width: 72px;
  height: 72px;
  margin: 0 auto 28px;
  filter: brightness(0) invert(1);
  opacity: 0.9;
}

.auth-brand-logo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.auth-brand-name {
  font-family: var(--font-serif);
  font-size: clamp(2rem, 3.5vw, 3rem);
  font-weight: 600;
  color: var(--brand-text);
  letter-spacing: 0.08em;
  line-height: 1.2;
  margin-bottom: 16px;
  text-wrap: balance;
}

.auth-brand-slogan {
  font-family: var(--font-serif);
  font-size: clamp(0.9375rem, 1.2vw, 1.125rem);
  font-weight: 400;
  color: oklch(0.92 0.005 260);
  letter-spacing: 0.15em;
  line-height: 1.8;
  opacity: 0.85;
}

/* ====== 右侧表单区：居中窄栏 ====== */
.auth-form-side {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 48px;
  position: relative;
  background: var(--bg-form-side);
}

.auth-form-container {
  width: 100%;
  max-width: 400px;
  animation: formEnter 0.6s var(--ease-out) 0.15s forwards;
  opacity: 0;
}

@keyframes formEnter {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ====== 眉标：两侧细线夹住小字距标识 ====== */
.auth-eyebrow {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 22px;
}

.auth-eyebrow-rule {
  flex: 1;
  height: 1px;
  background: var(--border-color);
}

.auth-eyebrow-text {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.26em;
  color: var(--text-muted);
  white-space: nowrap;
}

/* ====== 头部标题（居中排版） ====== */
.auth-header {
  text-align: center;
  margin-bottom: 28px;
}

.auth-title {
  font-family: var(--font-serif);
  font-size: 1.625rem;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.015em;
  margin-bottom: 8px;
  line-height: 1.3;
}

.auth-subtitle {
  font-size: 0.875rem;
  color: var(--text-secondary);
  font-weight: 400;
  line-height: 1.6;
}

/* ====== 全局消息（错误 / 锁定 / 成功） ====== */
.auth-message {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  background: var(--error-bg);
  border: 1px solid var(--error-border);
  border-radius: var(--radius-md);
  margin-bottom: 18px;
  font-size: 0.8125rem;
  color: var(--error);
  line-height: 1.5;
  animation: messageIn 0.25s var(--ease-out);
}

.auth-message--locked {
  background: var(--locked-bg);
  border-color: var(--locked-border);
  color: var(--locked);
}

/* 成功/提示类消息（找回密码发码成功、重置成功等） */
.auth-message--success {
  background: color-mix(in oklab, var(--success) 10%, transparent);
  border-color: color-mix(in oklab, var(--success) 32%, transparent);
  color: var(--success);
}

.auth-message-icon {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
}

@keyframes messageIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.auth-attempt-warning {
  font-size: 0.8125rem;
  color: var(--locked);
  margin-bottom: 16px;
  padding-left: 2px;
  font-weight: 500;
}

.auth-lock-timer {
  font-size: 0.8125rem;
  color: var(--locked);
  margin-bottom: 16px;
  text-align: center;
  font-weight: 500;
}

/* ====== 登录方式切换（分段控件） ====== */
.auth-tabs {
  position: relative;
  display: flex;
  padding: 3px;
  background: var(--bg-subtle);
  border-radius: 999px;
  margin-bottom: 26px;
}

/* 滑块：随 data-active 平移，位于 Tab 文字层之下 */
.auth-tabs-slider {
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: 3px;
  width: calc(50% - 3px);
  background: var(--bg-slider);
  border-radius: 999px;
  box-shadow: var(--shadow-slider);
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
  pointer-events: none;
}

.auth-tabs[data-active="qr"] .auth-tabs-slider {
  transform: translateX(100%);
}

.auth-tab {
  position: relative;
  z-index: 1;
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 9px 12px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--text-muted);
  font-size: 0.8438rem;
  font-weight: 500;
  cursor: pointer;
  transition: color var(--transition-fast);
}

.auth-tab:hover {
  color: var(--text-secondary);
}

.auth-tab.is-active {
  color: var(--text-primary);
  font-weight: 600;
}

.auth-tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.auth-tab-icon {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  opacity: 0.75;
}

.auth-tab.is-active .auth-tab-icon {
  opacity: 1;
}

/* ====== 面板容器：等高堆叠，is-hidden 控制显隐 ====== */
.auth-panels {
  display: grid;
}

.auth-panels > * {
  grid-area: 1 / 1;
  min-width: 0;
}

/* 通用显隐工具类：覆盖 auth-panels 直接子面板 + forgotView 内嵌套的两步表单 */
.is-hidden {
  display: none !important;
}

.auth-form {
  animation: formSwitch 0.3s var(--ease-out);
}

@keyframes formSwitch {
  from { opacity: 0; transform: translateX(8px); }
  to { opacity: 1; transform: translateX(0); }
}

/* ====== 表单字段：静态置顶标签 ====== */
.auth-field {
  margin-bottom: 20px;
}

.auth-label {
  display: block;
  margin-bottom: 8px;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-secondary);
  letter-spacing: 0.01em;
  line-height: 1.4;
}

.auth-input-wrap {
  position: relative;
}

.auth-input {
  width: 100%;
  height: 46px;
  padding: 0 14px;
  background: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 400;
  line-height: 1.4;
  outline: none;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

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

.auth-input:focus {
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}

/* 密码输入框：为可见性切换按钮预留右侧空间 */
.auth-input-wrap:has(.auth-pw-toggle) .auth-input {
  padding-right: 44px;
}

/* 行内错误提示（form-enhance.js 实时校验写入） */
.auth-field-msg {
  margin: 6px 2px 0;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--error);
}

.auth-input-wrap.is-invalid .auth-input {
  border-color: var(--error);
}

.auth-input-wrap.is-invalid .auth-input:focus {
  box-shadow: var(--shadow-focus-error);
}

/* 浏览器自动填充的底色覆盖（浅/深主题各自透过变量生效） */
.auth-input:-webkit-autofill,
.auth-input:-webkit-autofill:hover,
.auth-input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--text-primary);
  -webkit-box-shadow: 0 0 0 1000px var(--bg-input) inset;
  transition: background-color 99999s ease-in-out 0s;
  caret-color: var(--text-primary);
}

/* ====== 密码可见性切换 ====== */
.auth-pw-toggle {
  position: absolute;
  right: 7px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  padding: 8px;
  cursor: pointer;
  color: var(--text-muted);
  transition: color var(--transition-fast);
  display: flex;
  align-items: center;
  border-radius: 6px;
}

.auth-pw-toggle:hover {
  color: var(--text-secondary);
}

.auth-pw-toggle svg {
  width: 17px;
  height: 17px;
  display: block;
}

.auth-pw-toggle:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-radius: 6px;
}

/* ====== 记住我 / 忘记密码 ====== */
.auth-options {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 4px 2px 22px;
}

.auth-remember {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.8125rem;
  color: var(--text-secondary);
  cursor: pointer;
  user-select: none;
  position: relative;
  line-height: 1.4;
}

.auth-remember input[type="checkbox"] {
  position: absolute;
  opacity: 0;
  width: 18px;
  height: 18px;
  margin: 0;
  cursor: pointer;
}

.auth-remember-check {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  border: 1.5px solid var(--border-strong);
  border-radius: 5px;
  background: var(--bg-input);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.auth-remember-check::after {
  content: "";
  width: 9px;
  height: 5px;
  border-left: 2px solid var(--accent-contrast);
  border-bottom: 2px solid var(--accent-contrast);
  transform: rotate(-45deg) scale(0);
  margin-top: -1px;
  transition: transform 0.18s var(--ease-out);
}

.auth-remember:hover .auth-remember-check {
  border-color: var(--text-muted);
}

.auth-remember input:checked + .auth-remember-check {
  background: var(--accent);
  border-color: var(--accent);
}

.auth-remember input:checked + .auth-remember-check::after {
  transform: rotate(-45deg) scale(1);
}

.auth-remember input:focus-visible + .auth-remember-check {
  box-shadow: var(--shadow-focus);
}

.auth-forgot-link {
  background: none;
  border: none;
  padding: 4px 2px;
  color: var(--text-secondary);
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
  border-radius: 6px;
  transition: color var(--transition-fast);
}

.auth-forgot-link:hover {
  color: var(--text-primary);
}

.auth-forgot-link:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ====== 主按钮 ====== */
.auth-btn {
  width: 100%;
  height: 46px;
  background: var(--accent);
  color: var(--accent-contrast);
  border: none;
  border-radius: var(--radius-md);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  position: relative;
  box-shadow: var(--shadow-btn);
  transition: background var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast), opacity var(--transition-fast);
}

/* 注意：.auth-btn-spinner 的显隐由内联样式控制（app.js setBtnLoading），此处不得设置 display；
   颜色跟随 currentColor，深浅主题下随按钮文字自动反转 */
.auth-btn-spinner {
  width: 17px;
  height: 17px;
  border: 2px solid color-mix(in oklab, currentColor 30%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

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

.auth-btn:hover:not(:disabled) {
  background: var(--accent-hover);
  box-shadow: var(--shadow-btn-hover);
}

.auth-btn:active:not(:disabled) {
  transform: scale(0.985);
  box-shadow: var(--shadow-btn);
}

.auth-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.auth-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ====== 分隔线 / 第三方登录 ====== */
.auth-divider {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 22px 0 14px;
  color: var(--text-muted);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
}

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

.auth-oauth-group {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.auth-oauth-btn {
  height: 44px;
  min-width: 0;
  padding: 0 8px;
  background: var(--bg-input);
  color: var(--text-primary);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast), opacity var(--transition-fast);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  white-space: nowrap;
}

.auth-oauth-btn:hover {
  border-color: var(--border-strong);
  box-shadow: 0 1px 4px oklch(0 0 0 / 0.08);
}

.auth-oauth-btn:active {
  box-shadow: none;
}

.auth-oauth-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.auth-oauth-icon {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--text-muted);
  transition: color var(--transition-fast);
}

/* 图标默认灰阶，悬停时点亮品牌色（按钮底色保持中性） */
.auth-oauth-btn--github:hover .auth-oauth-icon { color: #24292F; }
.auth-oauth-btn--gitee:hover .auth-oauth-icon { color: #C71D23; }
.auth-oauth-btn--gitcode:hover .auth-oauth-icon { color: #DA203E; }

/* 点击跳转前的 loading 状态（app.js bindOauthLoginBtn 添加 is-loading） */
.auth-oauth-btn.is-loading {
  pointer-events: none;
  opacity: 0.75;
}

.auth-oauth-spinner {
  display: none;
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  opacity: 0.6;
  animation: spin 0.6s linear infinite;
}

.auth-oauth-btn.is-loading .auth-oauth-spinner {
  display: inline-block;
}

/* ====== 2FA / 找回密码的操作行（重发 + 返回） ====== */
.auth-twofa-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 4px 0 20px;
}

.auth-twofa-resend,
.auth-twofa-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  padding: 6px 2px;
  color: var(--text-secondary);
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
  border-radius: 6px;
  transition: color var(--transition-fast);
}

.auth-twofa-resend svg,
.auth-twofa-back svg {
  width: 14px;
  height: 14px;
}

.auth-twofa-resend:hover:not(:disabled),
.auth-twofa-back:hover {
  color: var(--text-primary);
}

.auth-twofa-resend:disabled {
  color: var(--text-muted);
  cursor: not-allowed;
}

/* ====== 2FA 分格验证码输入（六格 OTP） ======
   结构：.otp-input > .otp-cell（.otp-slot 真实输入 + .otp-ring 成功描边 + .otp-char-layer 字符动画）
   真实 input 文字透明、光标隐藏，仅负责交互；可见字符/光标全部为叠加的视觉层
   --plain 变体（找回密码邮箱验证码）：普通可见文字输入，无动画层 */
.otp-input {
  position: relative;
  display: flex;
  justify-content: center;
  gap: 8px;
}

.otp-cell {
  position: relative;
  flex: 1 1 0;
  max-width: 46px;
}

.otp-slot {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  padding: 0;
  background: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-md);
  color: transparent;
  caret-color: transparent;
  text-align: center;
  font-family: var(--font-sans);
  font-size: 1.125rem;
  font-weight: 600;
  outline: none;
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

.otp-slot::selection {
  background: transparent;
}

.otp-slot:hover {
  border-color: var(--border-strong);
}

.otp-slot:focus {
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}

.otp-slot:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* --plain 变体：可见文字 + 常规光标 */
.otp-input--plain .otp-slot {
  color: var(--text-primary);
  caret-color: var(--text-primary);
}

.otp-input--plain .otp-slot::selection {
  background: color-mix(in oklab, var(--accent) 22%, transparent);
}

/* 错误态：整行先抖动，红描边延迟 150ms 跟上，形成时序层次 */
.otp-input[data-status="error"] {
  animation: otpShake 0.32s var(--ease-out);
}

.otp-input[data-status="error"] .otp-slot {
  border-color: var(--error);
  box-shadow: 0 0 0 2px var(--error);
  transition-delay: 0.15s;
}

/* 字符动画层：overflow 裁切出「从格子边缘滚入」的效果 */
.otp-char-layer {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-radius: var(--radius-md);
  pointer-events: none;
}

.otp-char {
  font-family: var(--font-sans);
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--text-primary);
}

/* 输入：自下滑入；覆盖：旧字符向上出场；退格（cleared 语义）：向下出场 */
.otp-char.is-enter {
  animation: otpRollIn 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}

.otp-char.is-exit-up {
  animation: otpRollOutUp 0.28s cubic-bezier(0.55, 0, 0.55, 0.2) forwards;
}

.otp-char.is-exit-down {
  animation: otpRollOutDown 0.28s cubic-bezier(0.55, 0, 0.55, 0.2) forwards;
}

/* 成功描边：pathLength 归一化，逐格延迟推进 */
.otp-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
}

.otp-ring rect {
  fill: none;
  stroke: var(--success);
  stroke-width: 2;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

.otp-input[data-status="success"] .otp-ring {
  opacity: 1;
}

.otp-input[data-status="success"] .otp-ring rect {
  animation: otpDraw 0.45s var(--ease-out) forwards;
  animation-delay: calc(0.15s + var(--otp-i) * 0.05s);
}

/* 自绘光标：仅聚焦且空格时显示，x 随格子切换平滑滑动 */
.otp-caret {
  position: absolute;
  left: 0;
  top: 50%;
  width: 2px;
  height: 22px;
  margin-top: -11px;
  border-radius: 1px;
  background: var(--text-primary);
  opacity: 0;
  pointer-events: none;
  transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.15s;
}

.otp-caret.is-visible {
  opacity: 1;
  animation: otpBlink 1.1s linear infinite;
}

@keyframes otpRollIn {
  from { transform: translateY(110%); }
  to { transform: translateY(0); }
}

@keyframes otpRollOutUp {
  from { transform: translateY(0); }
  to { transform: translateY(-110%); }
}

@keyframes otpRollOutDown {
  from { transform: translateY(0); }
  to { transform: translateY(110%); }
}

@keyframes otpDraw {
  to { stroke-dashoffset: 0; }
}

@keyframes otpShake {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-5px); }
  35% { transform: translateX(4px); }
  55% { transform: translateX(-2px); }
  75% { transform: translateX(0); }
}

/* 与原组件 opacity [1,1,0,0] 一致：硬切闪烁 */
@keyframes otpBlink {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* ====== 密码强度条（form-enhance.js 按 data-level 0-4 染色） ====== */
.pw-strength {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 8px 2px 0;
}

.pw-strength-track {
  display: flex;
  gap: 4px;
  flex: 1;
}

.pw-strength-track i {
  height: 4px;
  flex: 1;
  border-radius: 2px;
  background: var(--border-color);
  transition: background 0.25s var(--ease-out);
}

.pw-strength-label {
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-muted);
  min-width: 3em;
  text-align: right;
}

.pw-strength[data-level="1"] i:nth-child(-n+1) { background: var(--error); }
.pw-strength[data-level="2"] i:nth-child(-n+2) { background: var(--warning); }
.pw-strength[data-level="3"] i:nth-child(-n+3) { background: var(--info); }
.pw-strength[data-level="4"] i:nth-child(-n+4) { background: var(--success); }

.pw-strength[data-level="1"] .pw-strength-label { color: var(--error); }
.pw-strength[data-level="2"] .pw-strength-label { color: var(--warning); }
.pw-strength[data-level="3"] .pw-strength-label { color: var(--info); }
.pw-strength[data-level="4"] .pw-strength-label { color: var(--success); }

/* ====== 扫码登录视图 ====== */
#qrView {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.auth-qr-box {
  position: relative;
  width: 196px;
  height: 196px;
  padding: 8px;
  background: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-btn);
  transition: border-color 0.25s var(--ease-out), box-shadow 0.25s var(--ease-out);
}

#qrImage {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 8px;
}

/* 手机已打开登录页：绿描边提示「扫码即知」 */
.auth-qr-box.is-opened {
  border-color: oklch(0.60 0.13 150);
  box-shadow: 0 0 0 3px oklch(0.60 0.13 150 / 0.18);
}

/* 已扫码遮罩 */
.auth-qr-scanned {
  position: absolute;
  inset: 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: oklch(1 0 0 / 0.94);
  border-radius: 8px;
  animation: messageIn 0.25s var(--ease-out);
}

.auth-qr-scanned-icon {
  width: 42px;
  height: 42px;
  color: var(--success);
}

.auth-qr-scanned-text {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--success);
}

/* 过期/异常遮罩 */
.auth-qr-mask {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
  background: oklch(1 0 0 / 0.96);
  border-radius: var(--radius-lg);
  animation: messageIn 0.25s var(--ease-out);
}

.auth-qr-mask-text {
  font-size: 0.8125rem;
  color: var(--text-secondary);
  text-align: center;
  padding: 0 16px;
  line-height: 1.5;
}

.auth-qr-refresh {
  padding: 8px 16px;
  background: var(--accent);
  color: var(--accent-contrast);
  border: none;
  border-radius: var(--radius-sm);
  font-size: 0.8125rem;
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition-fast), transform var(--transition-fast);
}

.auth-qr-refresh:hover {
  background: var(--accent-hover);
}

.auth-qr-refresh:active {
  transform: scale(0.97);
}

.auth-qr-refresh:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.auth-qr-tip {
  margin-top: 16px;
  font-size: 0.8125rem;
  color: var(--text-secondary);
  text-align: center;
}

.auth-qr-countdown {
  margin-top: 6px;
  font-size: 0.75rem;
  color: var(--text-muted);
}

.auth-qr-countdown.is-warning {
  color: var(--warning);
  font-weight: 500;
}

.auth-qr-remember {
  margin-top: 20px;
}

/* ====== 页脚：细线之上居中小字 ====== */
.auth-footer {
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid var(--border-color);
  text-align: center;
  font-size: 0.75rem;
  color: var(--text-muted);
  letter-spacing: 0.06em;
}

/* ====== 响应式 ====== */
@media (max-width: 1024px) {
  .auth-brand-bg {
    inset: 28px;
  }

  .auth-form-side {
    padding: 40px 32px;
  }
}

@media (max-width: 880px) {
  .auth-page {
    grid-template-columns: 1fr;
    grid-template-rows: auto 1fr;
  }

  .auth-brand-bg {
    inset: 16px;
    border-radius: 20px;
  }

  .auth-brand-content {
    padding: 44px 24px;
  }

  .auth-brand-logo {
    width: 56px;
    height: 56px;
    margin-bottom: 16px;
  }

  .auth-brand-name {
    font-size: clamp(1.6rem, 6vw, 2.2rem);
    margin-bottom: 8px;
  }

  .auth-form-side {
    padding: 36px 20px 48px;
  }
}

@media (max-width: 480px) {
  .auth-eyebrow {
    gap: 10px;
    margin-bottom: 18px;
  }

  .auth-eyebrow-text {
    letter-spacing: 0.2em;
  }

  .auth-title {
    font-size: 1.4375rem;
  }

  .auth-header {
    margin-bottom: 22px;
  }

  .auth-tabs {
    margin-bottom: 20px;
  }

  .auth-field {
    margin-bottom: 16px;
  }

  .auth-options {
    margin-bottom: 18px;
  }

  .auth-oauth-group {
    gap: 8px;
  }

  .auth-oauth-btn {
    font-size: 0.8125rem;
  }
}

/* ====== 暗色主题（跟随系统） ====== */
@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --bg-body: oklch(0.155 0.012 260);
    --bg-form-side: oklch(0.155 0.012 260);
    --bg-subtle: oklch(0.208 0.012 260);
    --bg-input: oklch(0.195 0.012 260);
    --bg-slider: oklch(0.262 0.012 260);

    --border-color: oklch(0.278 0.012 260);
    --border-strong: oklch(0.36 0.014 260);

    --text-primary: oklch(0.94 0.006 260);
    --text-secondary: oklch(0.70 0.01 260);
    --text-muted: oklch(0.56 0.009 260);

    /* 强调色反转为近白，按钮/勾选底配深墨文字 */
    --accent: oklch(0.945 0.006 260);
    --accent-hover: oklch(0.97 0.004 260);
    --accent-contrast: oklch(0.175 0.012 260);

    --error: oklch(0.72 0.16 25);
    --error-bg: oklch(0.25 0.05 25);
    --error-border: oklch(0.37 0.08 25);
    --locked: oklch(0.78 0.12 65);
    --locked-bg: oklch(0.25 0.04 65);
    --locked-border: oklch(0.39 0.07 65);
    --success: oklch(0.75 0.13 150);
    --warning: oklch(0.78 0.12 70);
    --info: oklch(0.72 0.10 240);

    /* 品牌图：暗色下遮罩加深，与深色环境融合 */
    --brand-overlay: oklch(0.08 0.02 260 / 0.72);
    --brand-text: oklch(0.98 0.005 260);

    --shadow-focus: 0 0 0 4px oklch(0.945 0.006 260 / 0.16);
    --shadow-focus-error: 0 0 0 4px oklch(0.72 0.16 25 / 0.20);
    --shadow-slider: 0 1px 2px oklch(0 0 0 / 0.35);
    --shadow-btn: 0 1px 2px oklch(0 0 0 / 0.40);
    --shadow-btn-hover: 0 4px 14px oklch(0 0 0 / 0.50);
  }

  /* 品牌图卡片阴影加深 */
  .auth-brand-bg {
    box-shadow:
      0 24px 60px oklch(0 0 0 / 0.50),
      0 4px 16px oklch(0 0 0 / 0.30);
  }

  /* GitHub 图标近黑色，暗色下悬停反白保持可辨 */
  .auth-oauth-btn--github:hover .auth-oauth-icon {
    color: oklch(0.95 0.005 260);
  }

  /* 扫码状态遮罩与提示色 */
  .auth-qr-box.is-opened {
    border-color: oklch(0.78 0.15 150);
    box-shadow: 0 0 0 3px oklch(0.78 0.15 150 / 0.22);
  }

  .auth-qr-scanned {
    background: oklch(0.21 0.012 260 / 0.94);
  }

  .auth-qr-scanned-icon {
    color: oklch(0.78 0.15 150);
  }

  .auth-qr-scanned-text {
    color: oklch(0.82 0.12 150);
  }

  .auth-qr-mask {
    background: oklch(0.21 0.012 260 / 0.96);
  }
}

/* ====== 降低动效偏好 ====== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ====== Cloudflare Turnstile 人机验证 ====== */
.auth-captcha {
  margin: 4px 0 16px;
  min-height: 65px;
  display: flex;
  justify-content: center;
}

.auth-captcha[hidden] {
  display: none;
}

.auth-captcha iframe {
  border-radius: 8px;
}
