/* Personal Hub · app.css
   结构：token 层 → 基础层 → 组件层 → 布局/页面 → 管理台 → 插件视图 → 响应式 → 动效降级
   设计基线：docs/design/ui-proposal/design-genome.md（v1 冻结）
   取值来源：docs/design/ui-proposal/design-dna.json（token 层）
   本文件当前对应 CR-002 批 2 + 批 3：换设计语言 —— 暖纸底 / 三级墨 / 衬线标题 /
   等宽编号，加签名元素（索引编号 / 双线章节头 / 页边注栏）；批 3 增暗色主题、
   ⌘K 命令面板、管理台「高级（JSON）」折叠。批 1、批 2 成果原样保留。 */

:root {
  color-scheme: light;

  /* ── Token 层：色板（design-dna.json › design_system.color）─────
     层级靠墨的深浅表达，不靠透明度；强调色只有松绿一支，
     陶土只用于标记 / 引用 / 警告，不参与装饰。 */
  --paper: #faf7f1;         /* surface.background */
  --surface: #fffffe;       /* surface.card（近白，带纸温） */
  --sunken: #f2ede3;        /* surface.sunken */
  --ink: #1c1b18;           /* 墨一级：标题与正文（≈15:1） */
  --ink-2: #6b665c;         /* 墨二级：说明与元信息（5.3:1，正文可用） */
  --ink-3: #948e82;         /* 墨三级：仅装饰（3.0:1，见下方「对比度纪律」） */
  --line: #e4ded2;          /* 常态分隔线 */
  --line-2: #c9c2b4;        /* 强描边：输入框 / 双线 / 悬停 */
  --accent: #0f5c43;        /* 松绿：强调与主操作（dna primary/accent） */
  --accent-ink: #0b3f2e;
  --accent-soft: #e6f0ea;
  --clay: #b0552f;          /* 陶土：标记 / 引用 / 警告（dna secondary/warning） */
  --clay-ink: #8a4a22;
  --clay-soft: #f6ebe3;
  --danger: #a3352a;
  --danger-ink: #7e2a21;
  --danger-soft: #f8e9e6;
  --ring: 0 0 0 3px var(--accent-soft);

  /* 浮层（dna elevation：常态零阴影，仅 ⌘K / 弹层用一级软阴影）与遮罩 */
  --overlay: rgba(28, 27, 24, .32);
  --shadow-overlay: 0 16px 48px rgba(28, 27, 24, .14);
  --shadow-ring: rgba(28, 27, 24, .08);

  /* ── Token 层：字体三声部（dna typography）────────────────────
     衬线标题 / 无衬线正文 / 等宽编号。计数、编号、路径、版本一律等宽。 */
  --serif: "Songti SC", "Noto Serif SC", "Source Han Serif SC", "SimSun", Georgia, serif;
  --sans: Inter, "PingFang SC", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "SF Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  /* ── Token 层：尺度（dna layout / shape）────────────────────── */
  --form-narrow: 560px;
  --form-wide: 680px;
  --reading: 720px;         /* 阅读正文行宽 */
  --rail: 240px;            /* 页边索引栏（阅读页与管理台同一取值） */
  --radius-ctl: 3px;        /* dna shape.small：按钮 / 输入框 */
  --radius-card: 6px;       /* dna shape.medium：卡片 / 面板 */
  --radius-pill: 999px;

  /* ── Token 层：动效（dna motion）──────────────────────────────
     duration_scale = 120 / 180 / 240；phases 另点名悬停 140ms（更具体，
     故单列 --dur-hover）。两处口径差见 CR-002 §9 记录。 */
  --dur-micro: 120ms;
  --dur-hover: 140ms;
  --dur-state: 180ms;
  --dur-enter: 240ms;
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --ease-enter: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-exit: cubic-bezier(0.4, 0, 1, 1);
}

/* ── Token 层：暗色（CR-002 批 3）────────────────────────────────
   dna dark_mode 激活：background #131210 / card #1B1A17 / text #EFEAE0 /
   line #2C2A25；其余 token 由明色按同一角色派生。对比度实测（WCAG 2.1，
   相对底色 paper/surface 取较小者）：ink 15.6 / ink-2 6.9 / ink-3 3.4
   （仅装饰，与明色同纪律）/ accent 作文字 9.0、作主钮底色 8.4 /
   danger 作文字 6.3、作底线钮底色 5.9 / clay-ink 7.8 / danger-ink 7.0。
   机制：系统偏好自动（@media）+ 显式选择覆盖（[data-theme]）双通道；
   head 引导脚本仅在用户显式点选后写 data-theme 并持久化。
   注意：下方两块逐字相同（媒体块服务无 JS 环境，属性块服务显式选择与
   开关），改动务必同步两处。 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --paper: #131210;
    --surface: #1b1a17;
    --sunken: #0e0d0b;
    --ink: #efeae0;
    --ink-2: #a39c8d;
    --ink-3: #6f695e;
    --line: #2c2a25;
    --line-2: #403c34;
    --accent: #85c0a4;
    --accent-ink: #9ccfb5;
    --accent-soft: #1e2c25;
    --clay: #ce8a63;
    --clay-ink: #e3ac8a;
    --clay-soft: #2e2119;
    --danger: #dc7b6f;
    --danger-ink: #e89a90;
    --danger-soft: #32201d;
    --overlay: rgba(0, 0, 0, .55);
    --shadow-overlay: 0 16px 48px rgba(0, 0, 0, .55);
    --shadow-ring: rgba(0, 0, 0, .4);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;

  --paper: #131210;
  --surface: #1b1a17;
  --sunken: #0e0d0b;
  --ink: #efeae0;
  --ink-2: #a39c8d;
  --ink-3: #6f695e;
  --line: #2c2a25;
  --line-2: #403c34;
  --accent: #85c0a4;
  --accent-ink: #9ccfb5;
  --accent-soft: #1e2c25;
  --clay: #ce8a63;
  --clay-ink: #e3ac8a;
  --clay-soft: #2e2119;
  --danger: #dc7b6f;
  --danger-ink: #e89a90;
  --danger-soft: #32201d;
  --overlay: rgba(0, 0, 0, .55);
  --shadow-overlay: 0 16px 48px rgba(0, 0, 0, .55);
  --shadow-ring: rgba(0, 0, 0, .4);
}

/* ── 基础层 ──────────────────────────────────────────── */

* { box-sizing: border-box; }
html { scroll-behavior: smooth; scroll-padding-top: 24px; }
body {
  margin: 0;
  color: var(--ink);
  background: var(--paper);
  font: 400 15px/1.7 var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
a { color: inherit; text-decoration: none; }
strong, b { font-weight: 650; }

/* 对比度纪律：--ink-3 实测 3.0:1，只用于 aria-hidden 的装饰与占位提示；
   一切承载信息的文字（编号、计数、时间、路径）一律用 --ink-2（5.3:1），
   与 design-genome「禁止用低于 4.5:1 的灰承载正文」一致。 */

/* 全站焦点可见性（批 1 建立）：:where() 特异性为 0，组件规则可覆盖。 */
:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
/* 仅脚本环境可见（CR-002 批 3）：隐藏无 JS 时的死控件（正文编辑器、⌘K、开关）。 */
html:not(.js) .js-only { display: none; }
/* hidden 纪律：类的 display 声明（.empty 的 grid、.palette-hint 的 inline-flex、
   :is(.admin-form, …) label 的 grid 等）特异性高于 UA 的 [hidden]，会把 hidden
   顶掉——近期浏览空态与列表同屏、? 帮助入口在无工作区的页面成了死按钮、卸载
   页二次确认字段常显，都是这一处。统一在此兜底；组件层各自的 *.foo[hidden]
   特例已随本批移除。 */
[hidden] { display: none !important; }

/* 等宽元信息的统一排法（dna typography.mono） */
:is(.plugin-row small, .resource-row small, .def-row small, .stats, .breadcrumbs,
    .section-heading span, .plugin-row > span[aria-hidden], a.resource-row > span[aria-hidden],
    .page-tabs small, .admin-item summary > span:last-child, .admin-sidebar-title span,
    .folder-tree__count, .tag-cloud .count, .frontmatter dt, .pagination, .result-snippet code) {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
/* 时间戳整段不折行：窄屏上「2026-10-11 21:24:59」会被从中间拆开（见 .stats）。 */
time { white-space: nowrap; }

/* ── 组件层：按钮 ──────────────────────────────────────
   一套定义服务全站（批 1 收敛成果）。变体：
   .button / .button-primary（主）｜.button-secondary（次）｜.button-ghost（行内）
   ｜.button-danger（危险）。尺寸：默认 40px；.button-sm 36px（CR-002 D3）。 */
.button, .button-primary, .button-secondary, .button-ghost, .button-danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 15px;
  border: 1px solid var(--accent);
  border-radius: var(--radius-ctl);
  color: var(--surface);
  background: var(--accent);
  font: 650 14px/1 var(--sans);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur-hover) var(--ease-standard),
              border-color var(--dur-hover) var(--ease-standard),
              color var(--dur-hover) var(--ease-standard),
              transform var(--dur-micro) var(--ease-standard);
}
.button:hover, .button-primary:hover { background: var(--accent-ink); border-color: var(--accent-ink); }
.button-secondary { color: var(--ink); background: var(--surface); border-color: var(--line-2); }
.button-secondary:hover { background: var(--sunken); border-color: var(--line-2); }
.button-ghost { padding: 0 8px; color: var(--accent); background: none; border-color: transparent; }
.button-ghost:hover { background: var(--accent-soft); }
.button-danger { background: var(--danger); border-color: var(--danger); }
.button-danger:hover { background: var(--danger-ink); border-color: var(--danger-ink); }
.button:active, .button-primary:active, .button-secondary:active,
.button-ghost:active, .button-danger:active { transform: scale(0.99); }
.button-sm { min-height: 36px; padding: 0 12px; font-size: 13px; }
.button:disabled, .button-primary:disabled, .button-secondary:disabled,
.button-ghost:disabled, .button-danger:disabled,
.button[aria-disabled="true"], .button-primary[aria-disabled="true"],
.button-secondary[aria-disabled="true"], .button-danger[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* ── 组件层：表单控件 ──────────────────────────────────
   容器用 :is() 提到同一特异性，聚焦态才能稳定压过常态描边。 */
:is(.admin-form, .compact-form, .stack-form, .filter-form) :is(input, textarea, select) {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-ctl);
  color: var(--ink);
  background: var(--surface);
  font: 400 14px/1.5 var(--sans);
  transition: border-color var(--dur-hover) var(--ease-standard),
              box-shadow var(--dur-hover) var(--ease-standard);
}
:is(.admin-form, .compact-form, .stack-form, .filter-form) :is(input, textarea, select):focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--ring);
}
:is(.admin-form, .compact-form, .stack-form, .filter-form) :is(input, textarea, select):disabled {
  color: var(--ink-3);
  background: var(--sunken);
}
:is(.admin-form, .compact-form, .stack-form, .filter-form) ::placeholder { color: var(--ink-3); }
:is(.admin-form, .compact-form) textarea { resize: vertical; }
.admin-form textarea { font-family: var(--mono); font-size: 13px; line-height: 1.7; }
:is(.admin-form, .compact-form, .stack-form, .filter-form) label { display: grid; gap: 6px; color: var(--ink-2); font-size: 12.5px; font-weight: 650; }
.compact-form label { gap: 5px; }
/* 「勾选项 + 说明」的行内标签全站一种排法。放在容器 label 规则之后，同位阶取胜。 */
label.check-label { display: flex; align-items: center; gap: 8px; font-size: 13.5px; font-weight: 400; }
.check-label input { width: 16px; min-height: 16px; padding: 0; }
/* 字段级错误：附在字段下方的一句话（页级错误走 .notice--error，CR-002 D2 拆分） */
.form-error { display: block; margin-top: 2px; color: var(--danger); font-size: 12.5px; font-weight: 400; }

/* ── 组件层：通知 ──────────────────────────────────────
   语义变体：默认成功（accent）/ --warn（clay，dna semantic.warning）
   / --error（danger，dna semantic.error）；均可关闭。 */
