/* ==========================================================================
   UU · Design System v4 — 深空 / 宇宙科技（双主题）
   参考语言：企业级招聘门户（首屏大图 + 大标题 + 单色蓝强调 + 图像卡片）

   主题怎么切：
     · 默认 = 暗色（深空 · 地球 · 流星），写在下面 `:root` 里
     · 亮色 = 写在 `[data-theme="light"]` 里，覆盖同名变量
     · 由 base.html 里的一段内联脚本在**首帧之前**把 data-theme 写到 <html> 上，
       所以不会出现"先闪一下暗色再变亮"（这是主题切换最容易翻车的地方）

   ⚠️ 改样式的铁律：**不要再写死颜色**。
   写 rgba(255,255,255,.1) 这种"白色半透明"在暗色下是分隔线、在亮色下就彻底看不见。
   要分隔线用 var(--hair)，要 hover 底用 var(--hover)，要强调文字用 var(--strong)，
   要"深空那片底"用 var(--veil-rgb)（它是 RGB 三元组，配 rgba() 用）。
   ========================================================================== */

:root {
  /* 告诉浏览器原生控件（滚动条、表单、下拉）该用哪套配色 */
  color-scheme: dark;

  /* 深空色阶。
     原来是 #04060C 起（近黑），实测"太暗"—— 在普通显示器上基本看不出层次，
     四个色阶挤在一起都像纯黑。整体抬到**深海军蓝**：底子亮一档，
     相邻色阶的差值也拉开，卡片/面板才浮得起来。 */
  /* 四档的 CIE 亮度 L* 大致是 7 / 11 / 16 / 21 —— 步长均匀，
     面板之间才分得开。原来那组是 0 / 1.6 / 4 / 8.5，
     在普通显示器上四个档几乎都等于纯黑。 */
  --space-0:  #08142B;   /* 页面底 */
  --space-1:  #0E1C3A;   /* 面板 / 卡片 */
  --space-2:  #16264C;
  --space-3:  #1E3160;

  /* 线 / 字 */
  --line:     rgba(255, 255, 255, .14);
  --line-2:   rgba(255, 255, 255, .24);
  --text:     #FFFFFF;
  --text-2:   rgba(232, 238, 250, .78);
  /* 注意：--muted 不是「装饰色」。导航标签、面包屑、表格副行、
     各种提示文字都用它 —— 它必须**能被读**（≥4.5:1）。
     .52 在深底上只有 4.9，配 11px 的小字太勉强。 */
  --muted:    rgba(232, 238, 250, .68);

  /* 唯一强调色（冷冽电光蓝） */
  --accent:       #0F6BFF;
  --accent-lt:    #5EA8FF;
  --accent-hover: #2A80FF;
  --accent-wash:  rgba(15, 107, 255, .12);

  --ok:   #2ED47A;
  --warn: #FFB020;

  /* ---- 语义令牌：主题切换真正要改的就是这一组 ---- */

  /* 深浅无关：强调色上的文字 */
  --on-accent: #fff;

  /* "更亮的文字"：暗色下是纯白，亮色下是近黑 */
  --strong: #fff;
  /* 深色文字的 RGB 三元组，用于 rgba(var(--ink-rgb), .34) 这种半透明文字。
     暗色主题下"次要文字"其实是**浅**色，所以这个名字叫 ink 有点反直觉 ——
     但它代表的是"正文墨色在亮色主题下的样子"，亮色下直接就是墨色本身。 */
  --ink-rgb: 232, 238, 250;
  /* 「深空那片底」的 RGB 三元组，用于各种遮罩 / scrim */
  --veil-rgb: 8, 20, 43;

  /* 压在**图片**上的文字专用的颜色元组。**刻意两套主题同值** ——
     全站唯一一个不跟主题走的文字色，所以亮色块里也不要覆盖它。
     理由：图片本身不跟主题换（研究方向那六张一律是暗调的芯片/机器人/中控室语言），
     压在图片上的字就得跟着图片、而不是跟着页面。用 --ink-rgb 的话，
     亮色主题下会变成近黑字压在暗图上 —— 直接消失（真踩过，"01"整个不见）。 */
  --media-ink: 232, 238, 250;

  /* ---- 侧栏（暗色：深海军蓝）----
     侧栏不跟 --text / --line 走 —— 那套在亮色主题下是"白底近黑字"，
     套到侧栏上就成了"深蓝底 + 近黑字"，看不见。
     所以它自成一套 `--nav-*`；亮色主题里会把这一整套换成亮蓝（见下面 light 块）。 */
  --nav-bg:     #0E1C3A;
  --nav-bg-2:   #08142B;
  --nav-text:   #FFFFFF;
  --nav-text-2: rgba(232, 238, 250, .76);
  --nav-muted:  rgba(232, 238, 250, .50);
  --nav-hair:   rgba(255, 255, 255, .14);
  --nav-hover:  rgba(255, 255, 255, .07);
  --nav-active-bg: var(--accent-wash);
  /* 侧栏底色的"光泽层"。暗色不需要（本来就是深色平面），亮色下是金属的关键 */
  --nav-bg-image: none;
  /* 深底上要用**浅**蓝；--accent-lt 是深蓝，压上去等于没有 */
  --nav-accent: #5EA8FF;

  /* ---- 深色带：首屏 / 页头 ----
     两套主题下首屏都是那片深空（用户的要求），所以它上面的文字永远是白的，
     遮罩永远用深空色。同样不能跟着 --text / --veil-rgb 走。 */
  --band-fg:       #FFFFFF;
  --band-fg-2:     rgba(232, 238, 250, .78);
  --band-muted:    rgba(232, 238, 250, .74);
  --band-veil-rgb: 8, 20, 43;
  /* 深空带上的强调色也要是**浅**蓝：--accent-lt 在亮色主题下是深蓝，压在深空上等于没有 */
  --band-accent: #5EA8FF;
  /* 带子内部的细线（首屏数据条的分隔、带子的上下边）—— 用浅色，不是黑 */
  --band-hair:   rgba(255, 255, 255, .16);

  /* ---- 首屏专用（**跟主题走**，和 --band-* 分开）----
     暗色首屏是深空 → 白字；亮色首屏是明亮的空间站舱内 → 深字。
     页头那边不跟主题走（配图恒暗、字恒白），所以两组必须分开，
     否则亮色下页头标题会变成深字压在暗图上。 */
  --hero-fg:       #FFFFFF;
  --hero-fg-2:     rgba(232, 238, 250, .78);
  --hero-muted:    rgba(232, 238, 250, .74);
  --hero-accent:   #5EA8FF;
  --hero-hair:     rgba(255, 255, 255, .16);
  --hero-veil-rgb: 8, 20, 43;

  /* 分隔线：比 --line 更弱的一档 */
  --hair:   rgba(255, 255, 255, .14);
  --hair-2: rgba(255, 255, 255, .07);

  /* 交互底：hover / 选中的轻微填充 */
  --hover: rgba(255, 255, 255, .09);
  /* 抬高块：码块、徽标里的值这种"比底稍亮一点"的小面 */
  --raise: rgba(255, 255, 255, .09);

  /* 标签页选中态。暗色下靠半透明蓝就够，亮色下必须换成实心蓝，
     否则白字贴在浅底上根本读不出来。 */
  --tab-on-bg: rgba(15, 107, 255, .30);

  /* 语义色的"前景 / 背景 / 描边"三件套。暗色下都是浅色文字，
     亮色下必须换成深色，否则浅底上的浅红等于看不见。 */
  --err-fg: #ffb4b4;  --err-bg: rgba(192, 0, 0, .16);  --err-line: rgba(192, 0, 0, .36);
  --ok-fg:  #9fe0a8;  --ok-bg:  rgba(83, 129, 53, .16); --ok-line:  rgba(83, 129, 53, .40);
  --warn-fg: #ffd79a; --warn-bg: rgba(255, 176, 32, .14); --warn-line: rgba(255, 176, 32, .38);

  /* 浮层投影 */
  --shadow-lg: 0 20px 60px rgba(0, 0, 0, .6);

  /* 首屏底图：暗色是「地球」，亮色是「月球」（在下面的 light 块里换掉）。 */
  --hero-filter: none;

  --sidebar-w: 260px;
  --r:    6px;
  --r-sm: 4px;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB",
          "Microsoft YaHei", Roboto, Helvetica, Arial, sans-serif;
}

/* --------------------------------------------------------------------------
   亮色主题：白纸 + 深蓝侧栏 + 明显的黑边线
   --------------------------------------------------------------------------
   和暗色主题的区别**只在页面主体**，两处是刻意不变的：

     · 侧栏：两套主题都是深蓝（--nav-* 自成一套，不跟着 --text 走）
     · 首屏 / 页头：两套主题都是那片深空（--band-*，白字 + 深空遮罩）

   所以这里只需要换"白纸那部分"的令牌：背景白、文字近黑、**边线用明显的黑色**。
   卡片也是白 —— 层次不再靠底色深浅，而是靠那条黑边（用户要的"边界分明"）。
   -------------------------------------------------------------------------- */
