/* ══════════════════════════════════════════════════════════════════════
   Signeve — 应用页（登录 / 注册 / 条款 / 隐私 / 状态）共用样式
   ══════════════════════════════════════════════════════════════════════

   颜色、字号、间距、圆角全部来自 tokens.css，这里一个色值都不写死。
   改主题只改 tokens.css 一处。

   这一页和落地页的区别：落地页的任务是让人**想要**这个东西，所以有
   大标题、演示、对比图；这几页的任务是让人**赶紧办完一件事**，所以
   只有一张窄卡片、一个表单、一个按钮。
   把「说服」和「办事」混在一页上，两边都做不好。
*/

.ap {
  margin: 0;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--surface-sunken, var(--ink-50));
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--text-md);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

.ap-wrap { width: min(100% - 2.5rem, 1080px); margin-inline: auto; }

/* ── 顶栏 ───────────────────────────────────────────────────────────── */

.ap-nav {
  background: var(--surface-raised);
  border-bottom: 1px solid var(--border-subtle);
}
.ap-nav-in {
  display: flex; align-items: center; justify-content: space-between;
  min-height: 56px; gap: 1rem;
}
.ap-brand {
  display: inline-flex; align-items: center; gap: 0.5rem;
  color: var(--text-primary); text-decoration: none;
  font-weight: 650; letter-spacing: -0.01em;
}
.ap-brand img { border-radius: var(--radius-sm); }
.ap-nav-back {
  color: var(--text-secondary); text-decoration: none;
  font-size: var(--text-sm);
}
.ap-nav-back:hover { color: var(--text-primary); }

/* ── 主区 ───────────────────────────────────────────────────────────── */

.ap-main {
  flex: 1;
  display: flex; flex-direction: column; align-items: center;
  padding: clamp(2rem, 6vh, 4.5rem) 1.25rem clamp(2rem, 5vh, 3.5rem);
  gap: 1.25rem;
}
.ap-main--doc { padding-top: clamp(1.5rem, 4vh, 3rem); }

/* ── 表单卡片 ───────────────────────────────────────────────────────── */

.ap-card {
  width: 100%; max-width: 27rem;
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 4vw, 2.25rem);
  box-shadow: var(--shadow-sm);
}

.ap-h1 {
  margin: 0 0 0.35rem;
  font-size: var(--text-2xl);
  line-height: 1.25;
  letter-spacing: -0.02em;
  font-weight: 680;
}
.ap-lede { margin: 0 0 1.5rem; color: var(--text-secondary); font-size: var(--text-sm); }

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

.ap-form { display: flex; flex-direction: column; gap: 1rem; }

.ap-field { display: flex; flex-direction: column; gap: 0.35rem; }

.ap-label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--text-primary);
}

.ap-input {
  width: 100%;
  box-sizing: border-box;
  min-height: var(--size-touch-min, 44px);
  padding: 0.55rem 0.75rem;
  font: inherit;
  font-size: var(--text-md);
  color: var(--text-primary);
  background: var(--surface-raised);
  border: 1px solid var(--border-default, var(--border-subtle));
  border-radius: var(--radius-md);
  transition: border-color var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard);
}
.ap-input:hover { border-color: var(--border-strong, var(--text-tertiary)); }
.ap-input:focus-visible,
.ap-input:focus {
  outline: none;
  border-color: var(--brand-600);
  box-shadow: var(--shadow-focus, 0 0 0 3px rgb(var(--brand-600-rgb) / 0.18));
}
.ap-input[aria-invalid="true"] {
  border-color: var(--red-500);
  box-shadow: 0 0 0 3px rgb(var(--red-500-rgb) / 0.14);
}

.ap-hint { font-size: var(--text-xs); color: var(--text-tertiary); }

/* 密码框 + 显示/隐藏 */
.ap-pass { position: relative; display: block; }
.ap-pass .ap-input { padding-right: 2.75rem; }
.ap-pass-toggle {
  position: absolute; top: 50%; right: 0.35rem;
  transform: translateY(-50%);
  display: grid; place-items: center;
  width: 2.25rem; height: 2.25rem;
  padding: 0;
  color: var(--text-tertiary);
  background: none; border: 0; border-radius: var(--radius-sm);
  cursor: pointer;
}
.ap-pass-toggle:hover { color: var(--text-primary); background: var(--ink-50); }