.notice {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0 0 22px;
  padding: 11px 14px;
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-ctl);
  color: var(--accent-ink);
  background: var(--accent-soft);
}
.notice--warn { border-left-color: var(--clay); color: var(--clay-ink); background: var(--clay-soft); }
.notice--error { border-left-color: var(--danger); color: var(--danger-ink); background: var(--danger-soft); }
.notice__close {
  flex: 0 0 auto;
  margin: -2px -4px -2px auto;
  padding: 4px;
  border: 0;
  background: none;
  color: inherit;
  cursor: pointer;
  opacity: 0.72;
  transition: opacity var(--dur-hover) var(--ease-standard);
}
.notice__close:hover { opacity: 1; }
.notice__close::before {
  content: "";
  display: block;
  width: 11px;
  height: 11px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 3.5l9 9M12.5 3.5l-9 9' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3.5 3.5l9 9M12.5 3.5l-9 9' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ── 组件层：空态 ──────────────────────────────────────
   单色线稿图标 + 一句人话 + 一个动作（有真实去向时）。 */
.empty {
  display: grid;
  justify-items: center;
  gap: 10px;
  padding: 40px 20px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  color: var(--ink-2);
  text-align: center;
}
.plugin-list > .empty:first-child, .resource-list > .empty:first-child { border-top: 0; }
.empty p { margin: 0; max-width: 62ch; font-size: 13.5px; line-height: 1.75; }
.empty strong { color: var(--ink); font-size: 15px; }
.empty-action { color: var(--accent); font-size: 13.5px; font-weight: 650; }
.empty-action:hover { text-decoration: underline; }
.empty::before {
  content: "";
  width: 40px;
  height: 40px;
  margin-bottom: 2px;
  background: currentColor;
  opacity: 0.55;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 13h5l2 3h4l2-3h5' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M5.5 5h13l2.5 8v6H3v-6z' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M3 13h5l2 3h4l2-3h5' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M5.5 5h13l2.5 8v6H3v-6z' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ── 组件层：索引行 ────────────────────────────────────
   「编号 → 名称 → 元信息」三段式，任何一行都能被单独引用。
   编号由 CSS 计数器生成（模板零改动）；仅索引行有编号，
   详情页的「字段 → 值」行走 .def-row，不带编号。 */
.plugin-list, .resource-list { counter-reset: idx; border-top: 1px solid var(--line); }
.plugin-row, .resource-row {
  display: grid;
  align-items: center;
  gap: 14px;
  min-height: 64px;
  padding: 8px 4px;
  border-bottom: 1px solid var(--line);
  transition: background-color var(--dur-hover) var(--ease-standard);
}
.plugin-row { grid-template-columns: 34px 36px minmax(0, 1fr) auto; }
.resource-row { grid-template-columns: 34px minmax(0, 1fr) auto; }
.plugin-row::before, .resource-row::before {
  counter-increment: idx;
  content: counter(idx, decimal-leading-zero);
  color: var(--ink-2);
  font: 500 12px/1.6 var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
}
.plugin-row:hover, a.resource-row:hover, article.resource-row:hover { background: var(--surface); }
.plugin-row strong, .plugin-row small, .resource-row strong, .resource-row small,
.def-row strong, .def-row small { display: block; }
.plugin-row strong, .resource-row strong { font-size: 15.5px; font-weight: 650; transition: color var(--dur-hover) var(--ease-standard); }
.plugin-row:hover strong, a.resource-row:hover strong, article.resource-row:hover strong { color: var(--accent-ink); }
.plugin-row small, .resource-row small { margin-top: 3px; color: var(--ink-2); font-size: 13px; }
.resource-row small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.plugin-row > span[aria-hidden], a.resource-row > span[aria-hidden] {
  color: var(--ink-3);
  font-size: 12px;
  transition: transform var(--dur-hover) var(--ease-standard), color var(--dur-hover) var(--ease-standard);
}
.plugin-row:hover > span[aria-hidden], a.resource-row:hover > span[aria-hidden] { transform: translateX(2px); color: var(--accent); }
.plugin-mark {
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-ctl);
  color: var(--accent-ink);
  background: var(--sunken);
  font-weight: 700;
}
.resource-note { cursor: default; }
.resource-note small { white-space: normal; }

/* 导航仪表盘：分类分组的纯文本卡片网格（visitor-surface-trim D1）。
   零 JS、无图标：标题 + 一句描述，外链新标签打开。 */
.link-board { display: grid; gap: 24px; }
.link-group { display: grid; gap: 12px; }
.link-group h3 { margin: 0; color: var(--ink-2); font-size: 13px; font-weight: 700; letter-spacing: 0.05em; }
.link-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; }
.link-card {
  display: grid;
  align-content: start;
  gap: 5px;
  min-height: 84px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-ctl);
  background: var(--surface);
  transition: border-color var(--dur-hover) var(--ease-standard), transform var(--dur-hover) var(--ease-standard);
}
.link-card:hover { border-color: var(--accent); transform: translateY(-1px); }
.link-card strong { font-size: 15px; font-weight: 650; transition: color var(--dur-hover) var(--ease-standard); }
.link-card:hover strong { color: var(--accent-ink); }
.link-card small { color: var(--ink-2); font-size: 12.5px; line-height: 1.6; }

/* 资源库浏览（resources-file-manager）：左目录树 + 右内容瓦片的文件管理器。
   树为纯链接（无 JS），当前目录标 ◀ 并加深强调；右栏瓦片沿用导航仪表盘卡片
   基调，四类节点以等宽文字徽标区分；窄屏（站点既有 720px 断点）单列堆叠。 */
.resource-browser {
  display: grid;
  grid-template-columns: minmax(200px, 240px) minmax(0, 1fr);
  gap: 32px;
  align-items: start;
}
.folder-tree { min-width: 0; }
.folder-tree ul { margin: 0; padding: 0; list-style: none; }
.folder-tree ul ul { padding-inline-start: 14px; }
.folder-tree__item {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 6px 8px;
  border-radius: var(--radius-ctl);
  color: var(--ink-2);
  font-size: 13.5px;
  line-height: 1.5;
  transition: color var(--dur-hover) var(--ease-standard),
              background var(--dur-hover) var(--ease-standard);
}
.folder-tree__item:hover { color: var(--accent); background: var(--sunken); }
.folder-tree__name { min-width: 0; overflow-wrap: anywhere; }
.folder-tree__marker { color: var(--accent); font-size: 10px; }
.folder-tree__item--current { color: var(--ink); font-weight: 650; }
.folder-tree__item--current:hover { color: var(--ink); }
.resource-browser__content { min-width: 0; }
/* 右栏顶部的面包屑：收掉全局负上边距，与树首项视觉对齐。 */
.resource-browser .breadcrumbs { margin: 0 0 20px; }
.resource-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 12px;
}
.resource-tile {
  display: grid;
  align-content: start;
  gap: 5px;
  min-height: 96px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-ctl);
  background: var(--surface);
  transition: border-color var(--dur-hover) var(--ease-standard),
              transform var(--dur-hover) var(--ease-standard);
}
a.resource-tile:hover,
a.resource-tile:focus-visible { border-color: var(--accent); }
a.resource-tile:hover { transform: translateY(-1px); }
.resource-tile strong { font-size: 15px; font-weight: 650; overflow-wrap: anywhere; transition: color var(--dur-hover) var(--ease-standard); }
a.resource-tile:hover strong { color: var(--accent-ink); }
.resource-tile small { color: var(--ink-2); font-size: 12.5px; line-height: 1.6; overflow-wrap: anywhere; }
.resource-tile__kind { color: var(--ink-2); font: 600 11px/1.6 var(--mono); letter-spacing: 0.08em; }
.resource-tile--note { cursor: default; }
.resource-grid > .empty { grid-column: 1 / -1; border-top: 0; }

/* 文件预览页（resources-file-preview）：面包屑 → 标题 → 元信息 → 动作区 →
   按类型分支的内容区。正文宽度沿用阅读列 --reading；元信息走等宽（路径 /
   版本 / 计数的既有口径）；pre 视觉对齐 .note-body pre，但换行而非横滚。 */
.file-preview__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin: 4px 0 0;
  color: var(--ink-2);
  font: 400 12.5px/1.6 var(--mono);
  overflow-wrap: anywhere;
}
.file-preview__meta span[aria-hidden] { color: var(--ink-3); }
.file-preview__actions { display: flex; flex-wrap: wrap; gap: 10px; margin: 22px 0 32px; }
.file-preview { max-width: var(--reading); }
.file-preview__figure { margin: 0; }
.file-preview__figure img {
  max-width: 100%;
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.file-preview__frame {
  display: block;
  width: 100%;
  min-height: min(70vh, 720px);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.file-preview__text {
  margin: 0;
  padding: 16px 18px;
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.75;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.file-preview__hint { margin: 10px 0 0; color: var(--ink-2); font-size: 13px; }

/* 资源瓦片右键菜单（app.js 渐进增强，无 JS 时不存在）：单例浮层，坐标由
   脚本给出；视觉沿用浮层口径（--shadow-overlay + 一级边线 + 小圆角）。
   进入微动效（opacity + 2px 上浮），关闭即时——同 ⌘K 面板口径；过渡属性
   的 reduced-motion 降级由文件尾全局块覆盖。 */
.tile-menu {
  position: fixed;
  z-index: 40;
  display: grid;
  min-width: 184px;
  padding: 5px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-ctl);
  background: var(--surface);
  box-shadow: var(--shadow-overlay), 0 0 0 1px var(--shadow-ring);
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity var(--dur-micro) var(--ease-standard),
              transform var(--dur-micro) var(--ease-standard);
}
.tile-menu.is-open { opacity: 1; transform: none; }
.tile-menu__item {
  display: block;
  padding: 8px 10px;
  border-radius: var(--radius-ctl);
  color: var(--ink);
  font-size: 13.5px;
  line-height: 1.4;
  text-decoration: none;
  cursor: pointer;
}
.tile-menu__item:hover, .tile-menu__item:focus-visible { color: var(--accent-ink); background: var(--accent-soft); }
.tile-menu__item:focus-visible { outline: none; }

/* 应用宫格（apps-launcher-grid）：纯 CSS 悬浮预览的启动器卡片——卡面仅
   图标 + 名称；悬浮 / 聚焦时浮层展开简介 / 状态 / 地址（只动 opacity /
   transform）；禁用卡片灰显不可点。零 JS，基调沿用导航仪表盘卡片。 */
.app-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(196px, 1fr)); gap: 12px; }
.app-card {
  position: relative;
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 8px;
  min-height: 128px;
  padding: 18px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
  color: inherit;
  text-align: center;
  transition: border-color var(--dur-hover) var(--ease-standard),
              transform var(--dur-hover) var(--ease-standard);
}
/* 交互反馈只给可点卡片；禁用卡悬浮仅展开预览（状态可见），不给可点击暗示。 */
a.app-card:not(.app-card--disabled):hover,
a.app-card:not(.app-card--disabled):focus-visible { border-color: var(--accent); z-index: 3; }
a.app-card:not(.app-card--disabled):hover { transform: translateY(-1px); }
.app-card__icon { font-size: 30px; line-height: 1; }
.app-card__name { font-size: 15px; font-weight: 650; transition: color var(--dur-hover) var(--ease-standard); }
a.app-card:not(.app-card--disabled):hover .app-card__name { color: var(--accent-ink); }
.app-card--disabled { background: var(--sunken); cursor: default; }
.app-card--disabled .app-card__name { color: var(--ink-2); }
.app-card--disabled .app-card__icon { filter: grayscale(1); opacity: 0.6; }

/* 悬浮预览浮层：卡片下缘展开，边缘与卡片对齐；decorative（pointer-events 关闭）。 */
.app-card__preview {
  position: absolute;
  left: -1px;
  right: -1px;
  top: calc(100% + 6px);
  display: grid;
  gap: 4px;
  padding: 10px 12px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-card);
  background: var(--surface);
  box-shadow: var(--shadow-overlay);
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity var(--dur-hover) var(--ease-standard),
              transform var(--dur-hover) var(--ease-standard);
  pointer-events: none;
  z-index: 2;
}
.app-card:hover .app-card__preview,
.app-card:focus-visible .app-card__preview { opacity: 1; transform: translateY(0); }
.app-card__summary { color: var(--ink-2); font-size: 12.5px; line-height: 1.6; white-space: normal; }
.app-card__meta { font-size: 12.5px; font-weight: 650; }
.app-card__meta[data-tone="ok"] { color: var(--accent-ink); }
.app-card__meta[data-tone="busy"] { color: var(--clay-ink); }
.app-card__meta[data-tone="muted"] { color: var(--ink-2); }
.app-card__meta[data-tone="danger"] { color: var(--danger-ink); }
.app-card__addr { color: var(--ink-2); font-family: var(--mono); font-size: 12px; word-break: break-all; }

/* 触屏（无 hover）：预览静态常显在卡面下方，状态可见性不丢。 */
@media (hover: none) {
  .app-card__preview {
    position: static;
    opacity: 1;
    transform: none;
    margin-top: 6px;
    padding: 8px 0 0;
    border: 0;
    border-top: 1px solid var(--line);
    border-radius: 0;
    box-shadow: none;
    pointer-events: auto;
  }
}

/* 「字段 → 值」定义行（应用详情 / 卸载确认）。与索引行同形不同意图。 */
.def-list { border-top: 1px solid var(--line); }
.def-row { min-height: 56px; padding: 12px 4px; border-bottom: 1px solid var(--line); }
.def-row strong { color: var(--ink-2); font-size: 12.5px; font-weight: 650; }
.def-row small { margin-top: 4px; color: var(--ink); font-size: 13.5px; overflow-wrap: anywhere; }
.def-row small code { font-family: var(--mono); font-size: 12.5px; }

/* ── 组件层：章节头（双线）────────────────────────────
   dna shape.border_usage：章节标题用双线（1px + 3px 间隔 + 1px）。 */
.section-heading {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 0 0 20px;
  padding-bottom: 15px;
  border-bottom: 1px solid var(--line-2);
}
.section-heading::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 4px;
  height: 1px;
  background: var(--ink-2);
}
.section-heading h2 { margin: 0; }
.section-heading span { margin-left: auto; color: var(--ink-2); font-size: 12.5px; }
h2.section-heading { display: block; font-size: 19px; }

/* ── 布局与页面 ──────────────────────────────────────── */

.topbar {
  height: 60px;
  padding: 0 max(24px, calc((100vw - 1080px) / 2));
  display: flex;
  align-items: center;
  gap: 24px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}
.brand { margin-right: auto; font: 700 17px/1.4 var(--serif); }
.topbar a:not(.brand) {
  align-self: stretch;
  display: inline-flex;
  align-items: center;
  border-bottom: 2px solid transparent;
  transition: color var(--dur-state) var(--ease-standard), border-color var(--dur-state) var(--ease-standard);
}
.topbar a:not(.brand):hover { color: var(--ink); }
.topbar a[aria-current="page"] { color: var(--accent-ink); border-bottom-color: var(--accent); font-weight: 650; }
.topbar a.nav-locked { color: var(--ink-2); }
.nav-lock { margin-right: 5px; vertical-align: -1px; }

/* 顶栏工具区（CR-002 批 3）：⌘K 提示 + 明暗开关。两者都需要脚本才有行为，
   无 JS 时整块不渲染——不给死按钮。 */
.topbar-tools { display: none; align-items: center; gap: 10px; }
html.js .topbar-tools { display: flex; }
.palette-hint, .theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-ctl);
  color: var(--ink-2);
  background: var(--surface);
  cursor: pointer;
  transition: color var(--dur-hover) var(--ease-standard),
              border-color var(--dur-hover) var(--ease-standard),
              background-color var(--dur-hover) var(--ease-standard);
}
.palette-hint:hover, .theme-toggle:hover { color: var(--ink); border-color: var(--ink-2); background: var(--sunken); }
.palette-hint { height: 28px; padding: 0 9px; font: 500 11.5px/1 var(--mono); letter-spacing: 0.04em; }
.theme-toggle { width: 28px; height: 28px; padding: 0; }
.theme-toggle svg { width: 15px; height: 15px; }
.theme-toggle .icon-sun { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

/* ── 组件层：⌘K 命令面板（CR-002 批 3）────────────────────
   <dialog> 原生模态：Esc 关闭与焦点陷阱由浏览器提供，不手写。
   进入 240ms opacity + scale(.98→1)（dna 提案动效表）；关闭即时——
   动效表只点名进入，退出不做未设计的补间。reduce-motion 由文件尾部全局降级覆盖。 */
.palette {
  width: min(560px, calc(100vw - 48px));
  margin: 12vh auto auto;
  padding: 0;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-card);
  color: var(--ink);
  background: var(--surface);
  box-shadow: var(--shadow-overlay), 0 0 0 1px var(--shadow-ring);
  opacity: 0;
  transform: scale(.98);
  transition: opacity var(--dur-enter) var(--ease-enter), transform var(--dur-enter) var(--ease-enter);
}
.palette.is-open { opacity: 1; transform: none; }
.palette::backdrop { background: var(--overlay); }
/* 模态容器本身不画 UA 焦点环（Chrome 对 showModal 聚焦的 dialog 会画蓝框）：
   视觉边界由 --shadow-overlay + 遮罩给出；内部可聚焦元素仍有全站焦点环。 */