[data-theme="light"] {
  color-scheme: light;

  --space-0: #FFFFFF;   /* 页面底：白 */
  --space-1: #FFFFFF;   /* 面板 / 卡片：也是白，靠黑边分开 */
  --space-2: #F1F3F6;   /* 灰：表头、码块、徽标这类需要一个底色的块 */
  --space-3: #E4E7EC;

  /* 「边界分明的地方用明显的黑色」—— 这里是真的黑，不是淡灰 */
  --line:   rgba(9, 12, 18, .58);
  --line-2: rgba(9, 12, 18, .88);
  --text:   #0A0E14;
  --text-2: rgba(10, 14, 20, .80);
  /* 同上：--muted 承担大量真实文字，白底上要 ≥4.5 → .72（约 6.3:1） */
  --muted:  rgba(10, 14, 20, .72);

  --accent:       #0F6BFF;
  /* 白底上要用够深的蓝。#0946C4 在白底上对比度 7.4，绰绰有余 */
  --accent-lt:    #0946C4;
  --accent-hover: #0A5AE0;
  --accent-wash:  rgba(15, 107, 255, .10);

  --ok:   #12864F;
  --warn: #B3700A;

  --strong: #0A0E14;
  --ink-rgb: 10, 14, 20;

  /* 顶栏玻璃 / 卡片图上的渐变仍是白的 —— 那是"页面"的一部分，
     深空带（首屏、页头）另有 --band-veil-rgb，不在这里。 */
  --veil-rgb: 255, 255, 255;

  --hair:   rgba(9, 12, 18, .20);
  --hair-2: rgba(9, 12, 18, .10);
  --hover:  rgba(9, 12, 18, .06);
  --raise:  rgba(9, 12, 18, .05);

  --tab-on-bg: var(--accent);

  --err-fg: #B3261E;  --err-bg: rgba(192, 0, 0, .07);  --err-line: rgba(192, 0, 0, .30);
  --ok-fg:  #0F7B3E;  --ok-bg:  rgba(18, 161, 80, .09); --ok-line: rgba(18, 161, 80, .32);
  --warn-fg: #8A5200; --warn-bg: rgba(200, 122, 0, .12); --warn-line: rgba(200, 122, 0, .40);

  --shadow-lg: 0 18px 44px rgba(9, 12, 18, .18);

  /* 首屏是深空，两套主题共用一套调色；月球那张已经调成暗色调，这里只补一点饱和度 */
  --hero-filter: saturate(1.05);

  /* 首屏：明亮的空间站舱内 → **深色字 + 浅色遮罩**。
     页头那组 --band-* 保持深空 + 白字，不要动。 */
  --hero-fg:       #0B0F16;
  --hero-fg-2:     rgba(11, 15, 22, .80);
  --hero-muted:    rgba(11, 15, 22, .62);
  --hero-accent:   #0F6BFF;
  --hero-hair:     rgba(11, 15, 22, .16);
  --hero-veil-rgb: 255, 255, 255;

  /* ---- 亮色的侧栏：更亮的蓝 ----
     ⚠️ **只有亮色改**。暗色主题的侧栏保持深海军蓝（:root 里那套），
     这是用户明确要求的：暗色那边一点都不要动。
     底色一亮，它那一套文字/描边/选中底色必须**整套**跟着提 ——
     只改底色的话，白字压在亮蓝上反而更糊。 */
  /* 侧栏：金属灰。上浅下深两档灰 = 金属板最常见的受光方式；
     字是**深色**（压在灰底上），所以下面这一组全是深色，不是白。 */
  --nav-bg:     #DCE0E6;
  --nav-bg-2:   #BFC6D0;
  --nav-text:   #0B0F16;
  --nav-text-2: rgba(11, 15, 22, .84);
  /* .68 而不是 .62：金属渐变**最暗的那一档**（--nav-bg-2）上，
     .62 只有 4.31:1，刚好卡在 AA 线下面 */
  --nav-muted:  rgba(11, 15, 22, .68);
  --nav-hair:   rgba(11, 15, 22, .16);
  --nav-hover:  rgba(11, 15, 22, .07);
  /* 灰底上要用**蓝**作选中色才醒目 */
  --nav-active-bg: rgba(15, 107, 255, .16);
  --nav-accent: #0B4FC4;
  /* 金属光泽：上下两档灰之外再叠一层很淡的斜向高光 ——
     这正是"金属"和"纯灰"的区别。压在灰底上，必须很轻。 */
  --nav-bg-image: linear-gradient(118deg,
    rgba(255, 255, 255, .55) 0%,
    rgba(255, 255, 255, 0) 34%,
    rgba(11, 15, 22, .05) 100%);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--sans);
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--text);
  background: var(--space-0);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; }
h1, h2, h3 { margin: 0; font-weight: 700; letter-spacing: -0.025em; }
p { margin: 0; }
dl, dt, dd { margin: 0; }
img { display: block; max-width: 100%; }
::selection { background: rgba(15, 107, 255, .35); }

/* 小标签：等宽 + 撑开字距 + 全大写。
   ⚠️ 只适合**短的大写拉丁词**（SKILL / ROOT / 概览 这种）。
   汉字没有大小写，"撑开" 只会把一个词拆散，所以别拿它去包整句话或中文串。 */
.nav-label, .eyebrow, .crumb, .kicker, .spec-key, .tag,
.hero-meta dt, .footer-meta, .side-meta, .status-key, .build-chip, .metric-key {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
}

/* 等宽元信息：哈希、时间戳、尺寸、文件名、编号……
   ⚠️ 这里**故意不放大写转换、也不放 .16em 字距**。两条都踩过坑：
   ① `text-transform: uppercase` 会把文件名 / 用户名 / Hash **显示成大写**，
      而这些全是**大小写敏感**的 —— 备份包 uu-site-20260922-100711.tar.gz
      在页面上显示成 UU-SITE-….TAR.GZ，用户照着抄下来的名字是错的；
      `register_mode` 也会从 invite 显示成 INVITE，而那正是要填进配置的值。
   ② 汉字不是拉丁字母，.16em 会把「累计下载 12 次」拆成「累 计 下 载 12 次」；
      而且汉字走的是等宽字体的回退字体，字宽和旁边的数字对不齐，整行看着是散的。
   要"撑开的大写标签"请用上面那一组类；要"含汉字的元信息整句"用 .meta-line。 */
.mono {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .02em;
}

/* 含汉字的元信息整句：「共 6 个 · 已共享 5 · 待审 0」这类。
   走正文字体 —— 汉字与数字混排时等宽字体帮不上忙，只会让字宽忽大忽小。
   数字用等宽数字（tabular-nums），这样上下两行的数字仍然对齐。 */
.meta-line {
  font-size: 12.5px;
  color: var(--muted);
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

/* 含汉字的**短**元信息（作者名、栏目名、标签这类）：字号跟旁边的 .mono 对齐，
   只把等宽字体换成正文字体 —— 汉字在等宽字体里只能走回退字体，
   字宽和旁边的拉丁数字对不齐，看着就是"散"的。 */
.meta-cjk {
  font-size: 12.5px;
  color: var(--muted);
  letter-spacing: 0;
}

/* 中文下的字距修正
   --------------------------------------------------------------------------
   上面那组标签类的 .16em / .22em 是**为拉丁文调的**：大写拉丁字母字面窄、
   x-height 小，撑开一点才像"小标签"。汉字是满格的方块字，同样的 .22em
   会把一个词拆成一串孤立的字（「可复用的能力」→「可 复 用 的 能 力」）。
   所以中文下收到 .1em：仍然看得出是标签，但不再一个字一个字往外蹦。
   **只对 lang="zh" 生效**，英文页面的观感一点都不变。

   ⚠️ 最后一行 `.page-head .eyebrow` 不能省：它自己也设了 `.22em`，
   特异性 (0,2,0) 与 `:lang(zh) .eyebrow` 相同，但它在文件后面 ——
   不加这一条就会被它盖掉，而页面头部恰好是汉字标签最多的地方。

   这份名单是 `cjk-web-typography` 技能里那把尺子（`scripts/cjk_audit.py`）扫出来的：
   凡是「自带 .1em 以上字距、又会被中文文案用到的类」都要列在这里，
   漏一个就会出现"别的都紧了、就这一处还是散的"。 */
:lang(zh) .nav-label, :lang(zh) .eyebrow, :lang(zh) .crumb,
:lang(zh) .kicker, :lang(zh) .spec-key, :lang(zh) .tag,
:lang(zh) .hero-meta dt, :lang(zh) .footer-meta, :lang(zh) .side-meta,
:lang(zh) .status-key, :lang(zh) .build-chip, :lang(zh) .metric-key,
:lang(zh) .back-link, :lang(zh) .scan-caption, :lang(zh) .module-idx,
:lang(zh) .page-head .eyebrow {
  letter-spacing: .1em;
}

/* ==========================================================================
   骨架
   ========================================================================== */

.shell { display: flex; min-height: 100vh; }

.main {
  flex: 1;
  min-width: 0;
  margin-left: var(--sidebar-w);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

/* ==========================================================================
   侧栏
   ========================================================================== */

.sidebar {
  position: fixed;
  inset: 0 auto 0 0;
  width: var(--sidebar-w);
  display: flex;
  flex-direction: column;
  padding: 20px 0 16px;
  background: var(--nav-bg-image),
              linear-gradient(180deg, var(--nav-bg) 0%, var(--nav-bg-2) 100%);
  border-right: 1px solid var(--line);
  z-index: 40;
}

.brand {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 20px 20px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--nav-hair);
  text-decoration: none;
}

/* 品牌徽标：图形标识（彗星掠过半个地球）。
   徽标自带 #0D1526 底色，在深色侧栏上需要一圈描边才立得住。
   圆角必须跟徽标内部一致（14/64 ≈ 21.9%），否则 box-shadow 描边会在四角悬空。
   描边颜色跟着侧栏底色走 —— 亮色主题的侧栏是亮蓝，得用更浅的一圈（见下面的 light 覆盖）。 */
.brand-mark {
  display: block;
  flex: none;
  width: 34px; height: 34px;
  border-radius: 7.5px;
  overflow: hidden;
  box-shadow:
    0 0 0 1px rgba(94, 168, 255, .30),
    0 0 16px rgba(15, 107, 255, .18);
}
.brand-mark img { display: block; width: 100%; height: 100%; }

.brand-text { display: flex; flex-direction: column; line-height: 1.25; }
.brand-text strong { font-size: 15px; letter-spacing: .18em; }
.brand-text small {
  color: var(--nav-muted);
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
}

.nav { display: flex; flex-direction: column; gap: 2px; padding: 0 12px; }
.nav-label { color: var(--nav-muted); padding: 0 10px 10px; letter-spacing: .24em; }

.nav-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  border-radius: var(--r-sm);
  color: var(--nav-text-2);
  text-decoration: none;
  font-size: 14px;
  transition: background .16s ease, color .16s ease;
}
.nav-item:hover { background: var(--nav-hover); color: var(--nav-text); }
.nav-item.is-active { background: var(--nav-active-bg); color: var(--nav-text); }
.nav-item.is-active::before {
  content: "";
  position: absolute;
  left: -12px; top: 50%;
  transform: translateY(-50%);
  width: 2px; height: 20px;
  background: var(--nav-accent);
}
.nav-idx { font-family: var(--mono); font-size: 10.5px; color: var(--nav-muted); }
.nav-item.is-active .nav-idx { color: var(--nav-accent); }
.nav-text { flex: 1; }
.nav-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--warn); }

.side-foot {
  margin-top: auto;
  padding: 16px 20px 0;
  border-top: 1px solid var(--nav-hair);
}
.side-status { display: flex; align-items: center; gap: 8px; }

.dot { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); }
.dot.is-warn, .side-status .dot, .build-chip .dot { background: var(--warn); }
.dot.is-ok { background: var(--ok); }

.side-status span:last-child { color: var(--nav-text-2); font-size: 12px; }
/* 品牌全称比原来的两字母缩写长得多，这里竖排两行避免在窄侧栏里折行 */
.side-meta {
  margin-top: 10px;
  color: var(--nav-muted);
  letter-spacing: .12em;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* ==========================================================================
   顶栏
   ========================================================================== */

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  height: 60px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 34px;
  background: rgba(var(--veil-rgb), .72);
  backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid var(--line);
}

.menu-btn {
  display: none;
  width: 36px; height: 36px;
  align-items: center; justify-content: center;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--strong);
  cursor: pointer;
}
.menu-btn svg { width: 18px; height: 18px; }

.crumbs { display: flex; align-items: center; gap: 9px; min-width: 0; color: var(--muted); }
/* 分隔符也是要读的字：.22 在白底上只有 1.4，基本看不见 */
.crumb-sep { color: var(--muted); }
.crumb-current { color: var(--strong); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }

.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 14px; }

.build-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 5px 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--text-2);
  white-space: nowrap;
}

.seg { display: inline-flex; padding: 2px; border: 1px solid var(--line-2); border-radius: var(--r-sm); }
.seg a {
  padding: 5px 12px;
  border-radius: 3px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--text-2);
  text-decoration: none;
}
.seg a.is-on { background: var(--accent); color: var(--on-accent); }

/* 主题开关：暗色下显示太阳（点了变亮），亮色下显示月亮（点了变暗）。
   两个图标都在 DOM 里，靠 data-theme 决定显示哪个 —— 纯 CSS 切换，
   不会出现"点完了图标慢半拍"的闪。 .theme-ico 的 display 由下面的规则管。 */
