/* 3APEX 后台 —— 样式
 *
 * 视觉语言（2026-10-05 重做）：
 *   · **近黑分层**：画布 / 面板 / 浮起 三层，靠发丝线分界，不靠"到处描边框的灰蓝卡片"
 *   · **品牌**：藏青打底 + 3APEX 金。金色只用于**主行动 / 当前态 / 品牌标记**，
 *     其余一律中性灰 —— 到处用金色等于没有重点。
 *   · **尺度**：字号 / 间距 / 圆角都走令牌，不在页面里手写 `margin-top:14px`
 *
 * 兼容（手机壳 console/app/ 是纯 WebView 壳，UI 全部来自这份 CSS）：
 *   · 真实内核下限是 **Chrome 86**（产物里有 `?.` / `??` / `replaceChildren`，
 *     见 capacitor.config.ts 的 minWebViewVersion 与 README），所以不用为 Chrome 60 做降级；
 *     但仍然避开更晚的特性：`:has()`(105)、`color-mix()`(111)、容器查询(105)、`dvh`(108)。
 *   · `env(safe-area-inset-*)` 继续走 `--safe-*`，刘海屏/手势条不被压住。
 *   · 保留 `table.stack` + `td[data-l]` 的"窄屏表格变卡片"约定（53 个 td 都在用）。
 *   · 保留 `.bar > i`（上传进度条，app.ts 用 querySelector 硬编码了这两个选择器）。
 */

/* ── 令牌 ─────────────────────────────────────────────── */

:root {
  /* 面：三层 + 两条发丝线 */
  --canvas: #0b0f16;      /* 页面底 */
  --surface: #111826;     /* 卡片 */
  --surface-2: #16202f;   /* 输入 / 次级按钮 / hover */
  --surface-3: #1e2a3c;   /* 再上一层 hover / 选中 */
  --line: rgba(255, 255, 255, .07);
  --line-2: rgba(255, 255, 255, .13);

  /* 字 */
  --ink: #e9eef7;
  --ink-2: #a7b3c6;
  --ink-3: #7b8798;

  /* 品牌 */
  --brand: #f3b94a;
  --brand-hi: #ffd98a;
  --brand-deep: #a9721c;
  --navy: #1b2333;        /* logo 的藏青，用在浅底上 */

  /* 语义 */
  --accent: #5aa9ff;
  --ok: #3ddc97;
  --warn: #ffc65c;
  --danger: #ff6b6b;
  --violet: #a97bf5;

  /* ── 结构性颜色（深浅两套主题都靠这些换肤，页面里不许再写死颜色） ── */
  --link: #8ac4ff;
  --on-brand: #241c08;              /* 金底上的字 */
  --side-bg: #0d1320;
  --appbar-bg: rgba(11, 15, 22, .92);
  --scrim: rgba(4, 7, 12, .6);
  --scrim-strong: rgba(4, 7, 12, .66);
  --plate-bg: #f1f4f9;              /* 放原色 logo 的浅底牌子 */
  --plate-line: rgba(0, 0, 0, .06);
  --hover: rgba(255, 255, 255, .022);
  --line-hover: rgba(255, 255, 255, .2);
  --fill-soft: rgba(255, 255, 255, .06);
  --fill-faint: rgba(255, 255, 255, .012);
  --track: rgba(255, 255, 255, .09);
  --dot-off: #3a465c;
  --skel-1: rgba(255, 255, 255, .05);
  --skel-2: rgba(255, 255, 255, .1);
  --selection: rgba(243, 185, 74, .28);
  --brand-soft: rgba(243, 185, 74, .06);
  --brand-ring: rgba(243, 185, 74, .14);
  --ok-ink: #6ee7ad;  --ok-bg: rgba(61, 220, 151, .13);   --ok-line: rgba(61, 220, 151, .35);
  --warn-ink: #ffd98a; --warn-bg: rgba(255, 198, 92, .12); --warn-line: rgba(255, 198, 92, .28);
  --danger-ink: #ff9b9b; --danger-bg: rgba(255, 107, 107, .12); --danger-soft: rgba(255, 107, 107, .12);
  --danger-line: rgba(255, 107, 107, .3); --danger-line-2: rgba(255, 107, 107, .4);
  --info-ink: #8ac4ff; --info-bg: rgba(90, 169, 255, .12); --info-line: rgba(90, 169, 255, .28);
  --violet-ink: #c9b0ff; --violet-bg: rgba(169, 123, 245, .16);
  --toast-err-bg: #2a1720;
  --glow-a: rgba(243, 185, 74, .10);
  --glow-b: rgba(90, 169, 255, .08);
  --page-glow-a: rgba(243, 185, 74, .045);
  --page-glow-b: rgba(90, 169, 255, .04);
  --shadow-plate: 0 30px 60px -30px rgba(0, 0, 0, .85);
  --shadow-card: 0 1px 0 rgba(255, 255, 255, .02) inset, 0 24px 60px -44px rgba(0, 0, 0, .95);

  /* 尺度 */
  --r-sm: 8px;
  --r: 12px;
  --r-lg: 16px;
  --s1: 4px; --s2: 8px; --s3: 14px; --s4: 22px; --s5: 34px; --s6: 56px;
  --t-xs: 12.5px; --t-sm: 13.5px; --t: 15px; --t-lg: 17px; --t-xl: 26px; --t-2xl: 42px;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-2: 0 1px 2px rgba(0, 0, 0, .4), 0 12px 32px -12px rgba(0, 0, 0, .7);

  /* ── 旧令牌：还在这份文件里/老页面里被引用的名字，映射到新值 ── */
  --bg: var(--canvas);
  --panel: var(--surface);
  --panel-hi: var(--surface-2);
  --ink-dim: var(--ink-2);
  --gold: var(--brand);
  --gold-hi: var(--brand-hi);
  --green: var(--ok);
  --red: var(--danger);
  --purple: var(--violet);
  --radius: var(--r);
  --gap: var(--s4);

  /* 刘海屏 / 手势条。⚠️ 桌面浏览器上这些恒为 0，calc() 等于没加。 */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);

  --sidebar-w: 264px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--canvas);
  color: var(--ink);
  font: var(--t)/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
        "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: none; color: var(--link); }

::selection { background: var(--selection); }

/* 焦点圈：键盘操作必须看得见（鼠标点击不显示，靠 :focus-visible） */
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 4px; }

#app { min-height: 100vh; }

/* 首屏占位（index.html 里那段 ES5 脚本会在超时后把它变成"内核太旧"的提示） */
.boot { min-height: 100vh; display: flex; flex-direction: column; align-items: center;
        justify-content: center; gap: var(--s4); color: var(--ink-3); font-size: var(--t-sm); }