/* 记住我 / 忘记口令 一行 */
.ap-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  margin-top: -0.25rem;
}
.ap-check {
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-size: var(--text-sm); color: var(--text-secondary);
  cursor: pointer;
}
.ap-check input { width: 1rem; height: 1rem; accent-color: var(--brand-600); cursor: pointer; }

.ap-link {
  color: var(--brand-700, var(--brand-600));
  text-decoration: none;
  text-underline-offset: 0.2em;
}
.ap-link:hover { text-decoration: underline; }
.ap-link:focus-visible { outline: 2px solid var(--brand-600); outline-offset: 2px; border-radius: var(--radius-xs); }

/* 主按钮 */
.ap-btn {
  min-height: var(--size-touch-min, 44px);
  margin-top: 0.35rem;
  padding: 0.6rem 1rem;
  font: inherit; font-size: var(--text-md); font-weight: 640;
  color: #fff;
  background: var(--brand-600);
  border: 0; border-radius: var(--radius-md);
  cursor: pointer;
  transition: background var(--duration-fast) var(--ease-standard),
              transform var(--duration-instant) var(--ease-standard);
}
.ap-btn:hover:not(:disabled) { background: var(--brand-700, var(--brand-600)); }
.ap-btn:active:not(:disabled) { transform: translateY(1px); }
.ap-btn:focus-visible { outline: 2px solid var(--brand-600); outline-offset: 2px; }
/* :disabled 在提交中是常态（网络慢的时候会停一会儿），
   所以不能只靠变暗 —— 要让它看起来像"正在做事"。 */
.ap-btn:disabled { opacity: 0.7; cursor: progress; }

.ap-legal { margin: 0; font-size: var(--text-xs); color: var(--text-tertiary); line-height: 1.6; }

.ap-alt {
  margin: 1.25rem 0 0;
  padding-top: 1.1rem;
  border-top: 1px solid var(--border-subtle);
  font-size: var(--text-sm);
  color: var(--text-secondary);
  text-align: center;
}

.ap-foot-note {
  max-width: 27rem;
  margin: 0;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  line-height: 1.65;
  text-align: center;
}

/* ── 错误提示 ───────────────────────────────────────────────────────── */

.ap-alert {
  margin-bottom: 1rem;
  padding: 0.7rem 0.85rem;
  font-size: var(--text-sm);
  color: var(--red-700, var(--red-500));
  background: rgb(var(--red-500-rgb) / 0.08);
  border: 1px solid rgb(var(--red-500-rgb) / 0.28);
  border-radius: var(--radius-md);
}
.ap-alert[hidden] { display: none; }

/* ── 条款 / 隐私 / 状态 ─────────────────────────────────────────────── */

.ap-doc {
  width: 100%; max-width: 46rem;
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 4vw, 3rem);
  box-shadow: var(--shadow-sm);
}

.ap-draft {
  margin: 0 0 1.75rem;
  padding: 0.55rem 0.8rem;
  font-size: var(--text-sm);
  color: var(--accent-800, var(--accent-700));
  background: var(--accent-50);
  border-left: 3px solid var(--accent-500);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.ap-prose { max-width: 40rem; }
.ap-prose > p { margin: 0 0 1rem; color: var(--text-secondary); }
.ap-prose strong { color: var(--text-primary); font-weight: 640; }
.ap-prose code {
  padding: 0.1em 0.35em;
  font-family: var(--font-mono);
  font-size: 0.9em;
  background: var(--ink-50);
  border-radius: var(--radius-xs);
}

.ap-h5 {
  margin: 2rem 0 0.75rem;
  font-size: var(--text-lg);
  font-weight: 660;
  letter-spacing: -0.01em;
  color: var(--text-primary);
}
.ap-h1 + .ap-prose .ap-h5:first-child { margin-top: 0.5rem; }

.ap-list {
  margin: 0 0 1rem;
  padding: 0;
  list-style: none;
  display: flex; flex-direction: column; gap: 0.55rem;
}
.ap-list li {
  position: relative;
  padding-left: 1.1rem;
  color: var(--text-secondary);
}
.ap-list li::before {
  content: "";
  position: absolute; left: 0.15rem; top: 0.62em;
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--brand-500);
}