.theme-btn {
  display: inline-flex;
  width: 36px; height: 36px;
  align-items: center; justify-content: center;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--strong);
  cursor: pointer;
  transition: border-color .18s ease, background .18s ease, color .18s ease;
}
.theme-btn:hover { background: var(--hover); border-color: var(--accent); }
.theme-btn svg { width: 17px; height: 17px; }
.theme-btn .ico-moon { display: none; }
[data-theme="light"] .theme-btn .ico-sun { display: none; }
[data-theme="light"] .theme-btn .ico-moon { display: block; }

/* ==========================================================================
   内容区
   ========================================================================== */

.content { flex: 1; padding: 0 34px 80px; }
.content > * { max-width: 1120px; position: relative; z-index: 1; }

/* ==========================================================================
   首屏
   ========================================================================== */

.hero {
  position: relative;
  /* 首屏上的文字走 --hero-*（跟主题走）：暗色深空配白字，
     亮色明亮的舱内配深字。它**不跟 --text 走**。 */
  color: var(--hero-fg);
  max-width: none !important;
  margin: 0 -34px;
  min-height: min(76vh, 660px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  border-bottom: 1px solid var(--hero-hair);
}

/* --------------------------------------------------------------------------
   首屏是**两套完整场景叠着**，切换时整层交叉淡入淡出：
     场景 A（地球）= 底图 + 深色遮罩 + 左下辉光
     场景 B（月球）= 底图 + 浅蓝遮罩 + 右下辉光

   为什么不是"一张图 + 一套遮罩、按主题换颜色"：遮罩是 `background-image`
   的渐变，**渐变本身没法 transition**，换主题时会"啪"地跳一下 ——
   而底图在慢慢淡出，两者对不上，看着就是穿帮。
   把遮罩和辉光一起塞进场景里，交叉淡入就全都平滑了。
   -------------------------------------------------------------------------- */
.hero-scenes { position: absolute; inset: 0; }

.hero-scene {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .9s ease;
}
[data-theme="dark"]  .hero-scene.is-earth,
[data-theme="light"] .hero-scene.is-moon { opacity: 1; }

.hero-bg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 72% 42%;
  animation: kenburns 30s ease-in-out infinite alternate;
}
@keyframes kenburns { from { transform: scale(1); } to { transform: scale(1.06); } }

/* 两张底图各自调色：地球是夜景原样，月球往蓝偏一点和新 UI 对齐。
   写成「按场景」而不是「按主题」—— 淡出中的那张不该跟着新主题换色。 */
.hero-scene.is-moon .hero-bg { filter: var(--hero-filter); }

.hero-veil {
  position: absolute;
  inset: 0;
}
/* 两套场景的遮罩都走 --band-veil-rgb（深空色）。
   首屏在明暗两套主题下都是那片深空，所以遮罩只有一个版本 ——
   之前按主题换遮罩（深色/浅蓝）是错的：那会让亮色主题的首屏被洗成一片白，
   正是"亮得耀眼"的来源。左边（文字区）压厚保对比度，右边留给星球。 */
.hero-scene.is-earth .hero-veil {
  background:
    linear-gradient(94deg, rgba(var(--hero-veil-rgb), .92) 0%, rgba(var(--hero-veil-rgb), .64) 42%, rgba(var(--hero-veil-rgb), .08) 100%),
    linear-gradient(180deg, rgba(var(--hero-veil-rgb), .55) 0%, rgba(var(--hero-veil-rgb), 0) 30%, rgba(var(--hero-veil-rgb), .72) 100%);
}
.hero-scene.is-moon .hero-veil {
  background:
    linear-gradient(94deg, rgba(var(--hero-veil-rgb), .90) 0%, rgba(var(--hero-veil-rgb), .60) 42%, rgba(var(--hero-veil-rgb), .06) 100%),
    linear-gradient(180deg, rgba(var(--hero-veil-rgb), .52) 0%, rgba(var(--hero-veil-rgb), 0) 30%, rgba(var(--hero-veil-rgb), .68) 100%);
}

/* 天体大气辉光：极淡的一圈缓慢呼吸，给星球"活着"的暗示。
   地球在左下、月球在右下 —— 这是两套场景最直观的区别。 */
.hero-aura {
  position: absolute;
  bottom: -30%;
  width: 84%;
  aspect-ratio: 1 / 1;
  z-index: 1;
  pointer-events: none;
  border-radius: 50%;
  filter: blur(14px);
  animation: auraBreathe 9.5s ease-in-out infinite;
}
.hero-scene.is-earth .hero-aura {
  left: -12%;
  background: radial-gradient(circle at 50% 50%,
    rgba(104, 176, 255, .30) 0%,
    rgba(58, 128, 236, .16) 30%,
    rgba(26, 74, 178, .06) 56%,
    rgba(8, 20, 43, 0) 76%);
}
.hero-scene.is-moon .hero-aura {
  left: auto;
  right: -12%;
  background: radial-gradient(circle at 50% 50%,
    rgba(158, 196, 255, .34) 0%,
    rgba(110, 156, 240, .18) 30%,
    rgba(58, 104, 200, .07) 56%,
    rgba(8, 20, 43, 0) 76%);
}
@keyframes auraBreathe {
  0%, 100% { opacity: .48; transform: scale(1); }
  50%      { opacity: .92; transform: scale(1.05); }
}

/* 群星闪耀层：由 starfield.js 在 canvas 上逐帧绘制
   四周各外扩 26px，pointer 视差位移时不会露出空边 */
.hero-stars {
  position: absolute;
  top: -26px;
  left: -26px;
  width: calc(100% + 52px);
  height: calc(100% + 52px);
  z-index: 1;
  display: block;
  pointer-events: none;
  will-change: transform;
  transition: transform .75s cubic-bezier(.22, .61, .36, 1);
}

.hero-inner { position: relative; z-index: 2; max-width: 780px; padding: 110px 34px 60px; }

.kicker {
  display: flex; align-items: center; gap: 12px;
  color: var(--text-2);
  letter-spacing: .24em;
}
/* 首屏和页头的小标签各跟各的：首屏跟主题，页头恒白 */
.hero .kicker { color: var(--hero-fg-2); }
.page-head .kicker { color: var(--band-fg-2); }
.kicker .bar { width: 34px; height: 2px; background: var(--accent); }

.hero-title {
  margin-top: 24px;
  color: var(--hero-fg);
  /* 上限从 78 收到 66：78px 时英文那串 "research & intelligence workspace"
     要折成四行，中文也顶到 780px 栏宽的边上，两边都难看。 */
  font-size: clamp(38px, 5vw, 66px);
  line-height: 1.08;
  letter-spacing: -0.032em;
}
.hero-title .hl { color: var(--hero-accent); }

.hero-lead {
  margin-top: 24px;
  font-size: 17px;
  line-height: 1.72;
  color: var(--hero-fg-2);
  max-width: 56ch;
}

.hero-cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 34px; }

.btn {
  display: inline-flex; align-items: center; gap: 10px;
  height: 46px;
  padding: 0 24px;
  border-radius: var(--r-sm);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  /* <button> 不像 <a> 会自动继承字体和颜色：不在这里抹平，
     原生按钮的浅灰底 + 白色 (btn-ghost) 文字就变成一片看不见的空按钮。 */
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  color: var(--strong);
  background: transparent;
  border: 1px solid transparent;
  transition: background .18s ease, border-color .18s ease, transform .18s ease,
              box-shadow .18s ease;
}
.btn-primary {
  background: var(--accent);
  color: var(--on-accent);
  /* 冷蓝与深空底同色系，用一圈同色辉光补回强调力度 */
  box-shadow: 0 0 22px rgba(15, 107, 255, .32);
}
.btn-primary:hover {
  background: var(--accent-hover);
  box-shadow: 0 0 30px rgba(15, 107, 255, .48);
}
.btn-ghost { border: 1px solid var(--line-2); color: var(--strong); }
.btn-ghost:hover { border-color: var(--strong); background: var(--hover); }

.hero-meta {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 0;
  border-top: 1px solid var(--hero-hair);
  background: rgba(var(--hero-veil-rgb), .55);
  backdrop-filter: blur(6px);
}
.hero-meta > div { padding: 18px 34px; border-right: 1px solid var(--hero-hair); }
.hero-meta > div:last-child { border-right: 0; }
.hero-meta dt { color: var(--hero-muted); margin-bottom: 6px; }
.hero-meta dd { font-size: 14.5px; font-weight: 600; color: var(--hero-fg); }

/* ==========================================================================
   区块
   ========================================================================== */

.section { padding-top: 74px; }
.section-head { display: flex; align-items: baseline; gap: 22px; flex-wrap: wrap; }
.section-head h2 { font-size: 26px; letter-spacing: -0.03em; }
.section-head p { color: var(--muted); font-size: 14px; }

.hairline { height: 1px; background: var(--line); margin-top: 20px; }

/* 状态条 */
.status-grid {
  margin-top: 26px;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--space-2);
  overflow: hidden;
}
.status-cell { padding: 20px; border-right: 1px solid var(--line); }
.status-cell:last-child { border-right: 0; }
.status-key { display: block; color: var(--muted); margin-bottom: 9px; }
.status-val { display: flex; align-items: center; gap: 8px; font-size: 15px; font-weight: 600; }
.status-val.is-muted { color: var(--muted); font-weight: 500; }

/* 研究方向：图像卡片 */
.focus-grid {
  margin-top: 26px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 20px;
}

.focus-card {
  position: relative;
  display: block;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--space-2);
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  transition: border-color .2s ease, transform .2s ease;
}
.focus-card:hover { border-color: rgba(15, 107, 255, .55); transform: translateY(-3px); }

.focus-media { position: relative; aspect-ratio: 16 / 10; overflow: hidden; }
.focus-media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .7s cubic-bezier(.22, .61, .36, 1);
}
.focus-card:hover .focus-media img { transform: scale(1.07); }
.focus-media::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(var(--veil-rgb), 0) 34%, rgba(var(--veil-rgb), .74) 100%);
}
/* 编号压在**图片**上，不是压在页面上 —— 所以它的颜色**不能跟主题走**。
   ⚠️ 踩过：原来这里写的是 `rgba(var(--ink-rgb), .78)`，而 `--ink-rgb`
   在亮色主题下是近黑（10,14,20）。于是亮色下"01"变成深色字压在暗色照片上，
   直接消失。六个研究方向图一律是暗调的（芯片 / 机器人 / 中控室那套语言），
   编号就一律用浅色。加一点投影，避免正好落在亮斑上时糊掉。 */
.focus-idx {
  position: absolute;
  z-index: 2;
  top: 14px; left: 16px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .2em;
  color: rgba(var(--media-ink), .84);
  text-shadow: 0 1px 4px rgba(4, 9, 18, .72);
}
.focus-body { padding: 20px 22px 22px; }
.focus-body h3 { font-size: 18px; letter-spacing: -0.02em; }
.focus-body p { margin-top: 10px; color: var(--text-2); font-size: 14px; line-height: 1.62; }
.focus-foot {
  margin-top: 16px; padding-top: 14px;
  border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between;
}
.tag { display: inline-flex; align-items: center; gap: 7px; color: var(--warn); }
.tag::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }

