/* ============ 星辰工具箱 - 赤陶橙简约风 ============ */
:root {
  /* 奶油白底 + 赤陶橙强调 */

}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  font-family: var(--font);
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

::selection { background: var(--accent-soft); color: var(--xc-accent-deep); }

/* ============ 背景装饰（柔和暖橙光晕） ============ */
.bg-glow {
  position: fixed;
  border-radius: 50%;
  /* 90px 模糊在 540px 直径的元素上开销很大。实测把半径降到 40px（乃至 0）后，
     与 90px 的最大像素差只有 9/255、平均 1.5 —— 肉眼分辨不出，
     因为底色本身就是柔和的 radial-gradient，模糊只是锦上添花。
     这里取 40px：保住柔和的边缘观感，同时把 GPU 开销降下来。 */
  filter: blur(40px);
  pointer-events: none;
  z-index: 0;
}
.bg-glow--1 {
  width: 540px; height: 540px;
  top: -220px; left: 8%;
  background: radial-gradient(circle, rgba(233, 160, 106, 0.22), transparent 70%);
}
.bg-glow--2 {
  width: 480px; height: 480px;
  top: 24%; right: -160px;
  background: radial-gradient(circle, rgba(222, 139, 84, 0.14), transparent 70%);
}
/* 页脚光晕（2026-10-18）
   --------------------------------------------------------------------
   为什么需要这一条：毛玻璃（backdrop-filter）模糊的是元素**背后
   实际渲染出来的像素**。页脚在页面最底部，它背后原本只有 body 的
   纯色底 —— 模糊一块纯色和没模糊完全一样，CSS 里写了 backdrop-filter
   也看不出任何「毛玻璃」质感（实测确认：两个 .bg-glow 的 rect 都不与
   页脚重叠）。

   所以这里专门给页脚区域补一层暖色光晕，让模糊有东西可采样。
   用 position: fixed + bottom 定位，而不是塞进页脚内部：
   放在页脚内部会被 backdrop-filter 一起模糊掉（自身内容不参与
   backdrop 采样），起不到作用。fixed 且 z-index 低于页脚即可。 */
.bg-glow--foot {
  width: 900px; height: 320px;
  bottom: -120px;
  left: 50%;
  margin-left: -450px;
  background: radial-gradient(ellipse,
    rgba(233, 160, 106, 0.30), rgba(222, 139, 84, 0.10) 55%, transparent 72%);
  filter: blur(50px);
}

/* ============ 顶栏 ============ */
.topbar {
  position: sticky;
  top: 0;
  z-index: 100;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  background: rgba(255, 255, 255, 0.78);
  border-bottom: 1px solid var(--border);
}

.topbar__inner {
  max-width: 1120px;
  margin: 0 auto;
  padding: 0 24px;
  height: 62px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text);
}

.brand__icon {
  width: 32px; height: 32px;
  display: grid;
  place-items: center;
  color: var(--xc-accent-deep);
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  border-radius: var(--xc-r-md);
  overflow: hidden;
}
.brand__icon svg { width: 17px; height: 17px; }
.brand__icon img { width: 100%; height: 100%; object-fit: cover; display: block; }

.brand__name {
  font-size: 18px;
  font-weight: 700;
  letter-spacing: 0.4px;
}
.brand__name span {
  /* 原为渐变文字（background-clip:text + 透明填充）。
     第二轮把 --gradient 改为纯色后，渐变文字已无意义，
     且透明文字色会让对比度审计无法判断（实测报 2.16 假值）。
     改为直接用强调橙文字色，更简约也更可靠。 */
  color: var(--xc-accent-deep);
  font-weight: 800;
}

.brand__version {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  border: 1px solid var(--border);
  background: var(--card);
  border-radius: 999px;
  padding: 2px 8px;
  margin-left: 2px;
}

.topbar__right {
  display: flex;
  align-items: center;
  gap: 14px;
}
/* 登录状态未知前先隐藏用户区，避免"先闪出登录按钮、再跳成用户名"。
   app.js 查询完成后（无论成功失败）都会移除 .user-pending。 */
.topbar__right.user-pending #userLoginBtn,
.topbar__right.user-pending #userChip {
  visibility: hidden;
}