/* 状态页 */
.ap-status {
  margin: 0 0 1.5rem;
  padding: 0;
  list-style: none;
  display: flex; flex-direction: column;
}
.ap-status-row {
  display: flex; align-items: center; gap: 0.7rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--border-subtle);
}
.ap-status-row:first-child { border-top: 1px solid var(--border-subtle); }
.ap-status-name { font-weight: 600; }
.ap-status-val { margin-left: auto; color: var(--text-secondary); font-size: var(--text-sm); }
.ap-dot {
  flex: none;
  width: 9px; height: 9px;
  border-radius: 50%;
}
.ap-dot--ok { background: var(--green-500); box-shadow: 0 0 0 3px rgb(var(--green-500-rgb) / 0.16); }
.ap-dot--bad { background: var(--red-500); box-shadow: 0 0 0 3px rgb(var(--red-500-rgb) / 0.16); }

.ap-aside { margin: 0 0 0.5rem; font-size: var(--text-xs); color: var(--text-tertiary); }
.ap-aside strong { color: var(--text-secondary); font-weight: 600; }

/* ── 页脚 ───────────────────────────────────────────────────────────── */

.ap-foot {
  border-top: 1px solid var(--border-subtle);
  background: var(--surface-raised);
}
.ap-foot-in {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  min-height: 64px;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}
.ap-foot-links { display: flex; gap: 1.25rem; }
.ap-foot-links a { color: var(--text-secondary); text-decoration: none; }
.ap-foot-links a:hover { color: var(--text-primary); text-decoration: underline; }

@media (max-width: 560px) {
  .ap-foot-in { justify-content: center; text-align: center; padding: 1rem 0; }
}

/* ── 成功提示（忘记口令那页原地报告「已发出」用） ───────────────────── */

.ap-alert--ok {
  color: var(--green-700, var(--green-500));
  background: rgb(var(--green-500-rgb) / 0.08);
  border-color: rgb(var(--green-500-rgb) / 0.3);
}

/* ── 登出（顶栏里的一个表单按钮） ───────────────────────────────────── */

.ap-logout { margin: 0; }
.ap-link--btn {
  padding: 0;
  font: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}
.ap-link--btn:hover { text-decoration: underline; }
.ap-link--btn:focus-visible { outline: 2px solid var(--brand-600); outline-offset: 2px; }

/* ── 合同列表 ───────────────────────────────────────────────────────── */

.ap-doc-head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap;
  margin-bottom: 1.5rem;
}
.ap-doc-head .ap-lede { margin-bottom: 0; }
.ap-doc-actions { display: flex; align-items: center; gap: 0.85rem; }

.ap-quota {
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  white-space: nowrap;
}

.ap-btn--sm {
  min-height: 38px;
  margin-top: 0;
  padding: 0.4rem 0.9rem;
  font-size: var(--text-sm);
}

/* 表格：窄屏横向滚动。
   合约名可能很长，让表格滚动而不是让整页滚动 —— 整页横向滚动时
   顶栏和页脚会跟着跑，人会失去方位感。 */
.ap-table-wrap {
  margin: 0 -0.25rem 1rem;
  overflow-x: auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}
.ap-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
}
.ap-table th {
  padding: 0.6rem 0.85rem;
  text-align: left;
  font-weight: 600;
  color: var(--text-tertiary);
  background: var(--ink-50);
  border-bottom: 1px solid var(--border-subtle);
  white-space: nowrap;
}
.ap-table td {
  padding: 0.7rem 0.85rem;
  border-bottom: 1px solid var(--border-subtle);
  vertical-align: middle;
}
.ap-table tr:last-child td { border-bottom: 0; }
.ap-table tbody tr:hover { background: var(--ink-50); }
.ap-cell-name { min-width: 14rem; }
.ap-cell-name a { font-weight: 600; }
.ap-num { text-align: right; font-variant-numeric: tabular-nums; }
.ap-when { color: var(--text-tertiary); white-space: nowrap; font-variant-numeric: tabular-nums; }