.boot .logomark { width: 40px; height: 40px; animation: pulse 1.6s ease-in-out infinite; }
.boot .stuck { display: none; max-width: 460px; text-align: center; line-height: 1.7; }
.boot.is-stuck .logomark { animation: none; opacity: .5; }
.boot.is-stuck .stuck { display: block; }
.boot.is-stuck .loading { display: none; }
@keyframes pulse { 0%, 100% { opacity: .35 } 50% { opacity: 1 } }

/* ── 品牌标记 ──────────────────────────────────────────
   ⚠️ **不给 logo 改色。** logo 是深藏青图案，放近黑侧栏上根本看不见 ——
   正确做法是给它一块浅底（和手机桌面那个 APK 图标同一种做法），
   而不是把品牌色反成白的 / 金的。改色等于让"3APEX 长什么样"出现第二个版本。
   ──────────────────────────────────────────────────────── */
.logomark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 30px; height: 30px;
  border-radius: 8px;
  background: var(--plate-bg);
  box-shadow: inset 0 0 0 1px var(--plate-line);
}
.logomark img { display: block; width: 72%; height: 72%; }

/* ── 外壳：侧栏 + 内容 ───────────────────────────────── */

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

.side {
  position: sticky;
  top: 0;
  align-self: flex-start;
  height: 100vh;
  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  background: var(--side-bg);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  padding: calc(var(--s4) + var(--safe-top)) 0 var(--s4);
  z-index: 30;
}

.side-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s2);
  padding: 0 var(--s3) var(--s5) var(--s4);
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: 0;
  color: var(--ink);
  font-size: var(--t-lg);
  font-weight: 700;
  letter-spacing: .06em;
  white-space: nowrap;
}
.brand:hover { color: var(--ink); }
.brand .logotext { display: flex; flex-direction: column; line-height: 1.15; }
.brand small {
  font-size: var(--t-xs);
  font-weight: 400;
  letter-spacing: .02em;
  color: var(--ink-3);
  margin-top: 2px;
}

.nav { display: flex; flex-direction: column; gap: 1px; padding: 0 var(--s2); overflow-y: auto; }
.nav-label {
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: var(--s4) var(--s3) var(--s1);
}
.nav-label:first-child { padding-top: 0; }

.nav a {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: 8px var(--s3);
  border-radius: var(--r-sm);
  color: var(--ink-2);
  font-size: var(--t);
  transition: background .12s ease, color .12s ease;
}
.nav a:hover { background: var(--surface-2); color: var(--ink); }
.nav a.on { background: var(--surface-3); color: var(--ink); font-weight: 600; }
.nav a.on::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--s2));
  top: 50%;
  transform: translateY(-50%);
  width: 2px; height: 16px;
  border-radius: 2px;
  background: var(--brand);
}

.side-foot {
  margin-top: auto;
  padding: var(--s3) var(--s3) 0;
  border-top: 1px solid var(--line);
  font-size: var(--t-sm);
  color: var(--ink-3);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}
.who { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
.who .avatar {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-3);
  color: var(--brand);
  font-weight: 700;
  font-size: var(--t-sm);
  text-transform: uppercase;
}
.who .who-text { min-width: 0; }
.who .who-name { color: var(--ink); font-size: var(--t); font-weight: 600;
                 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.who .who-role { font-size: var(--t-xs); color: var(--ink-3); }
.side-foot .foot-actions { display: flex; gap: var(--s2); }

/* 内容区 */
.content { flex: 1; min-width: 0; display: flex; flex-direction: column; }

.appbar {
  display: none;                 /* 桌面不需要（侧栏够用），≤720px 才出现 */
  position: sticky;
  top: 0;
  z-index: 20;
  align-items: center;
  gap: var(--s3);
  padding: calc(var(--s2) + var(--safe-top)) calc(var(--s4) + var(--safe-right))
           var(--s2) calc(var(--s4) + var(--safe-left));
  background: var(--appbar-bg);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
.appbar .brand { padding: 0; font-size: var(--t); }
.appbar .appbar-title { font-weight: 600; font-size: var(--t); color: var(--ink-2); margin-left: auto; }

.main {
  flex: 1;
  width: 100%;
  max-width: 1180px;
  padding: var(--s6) calc(var(--s6) + var(--safe-right)) calc(72px + var(--safe-bottom)) calc(var(--s6) + var(--safe-left));
}

.scrim {
  display: none;
  position: fixed;
  inset: 0;
  background: var(--scrim);
  z-index: 25;
}

/* ── 通用件 ───────────────────────────────────────────── */

h1 { font-size: var(--t-xl); margin: 0 0 var(--s1); font-weight: 650; letter-spacing: -.01em; }
h2 { font-size: var(--t-lg); margin: var(--s5) 0 var(--s3); color: var(--ink); font-weight: 600; }
h2:first-child { margin-top: 0; }
.sub { color: var(--ink-2); font-size: var(--t-sm); margin: 0 0 var(--s4); }

/* 页头：标题 + 说明 + 右侧行动 */
.ph { display: flex; align-items: flex-start; justify-content: space-between;
      gap: var(--s4); flex-wrap: wrap; margin-bottom: var(--s5); }
.ph .ph-text { min-width: 0; }
.ph .ph-actions { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.ph h1 { margin-bottom: 2px; }

/* 面包屑 */
.crumbs { display: flex; align-items: center; gap: var(--s2); font-size: var(--t-sm);
          color: var(--ink-3); margin-bottom: var(--s2); }
.crumbs a { color: var(--ink-3); }
.crumbs a:hover { color: var(--ink); }
.crumbs .sep { opacity: .5; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s4);
  overflow-x: auto;
}
.card.flush { padding: 0; overflow: hidden; }
.card + .card { margin-top: var(--s3); }
.card-title { font-size: var(--t); font-weight: 600; margin: 0 0 var(--s3); display: flex; align-items: center; gap: var(--s2); }
.card-note { color: var(--ink-3); font-size: var(--t-sm); }

/* 分节标题：一块一块，而不是一路 h2 堆下去 */
.section { margin-top: var(--s6); }
.section-head { display: flex; align-items: baseline; justify-content: space-between;
                gap: var(--s3); margin-bottom: var(--s3); flex-wrap: wrap; }
.section-head h2 { margin: 0; }
.section-head .hint { color: var(--ink-3); font-size: var(--t-sm); }

.grid { display: grid; gap: var(--s3); }
.grid.k2 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.grid.k3 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* ── 按钮 ─────────────────────────────────────────────── */

button, .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font: inherit;
  font-size: var(--t-sm);
  line-height: 1;
  padding: 8px 12px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-2);
  background: var(--surface-2);
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  transition: background .12s ease, border-color .12s ease, color .12s ease;
}
button:hover, .btn:hover { background: var(--surface-3); border-color: var(--line-2); color: var(--ink); }