.palette:focus, .workspace-help:focus, .note-lightbox:focus { outline: none; }
.palette-search { display: flex; align-items: center; gap: 10px; padding: 14px 16px; border-bottom: 1px solid var(--line); }
.palette-search svg { flex: none; width: 15px; height: 15px; color: var(--ink-3); }
.palette-search input {
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  color: var(--ink);
  background: none;
  font: 400 15px/1.5 var(--sans);
}
.palette-search input:focus { outline: none; }
.palette-search input::placeholder { color: var(--ink-3); }
.palette-list { margin: 0; padding: 6px; list-style: none; max-height: min(46vh, 420px); overflow-y: auto; }
.palette-row { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: var(--radius-ctl); color: var(--ink); cursor: pointer; }
.palette-row--locked { color: var(--ink-2); }
.palette-row-icon { flex: none; display: inline-flex; width: 16px; height: 16px; color: var(--ink-3); }
.palette-row-icon svg { width: 16px; height: 16px; }
.palette-row-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-row-kind { flex: none; margin-left: auto; color: var(--ink-2); font: 500 11px/1 var(--mono); letter-spacing: 0.06em; }
/* 命令行的快捷键功能提示：靠右排在分类前；无徽标时分类仍靠 auto 贴右。 */
.palette-row-shortcut { flex: none; margin-left: auto; padding: 2px 6px; border: 1px solid var(--line-2); border-radius: 5px; color: var(--ink-2); font: 600 10.5px/1.4 var(--mono); letter-spacing: 0.04em; }
.palette-row-shortcut + .palette-row-kind { margin-left: 0; }
.palette-row[aria-selected="true"] { background: var(--accent-soft); }
.palette-row[aria-selected="true"] .palette-row-icon { color: var(--accent); }
.palette-row[aria-selected="true"] .palette-row-title { color: var(--accent-ink); }
.palette-empty { margin: 0; padding: 18px 16px 20px; color: var(--ink-2); font-size: 13.5px; }

main { width: min(1080px, calc(100% - 48px)); margin: 0 auto; padding: 56px 0 72px; }
/* 页脚备案悬挂（base.html 的 .site-footer）：只有配了备案号才渲染。内边距与
   .topbar 同源，让备案行与品牌左对齐；position/z-index 是为应用启动页那层
   固定背景（z-index: 0）服务的——不给的话备案行会被渐变层压住。 */
.site-footer {
  position: relative;
  z-index: 1;
  padding: 20px max(24px, calc((100vw - 1080px) / 2)) 32px;
  border-top: 1px solid var(--line);
  color: var(--ink-2);
  font-size: 12.5px;
}
.site-footer p { margin: 0; display: flex; flex-wrap: wrap; gap: 6px 18px; }
.site-footer a:hover { color: var(--accent); }
.page-header { max-width: 720px; margin-bottom: 48px; }
.eyebrow { margin: 0 0 16px; color: var(--accent); font: 600 11px/1.6 var(--mono); letter-spacing: 0.14em; text-transform: uppercase; }
h1 { margin: 0 0 16px; font: 700 clamp(30px, 4.4vw, 40px)/1.15 var(--serif); letter-spacing: 0.01em; }
h2 { font-family: var(--serif); }
.page-header > p:last-child { margin: 0; color: var(--ink-2); font-size: 17px; line-height: 1.75; max-width: 62ch; }
.page-header > p.stats { margin: 0; max-width: none; color: var(--ink-2); font-size: 12.5px; line-height: 1.7; }
.content-block { margin-top: 56px; }
.content-block:first-of-type { margin-top: 0; }
.prose { margin-top: 16px; color: var(--ink); line-height: 1.8; white-space: pre-wrap; }
.breadcrumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: -20px 0 28px; color: var(--ink-2); font-size: 12.5px; }
.breadcrumbs a { color: var(--ink-2); }
.breadcrumbs a:hover { color: var(--accent); }

/* 页脚动作区与表单 */
.admin-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.logout-form { flex: 0 0 auto; }
.stack-form { display: grid; gap: 12px; }
.stack-form button { margin-top: 8px; }
.filter-form { max-width: var(--form-narrow); }
.filter-form button { justify-self: start; }
.form-intro { margin: 0 0 28px; color: var(--ink-2); line-height: 1.7; }
.auth-panel { width: min(520px, 100%); }
/* 门禁 / 登录 / 生成卡密三个居中窄面板的标题：比文档页 h1 小一档——
   它们是「一道门」，不是一篇文章。 */
.compact-title { font-size: clamp(24px, 3.4vw, 30px); }
.generated-key {
  display: grid;
  gap: 10px;
  margin-bottom: 28px;
  padding: 18px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-card);
  background: var(--accent-soft);
}
.generated-key span, .generated-key small { color: var(--ink-2); font-size: 12px; }
.generated-key code { overflow-wrap: anywhere; font-family: var(--mono); font-size: 16px; }
.pagination { display: flex; align-items: center; gap: 18px; margin-top: 32px; color: var(--ink-2); font-size: 12.5px; }
.pagination a { color: var(--accent); }

/* ── 管理台（workspace：沉底 + 纸白卡片）─────────────── */
body.admin { background: var(--sunken); }
.admin-main { width: min(1180px, calc(100% - 48px)); padding: 40px 0 72px; }
.admin-topline { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 28px; }
.admin-topline h1 { margin: 0; font: 700 30px/1.25 var(--serif); }
.admin-topline > div > p:last-child { margin: 8px 0 0; color: var(--ink-2); font-size: 14px; }
.admin-topline p.stats { margin: 8px 0 0; color: var(--ink-2); font-size: 12.5px; }
.admin-layout { display: grid; grid-template-columns: var(--rail) minmax(0, 1fr); gap: 32px; align-items: start; }
.admin-workspace { display: grid; gap: 22px; align-content: start; min-width: 0; }
.admin-section {
  margin-top: 22px;
  padding: 20px 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.admin-section-first, .admin-section:first-child { margin-top: 0; }
.admin-workspace > .admin-section { margin-top: 0; }
.admin-section-heading {
  position: relative;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 24px;
  padding-bottom: 15px;
  border-bottom: 1px solid var(--line-2);
}
.admin-section-heading::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 4px;
  height: 1px;
  background: var(--ink-2);
}
.admin-section-heading .eyebrow { margin-bottom: 5px; }
.admin-section-heading h2 { margin: 0; font-size: 22px; }
.admin-section-heading > a, .admin-section-heading > span { color: var(--ink-2); font-size: 12.5px; }
.admin-section-heading > a:hover { color: var(--accent); }

/* 页边索引栏 */
.admin-sidebar {
  position: sticky;
  top: 24px;
  min-width: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.admin-sidebar-title { display: flex; justify-content: space-between; align-items: baseline; padding: 13px 14px; border-bottom: 1px solid var(--line); }
.admin-sidebar-title strong { color: var(--ink-2); font: 600 11px/1.6 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; }
.admin-sidebar-title span { color: var(--ink-2); font-size: 11.5px; }
.page-tabs { display: grid; }
.page-tabs a {
  display: grid;
  gap: 3px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
  border-left: 2px solid transparent;
  transition: background-color var(--dur-hover) var(--ease-standard), border-color var(--dur-hover) var(--ease-standard);
}
.page-tabs a:hover { background: var(--sunken); }
.page-tabs a[aria-current="page"] { border-left-color: var(--accent); background: var(--accent-soft); }
.page-tabs a[aria-current="page"] span { color: var(--accent-ink); font-weight: 650; }
.page-tabs small { overflow: hidden; color: var(--ink-2); font-size: 11.5px; text-overflow: ellipsis; }

/* 表单与就地编辑 */
.admin-form { display: grid; gap: 14px; max-width: var(--form-wide); }
.admin-form-grid { max-width: none; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.field-wide { grid-column: 1 / -1; }
.admin-form-grid button { justify-self: start; }
.inline-danger-form { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.compact-form { display: grid; gap: 11px; }
.compact-form button { justify-self: start; }
.admin-create-panel { border-top: 1px solid var(--line); }
.admin-create-panel > summary { padding: 12px 14px; color: var(--accent); font-size: 13.5px; font-weight: 650; cursor: pointer; }
.admin-create-panel > form { padding: 0 14px 14px; }
.admin-create-inline { max-width: var(--form-narrow); }
.admin-create-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
.admin-breadcrumbs { margin: 0 0 16px; padding: 10px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }

/* 列表项（可展开就地编辑） */
.admin-block-list, .admin-library-list { border-top: 1px solid var(--line); }
.admin-item { border-bottom: 1px solid var(--line); }
.admin-item > summary {
  min-height: 60px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  padding: 10px 4px;
  cursor: pointer;
  list-style: none;
  transition: background-color var(--dur-hover) var(--ease-standard);
}
.admin-item > summary:hover { background: var(--paper); }
.admin-item > summary::-webkit-details-marker { display: none; }
.admin-item > summary > span:first-child { min-width: 0; }
.admin-item summary strong, .admin-item summary small { display: block; }
.admin-item summary strong { font-size: 15px; }
.admin-item summary small { overflow: hidden; margin-top: 4px; color: var(--ink-2); font-size: 13px; font-weight: 400; text-overflow: ellipsis; white-space: nowrap; }
.admin-item summary > span:last-child { color: var(--ink-2); font-size: 12px; }
.admin-item-form { margin: 0 0 16px; padding: 16px 18px; border-left: 2px solid var(--accent); border-radius: 0 var(--radius-card) var(--radius-card) 0; background: var(--paper); }

/* 管理台资源管理区（resources-admin-center D2）：左目录树 + 右当前目录面板，
   与浏览页同构（.folder-tree 树样式直接复用）；策略徽标独立命名空间
   .resource-badge（浏览页瓦片不改）；窄屏沿用站点 720px 断点单列降级。 */
.admin-library-layout {
  display: grid;
  grid-template-columns: minmax(200px, 240px) minmax(0, 1fr);
  gap: 32px;
  align-items: start;
}
.admin-library-tree .folder-tree__item { align-items: center; }
.admin-library-tree .folder-tree__name { flex: 1; }
.admin-library-panel { min-width: 0; }
.resource-badge {
  display: inline-flex;
  align-items: center;
  padding: 1px 8px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  background: var(--sunken);
  color: var(--ink-2);
  font-size: 11px;
  line-height: 1.7;
  white-space: nowrap;
}
.resource-badge--public { border-color: transparent; background: var(--accent-soft); color: var(--accent-ink); }
.resource-badge--card { border-color: transparent; background: var(--clay-soft); color: var(--clay-ink); }
.resource-badge--admin { border-color: transparent; background: var(--danger-soft); color: var(--danger-ink); }
/* apps-tunnel-entry A5：隧道入口「临时」徽标——虚线边标示易变（Quick Tunnel
   随机主机名重启即换），与矩形实心策略徽标区分。 */
.resource-badge--tunnel { border-style: dashed; }

/* 「高级（JSON）」折叠（CR-002 批 3）。genome：原始 JSON 与 extension 默认
   折叠、复杂度渐进暴露；主表单流里只留人话字段。 */
.advanced { border: 1px solid var(--line); border-radius: var(--radius-ctl); }
.advanced > summary { padding: 8px 12px; color: var(--ink-2); font-size: 12.5px; font-weight: 650; cursor: pointer; transition: color var(--dur-hover) var(--ease-standard); }
.advanced > summary:hover { color: var(--ink); }
.advanced[open] > summary { border-bottom: 1px solid var(--line); }
.advanced-body { display: grid; gap: 11px; padding: 12px; }
.advanced-body textarea { font-family: var(--mono); font-size: 13px; line-height: 1.6; }

/* 导航仪表盘编辑区（visitor-surface-trim D2）：行内四字段小表单 +
   formaction 动作（保存 / 上移 / 下移 / 移除），底部添加行。 */
.link-board-editor { display: grid; gap: 10px; margin: 0 0 16px; padding: 14px 18px; border-left: 2px solid var(--accent); border-radius: 0 var(--radius-card) var(--radius-card) 0; background: var(--paper); }
.link-board-editor .eyebrow { margin: 0; }
.link-row { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.8fr) minmax(0, 1.3fr) minmax(0, 0.9fr) auto; gap: 10px; align-items: end; }
.link-row-actions { display: flex; gap: 6px; align-items: end; }
.link-row-actions button { min-width: 36px; }
.link-board-empty { margin: 0; color: var(--ink-2); font-size: 13px; }
.link-row-add { border-top: 1px dashed var(--line-2); padding-top: 12px; }

/* ── 卡密管理（access-key-management D6）──────────────────────────
   独立管理页采用「生成侧栏 + 生命周期列表」；窄屏退为单列。明文结果
   只使用可选择的等宽文本，下载按钮属于渐进增强（无 JS 仍可复制）。 */
.access-key-layout {
  display: grid;
  grid-template-columns: minmax(260px, 0.75fr) minmax(0, 1.7fr);
  gap: 22px;
  align-items: start;
}
.access-key-layout > .admin-section { min-width: 0; }
.access-key-generate-form { max-width: none; }
.access-key-generate-form small, .form-hint {
  color: var(--ink-2);
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.6;
}
.access-key-scope-fieldset {
  display: grid;
  gap: 10px;
  margin: 0;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-ctl);
}
.access-key-scope-fieldset legend {
  padding: 0 5px;
  color: var(--ink-2);
  font-size: 12.5px;
  font-weight: 650;
}
.access-key-scope-detail { margin-left: 24px; }
.access-key-filter {
  display: flex;
  align-items: end;
  gap: 10px;
  max-width: none;
  margin-bottom: 18px;
}
.access-key-filter label { min-width: 170px; }
.access-key-list { border-top: 1px solid var(--line); }
.access-key-row { padding: 18px 0; border-bottom: 1px solid var(--line); }
.access-key-row__summary { display: grid; gap: 8px; }
.access-key-row__summary > div { display: flex; flex-wrap: wrap; align-items: center; gap: 9px; }
.access-key-row__summary strong { font-size: 15px; }
.access-key-row__summary code { color: var(--ink-2); font-size: 11.5px; }
.access-key-row__summary p { display: flex; flex-wrap: wrap; gap: 6px 12px; margin: 0; color: var(--ink-2); font-size: 12.5px; }
.access-key-status {
  display: inline-flex;
  padding: 2px 8px;
  border-radius: var(--radius-pill);
  background: var(--sunken);
  color: var(--ink-2);
  font-size: 11px;
  font-weight: 650;
}
.access-key-status--valid { background: var(--accent-soft); color: var(--accent-ink); }
.access-key-status--expired { background: var(--clay-soft); color: var(--clay-ink); }
.access-key-status--revoked { background: var(--danger-soft); color: var(--danger-ink); }
.access-key-missing { color: var(--danger); }
.access-key-meta, .access-key-result-meta {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px 18px;
  margin: 15px 0;
}
.access-key-meta div, .access-key-result-meta div { min-width: 0; }
.access-key-meta dt, .access-key-result-meta dt { color: var(--ink-2); font-size: 11.5px; }
.access-key-meta dd, .access-key-result-meta dd { margin: 3px 0 0; overflow-wrap: anywhere; font-size: 12.5px; }
.access-key-actions {
  display: grid;
  grid-template-columns: minmax(180px, 1fr) minmax(170px, 0.8fr) auto;
  gap: 10px;
  align-items: end;
  padding: 14px;
  border-radius: var(--radius-ctl);
  background: var(--paper);
}
.access-key-actions > form:last-child { align-self: end; }
.access-key-label-form, .access-key-extend-form { grid-template-columns: minmax(0, 1fr) auto; align-items: end; }
.generated-key-list { display: grid; gap: 10px; margin: 0 0 18px; padding: 0; list-style: none; }
.generated-key-list li {
  display: grid;
  gap: 6px;
  padding: 14px 16px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-ctl);
  background: var(--accent-soft);
}
.generated-key-list code { overflow-wrap: anywhere; font: 600 15px/1.6 var(--mono); user-select: all; }
.generated-key-list small { color: var(--ink-2); font-size: 12px; }
.access-key-result { max-width: 900px; }
@media (max-width: 900px) {
  .access-key-layout { grid-template-columns: 1fr; }
  .access-key-actions { grid-template-columns: 1fr; }
  .access-key-label-form, .access-key-extend-form { grid-template-columns: minmax(0, 1fr) auto; }
}
@media (max-width: 560px) {
  .access-key-meta, .access-key-result-meta { grid-template-columns: 1fr; }
  .access-key-label-form, .access-key-extend-form { grid-template-columns: 1fr; }
}