/* 模块卡片 */
.module-grid {
  margin-top: 26px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 20px;
}
.module {
  display: flex; flex-direction: column; gap: 14px;
  padding: 26px 24px 22px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--space-2);
  text-decoration: none;
  transition: border-color .2s ease, background .2s ease;
}
.module:hover { border-color: rgba(15, 107, 255, .55); background: var(--space-3); }
.module-top { display: flex; align-items: center; justify-content: space-between; }
.module-idx { font-family: var(--mono); font-size: 11px; letter-spacing: .18em; color: var(--accent-lt); }
.module-mark {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  color: var(--text-2);
}
.module-mark svg { width: 15px; height: 15px; }
.module h3 { font-size: 19px; letter-spacing: -0.025em; }
.module p { color: var(--text-2); font-size: 14px; line-height: 1.62; }
.module-foot {
  margin-top: auto; padding-top: 16px;
  border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between;
}
.module-arrow { font-family: var(--mono); color: var(--muted); transition: transform .18s ease, color .18s ease; }
.module:hover .module-arrow { transform: translateX(4px); color: var(--accent-lt); }

/* ==========================================================================
   栏目页
   ========================================================================== */

.page-head {
  position: relative;
  max-width: none !important;
  margin: 0 -34px;
  min-height: 340px;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
.page-head-bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 60% 40%;
  filter: saturate(.9);
}
/* 配了亮色图的那几个栏目，页头会有两张图（暗的 + 亮的），按主题二选一。
   没有亮色图的页面（404 之类）不会渲染 .is-light，这条对它们无影响。 */
.page-head-bg.is-light { display: none; }
[data-theme="light"] .page-head-bg.is-dark { display: none; }
[data-theme="light"] .page-head-bg.is-light { display: block; }
/* 页头和首屏一样是"深空带"：两套主题共用深空遮罩 + 白字。
   之前按主题换成白遮罩，结果这些夜景配图被洗成一片灰白，和首屏的深空对不上。 */
.page-head-veil {
  position: absolute; inset: 0;
  background:
    linear-gradient(90deg, rgba(var(--band-veil-rgb), .94) 0%, rgba(var(--band-veil-rgb), .58) 46%, rgba(var(--band-veil-rgb), .16) 100%),
    linear-gradient(180deg, rgba(var(--band-veil-rgb), .3) 0%, rgba(var(--band-veil-rgb), .82) 100%);
}
.page-head-inner { position: relative; z-index: 2; padding: 90px 34px 40px; max-width: 860px; }

/* 亮色主题下的「亮调页头」—— 只有配了 `cover_light` 的栏目走这条。
   把 band 令牌**重新指向页面调色**：白遮罩 + 深色字，
   和首屏那套 `--hero-*` 在亮色下做的事完全一样。

   为什么需要它：栏目页头原本恒为"深空带"（`--band-*` 在亮色下不覆盖），
   于是白页顶上压着一大块黑，加上配图也是夜景，整段和下面的白纸页面对不上。
   之前试过"亮色换白遮罩"，但那时候**配图还是夜景**，被洗成一片灰白 ——
   现在配图本身换成了亮调（中控室 / 白色月球车），白遮罩才成立。

   ⚠️ 只作用于 `.has-light`。其余页头（含 404 的 `.is-plain`）保持深空带不变，
   那是已经画好、也验收过的东西，别顺手改。 */
[data-theme="light"] .page-head.has-light {
  --band-fg:       var(--text);
  --band-fg-2:     var(--text-2);
  --band-muted:    var(--muted);
  --band-accent:   var(--accent);
  --band-veil-rgb: 255, 255, 255;
}

/* 无配图时的纯色头部（如 404） */
/* 无配图时的纯色头部（除了 placeholder，其余页面全走这条）。
   ⚠️ 它**不是**深空带，而是页面的一部分 —— 所以这里把 band 令牌**重新指向页面调色**。
   不这么做的话，`.stage-title` 拿的是 --band-fg（永远是白），
   而底部是 --space-1（亮色主题下是白）→ 白字白底，标题直接消失。
   重指之后两套主题都自动对：暗色→白字深底，亮色→黑字白底。 */
.page-head.is-plain {
  --band-fg:     var(--text);
  --band-fg-2:   var(--text-2);
  --band-muted:  var(--muted);
  --band-accent: var(--accent-lt);
  min-height: 260px;
  background:
    radial-gradient(120% 140% at 18% 0%, rgba(15, 107, 255, .12), transparent 62%),
    var(--space-1);
}
.page-head.is-plain .page-head-veil { background: none; }
.page-head .eyebrow {
  display: flex; align-items: center; gap: 12px;
  color: var(--band-fg-2); letter-spacing: .22em;
}
.page-head .eyebrow::before { content: ""; width: 34px; height: 2px; background: var(--accent); }
.stage-title { margin-top: 20px; font-size: clamp(32px, 4vw, 52px); line-height: 1.06; letter-spacing: -0.035em; color: var(--band-fg); }
.stage-tagline { margin-top: 14px; color: var(--band-fg-2); font-size: 15px; }

.stage-body {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(300px, .85fr);
  gap: 56px;
  align-items: start;
  padding-top: 56px;
}

.lead { font-size: 17px; line-height: 1.72; color: var(--text-2); max-width: 60ch; }

.spec { margin-top: 40px; border-top: 1px solid var(--line); }
.spec-row {
  display: grid;
  grid-template-columns: 160px minmax(0, 1fr);
  gap: 16px;
  padding: 15px 0;
  border-bottom: 1px solid var(--line);
}
.spec-key { color: var(--muted); padding-top: 2px; }
.spec-val { font-size: 14.5px; display: flex; align-items: center; gap: 8px; }
.spec-val.is-ok .dot { background: var(--ok); }
.spec-val.is-warn .dot { background: var(--warn); }

.back-link {
  display: inline-flex; align-items: center; gap: 9px;
  margin-top: 32px;
  color: var(--accent-lt);
  text-decoration: none;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.back-link:hover { text-decoration: underline; }

/* 扫描面板 */
.scan-panel {
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--space-2);
  padding: 22px;
  position: sticky;
  top: 84px;
}
.scan-frame {
  position: relative;
  aspect-ratio: 1;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background:
    linear-gradient(var(--hair-2) 1px, transparent 1px) 0 0 / 100% 25%,
    linear-gradient(90deg, var(--hair-2) 1px, transparent 1px) 0 0 / 25% 100%,
    radial-gradient(120% 100% at 50% 50%, rgba(15, 107, 255, .06), transparent 70%);
  overflow: hidden;
}
.corner { position: absolute; width: 12px; height: 12px; border: 1px solid var(--accent-lt); opacity: .8; }
.corner.tl { top: 8px; left: 8px; border-right: 0; border-bottom: 0; }
.corner.tr { top: 8px; right: 8px; border-left: 0; border-bottom: 0; }
.corner.bl { bottom: 8px; left: 8px; border-right: 0; border-top: 0; }
.corner.br { bottom: 8px; right: 8px; border-left: 0; border-top: 0; }

.radar { position: absolute; inset: 12%; border-radius: 50%; }
.radar-ring { position: absolute; border: 1px solid rgba(var(--ink-rgb), .16); border-radius: 50%; }
.radar-ring.r1 { inset: 0; }
.radar-ring.r2 { inset: 17%; border-color: rgba(var(--ink-rgb), .11); }
.radar-ring.r3 { inset: 34%; border-style: dashed; border-color: rgba(var(--ink-rgb), .11); }
.radar-cross { position: absolute; background: rgba(var(--ink-rgb), .10); }
.radar-cross.h { left: -8%; right: -8%; top: 50%; height: 1px; }
.radar-cross.v { top: -8%; bottom: -8%; left: 50%; width: 1px; }

.radar-sweep {
  position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(from 0deg,
    rgba(15, 107, 255, .34) 0deg, rgba(15, 107, 255, .08) 34deg,
    rgba(15, 107, 255, 0) 62deg, rgba(15, 107, 255, 0) 360deg);
  animation: sweep 5.2s linear infinite;
}
@keyframes sweep { to { transform: rotate(360deg); } }

/* 雷达中心：品牌徽标作为「锁定目标」，替换原来的 UU 文字方块 */
.radar-core {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 62px; height: 62px;
  border-radius: 13px;
  overflow: hidden;
  box-shadow:
    0 0 0 1px rgba(94, 168, 255, .38),
    0 0 0 8px rgba(15, 107, 255, .07),
    0 0 26px rgba(15, 107, 255, .22);
}
.radar-core img { display: block; width: 100%; height: 100%; }

.scan-foot {
  margin-top: 18px; padding-top: 16px;
  border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.scan-caption { color: var(--muted); font-family: var(--mono); font-size: 11px; letter-spacing: .16em; text-transform: uppercase; }
.scan-info { display: flex; flex-direction: column; gap: 4px; }
.scan-meta { color: var(--muted); }

.scan-bars { display: flex; gap: 3px; align-items: flex-end; height: 14px; }
.scan-bars i { width: 3px; background: rgba(var(--ink-rgb), .22); animation: bars 1.6s ease-in-out infinite; }
.scan-bars i:nth-child(1) { height: 6px; }
.scan-bars i:nth-child(2) { height: 12px; animation-delay: .18s; }
.scan-bars i:nth-child(3) { height: 8px;  animation-delay: .36s; }
.scan-bars i:nth-child(4) { height: 14px; animation-delay: .54s; }
.scan-bars i:nth-child(5) { height: 5px;  animation-delay: .72s; }
@keyframes bars { 0%, 100% { background: rgba(var(--ink-rgb), .22); } 50% { background: var(--accent-lt); } }

/* ==========================================================================
   页脚
   ========================================================================== */

.footer {
  border-top: 1px solid var(--line);
  background: var(--space-1);
  padding: 52px 34px 26px;
}

.footer-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
  gap: 40px;
  max-width: 1120px;
}
.footer-brand { display: flex; align-items: center; gap: 12px; }
.footer-brand .brand-mark {
  width: 30px; height: 30px;
  border-radius: 6.5px;
  box-shadow: 0 0 0 1px rgba(94, 168, 255, .26);
}
.footer-brand strong { letter-spacing: .18em; font-size: 14px; }
.footer-tagline { margin-top: 16px; color: var(--muted); font-size: 13.5px; max-width: 38ch; }

.footer-col h4 {
  margin: 0 0 14px;
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--muted);
}
.footer-col a, .footer-col span { display: block; color: var(--text-2); font-size: 13.5px; text-decoration: none; padding: 5px 0; }
.footer-col a:hover { color: var(--strong); }
.footer-col .row { display: flex; justify-content: space-between; gap: 12px; }
.footer-col .row em { font-style: normal; color: var(--muted); font-family: var(--mono); font-size: 11px; letter-spacing: .1em; }

.footer-bottom {
  margin-top: 44px; padding-top: 20px;
  border-top: 1px solid var(--line);
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  color: var(--muted);
  font-size: 12.5px;
}
.footer-meta { color: var(--muted); }

/* ==========================================================================
   动效
   ========================================================================== */