/* ⚠️ 之前只有 `button.primary` 这一条元素选择器，于是 `a.btn.primary`（项目详情 tab、
   「▶ 打开」主按钮）**从来没被上过色**。这里用类选择器一次修掉。 */
button.primary, .btn.primary {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--on-brand);
  font-weight: 600;
}
button.primary:hover, .btn.primary:hover { background: var(--brand-hi); border-color: var(--brand-hi); color: var(--on-brand); }

button.ghost, .btn.ghost { background: transparent; border-color: var(--line); color: var(--ink-2); }
button.ghost:hover, .btn.ghost:hover { background: var(--surface-2); color: var(--ink); }

button.danger, .btn.danger { color: var(--danger); border-color: var(--danger-line); background: transparent; }
button.danger:hover, .btn.danger:hover { background: var(--danger-soft); border-color: var(--danger-line-2); color: var(--danger-ink); }
/* 组合类要单独写一条：`button.sm.ghost` 比 `button.danger` 更具体，
   不加这条的话老页面里的「删除」（sm ghost danger）会被 ghost 的灰字盖掉。 */
button.ghost.danger, .btn.ghost.danger { color: var(--danger); border-color: var(--danger-line); }
button.ghost.danger:hover, .btn.ghost.danger:hover { color: var(--danger-ink); background: var(--danger-soft); }

button.sm, .btn.sm { padding: 5px 9px; font-size: var(--t-xs); }
button.sm.ghost, .btn.sm.ghost { padding: 5px 8px; }
button.icon, .btn.icon { padding: 6px; border-color: transparent; background: transparent; color: var(--ink-2); }
button.icon:hover, .btn.icon:hover { background: var(--surface-2); color: var(--ink); }

button:disabled, .btn:disabled { opacity: .45; cursor: not-allowed; }

/* 提交中：禁用 + 转圈。文字保留（不然按钮宽度会跳，"点没点上"也更难判断） */
.is-busy { pointer-events: none; opacity: .7; }
.is-busy::after {
  content: "";
  width: 12px; height: 12px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg) } }

/* 让按钮占满一行（登录页的「登录」） */
.btn-block { width: 100%; }

/* ── 表单 ─────────────────────────────────────────────── */

input, textarea, select {
  font: inherit;
  font-size: var(--t);
  width: 100%;
  padding: 8px 11px;
  border-radius: var(--r-sm);
  border: 1px solid var(--line-2);
  background: var(--surface-2);
  color: var(--ink);
  transition: border-color .12s ease, background .12s ease;
}
input::placeholder, textarea::placeholder { color: var(--ink-3); }
input:hover, textarea:hover, select:hover { border-color: var(--line-hover); }
input:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--brand);
  background: var(--surface-3);
  box-shadow: 0 0 0 3px var(--brand-ring);
}
textarea { min-height: 72px; resize: vertical; }
select { appearance: none; -webkit-appearance: none; padding-right: 30px;
         background-image: linear-gradient(45deg, transparent 50%, var(--ink-3) 50%),
                           linear-gradient(135deg, var(--ink-3) 50%, transparent 50%);
         background-position: calc(100% - 16px) 52%, calc(100% - 11px) 52%;
         background-size: 5px 5px, 5px 5px;
         background-repeat: no-repeat; }

.field { margin-bottom: var(--s3); }
.field > label, label {
  display: block;
  font-size: var(--t-sm);
  color: var(--ink-2);
  margin: 0 0 5px;
}
.field .hint { font-size: var(--t-xs); color: var(--ink-3); margin-top: 4px; }
.field.inline { display: flex; align-items: center; gap: var(--s2); }
.field.inline label { margin: 0; }
label.check { display: flex; align-items: center; gap: var(--s2); font-size: var(--t); color: var(--ink); margin: 0; }
label.check input { width: auto; }

.row { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.row.end { justify-content: flex-end; }
.row.mid { justify-content: center; }
.spread { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s3); flex-wrap: wrap; }
.mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.muted { color: var(--ink-3); }

/* ── 表格 ─────────────────────────────────────────────── */

table { width: 100%; border-collapse: collapse; font-size: var(--t); }
th, td { text-align: left; padding: 10px var(--s3); border-bottom: 1px solid var(--line); vertical-align: top; }
th { color: var(--ink-3); font-weight: 500; font-size: var(--t-xs);
     letter-spacing: .06em; text-transform: uppercase; white-space: nowrap; }
tbody tr { transition: background .1s ease; }
tbody tr:hover { background: var(--hover); }
tbody tr:last-child td { border-bottom: none; }
td.num { text-align: right; font-variant-numeric: tabular-nums; font-family: var(--mono); }
.cell-sub { color: var(--ink-3); font-size: var(--t-xs); margin-top: 2px; }
.checks li.err { color: var(--danger-ink); }
.lrow .l-meta.one { display: block; }

/* ── 标签 / 状态 ──────────────────────────────────────── */

.tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--t-xs);
  line-height: 1;
  padding: 4px 8px;
  border-radius: 999px;
  background: var(--fill-soft);
  color: var(--ink-2);
  white-space: nowrap;
}
.tag::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; opacity: .85; }

/* 语义色各占一档：「已上线」和「已完成」不再长得一模一样 */
.tag.live, .tag.ok, .tag.done { background: var(--ok-bg); color: var(--ok-ink); }
.tag.planning, .tag.doing, .tag.warn { background: var(--warn-bg); color: var(--warn-ink); }
.tag.archived, .tag.todo { background: var(--fill-soft); color: var(--ink-3); }
.tag.dev, .tag.info { background: var(--info-bg); color: var(--info-ink); }
.tag.milestone { background: var(--violet-bg); color: var(--violet-ink); }
.tag.bad, .tag.err { background: var(--danger-bg); color: var(--danger-ink); }
.tag.plain::before { display: none; }

/* ── 阶段轴 ───────────────────────────────────────────── */