/* ── Obsidian 笔记 (plugins/obsidian) ── */
/* 笔记库域壳宽（obsidian-client-alignment D2，设计偏差已登记）：三栏
   （左树 / 中内容 / 右元信息）在 1080 基础壳宽下会挤压阅读列，本域放宽。 */
.obsidian-main { width: min(1320px, calc(100% - 48px)); }
.obsidian-layout {
  display: grid;
  grid-template-columns: minmax(200px, 232px) minmax(0, 1fr) minmax(220px, 252px);
  gap: 36px;
  align-items: start;
}
/* 三栏显式定位：各页 DOM 序不同（笔记页正文在前，窄屏单列时内容优先），
   宽屏位置由类名统一钉住。 */
.obsidian-vault-tree { grid-column: 1; grid-row: 1; position: sticky; top: 28px; max-height: calc(100vh - 56px); overflow-y: auto; }
.obsidian-layout__content, .obsidian-layout > .note-body { grid-column: 2; grid-row: 1; min-width: 0; }
.obsidian-layout > .obsidian-sidebar { grid-column: 3; grid-row: 1; }
.obsidian-sidebar { position: sticky; top: 28px; min-width: 0; font-size: 13.5px; }
/* 文件树（数据面 folder_tree()）：目录 = <details>/<summary> 原生折叠
   （无 JS 可用）。行首 18px 让叶子与目录名同缩进对齐（目录行首是折叠箭头）。 */
.obsidian-vault-tree .folder-tree__summary { cursor: pointer; }
.obsidian-vault-tree .folder-tree__summary::-webkit-details-marker { display: none; }
.obsidian-vault-tree .folder-tree__summary::before {
  content: "▸";
  flex: none;
  width: 12px;
  color: var(--ink-2);
  font-size: 10px;
  transition: transform var(--dur-hover) var(--ease-standard);
}
.obsidian-vault-tree details[open] > .folder-tree__summary::before { transform: rotate(90deg); }
.obsidian-vault-tree a.folder-tree__item { padding-inline-start: 26px; }
.obsidian-vault-tree .folder-tree__count { margin-left: auto; color: var(--ink-2); font-size: 11.5px; }
.tag-cloud .count { color: var(--ink-2); font-size: 11.5px; }
/* 窄一档：右元信息列落到树与内容之下通栏。 */
@media (max-width: 1120px) {
  .obsidian-layout { grid-template-columns: minmax(200px, 232px) minmax(0, 1fr); }
  .obsidian-layout > .obsidian-sidebar { grid-column: 1 / -1; grid-row: 2; position: static; }
}
.obsidian-outline { list-style: none; margin: 0 0 28px; padding: 0; border-left: 1px solid var(--line); }
.obsidian-outline a { display: block; margin-left: -1px; padding: 5px 0 5px 12px; border-left: 2px solid transparent; color: var(--ink-2); transition: color var(--dur-hover) var(--ease-standard), border-color var(--dur-hover) var(--ease-standard); }
.obsidian-outline a:hover { color: var(--ink); }
.obsidian-outline a.is-active { color: var(--ink); border-left-color: var(--accent); }
.obsidian-outline .outline-level-1 { font-weight: 650; }
.obsidian-outline .outline-level-3 { padding-left: 24px; }
.obsidian-outline .outline-level-4, .obsidian-outline .outline-level-5, .obsidian-outline .outline-level-6 { padding-left: 36px; }
.tag-cloud { display: flex; flex-wrap: wrap; gap: 6px; }
.tag-pill {
  padding: 2px 9px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  color: var(--ink-2);
  background: var(--surface);
  font-size: 12px;
  transition: border-color var(--dur-hover) var(--ease-standard), color var(--dur-hover) var(--ease-standard);
}
.tag-pill:hover { color: var(--accent-ink); border-color: var(--accent); }
.link-list { list-style: none; margin: 0 0 28px; padding: 0; }
.link-list li { display: grid; gap: 2px; padding: 9px 0; border-bottom: 1px solid var(--line); }
.link-list a { font-weight: 650; font-size: 13.5px; }
.link-list small { color: var(--ink-2); font-family: var(--mono); font-size: 12px; overflow-wrap: anywhere; }
.frontmatter { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 6px 18px; margin: 0 0 36px; font-size: 14px; }
/* 元信息右栏里的属性块：与其他小节 28px 行距一致。 */
.obsidian-sidebar .frontmatter { margin-bottom: 28px; }
.frontmatter dt { color: var(--ink-2); font-size: 12.5px; }
.frontmatter dd { margin: 0; overflow-wrap: anywhere; }
.result-snippet { overflow-wrap: anywhere; }
.result-snippet mark { padding: 0 2px; background: var(--accent-soft); color: var(--accent-ink); }
/* 搜索页多标签 chips（obsidian-search-upgrade D3）：已选标签各带一个删除
   链接（×），删除链接保留关键词 / 目录等其余筛选。 */
.search-chips { margin: 10px 0 0; }
.search-chip { display: inline-flex; align-items: center; gap: 7px; }
.search-chip__remove { color: var(--ink-2); font-weight: 650; line-height: 1; }
.search-chip__remove:hover { color: var(--danger-ink); }
/* 层级标签树（obsidian-search-upgrade D3）：嵌套 <ul> 缩进出父子关系，父子
   同为 tag-pill 链接；父计数由服务端含子孙去重。 */
.tag-tree { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.tag-tree .tag-tree { margin: 8px 0 0 7px; padding-left: 14px; border-left: 1px solid var(--line); }
.tag-tree__node { display: grid; gap: 4px; justify-items: start; }

/* 搜索命中高亮与定位（obsidian-search-upgrade D4）：app.js 渐进增强把正文
   内的命中包成 <mark class="search-hit">。底色 / 墨色与 .result-snippet
   同口径（accent token，明暗自动翻转）；只加水平内边距、不改行高，长文不因
   高亮跳行。无 JS 时此规则不生效。 */
.note-body mark.search-hit {
  padding: 0 3px;
  border-radius: 4px;
  color: var(--accent-ink);
  background: var(--accent-soft);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* 阅读正文 */
.note-body { min-width: 0; max-width: var(--reading); font-size: 17px; line-height: 1.85; }
.note-body h2 { margin: 46px 0 14px; font: 700 27px/1.35 var(--serif); }
.note-body h3 { margin: 32px 0 10px; font: 700 20px/1.4 var(--serif); }
.note-body h4 { margin: 26px 0 8px; font: 700 17px/1.4 var(--serif); }
.note-body p { margin: 0 0 18px; }
.note-body ul, .note-body ol { margin: 0 0 18px; padding-left: 24px; }
.note-body li { margin: 4px 0; }
.note-body blockquote { margin: 0 0 20px; padding: 2px 0 2px 18px; border-left: 2px solid var(--clay); color: var(--ink-2); }
.note-body pre { margin: 0 0 20px; padding: 14px 16px; overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--surface); font-family: var(--mono); font-size: 13px; line-height: 1.75; }
.note-body code { padding: 1px 5px; border-radius: 4px; background: var(--sunken); font-family: var(--mono); font-size: 0.9em; }
.note-body pre code { padding: 0; background: none; }
/* 代码高亮（obsidian-client-alignment D3）：pygments 的 token 类只映射设计
   token —— 注释 = 墨二级斜体、关键字 = 松绿、字符串 = 陶土深、数字 = 松绿深；
   明暗双态由 token 翻转自动继承，无需第二套规则。名称 / 标点保持默认墨色
   （design-genome 纪律：层级靠墨的深浅，不堆颜色）。 */
.note-body .highlight .c, .note-body .highlight .c1, .note-body .highlight .cm, .note-body .highlight .cs, .note-body .highlight .ch, .note-body .highlight .cp, .note-body .highlight .cpf { color: var(--ink-2); font-style: italic; }
.note-body .highlight .k, .note-body .highlight .kc, .note-body .highlight .kd, .note-body .highlight .kn, .note-body .highlight .kp, .note-body .highlight .kr, .note-body .highlight .kt { color: var(--accent); font-weight: 600; }
.note-body .highlight .s, .note-body .highlight .s1, .note-body .highlight .s2, .note-body .highlight .sa, .note-body .highlight .sb, .note-body .highlight .sc, .note-body .highlight .sd, .note-body .highlight .se, .note-body .highlight .sh, .note-body .highlight .si, .note-body .highlight .sr, .note-body .highlight .ss, .note-body .highlight .sx, .note-body .highlight .dl { color: var(--clay-ink); }
.note-body .highlight .m, .note-body .highlight .mb, .note-body .highlight .mf, .note-body .highlight .mh, .note-body .highlight .mi, .note-body .highlight .mo { color: var(--accent-ink); }
.note-body .highlight .nf, .note-body .highlight .fm { font-weight: 650; }
.note-body .highlight .err { color: var(--danger); }
/* 数学（obsidian-client-alignment D3）：服务端只输出 TeX 原文（.math），
   KaTeX 加载后在这些容器内就地渲染（.katex 自带字体，盖过容器等宽）。
   无 JS 时块级公式以等宽原文呈现，段距并入 20px 节奏不塌陷。 */
.note-body .math { font-family: var(--mono); font-size: 0.93em; }
.note-body div.math { margin: 0 0 20px; }
.note-body .math .katex-display { margin: 0; }
.note-body img { max-width: 100%; height: auto; border-radius: var(--radius-card); }
/* 图片灯箱（obsidian-client-alignment D3）：JS 增强时才给可点提示；
   放大视图为单例 <dialog>，背板走全局遮罩 token。 */
.note-image-zoom { cursor: zoom-in; }
.note-lightbox { padding: 0; border: 0; background: transparent; max-width: none; max-height: none; }
.note-lightbox::backdrop { background: var(--overlay); }
.note-lightbox img { display: block; max-width: 92vw; max-height: 92vh; border-radius: var(--radius-card); box-shadow: var(--shadow-overlay); cursor: zoom-out; }
/* wikilink 悬浮预览卡（obsidian-client-alignment D3；app.js 渐进增强，无 JS
   时不存在）：浮层口径同瓦片菜单——fixed + 一级边线 + 进入微动效，坐标由
   脚本给出；内容以 textContent 组装，卡片自身零注入面。 */
.note-preview {
  position: fixed;
  z-index: 40;
  display: grid;
  gap: 3px;
  width: min(340px, calc(100vw - 32px));
  padding: 11px 13px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-card);
  background: var(--surface);
  box-shadow: var(--shadow-overlay), 0 0 0 1px var(--shadow-ring);
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity var(--dur-micro) var(--ease-standard),
              transform var(--dur-micro) var(--ease-standard);
}
.note-preview.is-open { opacity: 1; transform: none; }
.note-preview__title { font-weight: 650; font-size: 14px; line-height: 1.5; }
.note-preview__path { color: var(--ink-2); font-family: var(--mono); font-size: 11.5px; overflow-wrap: anywhere; }
.note-preview__excerpt { color: var(--ink-2); font-size: 13px; line-height: 1.6; max-height: 5.2em; overflow: hidden; }
.note-body table { width: 100%; margin: 0 0 20px; border-collapse: collapse; font-size: 14.5px; }
.note-body th, .note-body td { padding: 9px 11px; border-bottom: 1px solid var(--line); text-align: left; font-weight: 400; }
.note-body th { color: var(--ink-2); border-bottom-color: var(--line-2); font: 600 12px/1.6 var(--mono); letter-spacing: 0.06em; text-transform: uppercase; }
.note-body hr { margin: 32px 0; border: 0; border-top: 1px solid var(--line); }
.wikilink { color: var(--accent); border-bottom: 1px solid var(--line-2); }
.wikilink-unresolved { color: var(--ink-2); text-decoration: underline dotted; cursor: help; }
.embed-missing { color: var(--danger); font-style: italic; }