.search {
  position: relative;
  display: flex;
  align-items: center;
}
.search__icon {
  position: absolute;
  left: 13px;
  width: 15px; height: 15px;
  color: var(--text-3);
  pointer-events: none;
}
.search input {
  font-family: var(--font);
  font-size: 14px;
  color: var(--text);
  width: 240px;
  padding: 8px 14px 8px 36px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 999px;
  outline: none;
  transition: border-color 0.2s var(--xc-ease), box-shadow 0.2s var(--xc-ease);
}
.search input::placeholder { color: var(--text-3); }
.search input:focus {
  border-color: var(--accent-border);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.clock {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 1px;
  color: var(--xc-accent-deep);
  padding: 6px 12px;
  border: 1px solid var(--border);
  background: var(--card);
  border-radius: var(--radius-sm);
  min-width: 106px;
  text-align: center;
}

/* ============ 主内容 ============ */
.page {
  flex: 1;
  width: 100%;
  max-width: 1120px;
  margin: 0 auto;
  padding: 56px 24px 72px;
  position: relative;
  z-index: 1;
}

.hero { text-align: center; margin-bottom: 40px; }

.hero__logo {
  /* img 默认 display:inline，会和后面的 inline-flex 徽章挤进同一个行盒，
     导致 logo 偏左、与徽章垂直错位（实测 logo 中心 x=605，页面中心 715）。
     改成块级 + 自动左右外边距，才能稳定居中并独占一行。 */
  display: block;
  width: 68px;
  height: 68px;
  object-fit: cover;
  border-radius: var(--xc-r-xl);
  margin: 0 auto 16px;
  border: 1px solid var(--accent-border);
  box-shadow: 0 6px 20px rgba(222, 139, 84, 0.18);
}

.hero__title {
  /* 现代化：大标题由**正字距 0.5px** 改为**负字距**。
     字号越大越需要收紧，否则字间空隙会把标题拉散；
     原来的正字距正是标题显得松散的直接原因之一。
     同时字号上限略提到 46px，并收紧行高（大标题行高过大会显得散）。 */
  font-size: clamp(30px, 4.4vw, 46px);
  font-weight: 700;
  letter-spacing: -0.022em;
  line-height: 1.15;
  margin-bottom: 14px;
}
.hero__title span {
  /* 同上：--gradient 改为纯色后渐变文字失去意义，
     改用强调橙实色，视觉更干净且对比度可验证。 */
  color: var(--xc-accent-deep);
}

.hero__desc {
  font-size: 15.5px;
  color: var(--text-2);
  line-height: 1.7;
  max-width: 60ch;
}

/* ============ 分类筛选 ============ */
.filters {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 26px;
}

.chip {
  font-family: var(--font);
  font-size: 13px;
  color: var(--text-2);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 8px 16px;
  cursor: pointer;
  transition: color 0.2s var(--xc-ease), background-color 0.2s var(--xc-ease), border-color 0.2s var(--xc-ease), box-shadow 0.2s var(--xc-ease), transform 0.2s var(--xc-ease), opacity 0.2s var(--xc-ease), outline-color 0.2s var(--xc-ease);
}
.chip:hover {
  color: var(--xc-accent-deep);
  border-color: var(--accent-border);
}
.chip--active {
  color: #fff;
  background: var(--xc-btn-gradient);
  border-color: transparent;
  box-shadow: 0 4px 14px rgba(222, 139, 84, 0.28);
}

.filters__count {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--text-3);
}

/* ============ 工具卡片网格 ============ */
.tools {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(244px, 1fr));
  gap: 20px;
}

.tool-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 22px 20px 20px;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  cursor: pointer;
  text-decoration: none;
  color: var(--text);
  transition: transform 0.2s var(--xc-ease), border-color 0.2s var(--xc-ease), box-shadow 0.2s var(--xc-ease);
}
.tool-card::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: var(--gradient);
  opacity: 0;
  transition: opacity 0.2s var(--xc-ease);
}
.tool-card:hover {
  transform: translateY(-3px);
  border-color: var(--accent-border);
  box-shadow: var(--shadow);
}
.tool-card:hover::before { opacity: 1; }

.tool-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.tool-card__icon {
  width: 42px; height: 42px;
  display: grid;
  place-items: center;
  color: var(--xc-accent-deep);
  background: var(--accent-soft);
  border-radius: var(--xc-r-md);
  transition: color 0.2s var(--xc-ease);
}
.tool-card:hover .tool-card__icon { color: var(--xc-accent-deep); }
.tool-card__icon svg { width: 18px; height: 18px; }