.axis { display: flex; flex-direction: column; gap: 0; }
.axis-item {
  display: flex;
  gap: var(--s3);
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--line);
}
.axis-item:last-child { border-bottom: none; }
.axis-mark { flex: 0 0 22px; display: flex; flex-direction: column; align-items: center; padding-top: 3px; }
.dot { width: 10px; height: 10px; border-radius: 50%; background: var(--dot-off); }
.dot.done { background: var(--ok); }
.dot.doing { background: var(--brand); box-shadow: 0 0 0 4px var(--brand-ring); }
.axis-body { flex: 1; min-width: 0; }
.axis-name { font-weight: 600; display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.axis-goal { color: var(--ink-2); font-size: var(--t-sm); margin-top: 3px; }
.axis-evidence { color: var(--violet); font-size: var(--t-xs); margin-top: 5px; }

/* ── 时间线 ───────────────────────────────────────────── */

.tl { list-style: none; margin: 0; padding: 0; font-size: var(--t-sm); }
.tl li { display: flex; gap: var(--s3); padding: 7px 0; border-bottom: 1px solid var(--line); }
.tl li:last-child { border-bottom: none; }
.tl time, .tl .tl-key { flex: 0 0 122px; color: var(--ink-3); font-variant-numeric: tabular-nums; font-size: var(--t-xs); padding-top: 1px; }

/* ── 统计块 ───────────────────────────────────────────── */

.stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s4);
}
.stat .k { font-size: var(--t-xs); color: var(--ink-3); letter-spacing: .06em; text-transform: uppercase; }
.stat .v { font-size: var(--t-2xl); font-weight: 650; margin-top: 6px; line-height: 1.1;
           letter-spacing: -.02em; font-variant-numeric: tabular-nums; }
.stat .n { font-size: var(--t-sm); color: var(--ink-3); margin-top: 5px; }
.stat.accent .v { color: var(--brand); }

/* 列表行（替代"每个项目一张卡"）：项目名 + 状态 + 进度 + 最近上传 + 行动 */
.rows { display: flex; flex-direction: column; }
.lrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--s4);
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--line);
  transition: background .1s ease;
}
.lrow:last-child { border-bottom: none; }
.lrow:hover { background: var(--hover); }
.lrow .l-main { flex: 1; min-width: 0; }
.lrow .l-name { font-weight: 600; color: var(--ink); display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.lrow .l-desc { color: var(--ink-3); font-size: var(--t-sm); margin-top: 3px;
                overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* meta 默认是普通横排（游戏页那种"文字 + 文字"用）；数字列要用 .num 显式声明：
   **固定列宽 + 右对齐**，这样竖着扫一列数字才对得上 —— 表格唯一比卡片强的地方就在这。 */
.lrow .l-meta { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
                color: var(--ink-2); font-size: var(--t-sm); }
.lrow .l-meta.num { display: grid; grid-template-columns: 104px 128px 68px 132px; justify-items: end; }
.lrow .l-meta > * { white-space: nowrap; }
.lrow .l-act { display: flex; align-items: center; gap: var(--s2); }

/* 迷你进度条（阶段 3/7） */
.bar-mini { width: 76px; height: 4px; border-radius: 999px; background: var(--track); overflow: hidden; }
.bar-mini > i { display: block; height: 100%; background: var(--brand); border-radius: 999px; }

/* ── 上传区 ───────────────────────────────────────────── */

.drop {
  border: 1.5px dashed var(--line-2);
  border-radius: var(--r-lg);
  padding: var(--s6) var(--s4);
  text-align: center;
  color: var(--ink-2);
  cursor: pointer;
  background: var(--fill-faint);
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.drop:hover, .drop.over { border-color: var(--brand); background: var(--brand-soft); color: var(--ink); }
.drop strong { color: var(--ink); font-weight: 600; display: block; }
.drop .drop-hint { margin-top: 6px; font-size: var(--t-xs); color: var(--ink-3); }
.drop .drop-icon { color: var(--ink-3); margin-bottom: var(--s3); display: flex; justify-content: center; }
.drop:hover .drop-icon, .drop.over .drop-icon { color: var(--brand); }

/* ⚠️ 结构不能改：app.ts 用 querySelector('.bar') / querySelector('i') 拿填充条 */
.bar { height: 5px; background: var(--track); border-radius: 999px; overflow: hidden; margin-top: var(--s3); }
.bar > i { display: block; height: 100%; background: linear-gradient(90deg, var(--brand-deep), var(--brand)); width: 0; transition: width .15s ease; }

/* ── 检查结果 ─────────────────────────────────────────── */

.checks { list-style: none; margin: var(--s2) 0 0; padding: 0; font-size: var(--t-sm); }
.checks li { padding: 3px 0; display: flex; gap: var(--s2); align-items: flex-start; }
.checks .warn { color: var(--warn); }
.checks .ok { color: var(--ink-3); }
.checks .err { color: var(--danger-ink); }

/* ── 提示 / 空态 / 骨架 ───────────────────────────────── */

#toast {
  position: fixed;
  left: 50%;
  bottom: calc(var(--s5) + var(--safe-bottom));
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  z-index: 60;
  pointer-events: none;
  width: max-content;
  max-width: min(92vw, 520px);
}
.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--s2);
  background: var(--surface-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  padding: 10px 14px;
  font-size: var(--t-sm);
  line-height: 1.5;
  box-shadow: var(--shadow-2);
  animation: toast-in .18s ease-out;
}
.toast.err { background: var(--toast-err-bg); border-color: var(--danger-line-2); }
.toast.ok { border-color: var(--ok-line); }
.toast .ic { flex: 0 0 auto; margin-top: 1px; }
.toast.err .ic { color: var(--danger); }
.toast.ok .ic { color: var(--ok); }
.toast.leaving { animation: toast-out .16s ease-in forwards; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px) } to { opacity: 1; transform: none } }
@keyframes toast-out { to { opacity: 0; transform: translateY(6px) } }

.warn-box {
  display: flex;
  gap: var(--s2);
  align-items: flex-start;
  background: var(--warn-bg);
  border: 1px solid var(--warn-line);
  color: var(--warn);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  font-size: var(--t-sm);
  margin-bottom: var(--s3);
}
.warn-box.info { background: var(--info-bg); border-color: var(--info-line); color: var(--info-ink); }
.warn-box.danger { background: var(--danger-bg); border-color: var(--danger-line); color: var(--danger-ink); }

.empty {
  color: var(--ink-3);
  font-size: var(--t-sm);
  padding: var(--s6) var(--s3);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s3);
}
.empty .empty-icon { color: var(--line-2); }
.empty a { color: var(--accent); }

.skel { background: linear-gradient(90deg, var(--skel-1), var(--skel-2), var(--skel-1));
        background-size: 200% 100%; border-radius: 6px; animation: skel 1.3s ease-in-out infinite; }
.skel.line { height: 12px; margin: 8px 0; }
.skel.row { height: 44px; margin-bottom: var(--s2); }
@keyframes skel { 0% { background-position: 200% 0 } 100% { background-position: -200% 0 } }

/* ── 弹层（替代原生 confirm / 内联展开的表单） ─────────── */