.ap-pill {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  font-size: var(--text-xs);
  font-weight: 600;
  border-radius: 999px;
  white-space: nowrap;
  color: var(--text-secondary);
  background: var(--ink-100);
}
/* 只给"要注意"的两种状态上色。全部上色等于全部没上色 ——
   草稿和已完成如果都是彩色的，扫一眼看不出哪个需要处理。 */
.ap-pill--partially_signed { color: var(--accent-800, var(--accent-700)); background: var(--accent-50); }
.ap-pill--completed,
.ap-pill--signed           { color: var(--green-700, var(--green-500)); background: rgb(var(--green-500-rgb) / 0.12); }
.ap-pill--declined,
.ap-pill--expired          { color: var(--red-700, var(--red-500)); background: rgb(var(--red-500-rgb) / 0.1); }
.ap-pill--sent             { color: var(--accent-800, var(--accent-700)); background: var(--accent-50); }
/* draft / pending 用 .ap-pill 的默认灰：还没发生的事不需要颜色 */

.ap-empty {
  padding: 3rem 1.5rem;
  text-align: center;
  border: 1px dashed var(--border-default, var(--border-subtle));
  border-radius: var(--radius-md);
  margin-bottom: 1rem;
}
.ap-empty-t { margin: 0 0 0.35rem; font-weight: 620; color: var(--text-primary); }
.ap-empty-h { margin: 0; font-size: var(--text-sm); color: var(--text-tertiary); }

.ap-doc-hint { margin-top: 0.35rem; }

/* 上传进度条。用 indeterminate 之外的确定进度 —— 传大文件时
   "走了多少"比"还在转"有用得多。 */
.ap-progress {
  height: 4px;
  margin-bottom: 1rem;
  background: var(--ink-100);
  border-radius: 999px;
  overflow: hidden;
}
.ap-progress[hidden] { display: none; }
.ap-progress-bar {
  display: block;
  width: 0;
  height: 100%;
  background: var(--brand-600);
  border-radius: inherit;
  transition: width 120ms linear;
}

.ap-toast { display: none; }

/* ── 合同详情 ───────────────────────────────────────────────────────── */

.ap-back {
  display: inline-block;
  margin-bottom: 1rem;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  text-decoration: none;
}
.ap-back:hover { color: var(--text-primary); text-decoration: underline; }

.ap-sec { margin-top: 2rem; }
.ap-sec .ap-h5 { margin-top: 0; }

/* 概览用 dl，不是 ul+span。键值对本来就是"术语—定义"的关系，
   用对标签屏幕阅读器才知道哪个是标签哪个是值。 */
.ap-kvs {
  margin: 0;
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.45rem 1.5rem;
  font-size: var(--text-sm);
}
.ap-kv { display: contents; }
.ap-kv dt { color: var(--text-tertiary); }
.ap-kv dd { margin: 0; color: var(--text-primary); font-variant-numeric: tabular-nums; }

