/* ============================================================
   auth.css —— 登录 / 注册 / 忘记密码页（v28 A1 重建，v62 风格改版）
   1. 页面骨架（.auth-page 浅底 + .auth-card 白卡 + 页头）
   2. 页签 / 登录方式切换 / 表单字段 / 验证码行 / 提示
   3. 协议勾选行 + 协议全文弹层（.auth-agreement，z-index 见 layout.css §6 层级表：750）
   注：本页同时加载 base.css（CSS 变量与 .btn 组件）与 layout.css（层级表登记），
       本文件不书写任何 z-index（层级统一在 layout.css 底部「层级表」维护）。

   v62（需求 1）：视觉改为**广告落地页同款**（css/onboarding.css 是风格源）——
     浅底 #F5F7FF + 斜切渐变色带（蓝 #4F7BFF / 紫 #7C4DFF / 青 #22C9C0，.12 透明度）
     + 品牌行（深墨标 + 名称）+ 双色渐变大标题 + 白卡 18px 圆角 + 紫蓝渐变主按钮。
     ⚠️ 本页**刻意不走主题 CSS 变量**（不随 data-theme 变化）：
     它的定位是"广告页 → 登录页"同一视觉，与名片主题无关；
     主按钮用字面色值覆盖 .btn-primary（否则会跟着名片主题变蓝/绿/红）。
     表单结构、类名、id 一律未动（脚本与 QA 断言依赖）。
   ============================================================ */

/* ---------- 1. 页面骨架 ---------- */
/* v32 滚动修复：.auth-page 原为 min-height:100vh——随内容变高、无固定高度，
   自带 overflow-y:auto 永不触发且 body（base.css）禁滚 → 小屏表单超高时
   底部（注册按钮/协议区）不可达。改为固定 height:100vh/100dvh 让内部滚动
   生效；align-items 由 center 改 flex-start + 卡片 margin:auto 居中——
   避免 flex 居中在内容超高时把卡片顶部裁出可视区（可滚但滚不到顶的经典坑）。 */
.auth-page {
  position: relative;
  height: 100vh;
  height: 100dvh;
  display: flex;
  /* v151（需求一）：ICP 页脚印迁出本页 ⇒ 本页布局回到 v149 原样
     （v150 曾临时改 row → column 以便页脚贴底；页脚移走后横向排列恢复无副作用）。 */
  align-items: flex-start;
  justify-content: center;
  padding: 24px 16px calc(24px + var(--safe-bottom));
  background:
    radial-gradient(900px 460px at 100% -12%, rgba(124, 77, 255, .10), transparent 62%),
    radial-gradient(760px 420px at -10% 8%, rgba(79, 123, 255, .10), transparent 60%),
    #F5F7FF;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overflow-x: hidden;
}