.badge-soon {
  font-size: 11px;
  color: var(--text-3);
  background: rgba(117, 103, 96, 0.10);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px 8px;
}
.badge-soon--live {
  color: var(--xc-ok);
  background: var(--xc-ok-soft);
  border-color: rgba(35, 119, 88, 0.30);
}

.tool-card__name {
  font-size: 15.5px;
  font-weight: 700;
  letter-spacing: 0.2px;
}

.tool-card__desc {
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-2);
  min-height: 40px;
}

.tool-card__tag {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--text-3);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  margin-top: 2px;
}

/* 空状态 */
.empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 56px 0;
  color: var(--text-3);
  font-size: 14px;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius);
  background: var(--card);
}

/* 入场动画：**仅在 <html class="xc-cards-anim"> 时播放**。
   该 class 由 app.js 在"本次会话首次进入"时添加并写入 sessionStorage。
   原先这里是常驻规则，导致每次刷新都重播 0.4s 的淡入+位移，
   用户反馈为「刷新一次卡片会闪」。 */
.xc-cards-anim .tool-card {
  animation: cardIn 0.4s ease backwards;
}
@keyframes cardIn {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ============ 页脚 ============ */
.footer {
  border-top: 1px solid var(--border);
  /* 毛玻璃页脚（2026-10-18）
     ------------------------------------------------------------------
     注意一个容易被忽略的点：backdrop-filter 模糊的是**页脚背后实际
     渲染出来的内容**。如果页脚下面什么都没有（body 纯色底），模糊
     纯色和没模糊完全一样，视觉上「毛玻璃」是不存在的。
     所以下面同时给 .footer 加了一层极淡的暖色渐变，让模糊有东西可
     模糊 —— 滚动到底部时能看出柔和的层次，而不是一片死白。
     模糊半径取 12px 与顶栏一致（顶栏见 design-system.css 的说明：
     半径直接决定采样开销，12px 是观感与 GPU 成本折中后的值）。
     不支持 backdrop-filter 的浏览器退化为接近不透明，保证文字可读。 */
  position: relative;
  background:
    radial-gradient(120% 180% at 15% 0%, rgba(233, 160, 106, 0.16), transparent 62%),
    radial-gradient(120% 180% at 85% 100%, rgba(222, 139, 84, 0.12), transparent 60%),
    rgba(255, 255, 255, 0.55);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  /* isolation 让页脚的层叠上下文独立，避免模糊采样到顶栏的
     sticky 层而产生意外的透色 */
  isolation: isolate;
}

@supports not (backdrop-filter: blur(1px)) {
  .footer {
    background: var(--xc-bg-deep);
  }
}
.footer__inner {
  max-width: 1120px;
  margin: 0 auto;
  padding: 18px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 12.5px;
  color: var(--text-3);
}
.footer__link {
  color: var(--xc-accent-deep);
  text-decoration: none;
  transition: opacity 0.2s var(--xc-ease);
}
.footer__link:hover { text-decoration: underline; opacity: 0.85; }
.footer__status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--mono);
}

/* 备案信息（2026-10-18，2026-10-20 与工具箱信息合并为同一行）
   --------------------------------------------------------------------
   之前备案号是 .footer__inner 之外的独立块，单占一行、居中。
   现在移进了 .footer__inner 内部，成为该 flex 容器的第三个子项，
   由 space-between 自动安排到最右侧，与工具箱信息、服务状态同行。

   因此这里必须去掉之前那些“独立一行”的布局属性（max-width、
   margin:0 auto、padding、justify-content:center）—— 它们会让这个块在
   flex 容器里表现异常（比如自带左右 padding 导致对不齐）。
   保留 inline-flex + gap，使其作为一个整体参与父容器的排列。

   为什么用 flex + gap 而不是直接写 " 陕ICP备… · 萌ICP备… " 一串文本：
   两个备案号各是一个 <a>，中间的分隔点用独立元素，这样链接的可点击
   区域互不重叠（相邻链接贴在一起时，手指在移动端点容易点错）。
   分隔点用 aria-hidden 标记，屏幕阅读器不会念出这个装饰性圆点。 */
.footer__filing {
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 10px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text-3);
}