.ap-people, .ap-files {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.ap-person, .ap-file {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  padding: 0.6rem 0.75rem;
  font-size: var(--text-sm);
  background: var(--ink-50);
  border-radius: var(--radius-md);
}
.ap-person-n { font-weight: 620; }
.ap-person-e { color: var(--text-secondary); }
.ap-tag {
  margin-left: auto;
  padding: 0.1rem 0.5rem;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: 999px;
  white-space: nowrap;
}
.ap-file-meta { margin-left: auto; font-size: var(--text-xs); color: var(--text-tertiary); }

.ap-prose-p { margin: 0 0 0.75rem; font-size: var(--text-sm); color: var(--text-secondary); }

/* ★ 作废区 ★
 *
 * 这是详情页上唯一一个**不可撤销**的动作，所以它必须看起来跟别的不一样：
 *   · 整节用一条左侧色带和内容分开 —— 它不该被误读成"又一个普通操作"；
 *   · 按钮是朱砂色，跟主操作（品牌蓝）明确区分；
 *   · 色带而不是整块底色：整块底色会让这一节看起来像"报错"，
 *     而它平时是一个正当的选项，只有点开之后才是危险的。
 *
 * tokens.css 里 `--button-danger-*` 三件套早就定义好了（签署页的拒签按钮在用），
 * app 这边一直没有 `.ap-btn--danger` —— 又是一处"token 有了、没人接"。
 */
.ap-sec--danger {
  padding-left: 0.9rem;
  border-left: 3px solid var(--border-danger);
}
.ap-sec--danger .ap-h5 { color: var(--text-danger); }

.ap-btn--danger { background: var(--button-danger-bg); color: var(--button-danger-fg); }
.ap-btn--danger:hover:not(:disabled) { background: var(--button-danger-bg-hover); }
.ap-btn--danger:focus-visible { outline-color: var(--button-danger-bg-hover); }

/* 那段"收不回来"的说明用正文色而不是灰字 —— 它是**决策依据**，
   不是补充说明。灰字会被跳过，而这段被跳过就等于没写。 */
.ap-prose-p--warn {
  color: var(--text-danger);
  border-left: 2px solid var(--border-danger);
  padding-left: 0.7rem;
}

/* ── 详情页：加签署人 / 生成链接 ────────────────────────────────────── */

/* 折叠起来，是因为"添加签署人"是**低频**动作：一份合同加一两个签署人
   就完了，剩下时间都在看进度。摊开会让页面重心跑到表单上。 */
.ap-fold { margin-top: 0.9rem; border-top: 1px solid var(--border-subtle); padding-top: 0.9rem; }
.ap-fold > summary {
  cursor: pointer;
  font-size: var(--text-sm);
  font-weight: 620;
  color: var(--text-secondary);
  list-style: none;
}
.ap-fold > summary::-webkit-details-marker { display: none; }
.ap-fold > summary::before { content: "+ "; color: var(--text-tertiary); }
.ap-fold[open] > summary::before { content: "− "; }
.ap-fold > summary:hover { color: var(--text-primary); }

.ap-form--inline {
  margin-top: 0.75rem;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.65rem;
}
.ap-form--inline .ap-field { flex: 1 1 12rem; margin: 0; }
.ap-form--inline .ap-field--narrow { flex: 0 0 5.5rem; }

.ap-h6 { margin: 0 0 0.6rem; font-size: var(--text-sm); font-weight: 660; }

/* 链接一行：输入框吃掉剩余宽度，按钮不缩。 */
.ap-copyrow { display: flex; gap: 0.5rem; align-items: stretch; }
.ap-copyrow .ap-input { flex: 1 1 auto; min-width: 0; }
.ap-input--mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: var(--text-xs); }