/* 斜切渐变色带（装饰，不接收指针事件；复刻广告页 .ob-strip 的 100deg 三色带） */
.auth-strip {
  position: absolute;
  left: -60px;
  right: -60px;
  top: 96px;
  height: 150px;
  background: linear-gradient(100deg, #4F7BFF, #7C4DFF 50%, #22C9C0);
  opacity: .12;
  transform: rotate(-8deg);
  pointer-events: none;
}

.auth-card {
  position: relative;
  width: 100%;
  max-width: 400px;
  margin: auto;               /* 空间足够时垂直居中；超高时可完整滚动 */
  background: #FFFFFF;
  border: 1px solid #EDF1FA;
  border-radius: 18px;
  box-shadow: 0 12px 34px rgba(11, 27, 58, .07);
  padding: 26px 22px 22px;
}

/* 品牌行（左「巨」墨标 + 名称）—— 与广告页 .ob-mark 同构
   v171（需求 A）：本行右侧新增「一链三页 + 官方网址」竖排块（.auth-mark-r）。
   v171-1（发布前修副作用）：**本行绝不允许换行**。最初的写法靠 flex-wrap 让网址块
   在窄屏落到第二行，结果 320×568 上品牌行从 34px 撑到 103px（+69），
   `.auth-submit` 的 bottom 从 490.6 掉到 559.6 —— 登录主按钮只剩 8px 露在首屏，
   必须滑动才点得到。功能（把网址带走）不能以牺牲主转化按钮为代价，故改为：
     · ≤380px：`flex-wrap: nowrap` + 品牌名 `min-width:0` 收窄（超宽才出省略号）；
     · ≤340px：整行改横向紧凑版（隐藏「一链三页」胶囊与「官方网址」小标、缩字号），
       并压缩本页纵向节奏（卡片内边距 / 大标题 / 页签与字段间距），
       把省下的高度全部还给表单 —— 目标是 **320×568 首屏可见「登录」按钮**。
   wrap 仍留在基础规则里，只作为极端字号下的最后防线（正常字号不会触发）。 */
.auth-mark {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  row-gap: 8px;
  margin-bottom: 18px;
}
/* v171：右上竖排块（「一链三页」胶囊 + 官方网址块）—— 与广告页 .ob-mark-r 同构 */
.auth-mark-r {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 7px;
  flex: 0 0 auto;
  margin-left: auto;      /* 换行后仍贴右边，不会掉到左下角 */
}
.auth-mark-tag {
  font-size: 10.5px;
  font-weight: 800;
  color: #4F7BFF;
  border: 1.5px solid #D9E1F2;
  border-radius: 999px;
  padding: 5px 10px;
  line-height: 1;
  white-space: nowrap;
}
/* v185：原来是「深蓝圆角方块 + 白字『巨』」，改为老板给的品牌标（正圆，老板已确认）。
   · 尺寸仍是 34×34（品牌行节奏不变）
   · 圆角 11px → 50%（logo 本身是正圆，硬裁成方块会切掉边）
   · 底色改青色兜底：SVG 由 js/pages/auth.js 注入，万一脚本没跑到，
     看到的也是一个青色圆点，不会出现一个空洞（比白底空框体面）。
   · font-* 全部删掉：这里不再有文字。 */
.auth-dotmark {
  width: 34px;
  height: 34px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: #0ED0F4;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.auth-mark-nm {
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: .3px;
  color: #0B1B3A;
}

/* ============================================================
   v171（老板需求 A）：右上角「官方网址」块（点一下复制）
   ------------------------------------------------------------
   类名与配色**逐条照抄** css/onboarding.css 的 .onboarding .ob-site 那一段
   （广告页 v160 已经上线、老板要的就是"和广告页一样"）。
   为什么这里必须再写一遍而不是直接复用：onboarding.css 的每条选择器都前缀了
   .onboarding（那一屏的样式整块隔离，不污染别页），本页没有那个祖先类 ——
   直接加载 onboarding.css 会连带引入几十条与本页无关的规则。故按同一组数值
   在本页作用域（.auth-page）内复刻，数值一字不改（改一处必两边不一致）。
   ============================================================ */
.auth-page .ob-site {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 7px 4px 5px;
  background: #F2F5FF;
  border: 1px solid #DCE5FA;
  border-radius: 11px;
  cursor: pointer;
  /* 按钮元素的 UA 默认字体/内边距必须清掉，否则与广告页那块高度对不上 */
  font-family: inherit;
  text-align: left;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: background .16s ease, border-color .16s ease, transform .16s ease;
}
.auth-page .ob-site:active { background: #E7ECF5; border-color: #C9D6F4; transform: scale(.97); }
.auth-page .ob-site-ico {
  width: 20px;
  height: 20px;
  border-radius: 6px;
  background: linear-gradient(135deg, #4F7BFF, #7C4DFF);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}
.auth-page .ob-site-svg {
  width: 12px;
  height: 12px;
  fill: none;
  stroke: #fff;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.auth-page .ob-site-tx { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.auth-page .ob-site-lb {
  font-size: 8.5px;
  font-weight: 700;
  color: #46536B;
  letter-spacing: .9px;
  line-height: 1;
  text-align: left;
}
.auth-page .ob-site-url {
  font-size: 10.5px;
  font-weight: 800;
  color: #4F7BFF;
  letter-spacing: 0;
  line-height: 1.2;
  /* 网址永远不折行（折行就变成"两串看不懂的字符"）；整块靠 flex-wrap 换行 */
  white-space: nowrap;
  /* min-height 兜住"脚本未执行、网址还没填值"时的行高，避免块塌成一条 */
  min-height: 13px;
  /* 复制失败时程序化选中该文本，故必须允许选择（全局按钮多为 none） */
  -webkit-user-select: text;
  user-select: text;
}

/* 历史 logo 块（v62 起页头改用 .auth-mark，本规则保留不删，供回滚） */
.auth-logo {
  width: 64px;
  height: 64px;
  margin: 0 auto 14px;
  border-radius: 18px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  font-weight: 800;
  letter-spacing: 2px;
  color: #fff;
  background: linear-gradient(135deg, #4F7BFF 0%, #7C4DFF 100%);
  box-shadow: 0 4px 16px rgba(79, 123, 255, .22);
}

/* 双色渐变大标题（与广告页 .ob-h1 em 同款渐变裁字） */
.auth-title {
  font-size: 25px;
  font-weight: 900;
  line-height: 1.3;
  letter-spacing: -.4px;
  color: #0B1B3A;
}
.auth-title em {
  font-style: normal;
  background: linear-gradient(100deg, #4F7BFF, #7C4DFF 55%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.auth-title em.is-alt {
  background: linear-gradient(100deg, #7C4DFF, #22C9C0 70%);
  -webkit-background-clip: text;
  background-clip: text;
}

.auth-sub {
  margin-top: 8px;
  font-size: 12.5px;
  line-height: 1.7;
  color: #46536B;
}

/* v97：应急开关 smsEntry=false 的停用提示条（auth.js 按 __APP_FLAGS__ 打开）。
   [hidden] 显式声明 —— 与 .auth-tip 同因（避免将来给本类加 display 时静默失效）。 */
.auth-notice {
  margin-top: 12px;
  font-size: 12px;
  line-height: 1.65;
  color: #8A5A00;
  background: #FFF7E6;
  border: 1px solid #FFE0A3;
  border-radius: 10px;
  padding: 9px 12px;
}
.auth-notice[hidden] { display: none; }

/* ---------- 2. 页签与表单 ---------- */
.auth-tabs {
  display: flex;
  margin: 20px 0 16px;
  background: #F2F5FF;
  border-radius: var(--radius-btn);
  padding: 4px;
}
.auth-tab {
  flex: 1;
  border: 0;
  background: transparent;
  padding: 9px 0;
  border-radius: var(--radius-btn);
  font-size: 13px;
  font-weight: 600;
  color: #46536B;
  cursor: pointer;
  transition: all .2s ease;
}
.auth-tab.is-active {
  background: #FFFFFF;
  color: #4F7BFF;
  box-shadow: 0 2px 8px rgba(59, 91, 224, .12);
}

/* 登录方式切换（密码 / 验证码） */
.auth-mode-row {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
}
.auth-mode {
  flex: 1;
  border: 1px solid #E7ECF5;
  background: #FFFFFF;
  border-radius: var(--radius-btn);
  padding: 7px 0;
  font-size: 12px;
  font-weight: 600;
  color: #46536B;
  cursor: pointer;
  transition: all .2s ease;
}
.auth-mode.is-active {
  border-color: #B9CCFF;
  color: #4F7BFF;
  background: #F2F5FF;
}

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

.auth-field {
  display: block;
  margin-bottom: 14px;
}
.auth-field > span {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: #46536B;
  margin-bottom: 6px;
}
.auth-field input {
  width: 100%;
  height: 44px;
  padding: 0 14px;
  border: 1px solid #E7ECF5;
  border-radius: 12px;
  font-size: 14px;
  color: #0B1B3A;
  background: #F8FAFF;
  outline: none;
  transition: border-color .2s ease, box-shadow .2s ease;
  -webkit-appearance: none;
  appearance: none;
}
.auth-field input:focus {
  border-color: #4F7BFF;
  background: #FFFFFF;
  box-shadow: 0 0 0 3px rgba(79, 123, 255, .14);
}

/* v37：邮箱行 = 输入框 + 「获取验证码」按钮同一行（按钮在输入框右侧，不在其正下方）。
   原因：Chrome 的自动填充下拉属于浏览器 UI 层，会覆盖邮箱框下方的元素并吞掉第一次点击，
   导致真用户要点两次；把按钮挪到同一行后，下拉再高也盖不到它。 */
.auth-inline-row {
  display: flex;
  gap: 8px;
  align-items: center;
}
.auth-inline-row input { flex: 1; min-width: 0; }
.auth-inline-row > span {
  display: block;
  flex-shrink: 0;
}
.auth-inline-row > span[hidden] { display: none; }
.auth-inline-row .btn {
  flex-shrink: 0;
  white-space: nowrap;
  background: #F2F5FF;
  color: #3B6BF5;
  border: 1px solid #D8E2FF;
}
.auth-inline-row .btn:active { background: #E7EEFF; }

/* v135（需求 2.2）：发码按钮规格 —— **高 44px / 圆角 999px / 最小宽 104px / 等宽数字**。
   ── 为什么要逐条钉死（每一条都对应一个真实可见的缺陷）──
   · 44px：与同行的手机号输入框（.auth-field input 固定 44px）等高。不等高时按钮在
     一行里显得矮一截，且点击热区比输入框小（拇指命中成本更高）。
   · 圆角 999px：与本页 .auth-submit / .auth-rem-go 的胶囊口径统一（--radius-btn）。
   · **最小宽 104px 且切到 60s 时宽度不变**：按钮文字从「发送验证码」（6 字 ≈ 78px）
     变成「60s」（3 字符 ≈ 26px），若不锁宽，按钮会**肉眼可见地缩窄**，
     同一行的手机号输入框被向右撑开/左推 —— 页面在用户眼前"抖一下"，
     像是加载失败闪了一下（老板原话关切点）。锁死宽度后这一下抖动彻底消失。
   · `font-variant-numeric: tabular-nums`（**等宽数字**）：比例数字下「60」比「59」宽，
     每秒宽度变化一点点，三角形越来越明显；等宽数字让每一位占同样宽度。
   · 宽度锁死用 `min-width` + `flex-shrink:0`，padding 左右对称，保证 104px 恒定。 */
.auth-otp-btn {
  min-width: 104px;
  flex-shrink: 0;
  justify-content: center;
  height: 44px;
  padding: 0 12px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  -webkit-font-feature-settings: "tnum";
  font-feature-settings: "tnum";
  letter-spacing: .2px;
}

/* v135（需求 2.2）★ **禁用态必须压过全局的整块变透明** ——
   base.css:84 有 `button:disabled { opacity: .5 }`，而本页发码按钮是**浅底色**
   （背景 #F2F5FF、字色 #3B6BF5，本广告页配色）。opacity .5 会把底色和字色**一起打淡**，
   按钮在白色卡片上几乎"消失" —— 而它此刻正在显示「60s…1s」的倒计时，
   用户看到的是一个越来越淡、几乎看不见的东西 ⇒ 误判为**界面卡死**。
   实测 auth.css 此前零 disabled 覆盖，这一条是本轮补的关键。
   修法：把 opacity 拉回 1，**底色/边框一律保持不变**，只做两件事让"不可点"可读：
     · 字色降一档（#3B6BF5 → #8FA3D8，仍清晰可读，不是灰掉一片）；
     · 字重加到 700（.auth-otp-btn 已设，此处显式重申以防被后续规则覆盖）。
   特异性说明：`.auth-inline-row .btn` 是 (0,2,0)，本条同样是 (0,2,0) 但**写在后面**
   （auth.css 在 base.css 之后加载）⇒ 平局由后者胜出，压得住全局规则。 */
.auth-inline-row .auth-otp-btn:disabled,
button.auth-otp-btn:disabled {
  opacity: 1;
  /* cursor 保留 base.css 的 not-allowed（此处**不覆写**）：
     not-allowed 是"不可点"的标准语义信号，比 default 更有信息量；
     v135 初版在这里写了 cursor:default，把这个信号抹掉了 —— 属误伤，已去掉。 */
  color: #8FA3D8;
  background: #F2F5FF;
  border: 1px solid #D8E2FF;
  box-shadow: none;
  font-weight: 700;
  transform: none;      /* 压掉 .btn:active 的 scale(.96)：禁用态不该有按下反馈 */
}

/* v149（性能）：骨架先行 —— SDK 就绪前的「云端连接中」初始态（data-cloud-pending）。
   auth.html 让三个发码按钮初始 disabled + data-cloud-pending（手机号输入框不受影响，
   页面首屏即可输入）；auth.js 的 initCloud 成功后 activateOtpButtons() 摘除。
   样式直接沿用倒计时禁用态（color/bg/border 同上），无需另设一套 ——
   视觉语义一致：「现在不可点，稍后可用」；且 :disabled 规则已保证不整块变透明。 */
button.auth-otp-btn[data-cloud-pending] { opacity: 1; }

/* v135：发码失败的**行内**红字（紧贴出错那一行，见 auth.html 里三个 .auth-otp-err）。
   为什么不用 toast：toast 浮在页面正中（.toast 宽至 76%）且 2.2s 就消失，
   与"发送验证码"这个按钮隔着半屏；用户看完已经不知道自己错在哪一步。
   为什么不用 #authMsg（页面底部）：它在三个表单的**下方**，倒计时中按钮还在动，
   注意力在手机号那一行 —— 关联性同样很弱。
   行内红字 + 文字链（去登录 / 重试）是唯一能把"哪一步错了 + 下一步点哪里"讲清楚的形态。 */
.auth-otp-err {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.6;
  color: #D0453B;
}
/* [hidden] 必须显式声明：本类给了 display:flex，会盖掉 UA 的 [hidden]{display:none}
   —— 那样"没有错误"时也会占一行空白，把下方字段整体往下推（同 v45 / v131 同款坑）。 */
.auth-otp-err[hidden] { display: none; }
.auth-otp-err-link {
  border: 0;
  background: none;
  padding: 0;
  font-size: 12px;
  font-weight: 700;
  color: #3B6BF5;
  text-decoration: underline;
  cursor: pointer;
}

/* v135（需求 2.3）：底部 12px 灰字「密码忘了？点这里重设」。
   刻意做得**不显眼**（灰字、无边框、无底色）：它是给"真忘密码"的人兜底的，
   绝大多数用户密码是对的，绝不能把它做成一个和登录按钮抢注意力的第二入口。 */
.auth-forgot-row {
  margin-top: 10px;
  text-align: center;
}
.auth-forgot-link {
  border: 0;
  background: none;
  padding: 2px 6px;
  font-size: 12px;
  color: #8A93A6;
  cursor: pointer;
}
.auth-forgot-link:active { color: #4F7BFF; }

/* v135（需求 2.3）：**重设密码面板**（不是第三个页签，展开在登录页内）。
   结构刻意与「协议弹层」同款（head + body），用户不需要重新学一套交互。 */
.auth-subpanel { margin-top: 2px; }
.auth-subpanel[hidden] { display: none; }   /* 同上：.auth-subpanel 无 display 也要兜一层 */
.auth-subpanel-back {
  border: 0;
  background: none;
  padding: 0;
  margin-bottom: 10px;
  font-size: 12.5px;
  font-weight: 600;
  color: #4F7BFF;
  cursor: pointer;
}
.auth-subpanel-back:active { opacity: .7; }
.auth-subpanel-title {
  font-size: 17px;
  font-weight: 800;
  color: #0B1B3A;
  margin-bottom: 12px;
}

/* v135（需求 2.3）：密码错误弹窗的两颗按钮 —— **次在左 / 主在右，等宽 44px 胶囊**。
   ⚠ 弹窗 DOM 由 core/ui.js 的 confirmDialog 生成（class名 .confirm-box /
     .confirm-actions / .btn-ghost / .btn-primary），本页只能**覆写**它的样式，
     不能改 ui.js（那是全站共用的，动了会波及名片页/后台页的所有确认框）。
   覆写口径：
     · 两颗 flex:1（base.css 已有 .confirm-actions .btn{flex:1}）⇒ 等宽；
     · 高度锁 44px（base.css 的 .btn 是 padding 撑出来的 ~40px，矮一截）；
     · 圆角 999px（base.css 用 var(--radius-btn) 已是 999px，此处显式重申防主题覆写）；
     · 间距 12px（base.css .confirm-actions 已有 gap:12px）；
     · 次按钮 = .btn-ghost（透明底 + 1px 描边）、主按钮 = .btn-primary（实底 + 投影），
       与产品口径逐字一致 —— **只调几何，不改配色分工**。
   为什么按钮文案是「知道了」/「更改密码」而不是「取消」/「确定」：
   「取消」会被理解成"放弃这次登录"，而它真实的语义是"我知道了，回去改密码"；
   主按钮直说「更改密码」，用户不需要猜点下去会发生什么。 */
#overlayRoot .confirm-box { max-width: 320px; }
#overlayRoot .confirm-title {
  font-size: 16px;
  font-weight: 800;
  color: #0B1B3A;
}
#overlayRoot .confirm-message {
  font-size: 13px;
  line-height: 1.75;
  color: #46536B;
  margin-top: 10px;
  /* v135（需求 3 缺陷修复，产品经理实测发现）：confirmDialog 用 el() 的 `text` 属性写入，
     HTML 里 `\n` 会被折叠成空格 ⇒ 密码错误弹窗的两行文案糊成一行、
     与设计稿「两行」不符。加 pre-line 让 `\n` 正常换行。
     ⚠ 只加在 auth 专属覆盖里（#overlayRoot 前缀 + 已有覆盖块），**不改 base.css** ——
        全站 36 处 confirmDialog 调用方一律不动，避免影响其它页面弹窗的既有折行。 */
  white-space: pre-line;
}
#overlayRoot .confirm-actions { gap: 12px; }
#overlayRoot .confirm-actions .btn {
  flex: 1;
  height: 44px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .3px;
}
/* 轻提示（发送成功 / 垃圾邮件提醒） */
.auth-tip {
  margin-top: 8px;
  font-size: 11px;
  line-height: 1.6;
  color: #46536B;
  background: #F2F5FF;
  border-radius: 8px;
  padding: 6px 10px;
}

/* v45（用户需求 1）：登录方式互斥显示的真修复——
   .auth-field 有显式 display:block，会覆盖 [hidden] 的 UA display:none，
   导致「验证码登录」下密码栏照显、「密码登录」下验证码栏照显（T6-2 / v39 S9 同款坑）。
   显式声明 [hidden] 规则后，auth.js switchLoginMode 的既有 hidden 切换即真实生效。 */
.auth-field[hidden] { display: none; }
.auth-tip[hidden] { display: none; }

/* v88：注册通道的两个块（邮箱 / 手机号）——显式声明 [hidden] 生效，
   与上面 .auth-field 同因（避免将来给块加 display 时静默失效，v45 同款坑）。 */
#signupEmailBlock[hidden],
#signupPhoneBlock[hidden] { display: none; }

/* v62：主按钮改为广告页同款紫蓝渐变（**字面色值覆盖** .btn-primary，
   否则会跟着名片主题变色——本页的风格与名片主题无关） */
.auth-submit {
  width: 100%;
  height: 46px;
  margin-top: 4px;
  font-size: 15px;
  font-weight: 800;
  border-radius: 14px;
  background: linear-gradient(100deg, #4F7BFF, #7C4DFF);
  color: #fff;
  box-shadow: 0 10px 22px rgba(79, 123, 255, .30);
}

.auth-msg {
  min-height: 20px;
  margin-top: 12px;
  font-size: 12px;
  line-height: 1.6;
  text-align: center;
  color: #E0673C;
  word-break: break-all;
}
.auth-msg.is-ok { color: #12A594; }

.auth-back {
  display: block;
  margin-top: 14px;
  text-align: center;
  font-size: 12px;
  color: #8A93A6;
  text-decoration: none;
}
.auth-back:active { color: #4F7BFF; }
/* v205：`.auth-back` 有作者样式 display:block，会盖掉 UA 的 [hidden]{display:none}。
   裸进登录页时这条链接要被隐藏（否则点了又弹回本页），所以必须有这条兜底规则。
   ⚠ 同类坑记两次：v177 的 .ed-tab-badge 也是这个成因。以后凡是对带 display 的元素用
   hidden 属性，都要顺手补一条 `[hidden]{display:none}`。 */
.auth-back[hidden] { display: none; }

/* v132（需求 4）：页面版本小字 —— 排查「真机改版没生效＝旧缓存」用 */
.auth-version {
  margin-top: 10px;
  text-align: center;
  font-size: 11px;
  color: #A6ADBF;
  letter-spacing: 1px;
}

/* ---------- 3. 协议勾选行与全文弹层 ---------- */
.auth-agree-row {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 2px 0 14px;
  font-size: 11px;
  line-height: 1.7;
  color: #8A93A6;
  cursor: pointer;
}
.auth-agree-row input[type="checkbox"] {
  width: 15px;
  height: 15px;
  margin-top: 2px;
  flex-shrink: 0;
  accent-color: #4F7BFF;
}
.auth-link {
  border: 0;
  background: none;
  padding: 0;
  font-size: 11px;
  color: #4F7BFF;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
}

/* 协议全文弹层（z-index 750 在 layout.css §6 层级表登记，此处不书写 z-index） */
.auth-agreement {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px 16px;
}
.auth-agreement[hidden] { display: none; }
.auth-agreement-mask {
  position: absolute;
  inset: 0;
  background: rgba(10, 31, 66, .55);
}
.auth-agreement-card {
  position: relative;
  width: 100%;
  max-width: 420px;
  max-height: 76vh;
  display: flex;
  flex-direction: column;
  background: var(--c-card);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-float);
  overflow: hidden;
}
.auth-agreement-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px 10px;
  border-bottom: 1px solid var(--c-line);
}
.auth-agreement-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--c-text);
}
.auth-agreement-close {
  border: 0;
  background: none;
  font-size: 22px;
  line-height: 1;
  color: var(--c-text-2);
  cursor: pointer;
  padding: 0 4px;
}
.auth-agreement-body {
  flex: 1;
  overflow-y: auto;
  padding: 12px 16px;
  font-size: 12px;
  line-height: 1.9;
  color: var(--c-text-2);
  white-space: pre-wrap;
}
.auth-agreement-foot {
  padding: 10px 16px calc(12px + var(--safe-bottom));
  border-top: 1px solid var(--c-line);
  text-align: center;
}

/* ---------- v131：协议弹窗 consent 形态（未勾选点「获取验证码」触发） ----------
   醒目勾选条：22px 复选框 + 13px 加粗正文 + 11px 副文案；本形态下隐藏「我已知晓」
   按钮（.is-consent 由 auth.js 开关）。勾选即视为同意并自动关闭弹窗续跑发码。 */
/* ⚠ 默认必须是 display:none —— 该 <label> 带着 hidden 属性常驻 DOM，若这里写 display:flex
   会**盖掉 UA 的 [hidden]{display:none}**，于是「阅读形态」（点《服务协议》链接）也会把
   这条同意勾选条一起露出来（v131 自检实测到的真实缺陷）。显隐唯一由 .is-consent 决定。 */
.auth-consent-row {
  display: none;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 2px;
  padding: 12px 13px;
  border-radius: 12px;
  background: #F2F5FF;
  border: 1.5px solid #C9D8FF;
  cursor: pointer;
  text-align: left;
}
/* consent 形态才显示（与 auth.js 的 consentRow.hidden 双向一致，互为兜底） */
.auth-agreement.is-consent .auth-consent-row { display: flex; }
.auth-consent-row:active { background: #E7EEFF; }
.auth-consent-row input[type="checkbox"] {
  width: 22px;
  height: 22px;
  margin-top: 1px;
  flex: none;
  accent-color: #4F7BFF;
}
.auth-consent-tx {
  display: block;
  font-size: 13px;
  line-height: 1.55;
  font-weight: 700;
  color: #0B1B3A;
}
.auth-consent-tx b { color: #4F7BFF; }
.auth-consent-tx i {
  display: block;
  margin-top: 4px;
  font-style: normal;
  font-size: 11px;
  font-weight: 500;
  color: #7C8798;
}
/* consent 形态：隐藏「我已知晓」按钮，只留勾选条 */
.auth-agreement.is-consent .auth-agreement-foot > [data-close-agreement] { display: none; }

/* 窄屏适配（≤360px）：卡片与字段压缩 */
@media (max-width: 360px) {
  .auth-card { padding: 24px 18px 18px; }
  .auth-inline-row .btn { padding: 9px 10px; }
  /* v171（需求 A）：网址块在极窄屏再收紧 1px 内边距（仍显示完整 https:// 前缀，
     不做省略号截断）。v171-1：本档**不再换行**，见下面两个媒体块的说明。 */
  .auth-mark-nm { font-size: 13px; letter-spacing: 0; }
  .auth-mark-r { gap: 6px; }
  .auth-page .ob-site { padding: 4px 6px 4px 5px; }
}

/* ============================================================
   v171-1（发布前修副作用）：窄屏品牌行**强制单行**
   ------------------------------------------------------------
   问题（QA 实测）：≤360px 时 `.auth-mark` 换行，品牌行 34 → 103px（+69），
     320×568 下 `.auth-submit.bottom` 559.6 > 视口 568 的余量只剩 8px
     ⇒ 登录主按钮基本不可见，必须先滑动。
   治法（两条独立、但必须成对存在）：
     ① ≤380px —— 本行 `nowrap`，同时给品牌名 `min-width:0` + 省略号：
        100% 字号下品牌名宽度够（360 实测 130.5px，整行 290 ≤ 292），**看不出任何变化**；
        只有用户在系统里放大字号（text-size-adjust 130%）时才由品牌名出省略号兜底 ——
        绝不允许它把表单顶下去。
     ② ≤340px —— 直排块改横排紧凑版 + 压缩纵向节奏（见下一个媒体块）。
   为什么不选"把网址块挪到大标题上方另起一行"：那仍然净增一行高度（~30px），
     130% 字号下照样把 CTA 顶出首屏，只是把问题藏起来。
   ============================================================ */
@media (max-width: 380px) {
  .auth-mark { flex-wrap: nowrap; gap: 5px; row-gap: 0; }
  .auth-mark-nm { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 0 1 auto; letter-spacing: 0; }
  .auth-page .ob-site { padding: 4px 5px 4px 5px; }
}

/* ============================================================
   v171-1：≤340px（320×568 这一档）紧凑模式 —— 把高度还给登录按钮
   ------------------------------------------------------------
   取舍（每一条都为"首屏看得见「登录」"服务，别轻易回退）：
     · 网址块改为**横排、单行**（flex-direction:row）：竖排的「胶囊 + 网址块」
       两行在这里放不下，横排后整行高度 34px，与改动前的品牌行等高；
     · 隐藏「一链三页」胶囊与「官方网址」小标、隐藏小地球图标：
       350px 内的横向预算给"品牌名 + 完整 https://vcsl.cn"（需求一要求网址必须在、
       且不省略号截断，只能从装饰元素里腾地方）；
     · 品牌名 12px（原 13px）：让 20 字品牌名在 100% 字号下**不被截断**；
     · 卡片内边距 24/18 → 16/14、大标题 25 → 21px、页签与字段间距收紧：
       合计让出约 100px，320×568 @100% 的 CTA bottom 从 605.6 降到 478.2。
   ⚠️ 输入框高度（44px）与提交按钮高度（46px）**一律不动** —— 这是触控靶子，不是装饰。
   ============================================================ */
@media (max-width: 340px) {
  .auth-mark { margin-bottom: 10px; }
  .auth-mark-r { flex-direction: row; align-items: center; gap: 0; }
  .auth-mark-tag { display: none; }
  .auth-mark-nm { font-size: 12px; }
  .auth-page .ob-site { padding: 3px 7px 3px 6px; gap: 0; }
  .auth-page .ob-site-ico { display: none; }
  .auth-page .ob-site-lb { display: none; }
  .auth-page .ob-site-url { font-size: 10.5px; line-height: 1.1; }
  .auth-card { padding: 16px 14px 14px; }
  .auth-title { font-size: 21px; }
  .auth-tabs { margin: 12px 0 10px; }
  .auth-field { margin-bottom: 10px; }
  .auth-field > span { margin-bottom: 4px; }
  .auth-mode-row { margin-bottom: 10px; }
  .auth-submit { margin-top: 2px; }
}

/* ============================================================
   v63（需求 3）：本设备记忆账号（登录页一键登录）
   配色与本页（v62 广告落地页同款）一致，与名片主题无关（同 .auth-submit 口径）。
   ============================================================ */
.auth-remembered {
  margin-bottom: 14px;
  padding: 10px 10px 6px;
  border: 1px solid #E7ECF5;
  border-radius: 14px;
  background: #F8FAFF;
}
.auth-remembered[hidden] { display: none; }
.auth-rem-tip {
  font-size: 11px;
  font-weight: 600;
  color: #8A93A6;
  letter-spacing: 1px;
  margin: 0 2px 8px;
}
.auth-rem-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 2px;
}
.auth-rem-ava {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: linear-gradient(135deg, #7C4DFF, #4F7BFF);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
}
.auth-rem-mail {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 600;
  color: #17224A;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.auth-rem-go {
  flex: none;
  border: 0;
  border-radius: 999px;
  padding: 7px 13px;
  font-size: 12px;
  font-weight: 700;
  color: #fff;
  background: linear-gradient(100deg, #4F7BFF, #7C4DFF);
  box-shadow: 0 4px 12px rgba(79, 123, 255, .28);
  cursor: pointer;
  transition: transform .15s ease, opacity .2s ease;
}
.auth-rem-go:active { transform: scale(.96); opacity: .92; }
.auth-rem-go[disabled] { opacity: .6; cursor: default; }
.auth-rem-del {
  flex: none;
  width: 26px;
  height: 26px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: #B9C2D4;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}
.auth-rem-del:active { background: #E9EEF9; color: #46536B; }

