/* ============================================================
   login.css — 登录页（M2）
   ------------------------------------------------------------
   登录页是**独立入口**：不带外壳（无顶栏 / 侧边栏 / tabbar），
   所以这些样式不进 shell.css —— 按 §5.1 分层规则，它们只在登录页成立。
   视觉沿用 book 的登录卡（白色卡片 + 1px 描边 + 12px 圆角 + 墨黑主按钮）。
   ============================================================ */

/* ---- §0 页面基底（壳外页面必须自带，2026-09-17）----
   本页是全站**唯一不引 shell.css** 的入口，而 shell.css §2 的页面基底
   （`* { box-sizing: border-box }`）正是随外壳下发的 ⇒ 本页此前**没有任何基底**。
   后果（用户 2026-09-17 Safari 截图为证）：`.form-input { width:100%; padding:0 10px; border:1px }`
   在 content-box 下宽度恒 = 内容宽 + 22px ⇒ 右缘超出登录卡 21 − 卡片水平内距：
     - 视口 > 380px：内距 = --pad-x-lg(20) ⇒ 溢出 1px（肉眼看不出，所以这 Bug 藏了很久）
     - 视口 ≤ 380px：媒体查询把内距换成 --pad-x-sm(12) ⇒ 溢出涨到 9px，输入框明显戳出卡片
   ⚠️ 不是 WebKit 独有 —— 桌面 Chrome 把窗口拖到 ≤380px 一样复现（已用真浏览器对拍过），
      只是用户在 Safari 窄窗上先看到了。
   ⇒ 规则：**不引 shell.css 的页面必须自带这一行**，与 `design-system.html` 的内联同名声明同源。
      门禁：check-login.cjs 段 9（声明级）+ check-login-browser.cjs（几何级，窄视口）。 */
* { box-sizing: border-box; }

body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
  background: var(--dt-bg);
}

.login-card {
  width: 100%;
  max-width: 380px;
  padding: var(--pad-card-lg) var(--pad-x-lg);
  background: var(--dt-raised);
  border: 1px solid var(--dt-card-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.login-logo { display: flex; justify-content: center; }
.login-logo svg { width: 48px; height: 48px; }

.login-title {
  /* 第 102 批：下边距由 0 改为 `--gap-section`（分区块间距）——
     原来标题与第一个输入框之间的距离由下一行的 `.login-sub` 撑起来
     （`margin: 4px 0 var(--gap-section)`），该描述行删掉后若不补偿，
     两个盒子（标题 mb 0 ⊕ 表单 mt 0）会相邻塌陷成 0 ⇒ 标题贴住「用户名」。
     现由标题自带这一档间距，实测标题底 → 用户名标签顶 = 24px（原 45px）。 */
  margin: var(--gap-card) 0 var(--gap-section);
  font-size: var(--fs-heading);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  text-align: center;
  color: var(--dt-text1);
}

.form-group { margin-bottom: var(--gap-card); }

.form-label {
  display: block;
  margin-bottom: var(--sp-6);
  font-size: var(--fs-caption);
  color: var(--dt-text2);
}

.form-input {
  width: 100%;
  height: 36px;
  padding: 0 var(--sp-10);
  border: 1px solid var(--dt-border);
  border-radius: var(--radius-md);
  background: var(--dt-raised);
  color: var(--dt-text1);
  font-size: var(--fs-input);
  outline: none;
  transition: border-color .15s, box-shadow .15s;
}
.form-input:focus {
  border-color: var(--dt-accent-border);
  box-shadow: 0 0 0 3px var(--dt-accent-glow);
}
.form-input[readonly] {
  background: var(--dt-inset);
  color: var(--dt-text2);
}

/* ⚠️ 本页**不加载 shell.css**（登录页独立作用域）⇒ 共享件 `.check-label`
   （shell.css §5b-12）在本页不可达，故此处是**同名复刻**。
   第 64 批由 `.checkbox-label` 改名而来（规则体一字未动）：本页其余复刻件
   （`.form-input` / `.btn` / `.form-group` / `.form-label`…）全部同名，原异名
   `.checkbox-label` 是唯一的例外 ⇒ 统一命名后与共享件对齐（REGISTRY 已登记）。
   多出的 `margin-bottom` 是**处境**：登录表单里它下面紧跟提交按钮。 */
.check-label {
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  margin-bottom: var(--gap-card);
  font-size: var(--fs-caption);
  color: var(--dt-text2);
  cursor: pointer;
}
.check-label input { accent-color: var(--dt-interact); }

.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-6);
  width: 100%;
  height: 36px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  font-size: var(--fs-body);
  font-weight: var(--fw-medium);
  cursor: pointer;
  transition: background .15s, opacity .15s;
}
.btn-primary { background: var(--dt-interact); color: var(--dt-text-inv); }
.btn-primary:hover:not(:disabled) { background: var(--dt-interact-bg); }
/* 禁用态：与 shell.css §5b-2 的 `.btn:disabled` 同款（第 92 批同步）。
   本页不引 shell.css ⇒ 这份副本是登录页唯一的基底，共享档改了就得分头跟上。
   旧写法「`opacity: .55` + 保留色相」：提交钮禁用后是一块**墨黑洗淡的深灰**，
   与全站「禁用 = 中性」的样子不一致，实测字对比度也只有 3.99:1（其中还有
   一大截来自深色底，字反而更亮）。改中性后与其余三档统一 2.34:1。
   ⚠️ 上面 `.btn-primary:hover:not(:disabled)` 的守卫本来就在（本页是全仓守卫的**来源**），
      共享层第 92 批才补上；这里只需对齐配色。 */
.btn:disabled {
  opacity: 1; cursor: not-allowed;
  background: var(--dt-inset); color: var(--dt-text4); border-color: transparent;
}

/* 错误 / 提示条 */
.login-alert {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-6);
  margin-bottom: var(--gap-card);
  padding: var(--sp-8) var(--sp-10);
  border-radius: var(--radius-md);
  font-size: var(--fs-caption);
  line-height: var(--lh-prose);
}
.login-alert[hidden] { display: none; }
.login-alert.is-error {
  background: #fef2f2;
  border: 1px solid #ffc9c9;
  color: #c10007;
}
.login-alert.is-info {
  background: var(--dt-inset);
  border: 1px solid var(--dt-border);
  color: var(--dt-text2);
}
.login-alert code {
  font-family: var(--font-mono);
  font-size: var(--fs-caption);   /* 原 11px（野生档） */
  word-break: break-all;
}

.login-note {
  margin-top: var(--gap-card);
  padding-top: var(--gap-card);
  border-top: 1px solid var(--dt-border);
  font-size: var(--fs-caption);
  line-height: var(--lh-prose);
  color: var(--dt-text4);
  text-align: center;
}
.login-note code { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--dt-text3); }   /* 原 11px（野生档） */

/* 提交中转圈（纯 CSS，不引图标） */
.btn-spinner {
  width: 14px;
  height: 14px;
  border: 2px solid rgba(255, 255, 255, .4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: login-spin .7s linear infinite;
}
@keyframes login-spin { to { transform: rotate(360deg); } }

@media (max-width: 380px) {
  body { padding: var(--sp-16); }
  .login-card { padding: var(--pad-card-lg) var(--pad-x-sm, 16px); }
}