.modal-scrim {
  position: fixed;
  inset: 0;
  background: var(--scrim-strong);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s4);
  animation: fade-in .14s ease-out;
}
.modal {
  width: 100%;
  max-width: 460px;
  max-height: 88vh;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-2);
  padding: var(--s5);
  animation: modal-in .16s cubic-bezier(.2, .9, .3, 1.1);
}
.modal.wide { max-width: 620px; }
.modal h2 { margin: 0 0 var(--s2); font-size: var(--t-lg); }
.modal .modal-sub { color: var(--ink-2); font-size: var(--t-sm); margin: 0 0 var(--s4); }
.modal .modal-actions { display: flex; justify-content: flex-end; gap: var(--s2); margin-top: var(--s5); }
@keyframes fade-in { from { opacity: 0 } to { opacity: 1 } }
@keyframes modal-in { from { opacity: 0; transform: translateY(10px) scale(.98) } to { opacity: 1; transform: none } }

/* 「?」说明：把界面上的长文收进来 */
.help { position: relative; display: inline-flex; }
.help > button { width: 16px; height: 16px; padding: 0; border-radius: 50%; font-size: 10px;
                 border-color: var(--line-2); color: var(--ink-3); background: transparent; }
.help > button:hover { color: var(--brand); border-color: var(--brand); background: transparent; }
.help-pop {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  width: min(78vw, 340px);
  background: var(--surface-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  box-shadow: var(--shadow-2);
  padding: var(--s3);
  font-size: var(--t-sm);
  line-height: 1.65;
  color: var(--ink-2);
  z-index: 40;
}
.help-pop p { margin: 0 0 6px; }
.help-pop p:last-child { margin-bottom: 0; }
.help-pop code { font-family: var(--mono); font-size: var(--t-xs); }

/* ── 命令面板（⌘K） ───────────────────────────────────── */

.kbd {
  font-family: var(--mono);
  font-size: 10.5px;
  border: 1px solid var(--line-2);
  border-bottom-width: 2px;
  border-radius: 5px;
  padding: 2px 5px;
  color: var(--ink-3);
}
.cmdk-btn {
  display: flex; align-items: center; gap: var(--s2);
  font-size: var(--t-sm); color: var(--ink-3);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 6px 10px; cursor: pointer;
}
.cmdk-btn:hover { color: var(--ink); border-color: var(--line-2); background: var(--surface-2); }
.cmdk-list { margin: var(--s3) -var(--s2) calc(-1 * var(--s2)); max-height: 52vh; overflow-y: auto; }
.cmdk-item {
  display: flex; align-items: center; gap: var(--s3);
  padding: 9px var(--s3); border-radius: var(--r-sm);
  color: var(--ink-2); font-size: var(--t); cursor: pointer;
}
.cmdk-item .cmdk-hint { margin-left: auto; color: var(--ink-3); font-size: var(--t-xs); }
.cmdk-item.sel, .cmdk-item:hover { background: var(--surface-3); color: var(--ink); }
.cmdk-empty { color: var(--ink-3); font-size: var(--t-sm); padding: var(--s4); text-align: center; }
.cmdk-input { border: none; background: transparent; padding: 0; font-size: var(--t-lg); }
.cmdk-input:focus { box-shadow: none; background: transparent; }

/* ── 登录 / 改密 ──────────────────────────────────────── */

/* 登录页 = 门面。左边主视觉（原色 logo 大牌子 + 一句话），右边表单。
   窄屏堆成一列居中。 */
.login-wrap {
  min-height: 100vh;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-content: center;
  justify-items: center;
  gap: var(--s6);
  padding: calc(var(--s6) + var(--safe-top)) var(--s5) calc(var(--s6) + var(--safe-bottom));
  background:
    radial-gradient(900px 560px at 18% -10%, var(--glow-a), transparent 64%),
    radial-gradient(760px 520px at 100% 110%, var(--glow-b), transparent 62%),
    var(--canvas);
}
@media (min-width: 1000px) {
  .login-wrap {
    grid-template-columns: minmax(0, 1fr) 428px;
    align-items: center;
    gap: 96px;
    max-width: 1280px;
    margin: 0 auto;
    padding: calc(72px + var(--safe-top)) 64px calc(72px + var(--safe-bottom));
  }
}
.login-hero { display: grid; justify-items: center; text-align: center; gap: var(--s4); }
@media (min-width: 1000px) { .login-hero { justify-items: start; text-align: left; } }
.login-hero .hero-title { font-size: 34px; line-height: 1.2; letter-spacing: -.02em; margin: 0; }
.login-hero .hero-sub { color: var(--ink-2); font-size: 15px; line-height: 1.7; margin: 0; max-width: 30em; }
.login-hero .hero-meta {
  color: var(--ink-3); font-size: 12.5px; letter-spacing: .08em; text-transform: uppercase;
  display: flex; gap: var(--s3); align-items: center;
}
.login-hero .hero-meta i { width: 4px; height: 4px; border-radius: 50%; background: var(--line-2); display: inline-block; }
.login-panel { width: 100%; max-width: 428px; }
.login { width: 100%; }
/* 登录页不再用 .brand（改用 .login-hero 的主视觉） */
/* 整张 logo（带字）也是**原色**：给它一块浅底，而不是用滤镜把它反白 */
.login .logo-plate {
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--plate-bg);
  border-radius: 20px;
  padding: 30px 38px;
  box-shadow: var(--shadow-plate);
}
.login .logo-plate .logo-img { display: block; width: 208px; height: auto; }
.login .card { padding: 30px 28px; box-shadow: var(--shadow-2); }
.login input { padding: 12px 14px; font-size: 15px; }
.login .foot { margin-top: var(--s4); font-size: var(--t-sm); text-align: center; color: var(--ink-3); }
.login-note { margin-top: var(--s3); font-size: var(--t-xs); color: var(--ink-3); text-align: center; line-height: 1.6; }

/* ── 图标（内联 SVG，零依赖） ──────────────────────────── */

.ic { display: block; flex: 0 0 auto; }
.ic.spin { animation: spin .9s linear infinite; }

/* ── 移动端（≤720px）：侧栏变抽屉 + 顶栏 + 表格堆叠 ───── */