.reveal { animation: rise .6s cubic-bezier(.22, .61, .36, 1) both; animation-delay: var(--d, 0s); }
@keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }

.scrim { position: fixed; inset: 0; z-index: 35; background: rgba(2, 4, 9, .62); }

/* ==========================================================================
   账号：登录 / 注册 / 个人中心 / 用户管理
   ========================================================================== */

.auth-wrap { display: flex; justify-content: center; padding: 44px 20px 72px; }
.auth-card {
  width: 100%; max-width: 440px; padding: 34px 32px 28px;
  background: var(--space-1); border: 1px solid var(--line);
  border-radius: 16px; box-shadow: 0 22px 60px rgba(2, 4, 9, .5);
}
.auth-card .eyebrow { color: var(--accent-lt); }
.auth-title { margin-top: 14px; font-size: 27px; letter-spacing: -0.02em; }
.auth-lead { margin-top: 10px; color: var(--text-2); font-size: 14px; line-height: 1.6; }
.auth-alt { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line);
            font-size: 13.5px; color: var(--muted); }
.auth-alt a { color: var(--accent-lt); }

.field { margin-top: 16px; }
.field label {
  display: block; margin-bottom: 7px; font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--muted);
}
.field input {
  width: 100%; padding: 11px 13px; font: inherit; font-size: 14.5px;
  color: var(--text); background: var(--space-0);
  border: 1px solid var(--line); border-radius: 9px; outline: none;
  transition: border-color .18s ease, box-shadow .18s ease;
}
.field input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(15, 107, 255, .18); }
.btn-row { margin-top: 22px; display: flex; gap: 10px; }
.btn-row .btn { flex: 1; justify-content: center; text-align: center; }

/* 顶栏的账号区 */
.btn-sm { padding: 6px 13px; font-size: 12.5px; }
.user-chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 13px; font-size: 12.5px; border-radius: 999px;
  background: rgba(15, 107, 255, .12); border: 1px solid rgba(15, 107, 255, .34);
  color: var(--accent-lt); white-space: nowrap;
  transition: border-color .18s ease, background .18s ease;
}
.user-chip:hover { border-color: var(--accent); background: rgba(15, 107, 255, .2); }
.user-chip .dot { background: var(--accent-lt); }

.form-error {
  margin-top: 16px; padding: 10px 13px; font-size: 13.5px;
  color: var(--err-fg); background: var(--err-bg);
  border: 1px solid var(--err-line); border-radius: 9px;
}
.form-ok {
  margin-top: 16px; padding: 10px 13px; font-size: 13.5px;
  color: var(--ok-fg); background: var(--ok-bg);
  border: 1px solid var(--ok-line); border-radius: 9px;
}

/* 已开通模块的标签 */
.chip-row { display: flex; flex-wrap: wrap; gap: 9px; margin-top: 14px; }
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 13px; font-size: 13px; border-radius: 999px;
  background: rgba(15, 107, 255, .12); border: 1px solid rgba(15, 107, 255, .34);
  color: var(--accent-lt);
}
.chip .dot { background: var(--accent-lt); }
/* chip 里的次要片段（作者名等）—— 里面是汉字，只压透明度，字体跟着 chip 走 */
.chip-sub {
  opacity: .62;
  font-size: 11.5px;
  /* 它常常紧跟在一个名字后面（如网盘里的「来自帖子」），
     不给间距会和名字连成一句读不断 */
  margin-left: 6px;
}
.sub-head { margin-top: 34px; font-size: 15px; letter-spacing: .02em; }

/* 用户管理：每个账号一张卡片（卡片里套一个 form，HTML 才合法——
   表单包不住 table 行，所以不用表格布局） */
.admin-note { margin-top: 18px; font-size: 13px; color: var(--muted); }
.admin-list { margin-top: 22px; display: flex; flex-direction: column; gap: 14px; }
.admin-card {
  padding: 18px 20px 16px; background: var(--space-1);
  border: 1px solid var(--line); border-radius: 13px;
}
.admin-card.is-me { border-color: rgba(15, 107, 255, .42); }
.admin-card.is-off { opacity: .62; }
.admin-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.admin-head strong { font-size: 15px; }
.admin-head .mono { font-size: 12.5px; color: var(--muted); }
.admin-grid {
  margin-top: 14px; display: grid; gap: 14px;
  grid-template-columns: minmax(120px, 150px) minmax(90px, 120px) minmax(180px, 1fr);
}
.admin-cell > span {
  display: block; margin-bottom: 7px; font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--muted);
}
.admin-cell select, .admin-cell input {
  padding: 7px 9px; font: inherit; font-size: 13px; color: var(--text);
  background: var(--space-0); border: 1px solid var(--line);
  border-radius: 7px; outline: none; width: 100%; max-width: 260px;
}
.admin-cell select:focus, .admin-cell input:focus { border-color: var(--accent); }
.admin-checks { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 4px; }
/* flex: none 必须加：标签默认可以被压缩，容器一窄就被挤到
   「一个字一行」，中文尤其明显（独/特/思/考 竖着排）。 */
.admin-checks label {
  display: flex; align-items: center; gap: 7px; font-size: 13px;
  cursor: pointer; flex: none; white-space: nowrap;
}
.admin-checks input { accent-color: var(--accent); }
.admin-save { margin-top: 16px; }
.admin-save .btn { padding: 8px 18px; font-size: 13px; }
.admin-toggle { display: flex; align-items: center; gap: 8px; font-size: 13px; cursor: pointer; }
.admin-toggle input { accent-color: var(--accent); width: auto; }
.self-tag { display: inline-block; padding: 2px 8px; border-radius: 999px;
            font-size: 11px; background: rgba(15, 107, 255, .16); color: var(--accent-lt); }
.self-tag.is-off { background: var(--err-bg); color: var(--err-fg); }

/* 后台的标签页（用户 / 邀请码 / 日志） */
.admin-tabs {
  display: flex; gap: 4px; margin-top: 22px; padding: 5px;
  background: var(--space-1); border: 1px solid var(--line);
  border-radius: 12px; overflow-x: auto;
}
.admin-tab {
  flex: 1 0 auto; text-align: center; padding: 9px 18px; font-size: 13.5px;
  color: var(--muted); border-radius: 8px; white-space: nowrap;
  transition: color .18s ease, background .18s ease;
}
.admin-tab:hover { color: var(--text); }
.admin-tab.is-on { color: var(--on-accent); background: var(--tab-on-bg); }

/* 表单里输入框下方的补充说明 */
.hint { display: block; margin-top: 6px; font-size: 12px; color: var(--muted); }

/* 表格：邀请码与日志共用。外层容器负责横向滚动，
   窄屏上表格不至于把整个页面撑破 */
.table-wrap {
  margin-top: 16px; overflow-x: auto;
  border: 1px solid var(--line); border-radius: 13px; background: var(--space-1);
}
.data-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.data-table th, .data-table td {
  padding: 11px 14px; text-align: left; border-bottom: 1px solid var(--line);
  vertical-align: middle;
}
.data-table thead th {
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted); font-weight: 500; background: var(--space-0);
}
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table tbody tr.is-off { opacity: .6; }
.data-table .ta-r { text-align: right; }
.data-table .nowrap { white-space: nowrap; }
.data-table .wrap-any { word-break: break-word; max-width: 340px; }

/* 状态小标签 */
.pill {
  display: inline-block; padding: 3px 10px; border-radius: 999px;
  font-size: 11.5px; white-space: nowrap;
  border: 1px solid var(--line); color: var(--muted);
}
.pill.is-ok { color: var(--ok-fg); background: var(--ok-bg); border-color: var(--ok-line); }
.pill.is-warn { color: var(--err-fg); background: var(--err-bg); border-color: var(--err-line); }
/* 待审核用琥珀色，不用报错红 —— 它是「等一下」不是「出错了」 */
.pill.is-wait { color: var(--warn-fg); background: var(--warn-bg); border-color: var(--warn-line); }
.pill.is-muted { color: var(--muted); background: var(--space-0); }

/* 表格行里的按钮组：两个 form 并排，需要 inline-flex 才不会各占一行 */
.row-actions { display: inline-flex; gap: 7px; justify-content: flex-end; }
.row-actions form { display: inline; }
.btn.is-danger { color: var(--err-fg); border-color: var(--err-line); }
.btn.is-danger:hover { background: var(--err-bg); }

/* 邀请码表单是三个窄字段，用 auto-fit 更合用 */
.invite-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.invite-grid .admin-cell select, .invite-grid .admin-cell input { max-width: 100%; }

/* 会员专属首页区块 */
.member-bar {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin-top: 26px;
  padding: 24px 26px; border-radius: 15px;
  background: linear-gradient(135deg, rgba(15, 107, 255, .16), rgba(15, 107, 255, .04));
  border: 1px solid rgba(15, 107, 255, .3);
}
.member-title { margin: 10px 0 0; font-size: 25px; letter-spacing: -.01em; }
.member-lead { margin: 8px 0 0; font-size: 14px; color: var(--muted); max-width: 56ch; }
.member-side { flex: 0 0 auto; }
.chip-row .chip { transition: border-color .18s ease, background .18s ease; }
.chip-row a.chip:hover { border-color: var(--accent); background: rgba(15, 107, 255, .2); }

/* ==========================================================================
   个人中心这一组的页内页签（个人中心 / 我的网盘 / 我的空间 / Skill 库）
   --------------------------------------------------------------------------
   这四项原先在侧栏里各占一行、并列成顶级栏目。收成一组之后，
   这条横向入口就是它们的"侧栏"，所以做得像导航而不是像按钮：
   有下划线、当前项带一条主色指示条。

   ⚠️ 标签是汉字，所以**不用等宽字体、也不用宽字距** ——
   那两样是给大写拉丁标签调的，套到汉字上就是"一个字一个字往外蹦"。
   用正文字体 + `.18s` 的 hover 过渡，汉字看着才是一个词。
   ========================================================================== */
.tabs {
  display: flex; flex-wrap: wrap; gap: 22px;
  margin: 0 0 22px;
  border-bottom: 1px solid var(--line);
}
.tabs .tab {
  position: relative;
  padding: 10px 2px 12px;
  font-size: 13.5px;
  color: var(--text-2);
  text-decoration: none;
  white-space: nowrap;
  transition: color .18s ease;
}
.tabs .tab:hover { color: var(--text); }
.tabs .tab.is-on { color: var(--accent-lt); font-weight: 600; }
.tabs .tab.is-on::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; background: var(--accent);
}
/* 亮色下主色用深一点的那支，否则浅蓝压在白底上太飘 */
[data-theme="light"] .tabs .tab.is-on { color: var(--accent); }

/* ==========================================================================
   接入智能（Plugin）：知识载入 / 投影映射 / 模型接入
   --------------------------------------------------------------------------
   全是"表单 + 列表"，所以底座用页面已有的 .input / .btn / .pill / .ops-rows，
   这里只补这一模块独有的几块：选材料的双栏列表、计划卡、case 卡。
   ========================================================================== */

/* ---- 表单 ---- */
/* 「记住我」这种"一个勾选框 + 一行说明"的行。
   勾选框和文字的基线要对齐 —— 默认 inline 的时候勾选框会往下沉半行。 */