@media (max-width: 720px) {
  main { padding: 40px 0 56px; }
  .topbar { padding: 0 20px; overflow-x: auto; gap: 18px; }
  .palette-hint { display: none; } /* 触屏无 ⌘K；开关保留 */
  .page-header { margin-bottom: 36px; }
  .admin-topline { align-items: start; flex-direction: column; }
  .admin-layout { grid-template-columns: 1fr; gap: 28px; }
  .admin-sidebar { position: static; }
  .resource-browser { grid-template-columns: 1fr; gap: 28px; }
  .admin-library-layout { grid-template-columns: 1fr; gap: 28px; }
  .obsidian-layout { grid-template-columns: 1fr; gap: 32px; }
  .obsidian-vault-tree,
  .obsidian-layout__content,
  .obsidian-layout > .note-body,
  .obsidian-layout > .obsidian-sidebar { grid-column: auto; grid-row: auto; }
  .obsidian-vault-tree { position: static; max-height: none; overflow: visible; }
  .obsidian-sidebar { position: static; }
  .page-tabs { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .admin-form-grid, .admin-create-grid { grid-template-columns: 1fr; }
  .field-wide { grid-column: auto; }
  .admin-item-form { padding: 14px; }
  .plugin-row { grid-template-columns: 34px minmax(0, 1fr) auto; }
  .plugin-row .plugin-mark { display: none; }
}

/* 同步状态栏（obsidian-edit-sync）：页头「上次同步 + 立即同步」。
   四态由状态文件字段驱动（无记录 / 成功 / 失败 / 进行中）；「立即同步」
   是原生 POST 表单，JS 缺失时依然可用。 */
.obsidian-sync-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin: 20px 0 0; }
.obsidian-sync { font: 500 13px/1.6 var(--mono); color: var(--ink-2); }
.obsidian-sync.is-ok::before,
.obsidian-sync.is-error::before,
.obsidian-sync.is-running::before { content: "●"; margin-right: 6px; }
.obsidian-sync.is-ok::before { color: var(--accent); }
.obsidian-sync.is-running::before { color: var(--clay); }
.obsidian-sync.is-error { color: var(--danger-ink); }
.obsidian-sync.is-error::before { color: var(--danger); }
.obsidian-sync-form { margin: 0; }

/* 写动作（obsidian-client-alignment D5）：笔记页「编辑 / 重命名 / 删除」并排，
   重命名折叠在 <details> 内；浏览页「新建笔记」同型；删除确认页独立成页。
   全部原生表单，无 JS 可用。 */
.obsidian-note-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 16px 0 0; }
.obsidian-note-actions summary { list-style: none; }
.obsidian-note-actions summary::-webkit-details-marker { display: none; }
.obsidian-note-actions details[open] summary { margin-bottom: 10px; }
.obsidian-new-note { margin: 14px 0 0; max-width: 460px; }
.obsidian-new-note summary { list-style: none; }
.obsidian-new-note summary::-webkit-details-marker { display: none; }
.obsidian-new-note form { margin-top: 10px; }

/* 编辑页（obsidian-edit-sync）：原生表单为底，EasyMDE 只做渐进增强。 */
.obsidian-edit-form { display: grid; gap: 14px; max-width: var(--reading); }
.obsidian-edit-form textarea {
  width: 100%;
  min-height: 440px;
  padding: 14px 16px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-ctl);
  color: var(--ink);
  background: var(--surface);
  font: 400 13.5px/1.8 var(--mono);
  resize: vertical;
  transition: border-color var(--dur-hover) var(--ease-standard),
              box-shadow var(--dur-hover) var(--ease-standard);
}
.obsidian-edit-form textarea:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
.obsidian-edit-actions { display: flex; gap: 10px; }

/* EasyMDE 挂载后：压平其默认皮肤，改挂站点 token（含暗色两态）。 */
.obsidian-edit-form .EasyMDEContainer .CodeMirror {
  border: 1px solid var(--line-2);
  border-radius: 0 0 var(--radius-ctl) var(--radius-ctl);
  color: var(--ink);
  background: var(--surface);
  font: 400 13.5px/1.8 var(--mono);
}
.obsidian-edit-form .EasyMDEContainer .CodeMirror-cursor { border-left-color: var(--ink); }
.obsidian-edit-form .editor-toolbar { border-color: var(--line-2); border-radius: var(--radius-ctl) var(--radius-ctl) 0 0; background: var(--sunken); }
.obsidian-edit-form .editor-toolbar button { color: var(--ink-2); }
.obsidian-edit-form .editor-toolbar button.active,
.obsidian-edit-form .editor-toolbar button:hover { background: var(--accent-soft); border-color: transparent; }

/* 工具栏图标：Font Awesome Free 6.7.2（solid，CC BY 4.0——https://fontawesome.com/license/free），
   转换为 mask 内联 data-uri：零外部请求、吃 currentColor（明暗自适应）。
   EasyMDE 把图标的 fa 类塞进按钮内部 <i>（源码实证），故规则挂 button > i；
   按钮类就是 EasyMDE 按钮名（app.js 的 toolbar 列表——iconClassMap 在
   2.21.0 未被消费，不用），升级 EasyMDE 复跑转换即可。 */
.obsidian-edit-form .editor-toolbar button > i {
  display: inline-block;
  width: 15px;
  height: 15px;
  vertical-align: -2px;
  background-color: currentColor;
  -webkit-mask: var(--ob-icon) center / contain no-repeat;
  mask: var(--ob-icon) center / contain no-repeat;
}
.obsidian-edit-form .editor-toolbar button.active { color: var(--accent-ink); }
.obsidian-edit-form .editor-toolbar button.bold > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 384 512%22%3E%3Cpath d=%22M0 64C0 46.3 14.3 32 32 32l48 0 16 0 128 0c70.7 0 128 57.3 128 128c0 31.3-11.3 60.1-30 82.3c37.1 22.4 62 63.1 62 109.7c0 70.7-57.3 128-128 128L96 480l-16 0-48 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l16 0 0-160L48 96 32 96C14.3 96 0 81.7 0 64zM224 224c35.3 0 64-28.7 64-64s-28.7-64-64-64L112 96l0 128 112 0zM112 288l0 128 144 0c35.3 0 64-28.7 64-64s-28.7-64-64-64l-32 0-112 0z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.italic > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 384 512%22%3E%3Cpath d=%22M128 64c0-17.7 14.3-32 32-32l192 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-58.7 0L160 416l64 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 480c-17.7 0-32-14.3-32-32s14.3-32 32-32l58.7 0L224 96l-64 0c-17.7 0-32-14.3-32-32z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.strikethrough > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 512 512%22%3E%3Cpath d=%22M161.3 144c3.2-17.2 14-30.1 33.7-38.6c21.1-9 51.8-12.3 88.6-6.5c11.9 1.9 48.8 9.1 60.1 12c17.1 4.5 34.6-5.6 39.2-22.7s-5.6-34.6-22.7-39.2c-14.3-3.8-53.6-11.4-66.6-13.4c-44.7-7-88.3-4.2-123.7 10.9c-36.5 15.6-64.4 44.8-71.8 87.3c-.1 .6-.2 1.1-.2 1.7c-2.8 23.9 .5 45.6 10.1 64.6c4.5 9 10.2 16.9 16.7 23.9L32 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l448 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-209.9 0-.4-.1-1.1-.3c-36-10.8-65.2-19.6-85.2-33.1c-9.3-6.3-15-12.6-18.2-19.1c-3.1-6.1-5.2-14.6-3.8-27.4zM348.9 337.2c2.7 6.5 4.4 15.8 1.9 30.1c-3 17.6-13.8 30.8-33.9 39.4c-21.1 9-51.7 12.3-88.5 6.5c-18-2.9-49.1-13.5-74.4-22.1c-5.6-1.9-11-3.7-15.9-5.4c-16.8-5.6-34.9 3.5-40.5 20.3s3.5 34.9 20.3 40.5c3.6 1.2 7.9 2.7 12.7 4.3c0 0 0 0 0 0s0 0 0 0c24.9 8.5 63.6 21.7 87.6 25.6c0 0 0 0 0 0l.2 0c44.7 7 88.3 4.2 123.7-10.9c36.5-15.6 64.4-44.8 71.8-87.3c3.6-21 2.7-40.4-3.1-58.1l-75.7 0c7 5.6 11.4 11.2 13.9 17.2z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.heading > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 448 512%22%3E%3Cpath d=%22M0 64C0 46.3 14.3 32 32 32l48 0 48 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-16 0 0 112 224 0 0-112-16 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l48 0 48 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-16 0 0 144 0 176 16 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-48 0-48 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l16 0 0-144-224 0 0 144 16 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-48 0-48 0c-17.7 0-32-14.3-32-32s14.3-32 32-32l16 0 0-176L48 96 32 96C14.3 96 0 81.7 0 64z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.quote > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 448 512%22%3E%3Cpath d=%22M0 216C0 149.7 53.7 96 120 96l8 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-8 0c-30.9 0-56 25.1-56 56l0 8 64 0c35.3 0 64 28.7 64 64l0 64c0 35.3-28.7 64-64 64l-64 0c-35.3 0-64-28.7-64-64l0-32 0-32 0-72zm256 0c0-66.3 53.7-120 120-120l8 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-8 0c-30.9 0-56 25.1-56 56l0 8 64 0c35.3 0 64 28.7 64 64l0 64c0 35.3-28.7 64-64 64l-64 0c-35.3 0-64-28.7-64-64l0-32 0-32 0-72z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.unordered-list > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 512 512%22%3E%3Cpath d=%22M64 144a48 48 0 1 0 0-96 48 48 0 1 0 0 96zM192 64c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L192 64zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-288 0zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32l288 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-288 0zM64 464a48 48 0 1 0 0-96 48 48 0 1 0 0 96zm48-208a48 48 0 1 0 -96 0 48 48 0 1 0 96 0z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.ordered-list > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 512 512%22%3E%3Cpath d=%22M24 56c0-13.3 10.7-24 24-24l32 0c13.3 0 24 10.7 24 24l0 120 16 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-80 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l16 0 0-96-8 0C34.7 80 24 69.3 24 56zM86.7 341.2c-6.5-7.4-18.3-6.9-24 1.2L51.5 357.9c-7.7 10.8-22.7 13.3-33.5 5.6s-13.3-22.7-5.6-33.5l11.1-15.6c23.7-33.2 72.3-35.6 99.2-4.9c21.3 24.4 20.8 60.9-1.1 84.7L86.8 432l33.2 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-88 0c-9.5 0-18.2-5.6-22-14.4s-2.1-18.9 4.3-25.9l72-78c5.3-5.8 5.4-14.6 .3-20.5zM224 64l256 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-256 0c-17.7 0-32-14.3-32-32s14.3-32 32-32zm0 160l256 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-256 0c-17.7 0-32-14.3-32-32s14.3-32 32-32zm0 160l256 0c17.7 0 32 14.3 32 32s-14.3 32-32 32l-256 0c-17.7 0-32-14.3-32-32s14.3-32 32-32z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.check-list > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 448 512%22%3E%3Cpath d=%22M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-320c0-35.3-28.7-64-64-64L64 32zM337 209L209 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L303 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.code > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 640 512%22%3E%3Cpath d=%22M392.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm80.6 120.1c-12.5 12.5-12.5 32.8 0 45.3L562.7 256l-89.4 89.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l112-112c12.5-12.5 12.5-32.8 0-45.3l-112-112c-12.5-12.5-32.8-12.5-45.3 0zm-306.7 0c-12.5-12.5-32.8-12.5-45.3 0l-112 112c-12.5 12.5-12.5 32.8 0 45.3l112 112c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256l89.4-89.4c12.5-12.5 12.5-32.8 0-45.3z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.link > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 640 512%22%3E%3Cpath d=%22M579.8 267.7c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-1.1 1.6C206.5 251.2 213 330 263 380c56.5 56.5 148 56.5 204.5 0L579.8 267.7zM60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5L217.7 177.2c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.9l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6C433.5 260.8 427 182 377 132c-56.5-56.5-148-56.5-204.5 0L60.2 244.3z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.image > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 512 512%22%3E%3Cpath d=%22M0 96C0 60.7 28.7 32 64 32l384 0c35.3 0 64 28.7 64 64l0 320c0 35.3-28.7 64-64 64L64 480c-35.3 0-64-28.7-64-64L0 96zM323.8 202.5c-4.5-6.6-11.9-10.5-19.8-10.5s-15.4 3.9-19.8 10.5l-87 127.6L170.7 297c-4.6-5.7-11.5-9-18.7-9s-14.2 3.3-18.7 9l-64 80c-5.8 7.2-6.9 17.1-2.9 25.4s12.4 13.6 21.6 13.6l96 0 32 0 208 0c8.9 0 17.1-4.9 21.2-12.8s3.6-17.4-1.4-24.7l-120-176zM112 192a48 48 0 1 0 0-96 48 48 0 1 0 0 96z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.table > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 512 512%22%3E%3Cpath d=%22M64 256l0-96 160 0 0 96L64 256zm0 64l160 0 0 96L64 416l0-96zm224 96l0-96 160 0 0 96-160 0zM448 256l-160 0 0-96 160 0 0 96zM64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l384 0c35.3 0 64-28.7 64-64l0-320c0-35.3-28.7-64-64-64L64 32z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.horizontal-rule > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 448 512%22%3E%3Cpath d=%22M432 256c0 17.7-14.3 32-32 32L48 288c-17.7 0-32-14.3-32-32s14.3-32 32-32l352 0c17.7 0 32 14.3 32 32z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.clean-block > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 576 512%22%3E%3Cpath d=%22M290.7 57.4L57.4 290.7c-25 25-25 65.5 0 90.5l80 80c12 12 28.3 18.7 45.3 18.7L288 480l9.4 0L512 480c17.7 0 32-14.3 32-32s-14.3-32-32-32l-124.1 0L518.6 285.3c25-25 25-65.5 0-90.5L381.3 57.4c-25-25-65.5-25-90.5 0zM297.4 416l-9.4 0-105.4 0-80-80L227.3 211.3 364.7 348.7 297.4 416z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.undo > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 512 512%22%3E%3Cpath d=%22M48.5 224L40 224c-13.3 0-24-10.7-24-24L16 72c0-9.7 5.8-18.5 14.8-22.2s19.3-1.7 26.2 5.2L98.6 96.6c87.6-86.5 228.7-86.2 315.8 1c87.5 87.5 87.5 229.3 0 316.8s-229.3 87.5-316.8 0c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0c62.5 62.5 163.8 62.5 226.3 0s62.5-163.8 0-226.3c-62.2-62.2-162.7-62.5-225.3-1L185 183c6.9 6.9 8.9 17.2 5.2 26.2s-12.5 14.8-22.2 14.8L48.5 224z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.redo > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 512 512%22%3E%3Cpath d=%22M463.5 224l8.5 0c13.3 0 24-10.7 24-24l0-128c0-9.7-5.8-18.5-14.8-22.2s-19.3-1.7-26.2 5.2L413.4 96.6c-87.6-86.5-228.7-86.2-315.8 1c-87.5 87.5-87.5 229.3 0 316.8s229.3 87.5 316.8 0c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0c-62.5 62.5-163.8 62.5-226.3 0s-62.5-163.8 0-226.3c62.2-62.2 162.7-62.5 225.3-1L327 183c-6.9 6.9-8.9 17.2-5.2 26.2s12.5 14.8 22.2 14.8l119.5 0z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.preview > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 576 512%22%3E%3Cpath d=%22M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.side-by-side > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 512 512%22%3E%3Cpath d=%22M0 96C0 60.7 28.7 32 64 32l384 0c35.3 0 64 28.7 64 64l0 320c0 35.3-28.7 64-64 64L64 480c-35.3 0-64-28.7-64-64L0 96zm64 64l0 256 160 0 0-256L64 160zm384 0l-160 0 0 256 160 0 0-256z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-toolbar button.fullscreen > i { --ob-icon: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 448 512%22%3E%3Cpath d=%22M32 32C14.3 32 0 46.3 0 64l0 96c0 17.7 14.3 32 32 32s32-14.3 32-32l0-64 64 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L32 32zM64 352c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 96c0 17.7 14.3 32 32 32l96 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-64 0 0-64zM320 32c-17.7 0-32 14.3-32 32s14.3 32 32 32l64 0 0 64c0 17.7 14.3 32 32 32s32-14.3 32-32l0-96c0-17.7-14.3-32-32-32l-96 0zM448 352c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 64-64 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l96 0c17.7 0 32-14.3 32-32l0-96z%22/%3E%3C/svg%3E"); }
.obsidian-edit-form .editor-preview,
.obsidian-edit-form .editor-preview-side { color: var(--ink); background: var(--surface); border-color: var(--line-2); }
.obsidian-edit-form .editor-statusbar { color: var(--ink-2); }
/* 编辑页实时预览（obsidian-client-alignment D4）：预览容器由 app.js 挂
   .note-body 类，与阅读页完全共享排版 / 高亮 / 数学 / wikilink 规则
   （同一条渲染管线，预览即所见）；这里只补容器级差异与失败占位。 */
.obsidian-edit-form .editor-preview.note-body { padding: 14px 16px; }
.obsidian-preview-error { margin: 0; padding: 14px 16px; border: 1px dashed var(--line-2); border-radius: var(--radius-card); color: var(--ink-2); font-style: italic; }

/* ── 阅读增强（obsidian-reading-parity D2/D3/D4）：行内高亮 / Callout /
      Mermaid 图形与失败提示 / 标题锚点 / 代码复制按钮。全部手写映射到设计
      token，明暗双态随 token 自动翻转，不写第二套暗色规则；Mermaid 的 SVG
      由 vendor 主题着色，app.js 按 data-theme 在 dark / default 间选择。 */

/* 行内高亮（D2）：与 .result-snippet mark 同口径（accent-soft 底 +
   accent-ink 墨）；补内边距与圆角，跨行时逐行出块、两端都带圆角。 */
.note-body mark {
  padding: 0 3px;
  border-radius: 4px;
  color: var(--accent-ink);
  background: var(--accent-soft);
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* Callout（D1）：引用块扩展。背景走 surface、左条 3px 只用既有墨色 token
   ——层级靠墨的深浅，类型差异收敛为左条颜色（多数类型共享中性色）；折叠
   形态是原生 <details>，无 JS 可点击展开（去默认 marker，箭头口径同文件树）。 */
.note-body .callout {
  margin: 0 0 20px;
  padding: 13px 16px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--ink-2);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.note-body .callout__title,
.note-body details.callout > summary { margin: 0; color: var(--ink); font-size: 15px; font-weight: 650; line-height: 1.6; }
.note-body details.callout > summary { cursor: pointer; list-style: none; }
.note-body details.callout > summary::-webkit-details-marker { display: none; }
.note-body details.callout > summary::before {
  content: "▸";
  display: inline-block;
  margin-right: 6px;
  color: var(--ink-2);
  font-size: 10px;
  transition: transform var(--dur-hover) var(--ease-standard);
}
.note-body details.callout[open] > summary::before { transform: rotate(90deg); }
.note-body .callout__body { margin-top: 8px; }
.note-body .callout__body > :first-child { margin-top: 0; }
.note-body .callout__body > :last-child { margin-bottom: 0; }
/* 类型色（13 类白名单，未知类型由服务端回落 note）：只动左条——正向提示
   （tip/success/example）、行动项（info/todo）走松绿；提问/警示/引用走陶土；
   失败与缺陷（failure/danger/bug）走 danger；note/abstract 保持中性墨。 */
.note-body .callout--note, .note-body .callout--abstract { border-left-color: var(--ink-2); }
.note-body .callout--info, .note-body .callout--todo, .note-body .callout--tip,
.note-body .callout--success, .note-body .callout--example { border-left-color: var(--accent); }
.note-body .callout--question, .note-body .callout--warning, .note-body .callout--quote { border-left-color: var(--clay); }
.note-body .callout--failure, .note-body .callout--danger, .note-body .callout--bug { border-left-color: var(--danger); }

/* Mermaid（D3）：成功渲染的图形容器——横滚兜住超宽图、段距并入 20px 节奏；
   SVG 由 vendor 主题着色（明暗在 app.js 初始化时选定），随容器宽度自适应。 */
.mermaid-figure { margin: 0 0 20px; overflow-x: auto; }
.mermaid-figure svg { display: block; max-width: 100%; height: auto; }
/* 失败提示（app.js 注入）：弱提示不抢源码可读性——danger 圆点 + ink-2 文字
   （同同步状态栏口径），负上边距贴住源码块。 */
.mermaid-error { margin: -10px 0 20px; color: var(--ink-2); font-size: 13px; }
.mermaid-error::before { content: "●"; margin-right: 6px; color: var(--danger); }

/* 标题锚点（D4）：默认隐藏但占位（悬停不抖版）；悬停标题 / 锚点自身 /
   键盘聚焦时显现，无下划线（全局 a 规则）。无 JS 时是普通锚点导航；
   is-copied 用 accent 轻反馈（规则在显现之后，同位阶胜出）。 */
.note-body .heading-anchor {
  margin-left: 8px;
  color: var(--ink-3);
  font-size: 0.75em;
  font-weight: 400;
  opacity: 0;
  transition: opacity var(--dur-hover) var(--ease-standard),
              color var(--dur-hover) var(--ease-standard);
}
.note-body :is(h1, h2, h3, h4, h5, h6):hover .heading-anchor,
.note-body .heading-anchor:hover,
.note-body .heading-anchor:focus-visible { opacity: 1; color: var(--ink-2); }
.note-body :is(h1, h2, h3, h4, h5, h6) .heading-anchor.is-copied { opacity: 1; color: var(--accent); }

/* 代码复制按钮（D4）：绝对定位在容器右上（.highlight 包裹层或 <pre> 内，
   两者都是定位上下文）；默认透明，悬停 / 容器内聚焦显现，触屏无 hover 常显。 */
.highlight { position: relative; }
.note-body pre { position: relative; }
.code-copy {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 1;
  padding: 3px 9px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-ctl);
  color: var(--ink-2);
  background: var(--surface);
  font: 500 11.5px/1.7 var(--sans);
  letter-spacing: 0.02em;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--dur-hover) var(--ease-standard),
              color var(--dur-hover) var(--ease-standard),
              border-color var(--dur-hover) var(--ease-standard);
}
.note-body pre:hover .code-copy,
.note-body pre:focus-within .code-copy,
.note-body .highlight:hover .code-copy,
.note-body .highlight:focus-within .code-copy { opacity: 1; }
.code-copy:hover { color: var(--ink); border-color: var(--ink-2); }
.code-copy.is-copied { opacity: 1; color: var(--accent-ink); border-color: var(--accent); }
@media (hover: none) { .code-copy { opacity: 1; } }