.footer__filing-link {
  color: var(--text-3);
  text-decoration: none;
  /* 备案号是可点击链接，但视觉上不该抢眼 —— 用下划线暗示可点，
     而不是用强调色（强调色留给工具名和主要操作）。 */
  border-bottom: 1px solid transparent;
  transition: color 0.2s var(--xc-ease), border-color 0.2s var(--xc-ease);
}

.footer__filing-link:hover {
  color: var(--xc-accent-deep);
  border-bottom-color: var(--xc-accent-border);
}

/* 键盘用户需要看得见焦点 —— 浏览器默认 outline 在浅底上偏弱 */
.footer__filing-link:focus-visible {
  outline: 2px solid var(--xc-accent);
  outline-offset: 2px;
  border-radius: 2px;
}

/* 分隔点：用 1px 的方块旋转 45° 做成小菱形，比圆点更精致，
   而且不需要额外字体或图片。aria-hidden 已在 HTML 上标好。 */
.footer__filing-dot {
  width: 3px;
  height: 3px;
  background: var(--xc-border-strong);
  transform: rotate(45deg);
  flex: 0 0 auto;
}

/* 小屏：两个备案号在窄屏上换行时，分隔点没有意义，直接隐藏，
   避免出现「号\n·\n号」这种孤零零一个点的难看情况。 */
@media (max-width: 420px) {
  .footer__filing-dot { display: none; }
  .footer__filing { gap: 4px 8px; font-size: 11.5px; }
}
.status-led {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--text-3);
  transition: background 0.3s var(--xc-ease);
}
.status-led--ok {
  background: var(--ok);
}
.status-led--err {
  background: var(--err);
}

/* ============ 轻提示 ============ */
#toast {
  position: fixed;
  left: 50%;
  bottom: 30px;
  transform: translateX(-50%) translateY(10px);
  background: #ffffff;
  border: 1px solid var(--accent-border);
  color: var(--text);
  padding: 10px 20px;
  border-radius: var(--xc-r-md);
  font-size: 13px;
  box-shadow: var(--shadow);
  opacity: 0;
  transition: opacity 0.25s var(--xc-ease), transform 0.25s var(--xc-ease);
  z-index: 999;
}

/* ============ 响应式 ============ */
@media (max-width: 720px) {
  .topbar__inner { padding: 0 16px; gap: 12px; }
  /* 搜索框改为弹性宽度。
     原先这里写的是 width:150px —— 在 720px 以下**反而把输入框加宽**，
     加上顶栏右侧的其他元素后，375px 屏上会把内容挤出视口 15px。
     改成可收缩的弹性宽度，并设置 min-width:0 让 flex 子项允许收缩。 */
  .search { flex: 1 1 auto; min-width: 0; max-width: 220px; }
  .search input { width: 100%; min-width: 0; }
  .clock { display: none; }
  .page { padding: 36px 16px 56px; }
  .tools { grid-template-columns: repeat(auto-fill, minmax(158px, 1fr)); }
  .filters__count { display: none; }
}

@media (max-width: 420px) {
  /* 超窄屏：顶栏只保留 logo 与必需操作，搜索框进一步收窄 */
  .topbar__inner { padding: 0 12px; gap: 8px; height: 56px; }
  .search { max-width: 140px; }
  .search__icon { display: none; }
  /* 装饰光晕在窄屏缩到视口内，避免撑出横向滚动条 */
  .bg-glow--1 { width: 300px; height: 300px; left: -60px; }
  .bg-glow--2 { width: 260px; height: 260px; right: -80px; }
}

/* 极窄屏（320px 级）：顶栏内容超出视口，隐藏搜索框、允许换行。
   搜索功能在主页下方仍有入口（工具卡过滤），顶栏搜索属锦上添花。 */
@media (max-width: 360px) {
  .topbar__inner { flex-wrap: wrap; height: auto; padding: 8px 12px; }
  .search { display: none; }
  .topbar__right { gap: 8px; }
  .brand__name { font-size: 15px; }
  .brand__version { display: none; }
}