.check-row { display: flex; align-items: center; gap: 9px; margin: 2px 0 4px; }
.check-row label { cursor: pointer; font-size: 14px; }
.check-row input[type="checkbox"] { flex: 0 0 auto; margin: 0; cursor: pointer; width: 15px; height: 15px; }

/* 单个按钮 + 一句说明。**不能用 .btn-row** —— 那个是给"一排等宽按钮"设计的
   （`.btn-row .btn { flex: 1 }`），只放一个按钮时它会被拉成整幅宽，
   看起来像个横幅而不是按钮。 */
.form-actions { display: flex; align-items: center; gap: 14px;
                flex-wrap: wrap; margin-top: 6px; }
.form-actions .hint { margin: 0; }

/* ---- 勾选技能：一行一个，名字在前、来源标签在后 ----
   ⚠️ 这一块**不能**套在 .field 里：`.field label` 的
   `display:block` + `letter-spacing:.16em` + `text-transform:uppercase`
   特异度是 (0,1,1)，比 `.pick-row` 的 (0,1,0) 高，会把这里的 flex 布局
   和汉字字距一起盖掉（汉字被撑成一字一格、勾选框被挤到行尾）。
   所以外层用 .pick-block，并在这里把勾选框的宽度也定下来 ——
   `.field input { width:100% }` 同样会命中它。 */
.pick-block { margin-top: 16px; }
.pick-block .hint { margin-top: 4px; }
.pick-grid { display: flex; flex-direction: column; gap: 6px; margin: 10px 0 8px; }
.pick-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 13px; border: 1px solid var(--line); border-radius: 9px;
  cursor: pointer;
}
.pick-row:hover { border-color: var(--accent-lt); }
.pick-row input[type="checkbox"] {
  flex: 0 0 auto; margin: 0; cursor: pointer; width: 15px; height: 15px;
}
.pick-name { color: var(--text); font-weight: 500; }
.pick-row .pick-note { margin: 0; flex: 1 1 240px; min-width: 0; }
.card-form { display: flex; flex-direction: column; gap: 18px; max-width: 900px;
             margin: 18px 0 6px; }
.card-form .field { display: block; }
.card-form .field .hint { display: block; margin-top: 6px; }
.field-row { display: grid; gap: 14px;
             grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

/* ---- 选材料：网盘一栏、个人空间一栏 ---- */
.pick { border: 1px solid var(--line); border-radius: var(--r);
        padding: 12px 16px 16px; margin: 0; }
.pick legend { padding: 0 6px; }
.pick-cols { display: grid; gap: 18px; margin-top: 8px;
             grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.pick-head { margin: 0 0 8px; font-size: 12.5px; color: var(--muted); }
/* 文件多的时候这一栏自己滚，别把整页撑长 —— 页面变长会让下面"生成计划"
   那个按钮跑出视野，用户填完材料找不到提交在哪 */
.pick-col { max-height: 260px; overflow-y: auto; }
.pick-row { display: flex; align-items: center; gap: 9px; padding: 6px 4px;
            border-radius: var(--r-sm); font-size: 13.5px; cursor: pointer; }
.pick-row:hover { background: var(--hover); }
.pick-name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis;
             white-space: nowrap; }
.pick-size { font-style: normal; font-size: 11px; color: var(--muted);
             font-family: var(--mono); }

/* ---- 提示条（比 form-ok 更"要说点什么"）---- */
.notice { margin: 18px 0; padding: 13px 16px; border-radius: var(--r);
          border: 1px solid rgba(15, 107, 255, .4); background: rgba(15, 107, 255, .09);
          color: var(--text); font-size: 14px; line-height: 1.7; }
.notice a { color: var(--accent-lt); }

/* ---- 计划卡 ---- */
.plan-grid { display: grid; gap: 16px; margin-top: 20px;
             grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
.plan-card { display: flex; flex-direction: column; gap: 10px; padding: 18px;
             border: 1px solid var(--line); border-radius: var(--r);
             background: var(--space-1); text-decoration: none; color: inherit;
             transition: border-color .18s ease, background .18s ease; }
.plan-card:hover { border-color: var(--accent); background: rgba(15, 107, 255, .06); }
.plan-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.plan-subject { font-size: 15.5px; font-weight: 700; min-width: 0;
                overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plan-meta { margin: 0; font-size: 13px; color: var(--text-2); }
.plan-foot { display: flex; justify-content: space-between; gap: 10px; margin-top: auto;
             padding-top: 10px; border-top: 1px solid var(--line); }
.plan-go { font-family: var(--mono); font-size: 11.5px; color: var(--accent-lt); }
.plan-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
                margin: 20px 0 0; }
.plan-actions form { display: flex; align-items: center; gap: 8px; }

/* ---- 计划详情里的每个 case ---- */
.case { margin-top: 18px; padding: 20px 22px; border: 1px solid var(--line);
        border-radius: var(--r); background: var(--space-1); }
.case-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
            font-size: 11.5px; color: var(--muted); }
.case-seq { font-family: var(--mono); letter-spacing: .1em; color: var(--accent-lt); }
.case-diff { color: var(--text-2); }
/* 到期日推到最右边：一排里它是最需要扫一眼的那个 */
.case-due { margin-left: auto; font-family: var(--mono); }
.case-title { margin: 12px 0 0; font-size: 17px; }
/* 题面是模型给的，可能带换行和缩进 —— pre-wrap 保住它，
   否则一道题的选项会被并成一行 */
.case-body { margin-top: 8px; color: var(--text-2); font-size: 14px;
             line-height: 1.75; white-space: pre-wrap; }
.case-submit { margin-top: 16px; }
.case-submit summary { cursor: pointer; font-size: 13px; color: var(--accent-lt);
                       padding: 4px 0; }
.case-verdicts { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--line); }
.verdict { margin-top: 10px; }
.verdict-text { margin: 4px 0 0; font-size: 13.5px; color: var(--text-2);
                line-height: 1.7; white-space: pre-wrap; }

/* 画像正文：它是 Markdown 原文，按代码块显示最诚实 ——
   渲染成 HTML 会让人以为那是"页面的一部分"，其实它是要下载走的那份文件 */
.profile-body { margin-top: 16px; max-height: 520px; overflow: auto; }

/* ---- 已保存的模型接口：一列卡片，当前那条给主色描边 ---- */
.ep-list { display: flex; flex-direction: column; gap: 16px; margin-top: 20px; }
.ep-card { padding: 18px 20px; border: 1px solid var(--line);
           border-radius: var(--r); background: var(--space-1); }
/* 当前使用的那条要一眼看得出来 —— 页面上最要紧的信息就是"现在走哪条" */
.ep-card.is-on { border-color: var(--accent); background: rgba(15, 107, 255, .06); }
.ep-top { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.ep-label { font-size: 15.5px; font-weight: 700; }
/* 卡片内的 ops-rows 不要再带自己的上边距 */
.ep-card .ops-rows { margin: 0; }
.ep-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
              margin-top: 14px; padding-top: 14px;
              border-top: 1px solid var(--line); }
.ep-actions form { display: inline-flex; }

/* ==========================================================================
   网盘 + 个人空间
   ========================================================================== */

/* 通用输入框。原先只有 .field input 和 .admin-cell input 两种局部写法，
   网盘/个人空间的表单不在那两种容器里，所以补一个可以单独用的类。 */
.input {
  width: 100%; padding: 9px 12px;
  background: var(--space-0); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-sm);
  font-family: inherit; font-size: 14px;
}
.input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(15, 107, 255, .18); }
.input-sm { width: auto; min-width: 140px; padding: 5px 9px; font-size: 13px; }
.textarea { min-height: 260px; line-height: 1.75; resize: vertical; font-family: var(--mono); font-size: 13.5px; }
select.input { width: auto; min-width: 160px; }