/* ── 动效降级（design-dna.json › motion.reduce_motion） ──
   时长收敛为瞬时、位移归零、阶梯延迟取消。 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
  .plugin-row:hover > span[aria-hidden],
  a.resource-row:hover > span[aria-hidden],
  .link-card:hover,
  .resource-tile:hover,
  .app-card:hover, .app-card__preview,
  a.app-card:not(.app-card--disabled):focus-visible,
  .button:active, .button-primary:active, .button-secondary:active,
  .button-ghost:active, .button-danger:active { transform: none !important; }
  /* /apps 启动台（apps-launcher-cool）：扫光只在动效可用时存在（入场动画由
     上方 * 规则直达终态，卡片即时落位、不倾斜）。 */
  body.app-launchpad .app-card::after { opacity: 0 !important; }
}

/* ── Obsidian 分发面：导出 / 离线 / 同步感知（obsidian-publish-sync）──
   本节整体为追加：笔记页工具条（下载 / 打印 / 清理离线缓存）、离线状态条、
   同步提示条、同步管理页的历史表，以及打印契约。上面各节的口径不变。 */

/* 工具条（D1）：与写动作区同一条基线，无 JS 时打印按钮不出现
   （既有 .js-only 规则负责隐藏）。 */
.obsidian-note-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 14px 0 0; }
.obsidian-offline-tools { display: inline-flex; align-items: center; gap: 10px; }
.obsidian-note-tools .button-ghost { font-size: 13px; }

/* 同步提示条（D3）：阅读页的刷新入口 / 编辑页的只提醒条。强调色只用边框与
   浅底，不遮正文，不弹层。标记元素本身永不显示。 */
.obsidian-sync-watch { display: none; }
.sync-notice {
  margin: 14px 0 0;
  padding: 9px 14px;
  border: 1px solid var(--accent);
  border-left-width: 3px;
  border-radius: var(--radius-ctl);
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-size: 13.5px;
}
.sync-notice a { font-weight: 650; text-decoration: underline; }

/* 离线状态条（D2）：页面顶部一条，插在 body 首子元素前。 */
.offline-bar {
  margin: 0;
  padding: 8px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--clay-soft);
  color: var(--clay-ink);
  font-size: 13px;
  text-align: center;
}

/* 同步管理页（D4）：页头入口 + 历史表 + 消息展开。 */
.obsidian-sync-admin { font-size: 13px; text-decoration: underline; }
.sync-history { width: 100%; border-collapse: collapse; font-size: 13px; }
.sync-history th, .sync-history td {
  padding: 9px 10px;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}
.sync-history th { color: var(--ink-2); font-size: 12px; font-weight: 650; }
.sync-history td:first-child, .sync-history td:nth-child(2) { font-family: var(--mono); white-space: nowrap; }
.sync-history tr.is-error td { background: var(--danger-soft); }
.sync-history-message summary { cursor: pointer; color: var(--ink-2); overflow-wrap: anywhere; }
.sync-history-message pre, .sync-message {
  margin: 8px 0 0;
  padding: 10px 12px;
  overflow-x: auto;
  border-radius: var(--radius-ctl);
  background: var(--sunken);
  font-family: var(--mono);
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ── 组织能力：星标 / 回收站 / 文件夹 / 移动 / 排序 / 批量（obsidian-organization）──
   全部落在既有 token 与组件类之上：只加容器与状态类，不覆盖任何既有选择器。
   星标用 clay（标记色），操作条与确认页沿用 button / notice / link-list。 */
.folder-tree__item--starred { color: var(--clay-ink); }
.folder-tree__item--starred:hover { color: var(--clay-ink); }
.folder-tree__star { margin-left: 4px; color: var(--clay); font-size: 11px; }

/* 排序控件（D6）：原生链接，无 JS 可用；当前列加重并给出方向箭头。 */
.obsidian-sort { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; margin: 0 0 12px; }
.obsidian-sort__label { color: var(--ink-3); font-size: 11.5px; letter-spacing: 0.06em; text-transform: uppercase; }
.obsidian-sort__link { color: var(--ink-2); font-size: 13px; }
.obsidian-sort__link:hover { color: var(--accent); }
.obsidian-sort__link.is-active { color: var(--ink); font-weight: 650; }

/* 批量操作（D6）：复选框在行首，操作条在列表下方；无 JS 时按钮仍是提交入口。 */
.obsidian-batch-form { display: grid; gap: 12px; }
.obsidian-batch-row { display: flex; align-items: center; gap: 8px; }
.obsidian-batch-row__pick { flex: none; width: 16px; height: 16px; accent-color: var(--accent); }
.obsidian-batch-row .resource-row { flex: 1; min-width: 0; }
.obsidian-batch-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 0 0; border-top: 1px solid var(--line); }
.obsidian-batch-bar label { color: var(--ink-2); font-size: 12.5px; }
.obsidian-batch-bar input[type="text"] { width: 200px; padding: 7px 10px; border: 1px solid var(--line-2); border-radius: var(--radius-ctl); color: var(--ink); background: var(--surface); font: inherit; }
.obsidian-batch-report li { display: flex; align-items: baseline; gap: 6px; }
.obsidian-batch-report .is-ok > span[aria-hidden] { color: var(--accent); }
.obsidian-batch-report .is-failed > span[aria-hidden] { color: var(--danger); }

/* 星标（D1）：表单与按钮同行；已星标用标记色描边。 */
.obsidian-star-form { display: inline-flex; }
.obsidian-star-form .is-starred { color: var(--clay-ink); border-color: var(--clay); background: var(--clay-soft); }
.obsidian-star-manage { margin-top: 20px; }
.obsidian-star-manage summary { list-style: none; }
.obsidian-star-manage summary::-webkit-details-marker { display: none; }

/* 最近浏览（D2）：纯前端块；容器只在 html.js 下可见（app.css 顶部 .js-only 规则）。 */
.obsidian-recent { margin: 0 0 28px; }
.obsidian-recent__empty { padding: 10px 0; }
.obsidian-recent__list li { font-size: 13.5px; }

/* 回收站（D3）：条目卡一行，还原表单与彻底删除链接并排。 */
.obsidian-trash-list { display: grid; gap: 10px; }
.obsidian-trash-row { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 14px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--surface); }
.obsidian-trash-row__meta { display: grid; gap: 3px; min-width: 0; }
.obsidian-trash-row__meta small { color: var(--ink-2); }
.obsidian-trash-row__actions { display: flex; align-items: center; gap: 8px; }
.obsidian-trash-restore { display: inline-flex; }

/* 文件夹管理（D4）：三个面板并排（窄屏单列）。 */
.obsidian-folder-panels { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); margin-bottom: 28px; }
.obsidian-folder-panel { padding: 16px 18px; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--surface); }
.obsidian-folder-panel .section-heading { margin-top: 0; }
.obsidian-folder-hint { margin: 10px 0 0; color: var(--ink-2); font-size: 12.5px; }