@media (max-width: 899px) {
  .shell { display: block; }

  /* 抽屉里不需要"收起成图标条"那个按钮 —— 抽屉本身就是收起态 */
  .rail-btn { display: none; }
  .side-top { justify-content: flex-start; padding: 0 var(--s3) var(--s4) var(--s4); }

  .side {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    height: 100%;
    width: 84vw;
    max-width: 300px;
    transform: translateX(-102%);
    transition: transform .2s cubic-bezier(.2, .8, .3, 1);
    box-shadow: var(--shadow-2);
    padding-bottom: calc(var(--s4) + var(--safe-bottom));
    overflow-y: auto;
  }
  body.nav-open .side { transform: none; }
  body.nav-open .scrim { display: block; }

  .appbar { display: flex; }
  .appbar .logomark { width: 26px; height: 26px; border-radius: 7px; }

  .main {
    max-width: none;
    padding: var(--s4) calc(var(--s3) + var(--safe-right)) calc(84px + var(--safe-bottom)) calc(var(--s3) + var(--safe-left));
  }
  h1 { font-size: var(--t-lg); }
  h2 { font-size: var(--t); }
  .ph { margin-bottom: var(--s4); }
  .ph .ph-actions { width: 100%; }
  .ph .ph-actions > .btn, .ph .ph-actions > button { flex: 1; }
  .section { margin-top: var(--s5); }
  table { font-size: var(--t-sm); }
  th, td { padding: 8px 10px; }
  .tl time, .tl .tl-key { flex-basis: 84px; }

  /* 宽表格变成堆叠卡片（9 张表都带 .stack，53 个 td 都有 data-l） */
  table.stack thead { display: none; }
  table.stack tr { display: block; padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line); }
  table.stack tr:hover { background: none; }
  table.stack td { display: block; border: none; padding: 2px 0; }
  table.stack td::before {
    content: attr(data-l);
    display: block;
    color: var(--ink-3);
    font-size: 10.5px;
    letter-spacing: .06em;
    text-transform: uppercase;
  }
  .lrow { flex-direction: column; align-items: flex-start; gap: var(--s2); padding: var(--s3); }
  .lrow .l-act { width: 100%; }
  .lrow .l-act > .btn, .lrow .l-act > button { flex: 1; }

  /* 触屏上"拖进来"不存在，文案交给页面处理；这里只把触控目标放大 */
  .drop { padding: var(--s5) var(--s3); }
  .modal { max-width: none; }
  #toast { bottom: calc(76px + var(--safe-bottom)); }
}

/* 图标条（只有图标、没有字）：桌面手动收起 / 中屏自动（JS 给 .side 加 .rail）
   ⚠️ 只写一份规则，靠 JS 决定什么时候加类 —— 之前是"媒体查询里抄一遍"，改一处漏一处。 */
.side.rail { width: 64px; flex: 0 0 64px; }
.side.rail .side-top { flex-direction: column; justify-content: center; gap: var(--s3);
                       padding: 0 0 var(--s5); }
.side.rail .brand .logotext,
.side.rail .nav-label,
.side.rail .nav a span,
.side.rail .who .who-text { display: none; }
.side.rail .nav { padding: 0 6px; }
.side.rail .nav a { justify-content: center; padding: 9px 0; }
.side.rail .nav a.on::before { left: -6px; }
.side.rail .nav a.external::after { display: none; }
.side.rail .cmdk-btn span { display: none; }
.side.rail .cmdk-btn { justify-content: center; padding: 6px; }
.side.rail .side-foot { align-items: center; padding: var(--s3) 0 0; }
.side.rail .who { justify-content: center; }
.side.rail .foot-actions { flex-direction: column; width: 100%; }
.side.rail .foot-actions > * { width: 100%; justify-content: center; }

/* 中屏（900–1279px）：内容两侧留白收一点（侧栏收不收由 JS 的 .rail 决定） */
@media (min-width: 900px) and (max-width: 1279px) {
  .main {
    padding: var(--s5) calc(var(--s5) + var(--safe-right)) calc(72px + var(--safe-bottom)) calc(var(--s5) + var(--safe-left));
  }
}

/* 尊重系统的"减少动态效果" */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}


/* ─────────────────────────────────────────────────────────
   第二批零件（2026-10-05 第二刀）
   ───────────────────────────────────────────────────────── */

/* 分段控件：替代"用链接冒充 tab"（原来 4 个 <a class=btn> 既没有 aria-selected，
   主/次按钮还因为缺 .btn.primary 规则而全灰） */
.seg {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 11px;
}
.seg a {
  padding: 6px 13px;
  border-radius: 8px;
  font-size: var(--t-sm);
  color: var(--ink-2);
  white-space: nowrap;
}
.seg a:hover { color: var(--ink); background: var(--surface-2); }
.seg a.on { background: var(--surface-3); color: var(--ink); font-weight: 600; }

/* 行内菜单（⋯）：把"一格挤 4 个按钮"收成 1 个主行动 + 菜单 */
.menu-wrap { position: relative; display: inline-flex; }
.menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  min-width: 172px;
  z-index: 45;
  background: var(--surface-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  box-shadow: var(--shadow-2);
  padding: 5px;
  display: flex;
  flex-direction: column;
  animation: fade-in .12s ease-out;
}
.menu button, .menu a {
  justify-content: flex-start;
  background: transparent;
  border-color: transparent;
  color: var(--ink-2);
  padding: 7px 9px;
  font-size: var(--t-sm);
  border-radius: var(--r-sm);
}
.menu button:hover, .menu a:hover { background: var(--surface-2); color: var(--ink); }
.menu button.danger { color: var(--danger); }
.menu button.danger:hover { background: var(--danger-soft); color: var(--danger-ink); }
.menu .menu-sep { height: 1px; background: var(--line); margin: 4px 2px; }

/* 右栏的键值信息 */
.kv { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 7px var(--s3); font-size: var(--t-sm); margin: 0; }
.kv dt { color: var(--ink-3); white-space: nowrap; }
.kv dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }

/* 宽屏分栏：左内容 / 右元信息 */
.split { display: grid; gap: var(--s5); grid-template-columns: minmax(0, 1fr); }

/* 编号步骤：替代 ① ② ③（圈码在不同字体下大小不一，且是"AI 味"的重灾区） */
.steps { list-style: none; margin: 0; padding: 0; counter-reset: step; }
.steps li { position: relative; padding: 0 0 var(--s3) 30px; font-size: var(--t-sm); color: var(--ink-2); }
.steps li::before {
  counter-increment: step;
  content: counter(step);
  position: absolute;
  left: 0; top: 0;
  width: 20px; height: 20px;
  border-radius: 50%;
  background: var(--surface-3);
  color: var(--ink-2);
  font-size: 11px;
  font-family: var(--mono);
  display: flex; align-items: center; justify-content: center;
}
.steps li:last-child { padding-bottom: 0; }