.ap-invite {
  margin-top: 1rem;
  padding: 0.9rem 1rem;
  background: var(--ink-50);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.ap-btn--slim { padding: 0.25rem 0.7rem; font-size: var(--text-xs); }
.ap-person .ap-btn--slim { margin-left: 0.25rem; }
/* 顺序标签在按钮前面时不该再把按钮挤到最右 —— 有按钮就取消 margin-left:auto */
.ap-person:has(.ap-btn--slim) .ap-tag { margin-left: auto; }

/* 拒签理由：一行独占（.ap-person 是 flex-wrap，flex-basis:100% 就会换行）。
   理由可能是一整句话，所以不用 pill —— 挤在 pill 里会被截断。 */
.ap-person-r {
  flex-basis: 100%;
  font-size: var(--text-xs);
  color: var(--red-700, var(--red-500));
  padding-left: 0.1rem;
}
.ap-person-r::first-letter { letter-spacing: 0; }

.ap-people + .ap-fold { margin-top: 0.75rem; }

/* ── 改 / 删签署人 ────────────────────────────────────────────────────
   折叠块是列表里的另一个 <li>，不是套在原来那一行里面 ——
   `.ap-person` 是 flex-wrap 的一行，往里塞一个表单会把它挤成一团。
   用 :not([hidden]) 加左边框，让它看起来是"从上面那一行展开的"。 */
.ap-person--edit {
  display: block;
  border-left: 2px solid var(--border-strong, var(--border-subtle));
  margin: -0.25rem 0 0.5rem 0.25rem;
  padding: 0.6rem 0 0.2rem 0.75rem;
}
.ap-person--edit[hidden] { display: none; }
.ap-person--edit .ap-form--inline { margin-bottom: 0.4rem; }
.ap-roledel { margin-top: 0.35rem; }
.ap-roledel-c {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
}
.ap-roledel-c[hidden] { display: none; }
.ap-roledel-c .ap-hint { flex-basis: 100%; }
.ap-person--edit .ap-alert { margin-top: 0.5rem; }

/* ══ 字段编辑器 ══════════════════════════════════════════════════════
   全宽画布 + 左侧工具栏。工具栏窄（11rem）是因为它只在放字段时看，
   看完就该把地方还给 PDF。 */

.ed-main { padding: 0 0 3rem; }

.ed-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.6rem 1.25rem;
  background: var(--surface-raised);
  border-bottom: 1px solid var(--border-subtle);
}
.ed-back { font-size: var(--text-sm); color: var(--text-secondary); text-decoration: none; }
.ed-back:hover { color: var(--text-primary); text-decoration: underline; }
.ed-name {
  font-size: var(--text-sm);
  font-weight: 620;
  max-width: 26rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ed-stat { font-size: var(--text-xs); color: var(--text-tertiary); }
.ed-save { margin-left: auto; }

.ed-alert {
  margin: 0.75rem 1.25rem 0;
  padding: 0.6rem 0.85rem;
  font-size: var(--text-sm);
  color: var(--text-danger);
  background: var(--red-50);
  border: 1px solid rgb(var(--red-500-rgb) / 0.28);
  border-radius: var(--radius-md);
}
.ed-alert--ok { color: var(--text-success); background: var(--green-50); border-color: rgb(var(--green-500-rgb) / 0.3); }

.ed-body { display: flex; align-items: flex-start; gap: 1.25rem; padding: 1.25rem; }

.ed-palette {
  flex: 0 0 12.5rem;
  position: sticky;
  top: 3.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.ed-h {
  margin: 0.9rem 0 0.1rem;
  font-size: var(--text-xs);
  font-weight: 660;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}
.ed-h:first-child { margin-top: 0; }

.ed-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.ed-chip {
  padding: 0.3rem 0.6rem;
  font: inherit;
  font-size: var(--text-xs);
  color: var(--text-secondary);
  background: var(--surface-raised);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  cursor: pointer;
}
.ed-chip:hover { border-color: var(--border-strong); color: var(--text-primary); }
.ed-chip.is-on {
  color: var(--brand-700);
  background: var(--brand-50);
  border-color: var(--brand-400);
  font-weight: 620;
}

.ed-sel { display: flex; flex-direction: column; gap: 0.3rem; }
.ed-insp {
  padding: 0.6rem 0.7rem;
  font-size: var(--text-xs);
  background: var(--ink-50);
  border-radius: var(--radius-md);
}
.ed-insp-t { font-weight: 660; font-size: var(--text-sm); }
.ed-insp-r { margin-top: 0.15rem; color: var(--text-tertiary); font-variant-numeric: tabular-nums; }
.ed-insp-row { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.5rem; }
.ed-insp-row .ap-input { max-width: 8rem; padding: 0.2rem 0.4rem; font-size: var(--text-xs); }
.ed-del { margin-top: 0.6rem; width: 100%; padding: 0.3rem; font-size: var(--text-xs); }

.ed-legend { margin: 0; padding: 0; list-style: none; font-size: var(--text-xs); color: var(--text-secondary); }
.ed-legend li { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 0.25rem; }
.ed-sw { width: 0.7rem; height: 0.7rem; border-radius: 2px; flex: none; }
.ed-sw--req { background: var(--signer-field-border); }
.ed-sw--opt { background: var(--surface-raised); border: 1px dashed var(--border-strong); }
.ed-sw--filled { background: var(--signer-field-done-bd); }

.ed-pages { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 1.25rem; }
.ed-loading { color: var(--text-tertiary); font-size: var(--text-sm); }

.ed-page {
  position: relative;
  background: #fff;
  box-shadow: 0 1px 3px rgb(0 0 0 / 8%), 0 8px 24px rgb(0 0 0 / 6%);
  border-radius: 3px;
}
.ed-page canvas { display: block; border-radius: 3px; }
.ed-layer { position: absolute; inset: 0; }

.ed-pgno {
  position: absolute;
  right: 0.5rem;
  bottom: -1.15rem;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}

/* ── 字段框 ──
   颜色全部走 `--signer-field-*` —— 就是签署页那一套。
   一个字段编辑器如果不长得像签署人看到的那个样子，它就是在骗人：
   在这儿画成蓝天鹅绒，到对方屏幕上变成灰虚线，没人会认为这是同一个东西。
   （那组变量定义在 tokens.css:277，签署页 sign.css:320 用它画 ::before。）

   必填用实线、选填用虚线：差别是"签不签得完"，不该只靠颜色区分 ——
   色觉障碍的人看不出来。 */
.ed-f {
  position: absolute;
  box-sizing: border-box;
  border: 1.5px solid var(--signer-field-border);
  border-radius: 3px;
  background: var(--signer-field-bg);
  cursor: grab;
  touch-action: none;
}
.ed-f.is-req { border-style: solid; }
.ed-f:not(.is-req) { border-style: dashed; }
.ed-f.is-sel {
  outline: 2px solid var(--signer-field-border);
  outline-offset: 1px;
  background: var(--signer-field-active);
}
.ed-f.is-filled {
  border-color: var(--signer-field-done-bd);
  background: var(--signer-field-done-bg);
  cursor: not-allowed;
}
.ed-f-l {
  position: absolute;
  left: 0;
  top: -1.15rem;
  font-size: 0.68rem;
  line-height: 1;
  white-space: nowrap;
  color: var(--signer-field-border);
  pointer-events: none;
}
.ed-f.is-filled .ed-f-l { color: var(--signer-field-done-bd); }
.ed-f-h {
  position: absolute;
  right: -4px;
  bottom: -4px;
  width: 9px;
  height: 9px;
  background: var(--signer-field-border);
  border: 1.5px solid #fff;
  border-radius: 2px;
  cursor: nwse-resize;
  touch-action: none;
}

@media (max-width: 860px) {
  .ed-body { flex-direction: column; }
  .ed-palette { position: static; flex: none; width: 100%; }
}

/* 「放字段」那一行：按钮和解释并排，窄屏时竖向堆 */
.ap-alt .ap-hint--inline { margin-left: 0.6rem; }
@media (max-width: 620px) {
  .ap-alt .ap-hint--inline { display: block; margin: 0.4rem 0 0; }
}

/* ── 组织设置 ──────────────────────────────────────────────────────── */

.ap-input--narrow { max-width: 9rem; }
.ap-muted { color: var(--text-tertiary); font-weight: 400; }
.ap-note {
  margin: 0.9rem 0 0;
  padding: 0.7rem 0.85rem;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  background: var(--ink-50);
  border-radius: var(--radius-md);
}
.ap-overrides {
  margin: 0.55rem 0 0;
  padding-left: 1.2rem;
  font-size: var(--text-xs);
  color: var(--text-tertiary);
}
.ap-overrides code { font-size: inherit; color: var(--text-secondary); }
.ap-feats {
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0.4rem 1.2rem;
  font-size: var(--text-sm);
}
/* 没开的功能压暗而不是删掉 —— 用户要看的是"专业版给了什么"，
   少一行他就得去定价页对一遍。 */
.ap-feat { color: var(--text-tertiary); }
.ap-feat.is-on { color: var(--text-primary); }
/* 这里原来写的是 `var(--danger, #a3322f)` —— `--danger` 全项目从没定义过，
   所以它一直在用兜底的那个旧饱和红（不在低饱和色板里）。
   语义色现成就有：`--text-danger`（tokens.css:93 → `--red-700`）。 */
.ap-toast.is-bad { display: block; color: var(--text-danger); }