/* ── 图谱与 Canvas 只读视图（obsidian-graph-canvas D2/D4）─────────────────────
   本节的样式面：graph.js / canvas.js 的容器、图例与只读画布。
   - 图容器带 .js-only（复用既有 html:not(.js) 规则）：无 JavaScript 时不呈现、
     不占位；全局图页的 .no-js-only 说明在脚本环境隐藏、其余环境接手。
   - 颜色只走设计 token 或 canvas.py 校验过的 --canvas-color（#rrggbb 白名单）。
   - 缩放 / 平移只改一个 transform，静态版面（坐标与连线都在 HTML 里）不依赖脚本。 */
.obsidian-graph { min-width: 0; }
.obsidian-note-graph { grid-column: 2; grid-row: 2; margin-top: 36px; }
.graph-viewport {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
}
.graph-canvas { display: block; width: 100%; height: 320px; touch-action: pan-y; }
.obsidian-global-graph .graph-canvas { height: min(64vh, 560px); }
/* 导航代理：真实 <a>，只被脚本 click()；视觉上不可见、不参与布局与朗读。 */
.graph-link-proxy {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.graph-note { margin: 10px 0 0; color: var(--ink-2); font-size: 12.5px; }
.graph-note.is-warning {
  padding-left: 10px;
  border-left: 3px solid var(--clay);
  color: var(--clay-ink);
}
.graph-depth { display: flex; gap: 8px; margin-left: auto; }
.graph-depth__link {
  padding: 2px 10px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-pill);
  color: var(--ink-2);
  font-size: 12px;
}
.graph-depth__link.is-current { color: var(--accent-ink); border-color: var(--accent); background: var(--accent-soft); }
.graph-legend { margin: 0 0 28px; padding: 0; list-style: none; color: var(--ink-2); font-size: 12.5px; }
.graph-legend li { display: flex; align-items: center; gap: 8px; margin: 6px 0; }
.graph-legend__mark { flex: none; width: 12px; height: 12px; border: 1px solid var(--ink-3); border-radius: 50%; }
.graph-legend__mark--note { background: var(--accent); border-color: var(--accent); }
.graph-legend__mark--attachment { background: var(--clay); border-color: var(--clay); }
.graph-legend__mark--ghost { border-style: dashed; }
/* 图谱悬浮标题复用 .note-preview 的浮层口径；这里是只读提示，不接收事件。 */
.graph-tip { pointer-events: none; }
/* 仅无脚本环境呈现的说明（与 .js-only 相反的一侧）。 */
html.js .no-js-only { display: none; }
@media (max-width: 720px) {
  .obsidian-note-graph { grid-column: auto; grid-row: auto; margin-top: 8px; }
  .graph-canvas { height: 260px; }
}

.canvas-viewport {
  position: relative;
  overflow: auto;
  max-height: min(78vh, 760px);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--sunken);
}
.canvas-viewport.is-panning { cursor: grabbing; }
.canvas-stage { position: relative; }
.canvas-group {
  position: absolute;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-card);
  background: var(--surface);
  border-left: 3px solid var(--canvas-color, var(--line-2));
}
.canvas-group--depth-1 { background: var(--paper); }
.canvas-group__label { margin: 0; padding: 8px 12px; color: var(--ink-2); font: 600 12px/1.6 var(--mono); letter-spacing: 0.04em; }
.canvas-edges { position: absolute; inset: 0; overflow: visible; pointer-events: none; }
.canvas-edge { stroke: var(--canvas-color, var(--line-2)); stroke-width: 1.5; }
.canvas-edge--loop { fill: none; }
.canvas-edge__label { fill: var(--ink-2); font: 11px/1.4 var(--sans); text-anchor: middle; }
.canvas-node {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px 12px;
  overflow: hidden;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-card);
  background: var(--surface);
  color: var(--ink);
  font-size: 13px;
  text-align: center;
  overflow-wrap: anywhere;
}
.canvas-node--colored { border-left: 3px solid var(--canvas-color, var(--line-2)); }
.canvas-node--file { color: var(--accent-ink); font-weight: 600; }
.canvas-node--file:hover { border-color: var(--accent); }
.canvas-node--link { color: var(--clay-ink); }
.canvas-node--link:hover { border-color: var(--clay); }
.canvas-node.is-missing { color: var(--ink-3); border-style: dashed; border-left-style: solid; background: var(--paper); }
.canvas-node--text { align-items: stretch; justify-content: flex-start; padding: 12px 14px; overflow: auto; text-align: left; }
.canvas-node--text .canvas-node__body { width: 100%; max-width: none; font-size: 13.5px; line-height: 1.6; }
.canvas-node--text .canvas-node__body > :first-child { margin-top: 0; }
.canvas-node--text .canvas-node__body > :last-child { margin-bottom: 0; }
.canvas-node--text .canvas-node__body :is(h1, h2, h3, h4, h5, h6) { margin: 10px 0 6px; font-size: 15px; }
.canvas-node--text .canvas-node__body img { max-width: 100%; height: auto; }


/* ── 编辑页增强（obsidian-authoring）：属性面板 / 附件上传 / 草稿横幅 / 补全 ──
   面板与上传入口都只属于 JS 层：面板在服务端直出里带 hidden 且控件 disabled，
   上传块带 .js-only——无 JS 时编辑页仍是「textarea + 保存」的现状，一行不变。
   补全下拉的键盘流由 vendor addon 负责，这里只把它接到站点 token 上。 */

/* 属性面板（D3）：与源码 textarea 并存——面板只接管顶层标量 / 列表属性，
   正文始终以 textarea 为唯一数据源。 */
.obsidian-fm { display: grid; gap: 10px; padding: 12px 14px; border: 1px solid var(--line-2); border-radius: var(--radius-card); background: var(--sunken); }
.obsidian-fm-head { display: grid; gap: 2px; }
.obsidian-fm-title { margin: 0; font: 600 13px/1.6 var(--sans); color: var(--ink); }
.obsidian-fm-hint { margin: 0; color: var(--ink-2); font-size: 12.5px; line-height: 1.7; }
.obsidian-fm-rows { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
.obsidian-fm-row { display: grid; grid-template-columns: minmax(120px, 1fr) 84px minmax(160px, 2fr) auto; gap: 8px; align-items: center; }
.obsidian-fm-row input, .obsidian-fm-row select {
  width: 100%;
  padding: 7px 10px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-ctl);
  color: var(--ink);
  background: var(--surface);
  font: 400 13px/1.6 var(--mono);
}
.obsidian-fm-row input:focus, .obsidian-fm-row select:focus { outline: none; border-color: var(--accent); box-shadow: var(--ring); }
.obsidian-fm-row.is-removed input { color: var(--ink-2); text-decoration: line-through; opacity: 0.72; }
.obsidian-fm-remove { padding: 6px 10px; border: 1px solid var(--line-2); border-radius: var(--radius-ctl); color: var(--ink-2); background: var(--surface); font: 500 12.5px/1.6 var(--sans); cursor: pointer; }
.obsidian-fm-remove:hover { color: var(--danger-ink); border-color: var(--danger); }
.obsidian-fm-actions { display: flex; }
.obsidian-fm-add { align-self: start; }
.obsidian-fm-raw { margin: 0; padding: 10px 12px; max-height: 220px; overflow: auto; border: 1px dashed var(--line-2); border-radius: var(--radius-ctl); color: var(--ink-2); background: var(--surface); font: 400 12.5px/1.7 var(--mono); }
@media (max-width: 720px) { .obsidian-fm-row { grid-template-columns: 1fr; } }

/* 附件上传（D2）：入口 + 状态行（失败不阻塞正文，只在这里说话）。 */
.obsidian-upload { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin: 14px 0 0; padding: 10px 14px; border: 1px dashed var(--line-2); border-radius: var(--radius-card); color: var(--ink-2); font-size: 13px; }
.obsidian-upload-label { font-weight: 600; color: var(--ink); }
.obsidian-upload-input { font: 400 13px/1.6 var(--sans); color: var(--ink-2); }
.obsidian-upload-hint { color: var(--ink-2); font-size: 12.5px; }
.obsidian-upload-status { flex: 1 1 100%; margin: 0; color: var(--ink-2); font: 400 12.5px/1.7 var(--mono); }
.obsidian-upload-status.is-error { color: var(--danger-ink); }

/* 草稿横幅（D4）：复用 .notice 的语义配色；两个版本都以 <pre> 只读呈现，
   选中的一方改了编辑器，未选的一方留在 <details> 里可以继续复制。 */
.obsidian-draft { display: grid; gap: 8px; }
.obsidian-draft__message { margin: 0; }
.obsidian-draft__actions { display: flex; flex-wrap: wrap; gap: 8px; }
.obsidian-draft__version summary { cursor: pointer; font-size: 12.5px; }
.obsidian-draft__text { margin: 6px 0 0; padding: 8px 10px; max-height: 200px; overflow: auto; border: 1px solid var(--line-2); border-radius: var(--radius-ctl); color: var(--ink); background: var(--surface); font: 400 12.5px/1.7 var(--mono); white-space: pre-wrap; }

/* 补全下拉（D1）：vendor 主题的白底 / #08f 反白 → 站点 token（含暗色两态）。 */
.CodeMirror-hints { padding: 4px; border: 1px solid var(--line-2); border-radius: var(--radius-ctl); background: var(--surface); box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18); font: 400 13px/1.6 var(--mono); }
.CodeMirror-hint { padding: 3px 8px; border-radius: 6px; color: var(--ink); }
.CodeMirror-hints li.CodeMirror-hint-active { background: var(--accent-soft); color: var(--accent-ink); }


/* ── 打印契约（obsidian-publish-sync D1.2）─────────────────────────
   只留正文：导航 / 侧栏 / 文件树 / 操作区 / 面包屑 / 分页 / 命令面板 /
   同步与离线提示 / 代码复制与锚点按钮全部不打印；正文单栏满宽。
   明暗两套主题都强制输出白纸黑字（暗色 token 打印既费墨又对比差），
   选择器的特异度与篇幅都至少与上面的暗色块相等，靠源码顺序取胜。 */
@media print {
  :root,
  :root[data-theme="dark"],
  :root:not([data-theme="light"]) {
    color-scheme: light;
    --paper: #fff;
    --surface: #fff;
    --sunken: #f4f4f4;
    --ink: #111;
    --ink-2: #333;
    --ink-3: #666;
    --line: #bbb;
    --line-2: #999;
    --accent: #0f5c43;
    --accent-ink: #0b3f2e;
    --accent-soft: #eef4f0;
    --clay: #8a4a22;
    --clay-ink: #6d3a1b;
    --clay-soft: #f7f1ec;
    --danger: #a3352a;
    --danger-ink: #7e2a21;
    --danger-soft: #faf0ee;
  }

  body { background: #fff; font-size: 11pt; line-height: 1.6; }

  .topbar, .brand, .topbar-tools, .folder-tree, .obsidian-vault-tree,
  .obsidian-sidebar, .breadcrumbs, .obsidian-note-actions, .obsidian-note-tools,
  .obsidian-sync-bar, .obsidian-sync-watch, .sync-notice, .offline-bar,
  .pagination, .filter-form, .search-chips, .obsidian-new-note, .obsidian-rename,
  .obsidian-edit-actions, .editor-toolbar, .editor-statusbar, .code-copy,
  .heading-anchor, .note-lightbox, .note-preview, .tile-menu, .palette,
  .empty-action, .js-only, .obsidian-shortcut-hint {
    display: none !important;
  }

  .obsidian-main { width: auto; margin: 0; }
  .obsidian-layout { display: block; }
  .obsidian-layout > .note-body,
  .obsidian-layout__content,
  .note-body {
    max-width: none;
    font-size: 11pt;
    line-height: 1.65;
  }
  .page-header h1 { font-size: 18pt; }
  .note-body h2 { margin: 18pt 0 6pt; font-size: 16pt; }
  .note-body h3 { margin: 14pt 0 5pt; font-size: 13.5pt; }
  .note-body h4 { margin: 12pt 0 4pt; font-size: 12pt; }

  /* 代码不截断：换行输出，长行不丢字（横滚区在纸上等于被裁掉）。 */
  .note-body pre, .note-body .highlight {
    overflow: visible !important;
    white-space: pre-wrap;
    word-break: break-word;
    border: 1px solid var(--line);
    background: var(--sunken);
  }
  .note-body code { background: none; }
  .note-body img { max-width: 100%; height: auto; }
  .note-body pre, .note-body blockquote, .note-body table, .note-body figure,
  .note-body .highlight, .note-body img, .sync-history tr {
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .note-body h2, .note-body h3, .note-body h4 { break-after: avoid; page-break-after: avoid; }

  /* 链接在纸上没有可点性：内链保留下划线，外链把地址补在括号里。 */
  a { color: inherit; text-decoration: underline; }
  .note-body a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.82em;
    word-break: break-all;
  }
}

/* 页边距只在分页媒体里有意义，放媒体块外（部分浏览器忽略嵌套在 @media 内的
   @page）。 */
@page { margin: 16mm; }

/* ── 工作区：多标签 / 分屏 / 命令与快捷键（obsidian-workspace）────────────
   以下节点全部由 app.js 创建：无 JavaScript 时不存在，页面就是既有的整页
   导航。非分屏态下工作区容器不参与布局（main.obsidian-main 的既有宽度与
   三栏栅格原样生效）；分屏才并排两个面板，并把面板内的三栏退化为单列
   （半宽容器撑不开「树 + 正文 + 右栏」）。窄屏（data-narrow）只呈现活动
   面板，split / second 状态保留，拉宽即恢复。 */

.workspace-tabs {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px max(24px, calc((100vw - 1320px) / 2));
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  overflow-x: auto;
}
.workspace-tab {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 220px;
  padding: 4px 6px 4px 11px;
  border: 1px solid transparent;
  border-radius: var(--radius-ctl);
  color: var(--ink-2);
  background: none;
  cursor: pointer;
  font: 400 13px/1.5 var(--sans);
  white-space: nowrap;
}
.workspace-tab:hover { color: var(--ink); background: var(--sunken); }
.workspace-tab.is-active { color: var(--ink); border-color: var(--line-2); background: var(--paper); font-weight: 600; }
.workspace-tab__label { overflow: hidden; text-overflow: ellipsis; }
.workspace-tab__close {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 4px;
  color: var(--ink-3);
  font-size: 13px;
  line-height: 1;
}
.workspace-tab__close:hover { color: var(--danger-ink); background: var(--danger-soft); }
.workspace-tab-new {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius-ctl);
  color: var(--ink-2);
  background: none;
  cursor: pointer;
}
.workspace-tab-new:hover { color: var(--ink); border-color: var(--ink-2); }
.workspace-notice { margin: 0 0 0 10px; color: var(--ink-2); font-size: 12px; white-space: nowrap; }