/* 折叠块：长说明、发布配置这些"平时不用看"的东西 */
details.fold { border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--surface); }
details.fold > summary {
  cursor: pointer;
  padding: var(--s3) var(--s4);
  font-size: var(--t);
  color: var(--ink);
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--s2);
}
details.fold > summary::-webkit-details-marker { display: none; }
details.fold > summary::after {
  content: "";
  margin-left: auto;
  width: 7px; height: 7px;
  border-right: 1.6px solid var(--ink-3);
  border-bottom: 1.6px solid var(--ink-3);
  transform: rotate(45deg);
  transition: transform .15s ease;
}
details.fold[open] > summary::after { transform: rotate(-135deg); }
details.fold > .fold-body { padding: 0 var(--s4) var(--s4); }

/* 工具条 */
.toolbar { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.toolbar .grow { flex: 1; min-width: 0; }

/* 包这一行的"检查"摘要：一行放下徽标 + 简短明细 */
.checkline { display: flex; gap: var(--s2); align-items: flex-start; }
.checkline .checks { margin: 0; }

/* 宽屏才分栏 */
@media (min-width: 1100px) {
  .split { grid-template-columns: minmax(0, 1fr) 296px; align-items: start; }
  /* 右栏跟着滚（它放的是"随时想瞄一眼"的信息） */
  .split > .aside { position: sticky; top: var(--s5); }
}

/* 窄屏把上面的东西改成竖排 */
@media (max-width: 899px) {
  .lrow { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .lrow .l-meta, .lrow .l-meta.num { grid-template-columns: repeat(3, minmax(0, 1fr)); justify-items: start;
                                     width: 100%; gap: var(--s2); display: grid; }
  .seg { overflow-x: auto; max-width: 100%; }
  .split { gap: var(--s4); }
  .menu { right: auto; left: 0; }
}

/* 代码块（发布配置那几段）。等宽、可横向滚、别撑破卡片 */
pre.code-block {
  background: var(--canvas);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  padding: var(--s3);
  margin: 8px 0 0;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--ink-2);
  overflow-x: auto;
  white-space: pre;
}
/* 步骤里的小标题（编号 + 一句话） */
.steps li > span { color: var(--ink); }


/* ─────────────────────────────────────────────────────────
   规模（2026-10-05 追改）：让它"大气"而不是"紧凑的内部脚本"
   ⚠️ 这一节只动尺度（宽/高/字号/留白），不动配色与语义 ——
      想再调，改这里的数字就行，不要回到每个页面写内联 style。
   ───────────────────────────────────────────────────────── */

/* 画布上两道极淡的光，避免一整片死黑（固定定位，不参与滚动） */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(1200px 560px at 24% -12%, var(--page-glow-a), transparent 62%),
    radial-gradient(980px 520px at 104% 0%, var(--page-glow-b), transparent 60%);
}
.shell { position: relative; z-index: 1; }

.main {
  max-width: none;
  padding: var(--s6) calc(48px + var(--safe-right)) calc(88px + var(--safe-bottom)) calc(48px + var(--safe-left));
}
h1 { font-size: var(--t-xl); letter-spacing: -.02em; }
h2 { font-size: var(--t-lg); }
.ph { margin-bottom: var(--s5); }
.ph h1 { font-size: 30px; }
.ph .sub { font-size: 15px; }
.section { margin-top: var(--s6); }
.section-head { margin-bottom: var(--s4); }

.card { padding: 22px; box-shadow: var(--shadow-card); }
.card-title { font-size: 15px; }

.stat { padding: 22px 24px; }
.stat .k { font-size: 12px; letter-spacing: .1em; }
.stat .v { font-size: var(--t-2xl); margin-top: 10px; }
.stat .n { margin-top: 8px; }

.lrow { padding: 16px 22px; }
.lrow .l-name { font-size: 15.5px; }
.lrow .l-desc { margin-top: 5px; }
tbody td, tbody th { padding: 13px 16px; }
th { font-size: 11.5px; }

button, .btn { padding: 9px 14px; font-size: 13.5px; border-radius: 9px; }
button.sm, .btn.sm { padding: 6px 11px; font-size: 12.5px; }
input, textarea, select { padding: 11px 13px; border-radius: 9px; }
.seg a { padding: 8px 16px; }
.side-top { padding: 0 var(--s3) var(--s5) var(--s4); }
.brand { font-size: 17px; }
.brand small { font-size: 12px; }
.logomark { width: 34px; height: 34px; }
.nav a { padding: 10px var(--s3); font-size: 14.5px; }
.nav-label { padding: var(--s5) var(--s3) var(--s2); }
.side-foot { padding: var(--s4) var(--s3) 0; }
.appbar { padding: calc(var(--s2) + var(--safe-top)) calc(var(--s4) + var(--safe-right)) var(--s2) calc(var(--s4) + var(--safe-left)); }
.appbar .appbar-title { font-size: 14.5px; }
.drop { padding: var(--s6) var(--s4); }
.toast { padding: 12px 16px; font-size: 13.5px; }
.modal { padding: var(--s5); }
.modal h2 { font-size: 18px; }

/* 手机/中屏别把留白放大到浪费屏幕 */
@media (max-width: 899px) {
  .main { padding: var(--s4) calc(var(--s3) + var(--safe-right)) calc(84px + var(--safe-bottom)) calc(var(--s3) + var(--safe-left)); }
  .ph h1 { font-size: 23px; }
  .stat .v { font-size: 30px; }
  .login-hero .hero-title { font-size: 26px; }
  .login .logo-plate { padding: 22px 26px; }
  .login .logo-plate .logo-img { width: 152px; }
}

/* 页头的小字（"3APEX Game Studio"）—— 撑气势用的，别到处加 */
.eyebrow {
  font-size: 11.5px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 10px;
}

/* 分节标题下面加一条发丝线：这是"编辑感"，一眼能看出层级，也是"大气"的来源之一 */
.section-head {
  border-bottom: 1px solid var(--line);
  padding-bottom: 12px;
}
.section-head h2 { letter-spacing: -.01em; }

/* 侧栏顶部再松一点 */
.side { padding-top: calc(var(--s5) + var(--safe-top)); }
.side.rail .logomark { width: 30px; height: 30px; }

/* 表格：表头不要贴住内容 */
thead th { padding-bottom: 10px; }


/* ─────────────────────────────────────────────────────────
   浅色（"纸张"）主题
   ⚠️ 只覆盖**调色板**，不覆盖尺度 —— 尺度和主题是两件独立的事。
      页面里不许再出现写死的颜色：要新颜色就先在 :root 加令牌。
   ───────────────────────────────────────────────────────── */