/* 配额条：用宽度百分比表示占用，满格时转成警示色 */
.quota { margin-bottom: 6px; }
.quota-top { display: flex; justify-content: space-between; gap: 12px; color: var(--muted); }
.quota-note { margin: 8px 0 0; }
.quota-bar {
  height: 7px; margin-top: 8px; border-radius: 999px; overflow: hidden;
  background: var(--hair); border: 1px solid var(--line);
}
.quota-fill {
  display: block; height: 100%; min-width: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent-lt));
  transition: width .3s ease;
}
/* 快满了转成警示色：这时候用户该知道该清理了 */
.quota-fill.is-full { background: linear-gradient(90deg, #C0483A, #FFB020); }

.drive-upload, .drive-mkdir { margin: 14px 0; }
.drive-upload-row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
/* ⚠️ 原生 file input 的**整块**都是点击热区。
   以前这里写的是 `flex: 1 1 260px` —— 它被拉满整行，于是那一排的空白处
   点哪儿都会弹选择框（用户报的"上传文件那一排很大一片都能点到"）。
   现在把它藏起来（**保留可聚焦**，键盘和读屏照样能用），
   真正能点的只有旁边那个 `.file-pick` label。 */
.file-input {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
/* 键盘走到 input 上时，把焦点环画在旁边的 label 上 —— 否则用户看不见焦点在哪 */
.file-input:focus-visible + .file-pick {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.file-picked { font-size: 12.5px; color: var(--muted); }

/* ---- 已选文件清单 ----
   为什么要它：原生 file input 选完之后，用户只看到一个"3 个文件 · 12 MB"的
   数字，既不知道是哪三个，也没法去掉其中一个（想换一个就得全部重选）。
   用户明确提过这三件事。 */
.pick-panel {
  margin-top: 12px; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--r);
  background: var(--space-1);
}
.pick-panel-top {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 8px;
}
.pick-panel-title { font-size: 12.5px; color: var(--muted); }
/* "清空选择"是个低频动作，用文字链而不是按钮 —— 别跟"上传"抢注意力 */
.link-btn {
  border: 0; background: none; padding: 0; cursor: pointer;
  font: inherit; font-size: 12.5px; color: var(--accent-lt);
  text-decoration: underline; text-underline-offset: 3px;
}
.link-btn:hover { color: var(--accent); }

.pick-list { list-style: none; margin: 0; padding: 0; max-height: 220px; overflow-y: auto; }
.pick-item {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 0; border-top: 1px solid var(--line); font-size: 13.5px;
}
.pick-item:first-child { border-top: 0; }
.pick-name {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pick-size-cell { flex: 0 0 auto; font-size: 11.5px; color: var(--muted); }
/* 超过单文件上限的行标红 —— 在**提交之前**就告诉他，别等一次失败 */
.pick-item.is-over .pick-size-cell { color: var(--err-fg); }
.pick-item.is-over .pick-name { color: var(--err-fg); }
.pick-del {
  flex: 0 0 auto; width: 22px; height: 22px; line-height: 1;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--space-0); color: var(--muted);
  font-size: 15px; cursor: pointer; padding: 0;
}
.pick-del:hover { color: var(--err-fg); border-color: var(--err-line); background: var(--err-bg); }

/* ---- 上传进度 ----
   之前完全没有反馈：选了文件点上传，几十兆要等好几秒，页面上一点动静都没有，
   看起来就像"点了没反应"。 */
.up-progress { display: flex; align-items: center; gap: 12px; margin-top: 12px; }
.up-bar {
  flex: 1 1 auto; height: 7px; border-radius: 999px; overflow: hidden;
  background: var(--hair); border: 1px solid var(--line);
}
.up-fill {
  display: block; height: 100%; width: 0;
  background: linear-gradient(90deg, var(--accent), var(--accent-lt));
  transition: width .15s linear;
}
.up-fill.is-err { background: linear-gradient(90deg, #C0483A, #FFB020); }
.up-text { flex: 0 0 auto; font-size: 11.5px; color: var(--muted); font-family: var(--mono); }
.drive-mkdir { display: flex; gap: 10px; align-items: center; }
.drive-mkdir .input { max-width: 320px; }

.drive-crumbs { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin: 18px 0 10px; color: var(--muted); }
.drive-crumbs a { color: var(--accent-lt); text-decoration: none; }
.drive-crumbs a:hover { text-decoration: underline; }
.drive-tools { display: flex; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }

.data-table .cell-sub { color: var(--muted); margin-top: 3px; font-size: 11.5px; }

/* 网盘/个人空间的表格：状态、栏目、时间、操作这几列都不该被挤到折行。
   时间戳折成两行以后，整行高度翻倍，表格看着就散了。 */
.drive-table td:nth-child(2), .drive-table td:nth-child(3),
.drive-table td:nth-child(4), .drive-table th:nth-child(2),
.drive-table th:nth-child(3), .drive-table th:nth-child(4) { white-space: nowrap; }
.space-table td:nth-child(2), .space-table td:nth-child(3),
.space-table td:nth-child(4), .space-table th:nth-child(2),
.space-table th:nth-child(3), .space-table th:nth-child(4) { white-space: nowrap; }
.space-table td:nth-child(1) { min-width: 260px; }
.space-table .row-actions a { white-space: nowrap; }
/* 操作列的宽度按内容给，别让它把名字列挤窄 */
.space-table td:last-child, .drive-table td:last-child { width: 1%; }
/* 行内重命名输入框收窄：铺满整列会让每一行都显得很吵，
   而这只是「需要时才改一下」的次要操作 */
.drive-table .input-sm { width: 150px; }

/* 帖子编辑：正文占主栏，附件与申请公开放侧栏 */
.post-edit { display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(280px, .95fr); gap: 34px; align-items: start; }
.post-side { padding: 20px; border: 1px solid var(--line); border-radius: var(--r); background: var(--space-1); }
.post-form .field { display: block; margin-bottom: 16px; }
.field-key { display: block; margin-bottom: 6px; font-family: var(--mono); font-size: 11px; color: var(--muted); }

.media-list { list-style: none; margin: 12px 0; padding: 0; }
.media-list li { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.media-list li a { color: var(--accent-lt); flex: 1 1 auto; word-break: break-all; }
.media-list .mono { color: var(--muted); }
.media-list .badge { flex: 0 0 auto; }

/* 附件类型徽章（PDF / DOCX / ZIP…）。文件图标用 emoji 在不同系统上长得
   天差地别，用一个小色块写扩展名反而稳定、也一眼能分辨。 */
.badge {
  display: inline-block; min-width: 44px; padding: 2px 7px; border-radius: var(--r-sm);
  background: rgba(15, 107, 255, .16); border: 1px solid rgba(15, 107, 255, .34);
  color: var(--accent-lt); font-family: var(--mono); font-size: 10.5px;
  letter-spacing: .04em; text-align: center; white-space: nowrap;
}

/* ---- 图片区 ----
   图片要「铺出来给人看」，所以是网格而不是清单：
   auto-fit + minmax 让它在宽屏上排两列、窄屏自动变一列。 */
.post-gallery {
  display: grid; gap: 14px; margin: 16px 0 4px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.gallery-item {
  margin: 0; padding: 10px; border: 1px solid var(--line);
  border-radius: var(--r); background: var(--space-1);
}
.gallery-item img {
  width: 100%; height: 200px; object-fit: cover;
  border-radius: var(--r-sm); background: var(--space-0); display: block;
}
.gallery-item a { display: block; }
.gallery-item figcaption {
  margin-top: 8px; color: var(--muted); font-size: 11px;
  display: flex; align-items: center; gap: 8px; justify-content: space-between;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gallery-item figcaption code { color: var(--accent-lt); }
/* 编辑页里的图集缩小一号：那里是「管理附件」不是「欣赏作品」 */
.post-gallery.is-compact { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.post-gallery.is-compact .gallery-item { padding: 7px; }
.post-gallery.is-compact .gallery-item img { height: 110px; }
.post-gallery.is-compact .gallery-item figcaption { flex-wrap: wrap; white-space: normal; }

/* 「从网盘挑一个」是个低频动作，收进折叠里，别跟上传抢位置 */
.pick-existing { margin-top: 14px; }
.pick-existing summary {
  cursor: pointer; color: var(--muted); font-size: 12px;
  font-family: var(--mono); padding: 4px 0;
}
.pick-existing summary:hover { color: var(--accent-lt); }
.pick-existing .field { margin-top: 10px; }

/* 帖子正文。行高比正文区略大，长文读起来不累 */
.post-body { font-size: 16px; line-height: 1.85; color: var(--text-2); max-width: 74ch; }
.post-body a { color: var(--accent-lt); }
.post-body code {
  font-family: var(--mono); font-size: 13.5px; padding: 2px 6px;
  background: var(--raise); border-radius: var(--r-sm);
}
/* 正文里内联的图。约束最大高度，否则一张竖拍手机照片会把整页撑到看不出结构 */
.pm-img {
  display: block; max-width: 100%; max-height: 520px; width: auto; height: auto;
  border-radius: var(--r); border: 1px solid var(--line);
  margin: 16px auto; background: var(--space-1);
}

.quota-form { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }



/* ==========================================================================
   Skill 库
   ========================================================================== */

/* 卡片墙：一个技能一张卡。用 auto-fill 而不是 auto-fit ——
   技能少的时候卡片不会拉得很宽，看着更整齐。 */
.skill-grid {
  display: grid; gap: 16px; margin: 18px 0;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.skill-card {
  display: flex; flex-direction: column; gap: 10px;
  padding: 18px; border-radius: var(--r); text-decoration: none;
  border: 1px solid var(--line); background: var(--space-1);
  transition: border-color .18s ease, background .18s ease;
}
.skill-card:hover { border-color: var(--accent); background: rgba(15, 107, 255, .06); }
.skill-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.skill-name { font-size: 15.5px; font-weight: 700; letter-spacing: -.01em; }
.skill-sum { margin: 0; font-size: 13.5px; line-height: 1.65; color: var(--text-2); }
.skill-foot {
  display: flex; justify-content: space-between; gap: 10px;
  margin-top: auto; padding-top: 8px;
  font-size: 11px; color: var(--muted); border-top: 1px solid var(--line);
}

.skill-table td:nth-child(3), .skill-table td:nth-child(4),
.skill-table td:nth-child(5), .skill-table th:nth-child(3),
.skill-table th:nth-child(4), .skill-table th:nth-child(5) { white-space: nowrap; }
.skill-table td:last-child { width: 1%; white-space: nowrap; }

/* 详情页：三块说明并排，窄屏堆成一列 */
.skill-about { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); margin: 8px 0 18px; }
.skill-block h3 { margin-top: 0; }
.skill-block p { font-size: 14px; line-height: 1.75; color: var(--text-2); }

/* SKILL.md 正文。它比帖子长得多，行高和字号按长文来 */
.md-body {
  font-size: 14.5px; line-height: 1.8; color: var(--text-2);
  max-width: 82ch; margin-top: 12px;
}
.md-body h2, .md-body h3, .md-body h4 { color: var(--text); margin: 22px 0 10px;
  font-size: 16px; letter-spacing: -.01em; }
.md-body h2:first-child { margin-top: 0; }
.md-body p { margin: 0 0 12px; }
.md-body ul, .md-body ol { margin: 0 0 12px; padding-left: 22px; }
.md-body li { margin: 4px 0; }
.md-body a { color: var(--accent-lt); }
.md-body blockquote {
  margin: 12px 0; padding: 10px 14px; border-left: 3px solid var(--line-2);
  background: var(--space-1); border-radius: var(--r-sm); color: var(--muted);
}
.md-body .md-hr { border: 0; border-top: 1px solid var(--line); margin: 20px 0; }
/* 代码块要能横向滚 —— SKILL.md 里的命令行很长，硬折行反而看不清 */
.md-body .code {
  background: var(--space-0); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 12px 14px; overflow-x: auto; font-size: 12.5px; line-height: 1.7;
  margin: 0 0 14px; white-space: pre;
}
.md-body code {
  font-family: var(--mono); font-size: 12.5px;
  background: var(--raise); border-radius: var(--r-sm); padding: 1px 5px;
}
.md-body .code code { background: none; padding: 0; }

/* ==========================================================================
   后台「用户管理」：列表 + 搜索 → 点进单人编辑
   ========================================================================== */

/* 搜索条：人多时的主要导航方式，给它固定的位置 */
.user-search {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 16px 0 18px;
}
.user-search .input { max-width: 320px; }

/* 列表：一行一个用户。列宽固定下来，「调整」按钮就不会被挤到换行 */
.user-table td:last-child { width: 1%; white-space: nowrap; }
.user-table td:last-child .btn { white-space: nowrap; }
.user-table td:nth-child(2), .user-table td:nth-child(3),
.user-table th:nth-child(2), .user-table th:nth-child(3) { white-space: nowrap; }
.user-table td:nth-child(5) { white-space: nowrap; }
.user-table .cell-sub { color: var(--muted); margin-top: 3px; font-size: 11.5px; }
/* 板块权限用小胶囊列出来，一眼看出这个人被开了哪些 */
.user-table .chip-sm {
  display: inline-block; margin: 2px 4px 2px 0; padding: 2px 8px;
  font-size: 11px; border-radius: 999px;
  border: 1px solid var(--line); color: var(--text-2); background: var(--space-0);
}
.user-table .faint { color: var(--muted); }

/* 单人编辑页：整个卡片就是一个表单，宽度别铺满，行太长不好读 */
.user-edit { max-width: 880px; }
.user-edit .admin-grid { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.user-edit .admin-save { display: flex; gap: 10px; align-items: center; }
.user-edit .admin-cell select, .user-edit .admin-cell input { max-width: 100%; }

/* ==========================================================================
   运维面板（站长个人中心 → 网站运维）
   ========================================================================== */

/* 四个大数字：先给结论，细节放下面 */
/* 页面界面版本：两张预览图并排，一眼看出哪个是哪个。
   只放"亮色首页"一张就够 —— 版本之间的差别主要在那儿，
   两张缩略图并排已经能认出来，再堆暗色的反而看不清。 */
.ui-pick {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 16px;
}
.ui-pick-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--r);
  background: var(--space-1);
}
/* 正在用的那个给一圈明显的主色描边 —— 面板上最要紧的信息就是"现在是哪个" */
.ui-pick-card.is-on {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent) inset;
}
.ui-pick-thumb {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top left;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}
.ui-pick-body { display: flex; flex-direction: column; gap: 4px; }
.ui-pick-body strong { font-size: 14px; }

.ops-grid {
  display: grid; gap: 14px; margin: 18px 0;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.ops-card {
  padding: 16px 18px; border-radius: var(--r);
  border: 1px solid var(--line); background: var(--space-1);
  display: flex; flex-direction: column; gap: 6px;
}
/* 「已分配配额」是最常被问的那个数，给它一点强调 */
.ops-card.is-key { border-color: rgba(15, 107, 255, .45); background: rgba(15, 107, 255, .07); }
.ops-key { font-family: var(--mono); font-size: 11px; color: var(--muted); }
.ops-val { font-size: 24px; font-weight: 700; letter-spacing: -.02em; }
.ops-sub { font-size: 11.5px; color: var(--muted); line-height: 1.5; }

/* 明细行：左标签右数值，等宽字体好对齐 */
.ops-rows { border-top: 1px solid var(--line); margin: 6px 0 18px; }
.ops-row {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 9px 2px; border-bottom: 1px solid var(--line); font-size: 13.5px;
}
.ops-row span { color: var(--muted); }
.ops-row em { font-style: normal; font-family: var(--mono); font-size: 12.5px;
               word-break: break-all; text-align: right; }
/* 左右两边都是路径的行才走等宽 —— 标签是汉字时别挂 is-mono，
   汉字在等宽字体里只能走回退字体，和右边的路径对不齐。 */
.ops-rows.is-mono .ops-row span,
.ops-row.is-mono span { font-family: var(--mono); font-size: 12px; }

.ops-bar { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; margin: 14px 0; }
.ops-inline { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ops-bar .hint, .ops-inline .hint { margin: 0; }

/* 恢复与更新并排；窄屏自动堆成一列 */
.ops-two { display: grid; gap: 18px; margin: 24px 0; grid-template-columns: 1fr 1fr; }
.ops-panel { padding: 18px; border: 1px solid var(--line); border-radius: var(--r); background: var(--space-1); }
.ops-panel .sub-head { margin-top: 0; }
.ops-panel form { margin: 12px 0 10px; display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.ops-panel .file-input { flex: 1 1 180px; }

/* 「准备恢复/更新」的确认区。用醒目的左边框表示「这是待确认的覆盖性操作」 */
.ops-pending {
  margin: 22px 0; padding: 18px 20px; border-radius: var(--r);
  border: 1px solid var(--warn-line); border-left-width: 4px;
  background: var(--warn-bg);
}
.ops-pending .sub-head { margin-top: 0; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ops-pending .code { max-height: 220px; }

.ops-table .row-actions { gap: 6px; flex-wrap: wrap; }
/* 操作列（下载 / 恢复+模式 / 删除）需要固定宽度，否则会被压成竖排 */
.ops-table td:last-child { width: auto; min-width: 330px; }
.ops-table .row-actions form { display: flex; align-items: center; gap: 6px; }
.ops-table select.input-sm { min-width: 118px; }

/* ==========================================================================
   安装命令块（Skill 详情页 / 列表页）
   --------------------------------------------------------------------------
   原来这里是**裸 `<pre class="code">`** —— CSS 里只有 `.md-body .code` 有样式，
   而这两处的 `.code` 不在 `.md-body` 里，所以它一直是浏览器默认外观：
   系统等宽字体、没有背景、没有内边距，长命令行换行糊成一片。
   顺手补齐，和 SKILL.md 正文里的代码块统一。
   ========================================================================== */
.codebox .code {
  background: var(--space-0);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: 12px 14px;
  margin: 0;
  overflow-x: auto;
  font-family: var(--mono);
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--text-2);
  white-space: pre;
}

/* ==========================================================================
   切换主题时的整体过渡
   --------------------------------------------------------------------------
   直接换 data-theme 会让整页"啪"地一下翻色，很刺眼。
   这里的做法是：切换的那 560ms 里给 <html> 挂一个 `theme-anim` 类，
   只在**这段时间**给所有元素加颜色类过渡，完了就摘掉。

   为什么不做成常驻的 `* { transition: … }`：那会让 hover、抽屉、动画全都变钝，
   而且几百个元素常驻 transition 对合成器也是白白的负担。
   -------------------------------------------------------------------------- */
html.theme-anim,
html.theme-anim *,
html.theme-anim *::before,
html.theme-anim *::after {
  /* 故意不含 opacity / transform：首屏两套场景的交叉淡入有自己的 .9s 节奏，
     被这里覆盖掉就变成"整块一起闪"了 */
  transition: background-color .52s ease, border-color .52s ease,
              color .52s ease, fill .52s ease, stroke .52s ease,
              box-shadow .52s ease !important;
}

@media (prefers-reduced-motion: reduce) {
  /* 动效降级时不做过场，直接换 */
  html.theme-anim, html.theme-anim * { transition: none !important; }
}

/* ==========================================================================
   亮色主题的组件级补充
   --------------------------------------------------------------------------
   绝大多数组件只靠上面的变量就自动适配了。这一节只处理三类改不了的情况：

     ① **几何**：变量表达不了位置（首屏辉光的左右，已经写在一场景里了）。
     ② **手法**：暗色靠"发光"，亮色得靠"投影"。同一个 box-shadow 在两套
        配色下不是一回事 —— 深底上的蓝色辉光在浅底上会变成一圈脏边。
     ③ **叠加方向**：暗色里"比底更亮"用叠加白色，亮色里对应的动作是叠加墨色，
        但反过来又会让某些面消失（输入框盖在白卡片上就看不见了）。
   ========================================================================== */

/* 亮底上的"发光"要换成"投影"：深色底上那圈蓝光在浅底上是一圈脏边 */
[data-theme="light"] .btn-primary {
  box-shadow: 0 6px 16px rgba(15, 107, 255, .28);
}
[data-theme="light"] .btn-primary:hover {
  box-shadow: 0 8px 22px rgba(15, 107, 255, .36);
}

/* 品牌徽标：灰底上要用深一点的描边 */
[data-theme="light"] .brand-mark {
  box-shadow:
    0 0 0 1px rgba(11, 15, 22, .22),
    0 2px 10px rgba(11, 15, 22, .16);
}

/* 输入框：暗色下比底更亮才显得"凹进去"，亮色下必须反过来给近白，
   否则浅蓝的底盖在浅蓝卡片上根本看不出哪里能输入 */
[data-theme="light"] .input,
[data-theme="light"] .textarea,
[data-theme="light"] select.input {
  background: #EAF4FB;      /* 比卡片更亮一点点，但不再是纯白 */
}

/* 首屏底部那排数据条：亮色下不能用深色玻璃，改用浅色玻璃 */
[data-theme="light"] .hero-meta { backdrop-filter: blur(8px); }


@media (max-width: 1080px) {
  .ops-two { grid-template-columns: 1fr; }
}

.pill.is-err { color: var(--err-fg); background: var(--err-bg); border-color: var(--err-line); }

@media (max-width: 1080px) {
  .post-edit { grid-template-columns: 1fr; gap: 26px; }
}

/* ==========================================================================
   响应式
   ========================================================================== */

@media (max-width: 1080px) {
  .stage-body { grid-template-columns: 1fr; gap: 40px; }
  .scan-panel { position: static; max-width: 420px; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 960px) {
  .sidebar {
    transform: translateX(-100%);
    transition: transform .26s cubic-bezier(.22, .61, .36, 1);
    box-shadow: var(--shadow-lg);
  }
  body.nav-open .sidebar { transform: none; }

  .main { margin-left: 0; }
  .menu-btn { display: inline-flex; }
  .topbar { padding: 0 20px; }
  .content { padding: 0 20px 56px; }
  .hero, .page-head { margin: 0 -20px; }
  .hero-inner { padding: 84px 20px 46px; }
  .page-head-inner { padding: 72px 20px 32px; }
  .hero-meta > div { padding: 16px 20px; }
  .footer { padding: 40px 20px 22px; }

  .status-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .status-cell:nth-child(2) { border-right: 0; }
  .status-cell:nth-child(1), .status-cell:nth-child(2) { border-bottom: 1px solid var(--line); }
}

@media (max-width: 620px) {
  body { font-size: 15px; }
  .crumb-root, .crumb-sep, .build-chip { display: none; }
  .hero-meta { grid-template-columns: 1fr; }
  .hero-meta > div { border-right: 0; border-bottom: 1px solid var(--line); }
  .hero-meta > div:last-child { border-bottom: 0; }
  .status-grid { grid-template-columns: 1fr; }
  .status-cell { border-right: 0; border-bottom: 1px solid var(--line); }
  .status-cell:last-child { border-bottom: 0; }
  .spec-row { grid-template-columns: 1fr; gap: 4px; }
  .footer-grid { grid-template-columns: 1fr; gap: 28px; }
  .hero-title { font-size: 36px; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition: none !important; }
}

/* ==========================================================================
   中文排版覆盖（**故意放最后**）
   --------------------------------------------------------------------------
   上面那些负字距和 1.0x 的行距都是**为拉丁文调的**：拉丁字母字面窄、x-height 小，
   收紧一点更像标题、行距紧一点更成块。汉字是满格方块字，同样的值会反过来 ——
   负字距让**笔画相碰**，1.0x 行距让**两行贴在一起**。中文标题的安全值是
   `letter-spacing: 0` + `line-height ≈ 1.16`。

   ## 为什么这一块必须在文件最后

   `:lang(zh) h2` 和 `.section-head h2` **特异性都是 (0,1,1)** —— 一样重，谁在后面谁赢。
   放在中间就会被 `.section-head h2 { letter-spacing: -.03em }` 盖掉，
   而且盖得很安静：别的标题紧了、就那一处还是挤的。
   放最后 + 逐条列出组件名，两条保险都上。

   ## 为什么只动字距和行距，不动字号

   字号有响应式媒体查询在后面盯着（`.hero-title { font-size: 36px }` 那一组），
   而 `:lang(zh) .hero-title` 的特异性比 `.hero-title` 高 —— 这里再设一次字号，
   就会把窄屏的那条**越权压掉**。所以字号只在基础规则里调。

   英文页面一个字都不受影响，这是 `:lang()` 写法最大的好处。
   这份名单是 `cjk-web-typography` 技能里那把尺子（`scripts/cjk_audit.py`）扫出来的。
   ========================================================================== */
:lang(zh) h1, :lang(zh) h2, :lang(zh) h3,
:lang(zh) .hero-title, :lang(zh) .section-head h2,
:lang(zh) .focus-body h3, :lang(zh) .module h3,
:lang(zh) .stage-title, :lang(zh) .auth-title,
:lang(zh) .member-title, :lang(zh) .ops-val,
:lang(zh) .skill-name, :lang(zh) .md-body h4 {
  letter-spacing: 0;
}

/* 大字号的中文标题行距要跟上：字号越大，1.0x 越像两行贴在一起 */
:lang(zh) .hero-title { line-height: 1.18; }
:lang(zh) .stage-title { line-height: 1.18; }
:lang(zh) .section-head h2 { line-height: 1.4; }
:lang(zh) .module h3, :lang(zh) .focus-body h3 { line-height: 1.45; }

/* 首屏主标语：17px 的中文用 1.72 行距偏挤，一行放 56ch 又太长
   （`ch` 按拉丁文那个『0』的宽度算，跟方块字对不上）*/
:lang(zh) .hero-lead { line-height: 1.9; max-width: 30em; }