.workspace-panes { display: block; }
.workspace[data-split="true"] > .workspace-panes {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
}
.workspace[data-split="true"] > .workspace-panes > .workspace-pane { min-width: 0; }
.workspace[data-split="true"] > .workspace-panes > .workspace-pane + .workspace-pane { border-left: 1px solid var(--line); }
.workspace[data-split="true"] .workspace-pane[data-active="true"] { box-shadow: inset 0 2px 0 var(--accent); }
.workspace[data-split="true"] .workspace-pane > main.obsidian-main { width: auto; margin: 0; padding: 40px 28px 72px; }
.workspace[data-split="true"] .workspace-pane .obsidian-layout { grid-template-columns: minmax(0, 1fr); gap: 30px; }
.workspace[data-split="true"] .workspace-pane .obsidian-vault-tree,
.workspace[data-split="true"] .workspace-pane .obsidian-layout__content,
.workspace[data-split="true"] .workspace-pane .obsidian-layout > .note-body,
.workspace[data-split="true"] .workspace-pane .obsidian-layout > .obsidian-note-graph,
.workspace[data-split="true"] .workspace-pane .obsidian-layout > .obsidian-sidebar { grid-column: 1; grid-row: auto; }
.workspace[data-split="true"] .workspace-pane .obsidian-vault-tree { position: static; max-height: none; }
.workspace[data-split="true"] .workspace-pane .obsidian-sidebar { position: static; }
/* 窄屏回退：第二面板只呈现不参与布局（split / second 状态保留在 JS 里，
   拉宽即恢复；面板 DOM 不销毁）。栅格也要回到单列，否则被隐藏的右栏
   仍占着一半宽度。 */
.workspace[data-narrow="true"] > .workspace-panes { display: block; }
.workspace[data-narrow="true"] > .workspace-panes > .workspace-pane + .workspace-pane { display: none; }

/* ── 快捷键帮助浮层（D3：由注册表生成内容）──────────────────────── */
.workspace-help {
  width: min(460px, calc(100vw - 48px));
  margin: 10vh auto auto;
  padding: 18px 20px 16px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-card);
  color: var(--ink);
  background: var(--surface);
  box-shadow: var(--shadow-overlay), 0 0 0 1px var(--shadow-ring);
}
.workspace-help::backdrop { background: var(--overlay); }
.workspace-help__title { margin: 0 0 12px; font-size: 17px; }
.workspace-help__list { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 9px 16px; margin: 0; align-items: baseline; }
.workspace-help__key { font: 600 12px/1.5 var(--mono); letter-spacing: 0.04em; color: var(--accent-ink); }
.workspace-help__command { margin: 0; color: var(--ink-2); font-size: 13.5px; }
.workspace-help__hint { margin: 14px 0 0; color: var(--ink-2); font-size: 12px; }

/* ── 笔记库页面的快捷键功能提示（D3 可发现性）────────────────────
   容器直出 hidden，由脚本按注册表填充后取消隐藏；条目 = 键位 + 功能名。 */
.obsidian-shortcut-hint { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 14px; margin: 10px 0 0; color: var(--ink-2); font-size: 12.5px; }
.obsidian-shortcut-hint__label { color: var(--ink-3); font: 500 11px/1.4 var(--mono); letter-spacing: 0.08em; }
.obsidian-shortcut-hint__item { display: inline-flex; align-items: baseline; gap: 6px; }
.obsidian-shortcut-hint__item kbd { padding: 1.5px 5px; border: 1px solid var(--line-2); border-bottom-width: 2px; border-radius: 5px; background: var(--paper); color: var(--ink); font: 600 10.5px/1.4 var(--mono); letter-spacing: 0.04em; }
.obsidian-shortcut-hint__title { white-space: nowrap; }
/* 窄屏 / 触屏没有物理键盘，快捷键提示只占行不导流；帮助入口（?
  按钮）同样不呈现。规则需在组件声明之后，靠源码顺序取胜。 */
@media (max-width: 720px) { .obsidian-shortcut-hint { display: none; } }

/* 打印：标签条与帮助浮层是屏幕构件；分屏按活动面板单栏输出。 */
@media print {
  .workspace-tabs, .workspace-help { display: none !important; }
  .workspace[data-split="true"] > .workspace-panes { display: block; }
  .workspace[data-split="true"] > .workspace-panes > .workspace-pane + .workspace-pane { display: none !important; }
  .workspace[data-split="true"] .workspace-pane > main.obsidian-main { width: auto; padding: 0; }
  .workspace[data-split="true"] .workspace-pane[data-active="true"] { box-shadow: none; }
}

/* ── /apps 启动台：霓虹控制台（apps-launcher-cool）──
   纯 CSS，全部限定 body.app-launchpad（挂点：apps/list.html 的 body_class）。
   暗色＝深空 + 极光 + 霓虹，亮色＝浅色玻璃 + 柔和光晕；媒体块 / 属性块两块
   逐字相同（无 JS 兜底 / 显式选择双通道）。零 JS / 零依赖 / 无常驻动画；
   入场 stagger 由模板内联 --i 驱动，降级见文件尾 reduce 块。 */

body.app-launchpad {
  /* 亮色基调（默认） */
  --lp-page: linear-gradient(180deg, #f8f5ee, #efe9dc);
  --lp-aurora-1: rgba(15, 92, 67, .16);
  --lp-aurora-2: rgba(176, 85, 47, .13);
  --lp-grid: rgba(28, 27, 24, .045);
  --lp-vignette: rgba(28, 27, 24, .10);
  --lp-card-bg: linear-gradient(180deg, #fffffe, #f8f5ee);
  --lp-card-line: rgba(28, 27, 24, .12);
  --lp-card-shadow: 0 14px 36px -26px rgba(28, 27, 24, .6);
  --lp-stripe: rgba(28, 27, 24, .05);
  --lp-neon: rgba(15, 92, 67, .42);
  --lp-neon-hi: rgba(15, 92, 67, .78);
  --lp-neon-glow: rgba(15, 92, 67, .20);
  --lp-icon-bg: linear-gradient(150deg, rgba(15, 92, 67, .26), rgba(176, 85, 47, .16));
  --lp-sweep: rgba(15, 92, 67, .13);
  --lp-preview-bg: rgba(255, 255, 255, .97);

  background: var(--lp-page);
}

/* 暗色（满血霓虹）：系统偏好（无 JS 兜底）…… */
@media (prefers-color-scheme: dark) {
  html:not([data-theme="light"]) body.app-launchpad {
    --lp-page: linear-gradient(180deg, #080b11, #0d1220 58%, #07090e);
    --lp-aurora-1: rgba(45, 212, 191, .30);
    --lp-aurora-2: rgba(129, 140, 248, .26);
    --lp-grid: rgba(148, 197, 255, .055);
    --lp-vignette: rgba(0, 0, 0, .55);
    --lp-card-bg: linear-gradient(180deg, rgba(148, 197, 255, .10), rgba(16, 21, 31, .74) 46%);
    --lp-card-line: rgba(148, 197, 255, .16);
    --lp-card-shadow: 0 18px 44px -28px rgba(0, 0, 0, .95);
    --lp-stripe: rgba(148, 197, 255, .07);
    --lp-neon: rgba(56, 224, 190, .5);
    --lp-neon-hi: rgba(94, 234, 212, .9);
    --lp-neon-glow: rgba(56, 224, 190, .42);
    --lp-icon-bg: linear-gradient(150deg, rgba(56, 224, 190, .28), rgba(129, 140, 248, .22));
    --lp-sweep: rgba(170, 255, 240, .20);
    --lp-preview-bg: rgba(12, 16, 24, .95);
  }
}

/* …与显式选择（顶栏开关 / localStorage）两块逐字相同。 */
html[data-theme="dark"] body.app-launchpad {
  --lp-page: linear-gradient(180deg, #080b11, #0d1220 58%, #07090e);
  --lp-aurora-1: rgba(45, 212, 191, .30);
  --lp-aurora-2: rgba(129, 140, 248, .26);
  --lp-grid: rgba(148, 197, 255, .055);
  --lp-vignette: rgba(0, 0, 0, .55);
  --lp-card-bg: linear-gradient(180deg, rgba(148, 197, 255, .10), rgba(16, 21, 31, .74) 46%);
  --lp-card-line: rgba(148, 197, 255, .16);
  --lp-card-shadow: 0 18px 44px -28px rgba(0, 0, 0, .95);
  --lp-stripe: rgba(148, 197, 255, .07);
  --lp-neon: rgba(56, 224, 190, .5);
  --lp-neon-hi: rgba(94, 234, 212, .9);
  --lp-neon-glow: rgba(56, 224, 190, .42);
  --lp-icon-bg: linear-gradient(150deg, rgba(56, 224, 190, .28), rgba(129, 140, 248, .22));
  --lp-sweep: rgba(170, 255, 240, .20);
  --lp-preview-bg: rgba(12, 16, 24, .95);
}

/* 纸面层（D2）：极光（::before）＋ 网格与暗角（::after）固定视口、不参与点击；
   顶栏与内容层抬到 z-index 1（零新增 DOM）。 */
body.app-launchpad::before,
body.app-launchpad::after { content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none; }
body.app-launchpad::before { background: radial-gradient(42% 34% at 16% 6%, var(--lp-aurora-1), transparent 70%), radial-gradient(38% 30% at 84% 2%, var(--lp-aurora-2), transparent 72%); }
body.app-launchpad::after {
  background: radial-gradient(120% 92% at 50% -6%, transparent 52%, var(--lp-vignette) 100%), linear-gradient(var(--lp-grid) 1px, transparent 1px), linear-gradient(90deg, var(--lp-grid) 1px, transparent 1px);
  background-size: auto, 44px 44px, 44px 44px;
}
body.app-launchpad .topbar { position: relative; z-index: 1; background: transparent; border-bottom-color: var(--lp-card-line); }
body.app-launchpad main.admin-main { position: relative; z-index: 1; }

/* 卡片（D3）：玻璃卡面 + 内高光；可开启卡霓虹描边 + 轻微辉光；禁用卡
   去饱和 + 斜纹、无辉光。卡面仍只有图标与名称。 */
body.app-launchpad .app-card {
  isolation: isolate; min-height: 152px; padding: 20px 16px 18px;
  border: 1px solid var(--lp-card-line); background: var(--lp-card-bg); box-shadow: var(--lp-card-shadow);
  animation: app-launchpad-in 220ms var(--ease-enter) backwards;
  animation-delay: calc(var(--i, 0) * var(--dur-micro) / 3);
  transition: transform var(--dur-hover) var(--ease-standard),
              border-color var(--dur-hover) var(--ease-standard),
              box-shadow var(--dur-hover) var(--ease-standard);
}
body.app-launchpad a.app-card:not(.app-card--disabled) {
  border-color: var(--lp-neon);
  box-shadow: 0 0 0 1px var(--lp-neon), 0 0 26px -12px var(--lp-neon-glow), var(--lp-card-shadow);
}
body.app-launchpad .app-card__icon {
  display: grid; place-items: center; min-width: 54px; height: 54px; padding: 0 9px;
  border: 1px solid var(--lp-neon); border-radius: var(--radius-pill); background: var(--lp-icon-bg);
  box-shadow: inset 0 0 14px var(--lp-neon-glow), 0 0 24px -8px var(--lp-neon-glow); font-size: 26px;
}
body.app-launchpad .app-card--disabled { background: repeating-linear-gradient(135deg, transparent 0 9px, var(--lp-stripe) 9px 10px), var(--lp-card-bg); box-shadow: none; }
body.app-launchpad .app-card--disabled .app-card__icon { border-color: var(--lp-card-line); background: none; box-shadow: none; }

/* 交互（D4）：悬浮 / 聚焦倾斜上浮 + 扫光一掠 + 辉光增强。扫光是卡片伪元素
   （卡片不得 overflow: hidden——预览浮层在卡片外），靠 border-radius 收边；
   回程无过渡，只有单向一掠。过渡只动 transform 与色 / 阴影（已文档化例外）；
   禁用卡一律排除，不给可点击暗示。 */
body.app-launchpad a.app-card:not(.app-card--disabled):hover,
body.app-launchpad a.app-card:not(.app-card--disabled):focus-visible {
  transform: perspective(900px) rotateX(4deg) rotateY(-3deg) translateY(-4px);
  border-color: var(--lp-neon-hi);
  box-shadow: 0 0 0 1px var(--lp-neon-hi), 0 26px 52px -24px var(--lp-neon-glow), var(--lp-card-shadow);
  z-index: 3;
}
body.app-launchpad a.app-card:not(.app-card--disabled):hover .app-card__icon,
body.app-launchpad a.app-card:not(.app-card--disabled):focus-visible .app-card__icon {
  border-color: var(--lp-neon-hi);
  box-shadow: inset 0 0 16px var(--lp-neon-glow), 0 0 30px -6px var(--lp-neon-glow);
}
body.app-launchpad .app-card::after {
  content: ""; position: absolute; inset: 0; z-index: 1; border-radius: inherit;
  background: linear-gradient(105deg, transparent 40%, var(--lp-sweep) 50%, transparent 60%);
  transform: translateX(-130%); pointer-events: none;
}
body.app-launchpad a.app-card:not(.app-card--disabled):hover::after,
body.app-launchpad a.app-card:not(.app-card--disabled):focus-visible::after {
  transform: translateX(130%);
  transition: transform 240ms var(--ease-standard);
}

/* 预览浮层（D4）：结构定位不变，升级玻璃底与更强投影；触屏静态常显规则
   原样保留（上方 @media (hover: none) 块），这里只补静态兜底。 */
body.app-launchpad .app-card__preview {
  z-index: 3; border-color: var(--lp-neon); background: var(--lp-preview-bg);
  box-shadow: 0 20px 44px -22px rgba(0, 0, 0, .35), var(--lp-card-shadow);
}
@media (hover: none) {
  body.app-launchpad .app-card__preview { background: transparent; box-shadow: none; z-index: auto; }
}

/* 入场（D5）：一次性淡入上浮，--i 决定阶梯（40 毫秒步进、封顶 12）；无循环动画，reduce 直达终态。 */
@keyframes app-launchpad-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