:root[data-theme='light'] {
  --canvas: #f4f5f7;
  --surface: #ffffff;
  --surface-2: #f4f6f9;
  --surface-3: #e9edf3;
  --line: rgba(16, 24, 40, .08);
  --line-2: rgba(16, 24, 40, .14);

  --ink: #101828;
  --ink-2: #475467;
  --ink-3: #6b7280;

  /* 白底上金色要压深一点，才压得住 */
  --brand: #d99a2b;
  --brand-hi: #eab13f;
  --brand-deep: #8a5a12;
  --accent: #1d6fd0;
  --ok: #0a7d55;
  --warn: #b54708;
  --danger: #b42318;
  --violet: #6941c6;

  --link: #1d6fd0;
  --side-bg: #ffffff;
  --appbar-bg: rgba(255, 255, 255, .88);
  --scrim: rgba(16, 24, 40, .32);
  --scrim-strong: rgba(16, 24, 40, .42);
  --plate-bg: #ffffff;
  --plate-line: rgba(16, 24, 40, .10);
  --hover: rgba(16, 24, 40, .03);
  --line-hover: rgba(16, 24, 40, .28);
  --fill-soft: rgba(16, 24, 40, .055);
  --fill-faint: rgba(16, 24, 40, .02);
  --track: rgba(16, 24, 40, .09);
  --dot-off: #cbd5e1;
  --skel-1: rgba(16, 24, 40, .05);
  --skel-2: rgba(16, 24, 40, .09);
  --selection: rgba(243, 185, 74, .35);
  --brand-soft: rgba(217, 154, 43, .10);
  --brand-ring: rgba(217, 154, 43, .22);
  --ok-ink: #067647;  --ok-bg: rgba(6, 118, 71, .10);      --ok-line: rgba(6, 118, 71, .28);
  --warn-ink: #b54708; --warn-bg: rgba(181, 71, 8, .10);   --warn-line: rgba(181, 71, 8, .26);
  --danger-ink: #b42318; --danger-bg: rgba(180, 35, 24, .08); --danger-soft: rgba(180, 35, 24, .10);
  --danger-line: rgba(180, 35, 24, .28); --danger-line-2: rgba(180, 35, 24, .45);
  --info-ink: #175cd3; --info-bg: rgba(23, 92, 211, .09);  --info-line: rgba(23, 92, 211, .26);
  --violet-ink: #6941c6; --violet-bg: rgba(105, 65, 198, .10);
  --toast-err-bg: #fef3f2;
  --glow-a: rgba(217, 154, 43, .12);
  --glow-b: rgba(90, 169, 255, .08);
  --page-glow-a: rgba(217, 154, 43, .06);
  --page-glow-b: rgba(90, 169, 255, .05);
  --shadow-1: 0 1px 2px rgba(16, 24, 40, .06);
  --shadow-2: 0 1px 2px rgba(16, 24, 40, .06), 0 16px 40px -16px rgba(16, 24, 40, .28);
  --shadow-plate: 0 24px 50px -28px rgba(16, 24, 40, .35);
  --shadow-card: 0 1px 2px rgba(16, 24, 40, .04), 0 18px 40px -32px rgba(16, 24, 40, .35);
}

/* ─────────────────────────────────────────────────────────
   紧凑密度（"宽松"是默认）。只动尺度，不动配色。
   ───────────────────────────────────────────────────────── */
:root[data-density='compact'] {
  --r-sm: 7px; --r: 10px; --r-lg: 14px;
  --s1: 4px; --s2: 8px; --s3: 11px; --s4: 15px; --s5: 22px; --s6: 32px;
  --t-xs: 11.5px; --t-sm: 12.5px; --t: 13.5px; --t-lg: 15px; --t-xl: 22px; --t-2xl: 30px;
}
:root[data-density='compact'] .main { padding: var(--s6) 32px 72px; }
:root[data-density='compact'] .lrow { padding: 11px 16px; }
:root[data-density='compact'] tbody td, :root[data-density='compact'] tbody th { padding: 9px 12px; }

/* 外观浮层的零件 */
.menu-label {
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 6px 9px 4px;
}
.menu button.on { background: var(--surface-2); color: var(--ink); }
.menu.up { top: auto; bottom: calc(100% + 6px); }
/* 图标条只有 64px 宽：浮层要往右开，不然会跑出屏幕 */
.side.rail .menu { right: auto; left: calc(100% + 8px); top: auto; bottom: 0; }
:root[data-theme='light'] { color-scheme: light; }

/* 偏好（主题 / 密度）：分组标题 + 分段控件。.seg 原来只认 <a>，这里补上 <button> */
.seg a, .seg button {
  padding: 6px 13px;
  border-radius: 8px;
  font-size: var(--t-sm);
  color: var(--ink-2);
  border: none;
  background: transparent;
  white-space: nowrap;
}
.seg a:hover, .seg button:hover { color: var(--ink); background: var(--surface-2); }
.seg a.on, .seg button.on { background: var(--surface-3); color: var(--ink); font-weight: 600; }
.appear { display: grid; gap: var(--s3); }
.appear-group { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.appear-label { font-size: var(--t-sm); color: var(--ink-3); min-width: 3.5em; }

/* ─────────────────────────────────────────────────────────
   仓库：README 渲染 + 文件内容
   ⚠️ 颜色**全用现有变量**（--surface-3 / --line / --ink-3 …），
      不自己发明色值 —— 否则主题切换（深/浅色）时这一块会掉队。
   ───────────────────────────────────────────────────────── */
.md { font-size: var(--t-sm); line-height: 1.75; }
.md > *:first-child { margin-top: 0; }
.md > *:last-child { margin-bottom: 0; }
.md h1, .md h2, .md h3, .md h4, .md h5, .md h6 {
  margin: 20px 0 8px; line-height: 1.3; font-weight: 650;
}
.md h1 { font-size: 1.5em; padding-bottom: 6px; border-bottom: 1px solid var(--line); }
.md h2 { font-size: 1.25em; padding-bottom: 4px; border-bottom: 1px solid var(--line); }
.md h3 { font-size: 1.1em; }
.md p { margin: 9px 0; }
.md ul { margin: 9px 0; padding-left: 22px; }
.md li { margin: 3px 0; }
.md blockquote {
  margin: 10px 0; padding: 2px 0 2px 12px;
  border-left: 3px solid var(--line-2); color: var(--ink-3);
}
.md a { text-decoration: underline; }
.md code {
  font-family: var(--mono); font-size: 0.92em;
  background: var(--surface-3); padding: 1px 5px; border-radius: 4px;
}
.md pre, pre.repo-code {
  margin: 10px 0; padding: 12px 14px; border-radius: var(--r, 8px);
  background: var(--surface-3); border: 1px solid var(--line);
  overflow: auto; font-size: 12.5px; line-height: 1.65; max-height: 60vh;
}
.md pre code { background: none; padding: 0; font-size: inherit; }
pre.repo-code code { font-family: var(--mono); white-space: pre; }