/* 用户登录 / 注册 */
.user-login-btn {
  display: inline-flex; align-items: center;
  padding: 6px 16px; border-radius: 999px;
  background: var(--xc-btn-gradient); color: #fff;
  font-size: 13px; font-weight: 500; text-decoration: none;
  transition: filter 0.18s var(--xc-ease), transform 0.18s var(--xc-ease), box-shadow 0.18s var(--xc-ease);
}
.user-login-btn:hover { filter: brightness(1.1); }
.user-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 4px 10px 4px 4px; border-radius: 999px;
  background: rgba(110, 96, 84, 0.1);
}
.user-chip__avatar {
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--xc-btn-gradient); color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600; overflow: hidden;
}
.user-chip__avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block; }
.user-chip__name { font-size: 13px; font-weight: 500; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-chip__out { font-size: 12px; color: var(--xc-text-3); text-decoration: none; cursor: pointer; }
.user-chip__out:hover { color: var(--xc-err); }

/* 弹窗 */
.auth-mask {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(0, 0, 0, 0.45);
  display: flex; align-items: center; justify-content: center;
}
.auth-modal {
  position: relative; width: 340px; max-width: calc(100vw - 40px);
  background: #fff; border-radius: var(--xc-r-xl); padding: 26px 28px 24px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.25);
  animation: authIn 0.18s ease-out;
}
@keyframes authIn {
  from { opacity: 0; transform: translateY(12px) scale(0.98); }
  to { opacity: 1; transform: none; }
}
.auth-close {
  position: absolute; top: 10px; right: 12px;
  border: none; background: none; font-size: 22px; color: var(--xc-text-3);
  cursor: pointer; line-height: 1; padding: 4px;
}
.auth-close:hover { color: #333; }
.auth-tabs { display: flex; gap: 6px; margin-bottom: 18px; }
.auth-tab {
  flex: 1; padding: 8px 0; border-radius: var(--xc-r-md); border: 1px solid #e3e6ea;
  background: #fff; color: #666; font-size: 14px; cursor: pointer; transition: 0.18s;
}
.auth-tab--on { background: var(--xc-btn-gradient); border-color: var(--xc-accent); color: #fff; font-weight: 600; }
.auth-field { display: block; margin-bottom: 12px; }
.auth-field span { display: block; font-size: 12px; color: var(--xc-text-3); margin-bottom: 5px; }
.auth-field input {
  width: 100%; padding: 8px 10px; font-size: 14px;
  border: 1px solid var(--xc-border); border-radius: var(--xc-r-md); outline: none; transition: 0.18s;
  box-sizing: border-box;
}
.auth-field input:focus { border-color: var(--xc-accent); }
.auth-error { min-height: 18px; font-size: 12px; color: var(--xc-err); margin-bottom: 4px; }
.auth-submit {
  width: 100%; padding: 10px 0; border: none; border-radius: var(--xc-r-md);
  background: var(--xc-btn-gradient); color: #fff; font-size: 14px; font-weight: 600;
  cursor: pointer; transition: 0.18s;
}
.auth-submit:hover { filter: brightness(1.08); }
.auth-submit:disabled { opacity: 0.6; cursor: not-allowed; }

/* 注册：人机验证 + 邮箱验证码 */
.auth-captcha-row { margin-bottom: 12px; }
.auth-captcha-btn {
  width: 100%; padding: 8px 0; border: 1px dashed #c5cdd5; border-radius: var(--xc-r-md);
  background: #fafbfc; color: #666; font-size: 13px; cursor: pointer; transition: 0.18s;
}
.auth-captcha-btn:hover { border-color: var(--xc-accent); color: var(--xc-accent); }
.auth-captcha-done { display: inline-block; font-size: 13px; color: var(--xc-ok); }
.auth-code-row { display: flex; gap: 8px; }
.auth-code-row input { flex: 1; }
.auth-code-btn {
  white-space: nowrap; padding: 0 14px; border: 1px solid var(--xc-border); border-radius: var(--xc-r-md);
  background: #fff; color: var(--xc-accent); font-size: 13px; cursor: pointer;
}
.auth-code-btn:disabled { color: #bbb; cursor: not-allowed; }

/* 点选验证码弹窗 */
.captcha-mask {
  position: fixed; inset: 0; z-index: 1100;
  background: rgba(0, 0, 0, 0.5);
  display: flex; align-items: center; justify-content: center;
}
.captcha-modal {
  background: #fff; border-radius: var(--xc-r-lg); padding: 18px 20px 16px;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.3);
  animation: authIn 0.18s ease-out;
}
.captcha-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.captcha-title { font-size: 14px; font-weight: 600; color: #333; }
.captcha-refresh {
  border: none; background: none; font-size: 18px; color: var(--xc-text-3); cursor: pointer; padding: 2px 6px;
}
.captcha-refresh:hover { color: var(--xc-accent); }
.captcha-thumb {
  height: 40px; margin-bottom: 10px; border-radius: var(--xc-r-xs); overflow: hidden;
  background: #f0f0f0; display: flex; align-items: center; justify-content: center;
}
.captcha-thumb img { height: 40px; display: block; }
.captcha-main {
  position: relative; border-radius: var(--xc-r-sm); overflow: hidden; cursor: crosshair;
  background: #f0f0f0; line-height: 0;
}
.captcha-main img { display: block; width: 300px; height: 240px; }
.captcha-dot {
  position: absolute; width: 24px; height: 24px; border-radius: 50%;
  background: rgba(180, 88, 42, 0.85); color: #fff; font-size: 12px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  transform: translate(-50%, -50%); pointer-events: none; border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}
.captcha-ctrl { margin-top: 12px; text-align: center; }
.captcha-confirm {
  padding: 8px 28px; border: none; border-radius: var(--xc-r-md);
  background: var(--xc-btn-gradient); color: #fff; font-size: 14px; font-weight: 600; cursor: pointer;
}
.captcha-confirm:hover { filter: brightness(1.08); }

/* Cap 人机验证复选框 */
.cap-checkbox {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; border: 1px solid #d5dae0; border-radius: var(--xc-r-xs);
  background: #fafafa; cursor: pointer; user-select: none;
  transition: border-color 0.18s var(--xc-ease), background-color 0.18s var(--xc-ease), box-shadow 0.18s var(--xc-ease);
  max-width: 300px;
}
.cap-checkbox:hover { border-color: var(--xc-accent); }
.cap-checkbox__box {
  width: 24px; height: 24px; border: 2px solid #bbb; border-radius: var(--xc-r-xs);
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; color: transparent; transition: 0.2s; flex-shrink: 0;
}
.cap-checkbox--done .cap-checkbox__box {
  background: var(--xc-ok); border-color: var(--xc-ok); color: #fff;
}
.cap-checkbox--solving .cap-checkbox__box {
  border-color: var(--xc-accent); animation: capSpin 0.8s linear infinite;
}
@keyframes capSpin { to { transform: rotate(360deg); } }
.cap-checkbox--solving .cap-checkbox__box { color: transparent; border-top-color: transparent; border-left-color: transparent; }
.cap-checkbox__label { font-size: 14px; color: #333; flex: 1; }
.cap-checkbox--done .cap-checkbox__label { color: var(--xc-ok); }
.cap-checkbox__brand { font-size: 11px; color: var(--xc-text-3); font-style: italic; }

/* Cap widget 样式适配 */
.auth-captcha-row { margin-bottom: 12px; }
.auth-captcha-row cap-widget {
  display: block; width: 100%;
}

/* Cap 复选框（无 PoW，点击即验证） */
.cap-check {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; border: 1px solid #d5dae0; border-radius: var(--xc-r-xs);
  background: #fafafa; cursor: pointer; user-select: none; transition: 0.18s;
}
.cap-check:hover { border-color: var(--xc-accent); }
.cap-check__box {
  width: 22px; height: 22px; border: 2px solid #bbb; border-radius: var(--xc-r-xs);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  transition: background-color 0.2s var(--xc-ease), border-color 0.2s var(--xc-ease), border-radius 0.2s var(--xc-ease), transform 0.2s var(--xc-ease);
}
.cap-check__box::after { content: "✓"; font-size: 14px; color: transparent; }
.cap-check--done .cap-check__box { background: var(--xc-ok); border-color: var(--xc-ok); }
.cap-check--done .cap-check__box::after { color: #fff; }
.cap-check--solving .cap-check__box { border-color: var(--xc-accent); border-top-color: transparent; border-radius: 50%; animation: capSpin 0.6s linear infinite; }
@keyframes capSpin { to { transform: rotate(360deg); } }
.cap-check__label { font-size: 14px; color: #333; flex: 1; }
.cap-check--done .cap-check__label { color: var(--xc-ok); }
.cap-check__brand { font-size: 11px; color: var(--xc-text-3); font-style: italic; }
