/* ===== UniDoc — Microsoft Word 365 风格 UI ===== */
* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  /* Word 品牌蓝（彩色主题：标题栏 / 状态栏 / 主按钮同色） */
  --accent: #2b579a;
  --accent-dark: #1f4478;      /* 主按钮悬停深蓝 */
  --accent-weak: #deecf9;      /* Office 浅蓝（选中态底色） */
  /* Fluent 中性色板（Word 365 功能区视觉语言） */
  --ink: #323130;              /* 主文字 */
  --ink-2: #605e5c;            /* 次文字 / 组标签 */
  --line: #d2d0ce;             /* 常规描边 */
  --line-soft: #edebe9;        /* 发丝分隔线 */
  --hover: #edebe9;            /* 悬停灰 */
  --press: #e1dfdd;            /* 按下灰 */
  --on: #d2d0ce;               /* 切换按下态（Word 方形灰块） */
  --ribbon-bg: #ffffff;
  --ribbon-border: var(--line-soft);
  --canvas-bg: #e5e3e0;        /* Word 画布中性灰 */
  --page-w: 794px;            /* A4 @96dpi */
  --page-h: 1123px;
  --page-pad: 76px;           /* ~2cm 页边距 */
  /* 选区色：Word 灰（与 Word 白主题选中文本一致） */
  --selection-bg: rgba(0, 0, 0, .16);
  --word-format-mark: #7a7a7a;
  /* UniPPT selection controls compensate document zoom back to screen pixels. */
  --selection-ui-scale: 1;
}

/* 全局选区（正文/输入框等）；公式内部仍单独透明化 */
::selection {
  background: var(--selection-bg);
  color: inherit;
}
::-moz-selection {
  background: var(--selection-bg);
  color: inherit;
}

html, body { height: 100%; }
body {
  display: flex;
  flex-direction: column;
  font-family: "Segoe UI", "Microsoft YaHei", system-ui, sans-serif;
  overflow: hidden;
  background: var(--canvas-bg);
  /* Ribbon 固定定位后脱离文档流：用 padding-top 为其预留顶部空间，
     画布自此下方开始。高度由 --ribbon-h 驱动（JS 实测写入）。 */
  padding-top: var(--ribbon-h, 128px);
}

/* ---- Ribbon（Microsoft Word 365 彩色主题复刻） ---- */
/* 固定定位：脱离文档流，功能区高度变化（切选项卡/收起）不再通过 flex
 * 挤压下方 #canvas——点击页面时的反射波动绝不会传导为排版容器抖动。 */
#ribbon {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 40;
  background: var(--ribbon-bg);
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  user-select: none;
}
/* 标题栏：Word 蓝底白字（彩色主题招牌），居中文档名 */
#ribbon .rb-titlebar {
  position: relative;
  display: flex;
  align-items: center;
  height: 32px;
  background: var(--accent);
  color: #fff;
  padding-right: 6px;
}
/* 应用图标：全局 UD 品牌资产。 */
#ribbon .rb-app {
  width: 46px;
  align-self: stretch;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  font-weight: 700;
  font-family: "Segoe UI", sans-serif;
  color: #fff;
  flex: none;
}
#ribbon .rb-product-name {
  margin-left: 2px;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
}
#ribbon .rb-doc-name {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  width: 42vw;
  font-size: 12px;
  color: rgba(255, 255, 255, .95);
  white-space: nowrap;
  max-width: 42vw;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px solid transparent;
  outline: 0;
  background: transparent;
  text-align: center;
  user-select: text;
  -webkit-user-select: text;
  cursor: text;
}
#ribbon .rb-titlebar-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 2px;
}
#ribbon .rb-titlebar .rb-quick {
  display: inline-flex; align-items: center; gap: 5px;
  height: 26px; padding: 0 10px;
  border: 1px solid transparent; border-radius: 0;
  background: transparent; color: #fff;
  font-size: 12px; cursor: pointer;
}
#ribbon .rb-titlebar .rb-quick:hover { background: rgba(255, 255, 255, .16); }
#ribbon .rb-titlebar .rb-quick:active { background: rgba(255, 255, 255, .26); }
/* 选项卡栏：白底；文件为 Word 蓝底白字特殊选项卡 */
#ribbon .ribbon-tabs {
  display: flex;
  align-items: flex-end;
  gap: 0;
  padding: 0 4px;
  border-bottom: 1px solid var(--line-soft);
}
#ribbon .rb-tab {
  border: 0; background: transparent;
  padding: 7px 14px 8px;
  font-size: 12.5px; color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
}
#ribbon .rb-tab:hover { background: var(--hover); }
#ribbon .rb-tab.active { color: var(--accent); font-weight: 600; box-shadow: inset 0 -2px 0 var(--accent); }
#ribbon .rb-tab-context {
  margin-left: 0;
  color: var(--ink);
  background: transparent;
  box-shadow: none;
}
/* 上下文选项卡（图片格式/表设计/布局）默认隐藏，仅选中对象/表格时由 JS
   去掉 hidden 类才显现。其余 .hidden 规则都是 #id.hidden 特指，没有通用 .hidden，
   也没有作用于选项卡的；缺了这条，hidden 类就是摆设，选项卡从加载起就常驻。 */
#ribbon .rb-tab-context.hidden { display: none; }
#ribbon .rb-tab-context.active {
  color: var(--accent);
  background: transparent;
  box-shadow: inset 0 -2px 0 var(--accent);
}
#ribbon .rb-tab-file {
  margin-right: 2px;
}
#ribbon .rb-tabs-fill { flex: 1; }
#ribbon #btn-ribbon-toggle {
  align-self: center;
  margin-left: 2px; min-width: 26px; height: 24px;
  border: 1px solid transparent; background: transparent;
  font-size: 9px; color: var(--ink-2); cursor: pointer;
}
#ribbon #btn-ribbon-toggle:hover { background: var(--hover); color: var(--ink); }
/* 面板区（按 tab 切换，非激活面板 display:none 但保留在 DOM）。
 * 高度由当前面板的 Grid 决定并由 ResizeObserver 同步给画布；窄屏可形成第二行，
 * 不再依靠固定/绝对坐标把控件硬塞进某个桌面分辨率。 */
#ribbon .ribbon-panels {
  padding: 0 6px;
  min-height: 62px;
  box-sizing: border-box;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}
#ribbon .ribbon-panels::-webkit-scrollbar { display: none; }
#ribbon .ribbon-panel {
  display: none;
  align-items: center;
  gap: 0;
  flex-wrap: nowrap;
  width: 100%;
  min-height: 62px;
}
#ribbon .ribbon-panel.active { display: flex; }
#ribbon .rb-group {
  display: flex; flex-direction: column; align-items: center;
  justify-content: space-between;
  min-width: max-content;
  height: 62px;
  padding: 2px 8px 0;
  position: relative;
}
#ribbon .rb-group + .rb-group::before {
  content: ""; position: absolute; left: 0; top: 2px; bottom: 16px;
  width: 1px; background: var(--line-soft);
}
#ribbon .rb-tools { display: flex; align-items: center; gap: 2px; flex: 1; }
#ribbon .rb-glabel { font-size: 11px; color: var(--ink-2); padding: 2px 0 1px; }

/* Word 式上下文功能区：只有表格/对象被选中时才显示，不占普通选项卡宽度。 */
#ribbon .rb-context-panel { min-width: max-content; }
#ribbon .rb-table-style-group { min-width: 194px; }
#ribbon .rb-table-style-gallery {
  display: grid;
  grid-template-columns: repeat(4, 42px);
  gap: 4px;
  align-items: center;
  flex: 1;
}
#ribbon .tbl-style-card {
  width: 42px;
  height: 34px;
  padding: 3px;
  display: grid;
  gap: 2px;
  border: 1px solid #cbd3df;
  background: #fff;
  cursor: pointer;
}
#ribbon .tbl-style-card:hover { border-color: var(--accent); box-shadow: 0 0 0 1px rgba(43,87,154,.18); }
#ribbon .tbl-style-card span { display: block; height: 6px; border: 1px solid #aeb7c4; background: #fff; }
#ribbon .tbl-style-card.header span:first-child { background: #dce6f2; border-color: #9fb3cc; }
#ribbon .tbl-style-card.banded span:nth-child(even) { background: #eef3f8; }
#ribbon .tbl-style-card.accent span:first-child { background: #2b579a; border-color: #2b579a; }
#ribbon .tbl-style-card.accent span:not(:first-child) { border-color: #9bb7df; }
/* 特异度抬高（.rb-tools.rb-xxx-tools）压过后面 435 行的通用 .rb-tools button 规则；
 * nowrap：标签绝不竖排换行；flex:none：任何主题下按钮都不被压缩（修文字重叠）。 */
#ribbon .rb-tools.rb-table-tools,
#ribbon .rb-tools.rb-object-tools { gap: 4px; flex: 0 0 auto; }
#ribbon .rb-tools.rb-table-tools button,
#ribbon .rb-tools.rb-object-tools button {
  flex: none;
  width: auto;             /* 压过 app-docs-theme 的 width:30px 图标圆钮设定 */
  min-width: 36px;
  height: 26px;
  padding: 3px 9px;
  border: 1px solid transparent;
  background: transparent;
  border-radius: 3px;
  color: var(--ink);
  font-size: 12px;
  white-space: nowrap;
}
#ribbon .rb-tools.rb-table-tools button:hover,
#ribbon .rb-tools.rb-object-tools button:hover { background: var(--hover); border-color: var(--line); }
#ribbon .rb-tools.rb-table-tools button.danger { color: #b42318; }
#ribbon .rb-table-pen-tools { gap: 5px; }
#ribbon .rb-table-pen-tools select { height: 28px; max-width: 82px; }
#ribbon .rb-color-tool,
#ribbon .rb-angle-tool {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 26px;
  padding: 0;
  border: 0;
  background: transparent;
  font-size: 12px;
  white-space: nowrap;
  color: var(--ink);
  flex: none;
}
/* 角度值单框（Word 式）：描边圆角，° 收进框内右侧；聚焦时柔和强调色环 */
#ribbon .rb-angle-box {
  display: inline-flex; align-items: center; gap: 1px;
  height: 26px; padding: 0 8px; box-sizing: border-box;
  border: 1px solid var(--line); border-radius: 4px; background: #fff;
  transition: border-color .12s, box-shadow .12s;
}
#ribbon .rb-angle-box:hover { border-color: #a19f9d; }
#ribbon .rb-angle-box:focus-within { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-weak); }
#ribbon .rb-angle-box i { font-style: normal; color: var(--ink-2); font-size: 11px; }
#ribbon .rb-color-tool input { width: 25px; height: 20px; padding: 0; border: 0; background: none; }
#ribbon .rb-angle-box input {
  width: 34px; height: 24px; border: 0; background: transparent;
  text-align: center; font: inherit; font-size: 12px; color: inherit;
  -moz-appearance: textfield; appearance: textfield;
}
#ribbon .rb-angle-box input::-webkit-outer-spin-button,
#ribbon .rb-angle-box input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
#ribbon .rb-angle-box input:focus { outline: none; }
/* 对象尺寸：宽 [数字] px  [锁]  高 [数字] px —— px 作为框外淡色单位，数字居中小框 */
#ribbon .rb-size-tools { gap: 7px; }
#ribbon .rb-size-item { display: inline-flex; align-items: center; gap: 4px; flex: none; }
#ribbon .rb-size-cap { font-size: 12px; color: var(--ink-2); }
#ribbon .rb-size-num {
  width: 46px; height: 26px; box-sizing: border-box; padding: 0 4px;
  border: 1px solid var(--line); border-radius: 4px; background: #fff;
  text-align: center; font: inherit; font-size: 12px; color: var(--ink);
  -moz-appearance: textfield; appearance: textfield;
}
#ribbon .rb-size-num::-webkit-outer-spin-button,
#ribbon .rb-size-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
#ribbon .rb-size-num:hover { border-color: #a19f9d; }
#ribbon .rb-size-num:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-weak); }
#ribbon .rb-size-unit { font-size: 11px; color: var(--ink-2); }
#ribbon .rb-size-lock {
  width: 24px; height: 24px; flex: none; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent; border-radius: 4px;
  background: transparent; color: var(--ink-2);
  font-size: 16px; line-height: 1; cursor: pointer;
  transition: background .12s, color .12s;
}
#ribbon .rb-size-lock:hover { background: var(--hover); color: var(--ink); }
#ribbon .rb-size-lock.is-locked { color: var(--accent); background: var(--accent-weak); }

/* “开始”页：Office 式紧凑功能卡。控件使用真实内容宽度，不再随窗口拉成超长输入框；
 * 四个板块保持 62px 总高，窄屏只横向滚动而不会挤坏控件。 */
#ribbon .rb-home-grid.active {
  display: grid;
  grid-template-columns: 60px 338px 286px 44px;
  align-items: center;
  justify-content: start;
  gap: 4px;
  min-height: 62px;
  min-width: 740px;
  padding: 3px 0;
}
#ribbon .rb-home-grid .rb-group {
  min-width: 0;
  width: 100%;
  height: 56px;
  padding: 2px 5px 1px;
  border: 1px solid #e3e8f0;
  border-radius: 6px;
  background: linear-gradient(180deg, #fff 0%, #f8fafc 100%);
  box-shadow: 0 1px 2px rgba(26, 43, 67, .05);
}
#ribbon .rb-home-grid .rb-group + .rb-group::before { display: none; }
#ribbon .rb-home-grid .rb-glabel {
  padding: 0;
  color: #6b7687;
  font-size: 9.5px;
  line-height: 10px;
  letter-spacing: .02em;
}
#ribbon .rb-home-grid .rb-tools button,
#ribbon .rb-home-grid .fs-step {
  min-width: 24px;
  width: 24px;
  height: 21px;
  padding: 0 3px;
  font-size: 13px;
  border-radius: 4px;
  transition: background .12s, color .12s;
}
#ribbon .rb-home-grid .rb-tools button:hover,
#ribbon .rb-home-grid .fs-step:hover,
#ribbon .rb-home-grid .color-btn:hover { background: #e8f0fb; color: #1f5f9f; }
#ribbon .rb-home-grid svg.ri { width: 15px; height: 15px; }
#ribbon .rb-home-grid .color-btn {
  width: 24px;
  height: 21px;
  font-size: 12px;
  border-radius: 4px;
}
#ribbon .rb-home-grid .color-btn .cb-bar { width: 15px; height: 3px; }
#ribbon .rb-home-grid .color-btn .hl { font-size: 10px; }
#ribbon .rb-home-grid select,
#ribbon .rb-home-grid .fs-box .fs-num,
#ribbon .rb-home-grid .fs-caret {
  height: 21px;
  border-color: #cfd6e0;
  border-radius: 3px;
}
#ribbon .rb-home-grid .fs-box .fs-num { width: 38px; }
#ribbon .rb-home-grid .fs-box .fs-unit { width: 40px; }
#ribbon .rb-tools-quick {
  display: grid;
  grid-template-columns: repeat(2, 24px);
  grid-template-rows: repeat(2, 21px);
  place-content: center;
  gap: 1px;
}
#ribbon .rb-tools-font {
  display: grid;
  grid-template-rows: 21px 21px;
  align-content: center;
  gap: 1px;
  width: 100%;
  min-width: 0;
}
#ribbon .rb-font-top {
  display: grid;
  grid-template-columns: 180px max-content 24px 24px;
  align-items: center;
  gap: 1px;
  min-width: 0;
}
#ribbon .rb-font-top #sel-fontfamily { width: 180px; min-width: 0; }
#ribbon .rb-font-top .fs-box { min-width: 0; }
#ribbon .rb-font-bottom {
  display: flex;
  align-items: center;
  gap: 1px;
}
#ribbon .rb-script-glyph {
  position: relative;
  display: inline-block;
  width: 16px;
  height: 18px;
  color: currentColor;
  font: 16px/18px "Segoe UI", sans-serif;
  text-align: left;
}
#ribbon .rb-script-index {
  position: absolute;
  left: 9px;
  font-size: 9px;
  font-weight: 600;
  line-height: 1;
}
#ribbon .rb-script-index-super { top: 0; }
#ribbon .rb-script-index-sub { bottom: 0; }
#ribbon .rb-tools-paragraph {
  display: grid;
  grid-template-columns: 184px 50px;
  grid-template-rows: 21px 21px;
  align-content: center;
  justify-content: center;
  gap: 1px 2px;
  width: 100%;
  min-width: 0;
}
#ribbon .rb-paragraph-style { grid-column: 1; grid-row: 1; min-width: 0; }
#ribbon .rb-paragraph-style #sel-block { width: 184px; min-width: 0; }
#ribbon .rb-paragraph-more {
  grid-column: 2;
  grid-row: 1;
  display: flex;
  align-items: center;
  gap: 1px;
}
#ribbon .rb-paragraph-icons {
  grid-column: 1 / -1;
  grid-row: 2;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 1px;
}
#ribbon .rb-home-grid #btn-numbering {
  position: relative;
  top: 1px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 1px;
  width: 30px;
  min-width: 30px;
  padding: 2px 1px 0;
  overflow: hidden;
  line-height: 1;
}
#ribbon .rb-home-grid #btn-numbering .num-one {
  font-size: 9px;
  font-weight: 600;
  transform: translateY(.5px);
}
#ribbon .rb-home-grid #btn-numbering .num-bars {
  display: grid;
  width: 9px;
  gap: 2px;
}
#ribbon .rb-home-grid #btn-numbering .num-bars i {
  display: block;
  height: 1px;
  border-radius: 1px;
  background: currentColor;
}
#ribbon .rb-home-grid #btn-numbering .num-caret {
  margin-left: 1px;
  font-size: 7px;
  transform: translateY(1px);
}
#ribbon .rb-tools-clear { place-content: center; }

/* URL/iframe 嵌入外壳：普通打开不出现；嵌入态只保留“开始”，并从这里
 * 显式进入完整编辑器。真正 iframe 首次聚焦前由 passive 类隐藏整条 Ribbon。 */
#ribbon .rb-group-embed-mode { display: none; }
body.udoc-embed-mode #ribbon .rb-group-embed-mode {
  display: flex;
  width: 72px;
  min-width: 72px;
}
body.udoc-embed-mode #ribbon .rb-home-grid.active {
  grid-template-columns: 60px 338px 286px 44px 72px;
  min-width: 816px;
}
#ribbon .rb-tools-embed-mode { place-content: center; }
#ribbon .rb-tools-embed-mode #btn-embed-mode-toggle {
  width: 62px;
  min-width: 62px;
  gap: 5px;
  font-size: 11px;
}
#ribbon .rb-tools-embed-mode #btn-embed-mode-toggle svg { flex: none; }
body.udoc-embed-mode:not(.udoc-embed-expanded) #ribbon .rb-tab:not([data-tab="home"]) {
  display: none !important;
}
body.udoc-embed-mode:not(.udoc-embed-expanded) #ribbon #btn-ribbon-toggle,
body.udoc-embed-mode:not(.udoc-embed-expanded) #ribbon .rb-titlebar-right {
  display: none;
}
body.udoc-embed-mode.udoc-embed-passive {
  padding-top: 0 !important;
}
body.udoc-embed-mode.udoc-embed-passive #ribbon {
  display: none;
}
body.udoc-embed-mode:not(.udoc-embed-expanded) > #statusbar {
  display: none;
}
body.udoc-embed-mode:not(.udoc-embed-expanded) :is(#ai-panel, #toc-panel) {
  bottom: 0;
}

@media (max-width: 560px) {
  #ribbon .ribbon-tabs { overflow-x: auto; scrollbar-width: none; }
  #ribbon .ribbon-tabs::-webkit-scrollbar { display: none; }
  #ribbon .rb-tab { padding-inline: 10px; }
  #ribbon .rb-home-grid.active {
    grid-template-columns: 58px 330px 278px 42px;
    min-width: 724px;
  }
  body.udoc-embed-mode #ribbon .rb-home-grid.active {
    grid-template-columns: 58px 330px 278px 42px 72px;
    min-width: 800px;
  }
}
body.ribbon-collapsed #ribbon .ribbon-panels { display: none; }
/* 切换按下态：Word 方形灰块（无边框、无圆角） */
#ribbon button.on { background: var(--on); color: var(--ink); }
#ribbon button.active { background: var(--on); color: var(--ink); }
body.painter-mode .page-content { cursor: cell; }

/* Word 式对齐图标（纯 CSS 四线示意） */
.ali {
  display: inline-block;
  width: 14px; height: 12px;
  background-image:
    linear-gradient(#5a6a80, #5a6a80),
    linear-gradient(#5a6a80, #5a6a80),
    linear-gradient(#5a6a80, #5a6a80),
    linear-gradient(#5a6a80, #5a6a80);
  background-repeat: no-repeat;
  background-size: 100% 1.6px, 70% 1.6px, 100% 1.6px, 70% 1.6px;
}
.ali-l { background-position: left 0, left 3.5px, left 7px, left 10.5px; }
.ali-c { background-position: center 0, center 3.5px, center 7px, center 10.5px; }
.ali-r { background-position: right 0, right 3.5px, right 7px, right 10.5px; }
.ali-j { background-size: 100% 1.6px, 100% 1.6px, 100% 1.6px, 100% 1.6px;
         background-position: left 0, left 3.5px, left 7px, left 10.5px; }

/* 工具按钮（面板内）：Word 方形，灰悬停，无圆角 */
#ribbon .rb-tools button {
  min-width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent; background: transparent;
  font-size: 14px; cursor: pointer; color: var(--ink);
  padding: 0 6px;
}
#ribbon .rb-tools button:hover { background: var(--hover); }
#ribbon .rb-tools button:active { background: var(--press); }
#ribbon .rb-tools button .rb-txt { font-size: 12px; margin-left: 5px; }
/*
 * Selection-derived ribbon state must come after the generic transparent
 * button rule above.  Previously `.active` had the same specificity but was
 * declared earlier, so Chromium correctly computed `background: transparent`
 * and the selected state was effectively invisible.
 */
#ribbon .rb-tools button.active,
#ribbon .rb-home-grid .color-btn.active {
  background: #dbe9f8;
  color: #174a7e;
  box-shadow: inset 0 0 0 1px #91b7e3;
  transition: none;
}
#ribbon .rb-tools button[data-mixed="1"],
#ribbon .rb-home-grid .color-btn[data-mixed="1"] {
  /* Mixed document formatting is semantic state, not a selected toolbar
   * surface. Keep data-mixed/aria-pressed for accessibility without making
   * Ctrl+A look as if it selected every command button. */
  background: transparent;
  color: var(--ink);
  box-shadow: none;
  transition: none;
}
#ribbon select[data-mixed="1"],
#ribbon .fs-num[data-mixed="1"] {
  color: #586b80;
  background-color: #fff;
  box-shadow: none;
}
#ribbon .color-btn[data-mixed="1"] .cb-bar {
  background: #8b95a5 !important;
  outline: none;
}
#ribbon svg.ri {
  width: 18px; height: 18px;
  flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
  display: block;
}
#ribbon select {
  height: 24px;
  border: 1px solid var(--line);
  background: #fff;
  font-size: 12px;
  color: var(--ink);
}
#ribbon select:hover { border-color: #a19f9d; }
#ribbon select:focus { outline: 1px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
/* 字号双框（数值 + 单位） */
.fs-box { display: inline-flex; align-items: center; gap: 2px; }
.fs-box .fs-num {
  width: 48px;
  height: 24px;
  box-sizing: border-box;
  padding: 0 4px;
  border: 1px solid var(--line);
  background: #fff;
  font-size: 12px;
  color: var(--ink);
}
.fs-box .fs-num:focus { outline: 1px solid var(--accent); outline-offset: -1px; border-color: var(--accent); }
.fs-box .fs-unit { width: 52px; }
/* 字号数值框：隐原生上下微调箭头（只留预设下拉，避免图中双调节钮） */
.fs-box .fs-num { -moz-appearance: textfield; appearance: textfield; }
.fs-box .fs-num::-webkit-outer-spin-button,
.fs-box .fs-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.color-btn {
  position: relative;
  display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  font-weight: 700; font-size: 13px;
  cursor: pointer; color: #c00000;
}
.color-btn:hover { background: var(--hover); }
.color-btn .hl { background: #ffff00; color: #333; font-weight: 400; padding: 0 2px; font-size: 11px; }
.color-btn input[type="color"] {
  position: absolute; inset: 0; opacity: 0; cursor: pointer;
}
.color-btn .cb-bar { width: 18px; height: 4px; border-radius: 1px; margin-top: 1px; background: #c00000; }
/* Word 级取色弹层 */
.color-pop {
  position: fixed; z-index: 100050;
  background: #fff; border: 1px solid var(--line);
  box-shadow: 0 4px 16px rgba(0, 0, 0, .2);
  padding: 8px; width: max-content;
  font: 12px "Segoe UI", "Microsoft YaHei", sans-serif; color: var(--ink);
}
.color-pop .cp-auto, .color-pop .cp-more {
  display: block; width: 100%; text-align: left;
  padding: 6px 8px; border: none; background: transparent;
  cursor: pointer; font: inherit; color: var(--ink);
}
.color-pop .cp-auto:hover, .color-pop .cp-more:hover { background: var(--hover); }
.color-pop .cp-label { margin: 6px 2px 4px; font-size: 11px; color: #8b93a3; }
.color-pop .cp-grid { display: flex; gap: 3px; }
.color-pop .cp-col { display: flex; flex-direction: column; gap: 3px; }
.color-pop .cp-std { display: flex; gap: 3px; margin-bottom: 2px; }
.color-pop .cp-sw {
  width: 16px; height: 16px; padding: 0; border: 1px solid rgba(0, 0, 0, .15);
  border-radius: 2px; cursor: pointer;
}
.color-pop .cp-sw:hover { outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent); }
.color-swatch { width: 32px; height: 22px; border: 1px solid var(--line); cursor: pointer; padding: 0; vertical-align: middle; }
.color-swatch:hover { border-color: var(--accent); }
/* 字号 Word 标准下拉 */
.fs-box { display: inline-flex; align-items: center; }
.fs-caret {
  width: 15px; height: 24px; margin: 0 0 0 -1px; padding: 0;
  border: 1px solid var(--line); background: #fff; color: var(--ink-2);
  font-size: 9px; line-height: 1; cursor: pointer;
}
.fs-caret:hover { background: var(--hover); color: var(--ink); }
/* Word 增大/缩小字号（A▲ / A▼） */
#ribbon .fs-step {
  display: inline-flex; align-items: baseline; justify-content: center; gap: 1px;
  min-width: 28px; height: 30px; padding: 0 5px;
  border: none; background: transparent; color: var(--ink); cursor: pointer;
  font-size: 14px; font-weight: 600;
}
#ribbon .fs-step:hover { background: var(--hover); }
#ribbon .fs-step .fs-step-ar { font-size: 8px; color: #8a93a0; align-self: flex-start; }
#ribbon .fs-step .fs-step-a-sm { font-size: 11px; }
#fs-menu {
  position: fixed; z-index: 82;
  max-height: 340px; overflow-y: auto;
  background: #fff; border: 1px solid var(--line);
  box-shadow: 0 4px 16px rgba(0, 0, 0, .2); padding: 2px 0;
}
#fs-menu.hidden { display: none; }
#fs-menu .fs-item {
  display: block; width: 100%; text-align: left;
  padding: 5px 18px; border: none; background: transparent;
  font: 13px "Segoe UI", "Microsoft YaHei", sans-serif; color: var(--ink); cursor: pointer;
}
#fs-menu .fs-item:hover { background: var(--hover); }
#fs-menu .fs-item.active { background: var(--accent-weak); color: var(--accent); font-weight: 600; }
#fs-menu .fs-group { padding: 6px 18px 3px; font-size: 11px; color: #8b93a3; }
#fs-menu .fs-item-cn { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
#fs-menu .fs-item-cn .fs-pt { color: #98a3b5; font-size: 11.5px; }
#fs-menu .fs-item-cn.active .fs-pt { color: var(--accent); }
/* 高级取色器（SV 方块 + 色相条 + RGB/HEX + 确认） */
.color-pop.cp-advanced {
  box-sizing: border-box; padding: 14px; width: 356px; max-width: calc(100vw - 16px);
  max-height: calc(100vh - 16px); overflow: auto;
  border-color: #d9dde5; border-radius: 14px;
  box-shadow: 0 10px 34px rgba(32, 38, 50, .2);
}
.cp-adv { display: flex; flex-direction: column; gap: 10px; }
.cp-adv .cpa-sv {
  position: relative; width: 100%; height: 200px; border-radius: 7px; cursor: crosshair;
  background-image: linear-gradient(to top, #000, transparent), linear-gradient(to right, #fff, transparent);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06);
}
.cp-adv .cpa-sv-thumb {
  position: absolute; width: 16px; height: 16px; margin: -8px 0 0 -8px;
  border: 2px solid #fff; border-radius: 50%; box-shadow: 0 0 0 1px rgba(0, 0, 0, .45); pointer-events: none;
}
.cp-adv .cpa-hue {
  position: relative; width: 100%; height: 24px; border-radius: 12px; cursor: pointer;
  background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
}
.cp-adv .cpa-hue-thumb {
  position: absolute; top: -2px; width: 10px; height: 28px; margin-left: -5px;
  background: #fff; border: 1px solid rgba(0, 0, 0, .38); border-radius: 5px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .2); pointer-events: none;
}
.cp-adv .cpa-row { display: flex; align-items: center; gap: 10px; }
.cp-adv .cpa-preview { width: 44px; height: 36px; border: 1px solid #c3c9d2; border-radius: 5px; flex: none; }
.cp-adv .cpa-hexl { flex: 1; display: flex; align-items: center; gap: 8px; font-size: 14px; color: #737b88; }
.cp-adv .cpa-hex { box-sizing: border-box; flex: 1; width: 100%; height: 36px; border: 1px solid #c3c9d2; border-radius: 5px; padding: 0 10px; font: inherit; color: #27303d; }
.cp-adv .cpa-rgb label { flex: 1; display: flex; align-items: center; gap: 7px; font-size: 14px; color: #737b88; }
.cp-adv .cpa-rgb input { box-sizing: border-box; width: 100%; min-width: 0; height: 36px; border: 1px solid #c3c9d2; border-radius: 5px; padding: 0 6px; font: inherit; text-align: center; color: #27303d; }
.cp-adv input:focus { border-color: var(--accent); outline: 2px solid color-mix(in srgb, var(--accent) 18%, transparent); }
.cp-adv input.is-invalid { border-color: #d93025; }
.cp-adv .cpa-native { position: fixed; left: -9999px; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.cp-adv .cpa-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; margin-top: 4px; }
.cp-adv .cpa-actions button { height: 40px; min-width: 80px; padding: 0 18px; border: 1px solid #c3c9d2; border-radius: 6px; background: #fff; color: #2b3038; cursor: pointer; font: 14px "Segoe UI", "Microsoft YaHei", sans-serif; }
.cp-adv .cpa-actions .cpa-eyedropper { display: inline-flex; align-items: center; justify-content: center; min-width: 40px; width: 40px; padding: 0; margin-right: auto; color: #3d4653; }
.cp-adv .cpa-eyedropper svg { width: 21px; height: 21px; fill: currentColor; }
.cp-adv .cpa-eyedropper:hover, .cp-adv .cpa-eyedropper.is-picking { background: var(--accent-weak); color: var(--accent); border-color: var(--accent); }
.cp-adv .cpa-eyedropper.is-picking { cursor: progress; }
.cp-adv .cpa-actions .cpa-ok { background: var(--accent); color: #fff; border-color: var(--accent); }
.cp-adv .cpa-actions .cpa-cancel:hover { background: #f6f8fb; border-color: var(--accent); }
.cp-adv .cpa-actions .cpa-ok:hover { filter: brightness(.94); }
.color-pop .cp-more { position: relative; }
.color-pop .cp-more-inp { position: absolute; left: 10px; bottom: 4px; width: 1px; height: 1px; opacity: 0; border: 0; padding: 0; pointer-events: none; }
/* 超链接悬停：手型（拳头伸指头）光标 */
.page-content a[href], .udoc-textbox a[href], #present-mode a[href] { cursor: pointer; }

/* 画笔 / 荧光笔 / 套索 / 橡皮擦样式已拆分至 css/app-ink.css。 */
/* ---- 电子签名模态 ---- */
#sig-modal { position: fixed; inset: 0; z-index: 95; display: flex; align-items: center; justify-content: center; background: rgba(15, 20, 30, .4); }
#sig-modal.hidden { display: none; }
#sig-modal .sig-box { width: 600px; max-width: calc(100vw - 32px); background: #fff; box-shadow: 0 16px 48px rgba(0,0,0,.28); overflow: hidden; font: 13px "Segoe UI", "Microsoft YaHei", sans-serif; }
#sig-modal header { display: flex; align-items: center; justify-content: space-between; height: 36px; padding: 0 6px 0 14px; font-weight: 600; color: var(--ink); background: #f3f2f1; border-bottom: 1px solid var(--line-soft); }
#sig-modal header button { width: 30px; height: 26px; border: none; background: transparent; color: var(--ink-2); cursor: pointer; }
#sig-modal header button:hover { background: #e81123; color: #fff; }
#sig-modal .sig-pad { position: relative; margin: 16px; border: 1px dashed #b8c0cc; border-radius: 6px; background: #fcfdff; }
#sig-modal .sig-pad canvas { display: block; width: 100%; height: 220px; touch-action: none; cursor: crosshair; }
#sig-modal .sig-hint { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #aab2bf; pointer-events: none; font-size: 15px; }
#sig-modal .sig-row { display: flex; align-items: center; gap: 12px; padding: 0 16px 16px; }
#sig-modal .sig-row label { display: flex; align-items: center; gap: 6px; color: #5a6270; }
#sig-modal .sig-fill { flex: 1; }
#sig-modal .sig-row button { border: 1px solid #d7dce4; background: #fff; color: #2b3038; border-radius: 6px; padding: 7px 14px; cursor: pointer; font: inherit; }
#sig-modal .sig-row button:hover { border-color: var(--accent); }
#sig-modal .sig-row .sig-primary { background: var(--accent); color: #fff; border-color: var(--accent); }

/* ---- 画布与页面 ---- */
#canvas {
  flex: 1;
  overflow: auto;
  /* Pagination DOM moves are explicitly viewport-anchored in app.js.  Native
     scroll anchoring would apply a second correction when a caret paragraph is
     re-split across pages, producing a one-page snap after the Typst frame
     lands.  Keep a single owner for scroll compensation. */
  overflow-anchor: none;
  padding: 24px 0 60px;
  scrollbar-gutter: stable;
}
/* 画布滚动条：Word 扁平灰（无渐变、无圆角） */
#canvas::-webkit-scrollbar { width: 12px; height: 12px; }
#canvas::-webkit-scrollbar-track { background: transparent; }
#canvas::-webkit-scrollbar-thumb {
  background: #c8c6c4;
  border: 3px solid var(--canvas-bg);
}
#canvas::-webkit-scrollbar-thumb:hover { background: #a19f9d; }
#canvas::-webkit-scrollbar-corner { background: transparent; }
/* Allow one-finger/two-axis panning but never hand the canvas to browser pinch
 * zoom. UniDoc owns document scaling so browser UI, iframe and overlays stay in
 * one coordinate system. */
#canvas { touch-action: pan-x pan-y; }
/* 缩放尺寸补偿层：transform 不改变布局盒，滚动范围由 sizer 显式撑出 */
#pages-sizer {
  position: relative;
  margin: 0 auto;
  width: var(--page-w);
}
/* 页面绝对定位（top 由 JS 按索引直算）：万页规模下 flex 列每次几何读
 * 都要重排全部页盒（实测占击键耗时 90%）；绝对定位让布局代价与页数解耦。
 * 缩放：origin 用 top left 且 margin 归零 —— margin:auto 在缩小时因布局盒
 * 大于 sizer 而失效（归零），origin 居中会让视觉盒偏移出 sizer（不居中 bug） */
#pages {
  position: relative;
  width: var(--page-w);
  margin: 0;
  transform-origin: top left;
  outline: none;      /* 单一编辑宿主的 focus 外框会紧贴页面呈现为“黑框” */
}
.page {
  width: var(--page-w);
  height: var(--page-h);
  background: #fff;
  outline: 1px solid #d8d6d3;
  box-shadow: 0 1px 3px rgba(0,0,0,.1), 0 6px 18px rgba(0,0,0,.07);
  position: absolute;
  left: 0;
  /* 页面虚拟化：视口外页面跳过渲染与布局（万页文档滚动/编辑不卡的第一支柱）。
     页面尺寸固定，占位尺寸即真实尺寸，滚动条不跳。 */
  content-visibility: auto;
  contain-intrinsic-size: var(--page-w) var(--page-h);
}
/* ---- 分栏：一栏即一个页容器 ----
 * 各栏横向拼接后恰好是一张整页，所以纸张阴影不能逐栏投，否则栏缝处会
 * 出现一道假边。改由首栏用伪元素画一张跨整页的纸投影，栏容器自身无影。 */
.page.col-first, .page.col-rest { box-shadow: none; outline: none; }
.page.col-first::before {
  content: "";
  position: absolute;
  left: 0; top: 0;
  width: var(--sheet-w, var(--page-w));
  height: 100%;
  background: #fff;
  outline: 1px solid #d8d6d3;
  box-shadow: 0 1px 3px rgba(0,0,0,.1), 0 6px 18px rgba(0,0,0,.07);
  z-index: -1;
}
/* 页眉页脚属于整张纸，只在首栏渲染一份并横跨全宽 */
.page.col-rest .page-header,
.page.col-rest .page-num { display: none; }
.page.col-first .page-header {
  left: var(--sheet-pad-l, 76px);
  right: auto;
  width: calc(var(--sheet-w, 794px) - var(--sheet-pad-l, 76px) - var(--sheet-pad-r, 76px));
}
.page.col-first .page-num {
  left: var(--sheet-pad-l, 76px); right: auto;
  width: calc(var(--sheet-w, 794px) - var(--sheet-pad-l, 76px) - var(--sheet-pad-r, 76px));
}

.page-num {
  position: absolute;
  bottom: 28px;
  left: var(--page-pad-left, 76px);
  right: var(--page-pad-right, 76px);
  text-align: center;
  font-size: 11px; color: #999;
  min-height: 14px;
  cursor: text;
  user-select: none;
}
/* Ribbon labels and form controls are document commands, never document
 * content. Chromium gives input/select descendants their own UA
 * `user-select:auto`, so the value on #ribbon alone is not sufficient. */
#ribbon,
#ribbon * {
  -webkit-user-select: none !important;
  user-select: none !important;
}
/* Real text controls remain independently editable even though the surrounding
 * ribbon chrome is never part of a browser Range. */
#ribbon input,
#ribbon textarea,
#ribbon [contenteditable="true"] {
  -webkit-user-select: text !important;
  user-select: text !important;
}
.page-header {
  position: absolute;
  top: 28px;
  left: var(--page-pad-left, 76px);
  right: var(--page-pad-right, 76px);
  text-align: center;
  font-size: 11px; color: #999;
  min-height: 14px;
  cursor: text;
  user-select: none;
}
.page-header:hover, .page-num:hover { color: var(--accent); }

/* ---- 页码设置面板（双击页码打开） ---- */
#pagenum-dialog {
  position: fixed; inset: 0; z-index: 99998;
  display: flex; align-items: center; justify-content: center;
  background: rgba(20, 28, 44, .28);
}
#pagenum-dialog.hidden { display: none; }
#pagenum-dialog .pn-card {
  width: 384px; max-width: 92vw; background: #fff;
  box-shadow: 0 16px 48px rgba(0, 0, 0, .28); overflow: hidden;
  font: 13px/1.5 "Segoe UI", system-ui, sans-serif; color: var(--ink);
}
#pagenum-dialog header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0 6px 0 14px; height: 36px; font-weight: 600; color: var(--ink);
  background: #f3f2f1; border-bottom: 1px solid var(--line-soft);
}
#pagenum-dialog header .pn-x {
  border: 0; background: transparent; color: var(--ink-2);
  cursor: pointer; font-size: 14px; width: 30px; height: 26px;
}
#pagenum-dialog header .pn-x:hover { background: #e81123; color: #fff; }
#pagenum-dialog .pn-tabs { display: flex; gap: 2px; padding: 8px 12px 0; border-bottom: 1px solid #eef0f3; }
#pagenum-dialog .pn-tab { border: 0; background: transparent; padding: 7px 16px; font: inherit; color: var(--ink-2); cursor: pointer; }
#pagenum-dialog .pn-tab:hover { background: var(--accent-weak); }
#pagenum-dialog .pn-tab.on { color: var(--accent); font-weight: 600; box-shadow: inset 0 -2.5px 0 var(--accent); }
#pagenum-dialog .pn-globals { display: flex; align-items: center; gap: 14px; padding: 10px 14px 0; flex-wrap: wrap; font-size: 12.5px; }
#pagenum-dialog .pn-globals label { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
#pagenum-dialog .pn-parity { display: inline-flex; gap: 4px; margin-left: auto; }
#pagenum-dialog .pn-par { border: 1px solid #cfd6e0; background: #fff; border-radius: 5px; padding: 3px 10px; cursor: pointer; font: inherit; }
#pagenum-dialog .pn-par.on { background: var(--accent); color: #fff; border-color: var(--accent); }
#pagenum-dialog .pn-body { padding: 10px 14px; }
#pagenum-dialog .pn-row { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
#pagenum-dialog .pn-show { font-weight: 600; }
#pagenum-dialog select,
#pagenum-dialog input[type=text],
#pagenum-dialog input[type=number] {
  border: 1px solid #cfd6e0; border-radius: 5px; padding: 4px 6px; font: inherit;
}
#pagenum-dialog .pn-tpl { flex: 1; }
#pagenum-dialog .pn-align button,
#pagenum-dialog .pn-b, #pagenum-dialog .pn-i {
  border: 1px solid #cfd6e0; background: #fff; border-radius: 5px;
  padding: 3px 11px; cursor: pointer; font: inherit;
}
#pagenum-dialog .pn-b { font-weight: 700; }
#pagenum-dialog .pn-i { font-style: italic; }
#pagenum-dialog .pn-align button.on,
#pagenum-dialog .pn-b.on, #pagenum-dialog .pn-i.on {
  background: var(--accent); color: #fff; border-color: var(--accent);
}
#pagenum-dialog .pn-preview-row {
  margin-top: 10px; padding-top: 10px; border-top: 1px dashed #e5e9f0; color: #6b7280;
}
#pagenum-dialog .pn-preview {
  background: #f6f8fb; border: 1px solid #eef0f3; border-radius: 4px;
  padding: 2px 12px; min-width: 64px; text-align: center;
}
#pagenum-dialog footer {
  display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-top: 1px solid #eef0f3;
}
#pagenum-dialog footer .pn-fill { flex: 1; }
#pagenum-dialog footer button {
  border: 1px solid #c3c9d2; background: #fff; border-radius: 6px;
  padding: 6px 14px; cursor: pointer; font: inherit;
}
#pagenum-dialog footer .pn-apply { background: var(--accent); border-color: var(--accent); color: #fff; }
#pagenum-dialog footer .pn-del { color: #c0392b; border-color: #e0b4b0; }

/* ================= 插件系统 UI ================= */
#statusbar #plugin-tools { display: inline-flex; gap: 4px; }
#statusbar #btn-plugins, #statusbar .plugin-btn {
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid transparent; background: transparent; color: #fff;
  padding: 2px 9px; font: inherit; font-size: 12px; cursor: pointer;
}
#statusbar #btn-plugins:hover, #statusbar .plugin-btn:hover { background: rgba(255, 255, 255, .15); color: #fff; }
#plugin-manager { position: fixed; inset: 0; z-index: 100010; display: flex; align-items: center; justify-content: center; background: rgba(20,28,44,.28); }
#plugin-manager.hidden { display: none; }
#plugin-manager .pm-card { width: 460px; max-width: 92vw; max-height: 86vh; display: flex; flex-direction: column; background: #fff; box-shadow: 0 16px 48px rgba(0,0,0,.28); overflow: hidden; font: 13px/1.5 "Segoe UI", system-ui, sans-serif; }
#plugin-manager header { display: flex; align-items: center; justify-content: space-between; padding: 0 6px 0 14px; height: 36px; font-weight: 600; color: var(--ink); background: #f3f2f1; border-bottom: 1px solid var(--line-soft); }
#plugin-manager .pm-x { border: 0; background: transparent; color: var(--ink-2); cursor: pointer; font-size: 15px; width: 30px; height: 26px; }
#plugin-manager .pm-x:hover { background: #e81123; color: #fff; }
#plugin-manager .pm-list { padding: 10px 12px; overflow: auto; }
#plugin-manager .pm-row { display: flex; align-items: center; gap: 12px; padding: 11px 12px; margin-bottom: 6px; border: 1px solid #eef0f4; border-radius: 10px; background: #fff; transition: .14s; }
#plugin-manager .pm-row:hover { border-color: #d7e0f2; box-shadow: 0 2px 10px rgba(65,116,224,.08); }
#plugin-manager .pm-ic { width: 34px; height: 34px; flex: none; display: flex; align-items: center; justify-content: center; font-size: 17px; border-radius: 9px; background: var(--accent-weak); color: var(--accent); }
#plugin-manager .pm-meta { flex: 1; min-width: 0; }
#plugin-manager .pm-name { font-weight: 600; color: #1f2733; }
#plugin-manager .pm-tag { font-size: 10px; background: var(--accent-weak); color: var(--accent); border-radius: 3px; padding: 0 5px; font-weight: 500; }
#plugin-manager .pm-desc { color: #7a8494; font-size: 11.5px; margin-top: 1px; }
#plugin-manager .pm-switch { position: relative; width: 40px; height: 22px; flex: none; }
#plugin-manager .pm-switch input { opacity: 0; width: 0; height: 0; }
#plugin-manager .pm-switch span { position: absolute; inset: 0; background: #cbd2dc; border-radius: 22px; transition: .18s; cursor: pointer; }
#plugin-manager .pm-switch span::before { content:''; position: absolute; width: 16px; height: 16px; left: 3px; top: 3px; background: #fff; border-radius: 50%; transition: .18s; box-shadow: 0 1px 3px rgba(0,0,0,.25); }
#plugin-manager .pm-switch input:checked + span { background: var(--accent); }
#plugin-manager .pm-switch input:checked + span::before { transform: translateX(18px); }
#plugin-manager .pm-custom { border-top: 1px solid #eef0f3; padding: 10px 14px 12px; }
#plugin-manager .pm-custom-title { font-size: 11.5px; color: #6b7480; margin-bottom: 6px; }
#plugin-manager .pm-custom-title code { background: #f3f5f8; padding: 1px 4px; border-radius: 3px; }
#plugin-manager .pm-code { width: 100%; height: 72px; border: 1px solid #cfd6e0; border-radius: 6px; padding: 7px 9px; font: 12px/1.5 Consolas, Menlo, monospace; resize: vertical; }
#plugin-manager .pm-code:focus { outline: none; border-color: var(--accent); }
#plugin-manager .pm-custom-actions { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
#plugin-manager .pm-doc { color: var(--accent); text-decoration: none; font-size: 12px; }
#plugin-manager .pm-load { border: 1px solid var(--accent); background: var(--accent); color: #fff; border-radius: 6px; padding: 6px 16px; cursor: pointer; font: inherit; }
#plugin-toast { position: fixed; left: 50%; bottom: 64px; transform: translateX(-50%) translateY(10px); background: #1f2733; color: #fff; padding: 8px 16px; border-radius: 8px; font: 13px "Segoe UI","Microsoft YaHei",sans-serif; box-shadow: 0 8px 24px rgba(0,0,0,.3); opacity: 0; pointer-events: none; transition: .2s; z-index: 100060; }
#plugin-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
.plugin-panel { position: fixed; right: 16px; top: 84px; width: 320px; max-height: 70vh; display: flex; flex-direction: column; background: #fff; border: 1px solid var(--line); box-shadow: 0 8px 28px rgba(0,0,0,.22); z-index: 100005; overflow: hidden; opacity: 0; transform: translateY(8px); transition: .16s; }
.plugin-panel.show { opacity: 1; transform: none; }
.plugin-panel header { display: flex; align-items: center; justify-content: space-between; padding: 0 6px 0 14px; height: 34px; font-weight: 600; color: var(--ink); background: #f3f2f1; border-bottom: 1px solid var(--line-soft); }
.plugin-panel .pp-x { border: 0; background: transparent; color: var(--ink-2); cursor: pointer; font-size: 14px; width: 28px; height: 24px; }
.plugin-panel .pp-x:hover { background: #e81123; color: #fff; }
.plugin-panel .pp-body { padding: 10px 12px; overflow: auto; font: 12.5px/1.6 "Segoe UI","Microsoft YaHei",sans-serif; }
.plugin-panel .gm-ok { color: #2e9e5b; padding: 10px 4px; }
.plugin-panel .gm-row { display: flex; gap: 8px; align-items: flex-start; padding: 6px 4px; border-bottom: 1px solid #f0f2f5; }
.plugin-panel .gm-type { flex: none; font-size: 10.5px; background: #fdecec; color: #c0392b; border-radius: 3px; padding: 1px 6px; margin-top: 1px; }
.plugin-panel .gm-snip { color: #3a434f; word-break: break-all; }
.plugin-panel .gm-ai { margin-top: 10px; width: 100%; border: 1px solid var(--accent); background: var(--accent-weak); color: var(--accent); border-radius: 6px; padding: 8px; cursor: pointer; font: inherit; }
.plugin-panel .gm-ai:hover { background: var(--accent); color: #fff; }
.plugin-panel .gm-aiout { margin-top: 8px; padding: 8px 10px; background: #f6f8fb; border: 1px solid #eef0f3; border-radius: 6px; white-space: pre-wrap; color: #2a323c; font-size: 12px; line-height: 1.6; max-height: 40vh; overflow: auto; }

/* ---- 段落底纹 / 装饰面板 ---- */
#shading-dialog { position: fixed; inset: 0; z-index: 100010; display: flex; align-items: center; justify-content: center; background: rgba(20,28,44,.28); }
#shading-dialog.hidden { display: none; }
#shading-dialog .sd-card { width: 384px; max-width: 92vw; background: #fff; box-shadow: 0 16px 48px rgba(0,0,0,.28); overflow: hidden; font: 13px/1.5 "Segoe UI", system-ui, sans-serif; }
#shading-dialog header { display: flex; align-items: center; justify-content: space-between; padding: 0 6px 0 14px; height: 36px; font-weight: 600; color: var(--ink); background: #f3f2f1; border-bottom: 1px solid var(--line-soft); }
#shading-dialog .sd-x { border: 0; background: transparent; color: var(--ink-2); cursor: pointer; font-size: 14px; width: 30px; height: 26px; }
#shading-dialog .sd-x:hover { background: #e81123; color: #fff; }
#shading-dialog .sd-body { padding: 12px 14px; }
#shading-dialog .sd-presets { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
#shading-dialog .sd-preset { border: 1px solid #cfd6e0; background: #fff; border-radius: 14px; padding: 4px 12px; cursor: pointer; font: inherit; font-size: 12px; }
#shading-dialog .sd-preset:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-weak); }
#shading-dialog .sd-row { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
#shading-dialog .sd-row label { display: inline-flex; align-items: center; gap: 5px; cursor: pointer; }
#shading-dialog .sd-row input[type=number] { border: 1px solid #cfd6e0; border-radius: 5px; padding: 3px 6px; font: inherit; }
#shading-dialog .sd-preview-row { margin-top: 10px; padding-top: 10px; border-top: 1px dashed #e5e9f0; color: #6b7280; }
#shading-dialog .sd-preview { margin-top: 6px; font-family: STKaiti, KaiTi, serif; color: #2b2b2b; font-size: 15px; }
#shading-dialog footer { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-top: 1px solid #eef0f3; }
#shading-dialog footer button { border: 1px solid #c3c9d2; background: #fff; border-radius: 6px; padding: 6px 14px; cursor: pointer; font: inherit; }
#shading-dialog footer .sd-apply { background: var(--accent); border-color: var(--accent); color: #fff; }
#shading-dialog footer .sd-clear { color: #c0392b; border-color: #e0b4b0; }
/* 虚拟页（内容离场，仅留固定尺寸空壳撑滚动条） */
.page.virtual { background: #fdfdfd; }
.page.virtual::after {
  content: "";
  position: absolute; inset: 76px;
  background: repeating-linear-gradient(#f1f4f8 0 15px, transparent 15px 25.5px);
  opacity: .6;
}
.page-content {
  position: absolute;
  inset: var(--page-pad);
  /* 层叠序：正文在「衬于文字下方」浮动对象（z-index:0）之上、
     「浮于文字上方」对象（z-index:5）之下 */
  z-index: 1;
  /* 纵向 clip 而非 hidden：禁止浏览器为露出光标而悄悄滚动 content 区。
     横向必须 visible：段末 ↴ 是零布局占用的编辑辅助标记，允许画出版心进入
     右页边距，但最终仍受纸张本身边界约束；正文墨迹是否越界由行级终审兜底。 */
  overflow-x: visible;
  overflow-y: clip;
  /* text-box-trim: cap 会让 CJK/重音字形墨迹略微伸出版心几何盒。
     扩大“绘制裁切边”而不扩大布局盒、也不创建滚动容器，避免续页首行
     恰贴版心顶时被削掉约 5.5px 的字头。纸张本身仍是最终裁切边界。 */
  overflow-clip-margin: 8px;
  text-rendering: optimizeLegibility;
  outline: none;
  font-size: 15px;
  line-height: 1.7;
  color: #1a1a1a;
  word-wrap: break-word;
  cursor: text;
}
.page-content > * { margin: 0 0 .6em; }

/* 水平分隔线（Markdown --- / 工具栏插入）：真正的内容线，区别于分页符 */
.page-content hr {
  border: none;
  border-top: 1px solid #c8ccd2;
  clear: both;
  margin: 1em 0;
  height: 0;
  min-height: 0;
  line-height: 0;
}

/* HTML 单页纯流式视图：文档只保留一个连续编辑宿主，不计算页界、不注入
   Typst 行断。宽度和左右留白保持 A4 阅读尺度，但高度由内容自然撑开。 */
body.flow-mode #pages {
  height: auto !important;
}
body.flow-mode .page {
  position: relative;
  top: auto !important;
  height: auto;
  min-height: max(var(--page-h), var(--flow-overlay-bottom, 0px));
  content-visibility: visible;
  contain-intrinsic-size: none;
}
body.flow-mode .page.virtual::after,
body.flow-mode .page-header,
body.flow-mode .page-num {
  display: none;
}
body.flow-mode .page-content {
  position: relative;
  inset: auto;
  min-height: var(--page-h);
  padding: var(--page-pad);
  overflow: visible;
}
body.flow-mode .page-content > * {
  content-visibility: auto;
  contain-intrinsic-block-size: auto 3200px;
}
body.flow-mode .page-content > .flow-chunk {
  display: flow-root;                 /* float 环绕对象贡献稳定块高，不被惰性分组跳过 */
  margin: 0;
  /* flow-root 会阻断相邻段落的垂直 margin 折叠。JS 仅在每 64 块的派生分组
     边界写入补偿量，使段前/段后与分页态一致，不修改任何业务段落样式。 */
  margin-top: var(--udoc-flow-gap-correction, 0px);
  overflow-anchor: none;
}
/* 流式块默认外距：:where 压零特异性——让 .page-content h1 等元素级默认
   （段前段后）在流式下同样生效，分页/流式两个视图的段间距完全一致。
   （旧写法 body.flow-mode .flow-chunk > * 特异性(0,2,0) 压过 .page-content h1，
   标题段前段后在流式里被打平成 0/.6em，两个视图排版不一致。） */
:where(body.flow-mode .flow-chunk) > * {
  margin: 0 0 .6em;
}
/* Typst 行同步：换行全部由注入的 <br data-tbr> 决定，浏览器不得自主软换行
   —— DOM 每一行与 Typst/PDF 逐字一致（排版权威 = Typst） */
.page-content > .tls {
  white-space: nowrap;
  /* Chromium 的实验性 text-box-trim 会按正在编辑行的字形重新量相邻行盒：
     段中输入数字时，即使上方 tbr 完全未变，上一行也会跳 7.5px。
     TLS 改用稳定的完整 CSS line-height 行盒；Typst 契约以 fullLineBox=1
     同步加入上下半行距，HTML/PDF 仍共享同一垂直几何。 */
  text-box: normal !important;
  text-box-edge: auto !important;
  text-box-trim: none !important;
}
/* 正式的 HTML 纯流式页面类型：1440px 是保存/导出的设计基准，编辑画布
   连续增长，没有页眉、页码、页缝或 Typst 分页裁切。 */
body.html-flow-paper.flow-mode #canvas { padding-top: 12px; }
body.html-flow-paper.flow-mode .page {
  outline: 1px solid #dfe3e8;
  box-shadow: 0 8px 28px rgba(32, 45, 64, .10);
}
body.html-flow-paper.flow-mode .page-content {
  min-height: 900px;
  padding: 0;
}
/* TLS is an atomic contract: nowrap is valid only when Typst line separators
   are present. A stale or partial frame must remain browser-wrappable instead
   of clipping an entire paragraph at the right page edge. One-line blocks are
   unaffected because they naturally fit without a separator. */
.page-content > .tls:not(:has(br[data-tbr])) {
  white-space: normal;
  overflow-wrap: anywhere;
}
/* 编辑期间继续显示最后一版已接受的 TLS 拓扑；候选帧在离屏树完成校验，
   收敛后一次替换。浏览器软换行无法跨物理页根流动，不能充当临时分页器。 */
/* 新版 Chromium 默认给中西文边界加自动空隙/标点挤压，Typst 契约是
   cjk-latin-spacing: none —— 关掉浏览器侧，两引擎量宽同一语义 */
.page-content {
  text-autospace: no-autospace;
  text-spacing-trim: space-all;
}
/* 跨页续片不重复首行缩进（缩进只属于逻辑段第一行）。
   仅限真正页缝处的续片（页首=首子元素）—— 页中残留的陈旧 data-cont
   （编辑/合并事故）不得误伤缩进。 */
.page-content > [data-cont="1"]:first-child { text-indent: 0 !important; }
/* 段前/段后视觉只落在逻辑段首尾：样式值仍写在全部分片 style 上（换纸合并不丢），
   中间片用层叠压成 0，避免页缝重复占位。
   关键：只对「真正的页缝分片」生效——续片必是页首（:first-child）、拆头必是
   页尾（:last-child）。页中残留的陈旧 data-cont/data-split 不再屏蔽段间距
   （插入动态块后连续 Enter/删除会留下这种陈旧标记，导致行距/段前段后被误压）。 */
.page-content > [data-cont="1"]:first-child { margin-top: 0 !important; }
.page-content > [data-split="1"]:last-child { margin-bottom: 0 !important; }
/* A physical page split does not end its logical paragraph. Chromium otherwise
   leaves the tail line of every justified fragment ragged. JS derives this
   transient class from the continuation chain; the final fragment and any
   fragment containing an author-authored <br> keep normal last-line semantics. */
.page-content > :is(p, blockquote).ud-justify-fragment-tail:last-child:not(:has(br:not([data-tbr]))) {
  text-align-last: justify;
}
/* A data-tbr is a renderer line boundary, but Chromium classifies the line
   before BR as a forced final line and therefore skips normal justification.
   JS applies this only to fully authoritative, author-BR-free TLS chains. The
   true logical tail is wrapped in one shrink-to-fit inline box, so parent-level
   text-align-last can fill every tbr line without stretching the real last line. */
.page-content > :is(p, blockquote).ud-tbr-justify-lines {
  text-align-last: justify;
}
/* Chromium gives a forced BR a font-sized terminal caret box.  With
   text-align-last:justify that invisible box, rather than the preceding
   business glyph, is aligned to the inline end; the line therefore looks one
   CJK cell short even though its aggregate Range rectangle reaches the page
   edge.  Typst BRs are renderer-only separators, so collapse only their
   glyph metrics while preserving the native line break.  Author BRs keep
   their normal editable/caret geometry. */
.page-content > :is(p, blockquote).ud-tbr-justify-lines br[data-tbr] {
  font-size: 0;
  letter-spacing: 0;
}
.page-content > :is(p, blockquote).ud-tbr-justify-lines .ud-tbr-final-line {
  display: inline-block;
  max-inline-size: 100%;
  white-space: nowrap;
  text-align: justify;
  text-align-last: auto;
  text-indent: 0;
}
/* Sub-glyph Typst/Chromium advance differences are calibrated in a detached
   window before commit.  Never apply candidate-only tracking to live text: it
   becomes visible as a squeeze/relax flash during rapid edits. */
/* Pagination may synthesize a caret host before a Word cached-break
   continuation. It is not a source paragraph and must consume no page grid. */
.page-content > .blk-blank:first-child:has(+ [data-word-fragment="1"]) {
  display: none;
}
#pagenum-dialog .pn-section-context {
  color: var(--accent);
  font-weight: 600;
  white-space: nowrap;
}
/* Word/Typst 统一使用完整 CSS line-height 行盒。实验性 text-box-trim 会让
   流式视图裁掉段首/段尾半行距，而分页 TLS 为避免输入跳动又必须关闭裁边，
   最终造成相同 margin 在两种视图看起来不同。统一 normal 后，段距只由
   margin 决定，分片、视图切换和 Typst 回贴都不再改变段落几何。 */
.page-content :is(p, h1, h2, h3, h4, h5, h6, blockquote, pre, li) {
  text-box: normal;
  text-box-edge: auto;
  text-box-trim: none;
}
.page-content h1 { font-size: 26px; margin: .4em 0 .5em; }
.page-content h2 { font-size: 21px; margin: .4em 0 .4em; }
.page-content h3 { font-size: 17px; margin: .4em 0 .4em; }
.page-content blockquote {
  position: relative;
  display: flow-root;
  border: 0;
  padding: 4px 14px 4px 16px;
  color: #555;
  background: #f5f7fa;
}
.page-content blockquote::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  border-radius: 3px;
  background: var(--accent);
  pointer-events: none;
}
.page-content blockquote > :is(ol, ul),
.page-content blockquote > .callout-content > :is(ol, ul) {
  box-sizing: border-box;
  /* `outside` markers are painted to the inline-start of the list content.
     Without a dedicated marker gutter they land exactly on blockquote's
     decorative rule (most visible with 1./2./3. Markdown lists).  Keep the
     quote text aligned with normal paragraphs, but move only direct lists far
     enough inward for their marker box. Nested lists retain their own native
     indentation and therefore do not accumulate this compensation. */
  margin-block: .25em;
  margin-inline: 1.25em 0;
  padding-inline-start: 1.65em;
  list-style-position: outside;
}
.page-content pre {
  background: #f4f4f4; border: 1px solid #e0e0e0; border-radius: 4px;
  padding: 8px 12px; font-family: Consolas, "Courier New", monospace;
  font-size: 13px; white-space: pre-wrap;
}
/* 尾行哨兵：代码块末尾的孤立 \n 不产生可见空行（回车“没反应”错觉根源），
   ::after 铺零宽 ZWSP 让末行始终可见、光标可驻留；不入 DOM，档案零污染 */
.page-content pre::after,
.tbox-content pre::after { content: "\200B"; }
.page-content img { max-width: 100%; }
.page-content table { border-collapse: collapse; width: 100%; margin: .5em 0; }
.page-content td, .page-content th {
  border: 1px solid #d0d0d0;
  padding: 6px 10px;
  min-width: 40px;
  background: #fff;
  transition: background .12s;
}
/* DOCX tables carry their own cached grid and cell margins.  Generic editor
   padding/min-width used to be added on top of those Word widths: a 4-column
   table could grow by 80px, leave the physical sheet and then paginate at the
   wrong vertical positions.  Keep the saved grid authoritative and let cells
   wrap instead of widening the table. */
.page-content table.word-table {
  box-sizing: border-box;
  table-layout: fixed;
  margin-top: 0;
  margin-bottom: 0;
  max-width: calc(100% + var(--page-pad-right, 76px));
}
.page-content table.word-table > colgroup > col { min-width: 0; }
.page-content table.word-table :is(td, th) {
  box-sizing: border-box;
  min-width: 0;
  padding: var(--word-cell-pad, 0 7.2px);
  /* A Word cell has no browser-default decoration. w:tblHeader only means
     "repeat this row"; it does not make the row bold or gray. Every visible
     edge/fill/weight is supplied by the resolved OOXML cascade (inline). */
  border: none;
  background: transparent;
  font-weight: inherit;
  vertical-align: top;
  overflow-wrap: anywhere;
  word-break: normal;
  transition: none;
}
/* Every DOCX w:p remains an independently editable paragraph inside its
   cell.  The stack prevents sibling margin collapse (Word adds paragraph
   before/after spacing) while keeping one lightweight flex container per
   cell.  Browser default p/h margins are reset; imported inline margins and
   data-word spacing remain authoritative. */
.page-content table :is(td, th) > .word-cell-paragraphs {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  min-width: 0;
  max-width: 100%;
  margin: 0;
  padding: 0;
}
.page-content table .word-cell-paragraphs > .word-cell-paragraph {
  display: block;
  box-sizing: border-box;
  min-width: 0;
  max-width: 100%;
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
}
/* 悬停高亮 */
.page-content tbody tr:hover td,
.page-content tbody tr:hover th {
  background: #f5f5f5;
}
/* 表头深色底 + 加粗 */
.page-content th {
  font-weight: 600;
  background: #f7f7f7;
}

/* ---- 表格交互层（Word 式 ✥ 手柄 / 行列槽 / 边界抓手 / ⊕ 插入）----
 * 固定定位浮层，跟随鼠标所在表格；不进正文 DOM。
 * 槽与抓手平时是极淡的一层灰，指针压上去才亮成强调色 —— 正文里不抢眼，
 * 需要时一眼可见。 */
#table-ui { position: fixed; inset: 0; pointer-events: none; z-index: 60; }
#table-ui button, #table-ui .tui-grip {
  position: fixed;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  pointer-events: auto;
  box-sizing: border-box;
}

/* Word 左上移表柄：22px 白色方块，右下角与表格左上角相接。 */
#table-ui .tui-move {
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  border: 1px solid #a6a6a6;
  border-radius: 0;
  background: #fff;
  color: #666;
  line-height: 1;
  cursor: move;
  opacity: 1;
  box-shadow: none;
  transition: background .1s, border-color .1s, color .1s;
}
#table-ui .tui-move .material-symbols-rounded { font-size: 18px; font-weight: 400; }
#table-ui .tui-move:hover { background: #f2f2f2; color: #444; border-color: #7f7f7f; }

/* 行列选择槽只保留命中区域：Word 默认不显示灰色 gutter。 */
#table-ui .tui-row, #table-ui .tui-col {
  background: transparent;
  border: 0;
  transition: background .1s;
}
#table-ui .tui-row {
  width: 10px;
  border-right: 0;
  border-radius: 3px 0 0 3px;
  cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='18' height='18'><path d='M2 9h11M9 4l5 5-5 5' fill='none' stroke='%23111' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>") 9 9, pointer;
}
#table-ui .tui-col {
  height: 10px;
  border-bottom: 0;
  border-radius: 3px 3px 0 0;
  cursor: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='18' height='18'><path d='M9 2v11M4 9l5 5 5-5' fill='none' stroke='%23111' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>") 9 9, pointer;
}
#table-ui .tui-row:hover, #table-ui .tui-col:hover {
  background: rgba(15, 108, 189, .16);
}

/* 边界抓手：压在行列分隔线上，可拖尺寸；末端挂 Word 圆形加号。 */
#table-ui .tui-grip { background: transparent; }
#table-ui .tui-vgrip { width: 7px; cursor: default; }
#table-ui .tui-hgrip { height: 5px; cursor: default; }
#table-ui .tui-vgrip.tui-sizable { cursor: col-resize; }
#table-ui .tui-hgrip.tui-sizable { cursor: row-resize; }
#table-ui .tui-vgrip.tui-sizable:hover {
  background: linear-gradient(to right,
    transparent 3px, #0f6cbd 3px, #0f6cbd 4px, transparent 4px);
}
#table-ui .tui-hgrip.tui-sizable:hover {
  background: linear-gradient(to bottom,
    transparent 2px, #0f6cbd 2px, #0f6cbd 3px, transparent 3px);
}
#table-ui .tui-plus {
  position: absolute;
  display: grid;
  place-items: center;
  width: 22px; height: 22px;
  box-sizing: border-box;
  border: 1.5px solid #0f6cbd;
  border-radius: 50%;
  background: #fff;
  color: #0f6cbd;
  font-size: 18px;
  font-weight: 400;
  line-height: 1;
  text-align: center;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity .1s, color .1s, background .1s;
  box-shadow: none;
}
#table-ui .tui-vgrip .tui-plus { left: -8px; top: -11px; }
#table-ui .tui-hgrip .tui-plus { top: -9px; left: -11px; }
#table-ui .tui-grip:hover .tui-plus { opacity: 1; pointer-events: auto; }
#table-ui .tui-plus:hover { background: #0f6cbd; color: #fff; }
/* 拖尺寸期间全局锁光标，指针滑出抓手也不跳回 I 形 */
body.udoc-table-sizing { cursor: col-resize; }

/* Word 极简：行距/缩进下拉收进「段落」对话框（DOM 保留供回归钩子驱动，不再占工具栏） */
#sel-linespacing, #sel-indent { display: none !important; }
body.udoc-table-sizing-y { cursor: row-resize; }
body.udoc-table-sizing-xy { cursor: nwse-resize; }
body.udoc-table-sizing * { cursor: inherit !important; }

/* Word 右下整表缩放柄：白色中性方块，完全落在表格外侧。 */
#table-ui .tui-rz {
  position: fixed;
  width: 22px; height: 22px;
  box-sizing: border-box;
  border: 1px solid #999;
  border-radius: 0;
  background: #fff;
  pointer-events: auto;
  opacity: 1;
  box-shadow: none;
  transition: background .1s, border-color .1s;
}
#table-ui .tui-rz:hover { background: #f2f2f2; border-color: #666; }
#table-ui .tui-rz-se { cursor: nwse-resize; }

/* 选中格：整行/整表由原生选区上色，矩形选区靠这一层 */
.page-content td.tcell-sel, .page-content th.tcell-sel {
  background: var(--selection-bg) !important;
}
@media print {
  #table-ui { display: none !important; }
  .page-content td.tcell-sel, .page-content th.tcell-sel { background: none !important; }
}

/* ---- LaTeX 公式 ---- */
.latex-src {
  display: inline-block;
  /* Replaced/inline objects do not participate in a paragraph's first-line
     indentation.  Letting text-indent inherit makes a 20px Word equation
     consume another 28px in an indented paragraph and changes line/page
     breaks throughout imported DOCX files. */
  text-indent: 0;
  border-radius: 3px;
  padding: 0 2px;
  cursor: pointer;
  transition: background .15s;
}
.latex-src:hover { background: #eaf1fd; outline: 1px solid #b9cff5; }
/* 选中公式：整体一块柔和高亮 + 描边，内部不再逐字符出蓝色碎块 */
.latex-src ::selection { background: transparent; }
.latex-src::selection { background: transparent; }
.latex-src.sel {
  background: rgba(122, 158, 220, .20);
  outline: 1.5px solid rgba(43, 87, 154, .55);
  outline-offset: 1px;
}
/* $$ 公式：KaTeX displayMode 展示样式（大积分号、上下限在正上/正下）。包裹 span 沿用
 * .latex-src 的 inline-block（光标落点/选中高亮/编辑锁定均不变）；KaTeX 自带的
 * .katex-display 块盒 margin 归零（否则多出 1em 上下空白，段高实测失真）。
 * 「仅含 $$ 公式」的段落默认居中（与 docx 导出 jc=center 一致）；换行符 ↴ 仍是
 * 普通段落行为，回车拆出的空段不继承居中（clearFormulaSplitAlign）。 */
.latex-src.display {
  max-width: 100%;
  box-sizing: border-box;
  white-space: normal;
}
.latex-src.display .katex-display {
  margin: 0;
  max-width: 100%;
  overflow: visible;
}
.latex-src.display .katex-display > .katex,
.latex-src.display .katex-html { max-width: 100%; white-space: normal; }
.latex-src.display .katex-html { display: inline; }
.latex-src.display .katex-html > .base {
  display: inline;
  white-space: normal;
  line-height: 1.2;
}
.latex-src.display .formula-break { display: inline; }
.page-content :is(p, div, li):has(> .latex-src.display) { text-align: center; }

/* Word 默认 0.5in 制表位。宽度在插入时按当前横坐标固化，后续编辑无需
 * 每帧脚本量测；显示格式标记时才画轻量箭头，平时完全透明。 */
.word-tab {
  display: inline-block;
  box-sizing: border-box;
  min-width: 8px;
  max-width: 100%;
  height: .9em;
  overflow: hidden;
  white-space: pre;
  vertical-align: baseline;
  color: transparent;
  user-select: all;
}
body.show-marks .word-tab {
  color: #4e80c7;
  overflow: visible;
  position: relative;
}
body.show-marks .word-tab::after {
  content: "→";
  position: absolute;
  left: 1px;
  bottom: -.15em;
  font: 10px/1 "Segoe UI Symbol", sans-serif;
  color: #4e80c7;
}
/* 编辑中：原公式原地锁定占位（尺寸不变 → 不影响后续排版） */
.latex-src.editing-locked {
  background: #eaf1fd;
  outline: 1.5px solid var(--accent);
  opacity: .55;
}
.katex-error { color: #c00; background: #fff0f0; padding: 1px 4px; border-radius: 2px; }

/* 悬浮公式源码编辑框（脱离文档流，绝不触发重排） */
#formula-editor {
  position: fixed;
  z-index: 100;
  min-width: 160px;
  max-width: 60vw;
  background: #fffbe7;
  border: 1px solid #c9b458;
  border-radius: 6px;
  box-shadow: 0 6px 24px rgba(0,0,0,.22);
  padding: 8px 10px;
  font-family: Consolas, "Courier New", monospace;
  font-size: 14px;
  line-height: 1.4;
  color: #333;
  outline: none;
  white-space: pre-wrap;
  word-break: break-all;
}
#formula-editor::after {
  content: "Enter 确认 · Esc 取消";
  display: block;
  margin-top: 4px;
  font-family: "Segoe UI", "Microsoft YaHei", sans-serif;
  font-size: 10px;
  color: #a89b5a;
  user-select: none;
}

/* ---- 动态内容块（无边框；工具条从下方悬浮） ---- */
.dyn-block {
  position: relative;
  padding: 2px 0;
  user-select: none;
}
.dyn-block.dyn-flash { animation: dyn-flash 0.8s ease 2; }
@keyframes dyn-flash {
  50% { box-shadow: 0 0 0 3px rgba(43, 87, 154, .45); }
}
.dyn-head {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: #5a6a85;
  padding: 5px 8px;
  background: rgba(247, 250, 255, .96);
  box-shadow: 0 -2px 12px rgba(30, 60, 120, .14);
  opacity: 0;
  pointer-events: none;
  transform: translateY(100%);
  transition: opacity .18s ease, transform .18s ease;
}
.dyn-block:hover .dyn-head,
.dyn-block .dyn-head:focus-within {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
.dyn-badge {
  background: var(--accent);
  color: #fff;
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 8px;
  flex-shrink: 0;
}
.dyn-url {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: Consolas, monospace;
  font-size: 11px;
}
.dyn-time { margin-left: auto; flex-shrink: 0; font-size: 10px; color: #98a3b5; }
.dyn-head button {
  flex-shrink: 0;
  min-width: 22px; height: 22px;
  border: 1px solid #c4d2ea;
  border-radius: 4px;
  background: #fff;
  color: var(--accent);
  font-size: 12px;
  cursor: pointer;
  line-height: 1;
}
.dyn-head .dyn-interval { font-size: 10px; padding: 0 5px; }
.dyn-custom { font-size: 14px; line-height: 1.8; color: #1a2b45; user-select: text; }
.dyn-custom b { color: var(--accent); }
.dyn-head button:hover { background: #e1e8f5; }
.dyn-body {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 6px;
  font-size: 12px;
}
.dyn-item {
  background: #fff;
  border: 1px solid #e3ebf7;
  border-radius: 6px;
  padding: 5px 8px;
  min-width: 0;
}
.dyn-item .dyn-k {
  color: #8a97ab;
  font-size: 10px;
  font-family: Consolas, monospace;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dyn-item .dyn-v {
  color: #1a2b45;
  font-weight: 600;
  font-size: 13px;
  word-break: break-all;
}
@media print {
  .dyn-head { display: none !important; }
}
/* 动态块全屏查看：白底 + 滚动 */
.dyn-block:fullscreen {
  background: #fff;
  overflow: auto;
  padding: 28px 36px;
}

/* ---- 换行符（真实 DOM · Word 式可选中段落标记） ----
 * 空 span + ::before 画 ↴，不绑 NBSP/ZWSP（锚点会把段末光标吃掉导致不显示）。
 * 关键：::before 用 position:absolute 脱离常规流 —— 标记零占位，显/隐换行符不
 * 改变行长与居中排版（用户 bug）；mousedown 穿透下方文本行→原生拖选可用。 */
body.show-marks .page-content .para-mark {
  /* The shell is an inline anchor only.  A zero-width `inline` still inherits
     the paragraph line-height and therefore participates in Chromium's line
     box.  The sub-pixel ascent/descent delta accumulated over long Word
     imports and could move a table row or paragraph to the next page merely
     because formatting marks were visible.  A zero-size inline-block keeps
     the pseudo-element's static end-of-text anchor while contributing no
     width *or height* to pagination. */
  display: inline-block;
  position: relative;
  inline-size: 0;
  block-size: 0;
  vertical-align: baseline;
  overflow: visible;
  font: inherit;
  /* `font` resets line-height, so keep this after the shorthand. */
  line-height: 0;
  pointer-events: auto;            /* 可点击 ↴ 直接选中换行边界（#3）；拖选从正文起仍正常 */
  cursor: pointer;
  /* 选区完全忽略标记：cef 壳若参与选区，拖拽选中内容时会被当拖放源 → 🚫 无法复制 */
  user-select: none;
  -webkit-user-select: none;
}
body.show-marks .page-content .para-mark::before {
  content: "\21B4";               /* ↴ */
  position: absolute;             /* 脱离常规流：不占行宽 */
  left: 0;
  /* `.para-mark` is a zero-size inline anchor whose origin is the text
     baseline.  Leaving the absolute pseudo-element at `top:auto` resolves
     its border box *below* that baseline, so the visible ↴ sits noticeably
     lower than the last business glyph at every font size.  Move it by one
     of its own em boxes: with the glyph rendered at .85em, its visual centre
     then coincides with the inherited text em-box centre.  This is independent
     of paragraph line-height and, because the shell remains 0x0, cannot alter
     Word pagination. */
  top: -1em;
  /* Reset every paragraph/run metric which can leak into generated content.
     In particular text-indent is inherited: a 2-char Word first-line indent
     used to become an 80px selection rectangle before the tiny ↴ glyph. */
  box-sizing: border-box;
  inline-size: max-content;
  min-inline-size: 0;
  max-inline-size: none;
  margin: 0;
  padding: 0 2px;
  text-indent: 0 !important;
  letter-spacing: normal !important;
  word-spacing: normal !important;
  text-align: left;
  white-space: pre;
  color: var(--word-format-mark);
  font-size: .85em;
  line-height: 1;
  font-family: "Segoe UI Symbol", "Segoe UI", sans-serif;
}
body.show-marks .page-content :is(h1, h2, h3) > .para-mark::before { color: var(--word-format-mark); }
/* pm-sel：选区已含标记时给 ↴ 字形铺选中底（壳是 0 宽节点，背景必须画在 ::before 上才看得见） */
body.show-marks .page-content .para-mark.pm-sel {
  background: transparent;
}
body.show-marks .page-content .para-mark.pm-sel::before {
  color: var(--word-format-mark);
  background: var(--selection-bg);
  border-radius: 0;
}
body.show-marks .page-content :is(h1, h2, h3) > .para-mark.pm-sel::before { color: var(--word-format-mark); }
/* 空段只保留原生 <br>，标记用绝对定位伪元素画；真实原子 span 会破坏空段光标。
   标记是编辑装饰，不能参与行盒；否则 Word 固定行高小于字号时，↴ 会反向把
   空段撑高并把后续内容推到下一页。 */
body.show-marks .page-content .blk-blank {
  position: relative;
}

/* 云附件：字节不进入 DOM，卡片只呈现稳定身份和用户可改文件名。 */
.attachment-block {
  position: relative;
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) auto;
  align-items: center;
  gap: 11px;
  width: min(100%, 560px);
  min-height: 68px;
  padding: 10px 12px;
  box-sizing: border-box;
  border: 1px solid #d6e0ee;
  border-radius: 10px;
  background: linear-gradient(180deg, #fff, #f8fbff);
  box-shadow: 0 2px 8px rgba(34, 63, 99, .08);
  color: #26364d;
  font: 13px/1.35 "Segoe UI", "Microsoft YaHei", sans-serif;
  user-select: none;
}
.attachment-icon {
  display: grid;
  place-items: center;
  width: 42px;
  height: 46px;
  border-radius: 7px;
  background: #e7f0ff;
  color: var(--accent);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .3px;
}
.attachment-meta { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.attachment-name {
  overflow: hidden;
  color: #17253a;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: text;
}
.attachment-detail { overflow: hidden; color: #718096; font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
.attachment-download {
  display: inline-grid;
  place-items: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid #c9d7ea;
  border-radius: 9px;
  background: #fff;
  color: var(--accent);
  cursor: pointer;
  transition: background .12s, border-color .12s, box-shadow .12s, transform .12s;
}
.attachment-download-icon {
  width: 18px;
  height: 18px;
  background: currentColor;
  -webkit-mask: url('../images/icons/lucide-download.svg') center / contain no-repeat;
  mask: url('../images/icons/lucide-download.svg') center / contain no-repeat;
}
.attachment-download:hover {
  background: #edf4ff;
  border-color: #9db8dd;
  transform: translateY(-1px);
}
.attachment-download:focus-visible {
  outline: 0;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(43, 87, 154, .18);
}
.attachment-download:disabled { cursor: not-allowed; opacity: .45; }
.attachment-download:disabled:hover { transform: none; }
.attachment-download.attachment-upload-progress {
  width: 48px; min-width: 48px; height: 48px; border-radius: 50%;
  border: 2px solid #b8dcf4; color: #126bb5; background: #eef8ff;
  opacity: 1; font: 600 11px/1 system-ui, sans-serif; position: relative;
}
.attachment-upload-progress.is-waiting::after {
  content: ''; position: absolute; inset: -2px; border: 2px solid transparent;
  border-top-color: #0d9db8; border-radius: 50%; animation: attachment-confirm-spin 1s linear infinite;
}
.attachment-upload-progress.is-failed { color: #b13b36; border-color: #eab7b3; background: #fff4f3; }
@keyframes attachment-confirm-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .attachment-upload-progress.is-waiting::after { animation: none; } }
.page-content > table.word-table[data-word-floating-table="1"] {
  /* Word w:tblpPr tables are page-positioned but remain real editable tables. */
  position: absolute;
  z-index: 2;
}
.page-content > .word-floating-table-anchor {
  /* Layout-only wrap exclusion. The real table remains page-positioned. */
  display: block;
  padding: 0;
  border: 0;
}
.page-content > .word-floating-table-anchor > table.word-table[data-word-floating-table="1"] {
  position: absolute;
  z-index: 2;
}
body.show-marks .page-content .blk-blank::before {
  content: "\21B4";
  /* 字号与有内容段的 .para-mark 一致（同为 0.85em）；旧的 0.72em 把公式后空段的
     ↴ 压成光标底部一枚小钩，视觉上近似“未显示”。这枚装饰在流内，所以自身
     line-height 必须小于段落行盒；使用 1 只约束墨迹，段落自己的 Word 行距仍
     决定空行高度。原来的 1.7 会把 14pt 导入空段从 23.33px 撑到 26.97px。
     视觉盒与负外距严格等宽，布局前进量仍为 0：原生 <br>（以及光标）
     停在行首，完整 ↴ 从光标右侧绘制且不参与排版。 */
  display: inline-block;
  position: absolute;
  inline-size: 1em;
  margin: 0;
  white-space: nowrap;
  color: var(--word-format-mark);
  font: .85em/1 "Segoe UI Symbol", "Segoe UI", sans-serif;
  inset-block-start: 50%;
  inset-inline-start: .22em;
  transform: translateY(-50%);
  z-index: 1;
  pointer-events: none;
}
body.show-marks .page-content .blk-blank.pm-sel::before {
  background: var(--selection-bg);
}
/* 空编号段的编号由真实 .word-num-marker 显示；::before 不再复画编号，
 * 段落标记 ↴ 单独由 ::after 承担。 */
body.show-marks .page-content .blk-blank[data-num-id]::before {
  content: none;
  display: none;
}
body.show-marks .page-content .blk-blank[data-num-id]::after {
  content: "\21B4";
  color: var(--word-format-mark);
  font: .72em/1 "Segoe UI Symbol", "Segoe UI", sans-serif;
  vertical-align: baseline;
}
/* 粘贴内容可能带 -webkit-text-fill-color:transparent（渐变/描边文字），会被 ↴ 标记的伪元素
 * 继承 → 换行符被透明填充看不见（用户 bug）。标记是 UniDoc 自有装饰，强制用自身 color 填充，
  * 无论所在段落是什么花哨文字样式，↴/编号 恒可见。 */
body.show-marks .page-content .para-mark::before,
body.show-marks .page-content .para-mark.pm-sel::before,
body.show-marks .page-content .blk-blank::before,
body.show-marks .page-content .blk-blank[data-num-id]::after,
body.show-marks .page-content .word-num-marker {
  -webkit-text-fill-color: currentColor;
  -webkit-text-stroke: 0;          /* 防继承透明描边把 ↴ 字形掏空 */
  text-shadow: none;               /* 防继承阴影糊掉 ↴ */
  background-clip: border-box;
  -webkit-background-clip: border-box;
}
/* 关标记时彻底隐藏（节点由 syncParaMarks 移除；兜底防闪） */
body:not(.show-marks) .para-mark { display: none !important; }

/* 打印/导出 PDF：换行符 ↴ 是纯编辑辅助符，绝不能出现在打印件里（用户 bug：空段
 * 的 ↴ 会被打进 PDF）。无论 show-marks 是否开启，打印时一律隐藏所有 ↴ 变体；
  * 空编号段的真实编号 span 仍需保留，故只清 ↴ 所在的伪元素。 */
@media print {
  .page-content .para-mark { display: none !important; }
  .page-content .para-mark::before,
  .page-content .blk-blank::before,
  .page-content .blk-blank[data-num-id]::after,
  .page-content :is(.dyn-block, .attachment-block, .video-block, .html-embed)::after { content: none !important; }
  .attachment-download { display: none !important; }
  /* 无编号空段：::before 即 ↴ 本身 → 整体清掉；编号 span 不受影响 */
  .page-content .blk-blank:not([data-num-id])::before { content: none !important; }
}

/* 原子对象后的真实编辑段。
 * 旧版把 ↴ 直接画在 contenteditable=false 的动态块/视频/iframe 上，视觉像换行符，
 * 实际鼠标永远落不进去。现在对象后持久化一个真正的 <p><br></p>：整行均可点击，
 * Typst 也把它当普通段落参与分页，输入或 Enter 后自然变成正文。 */
.page-content p.object-trailing-paragraph {
  position: relative;
  display: block;
  box-sizing: border-box;
  min-height: 1.7em;
  margin-block: 0;
  clear: both;
  cursor: text;
}
body.show-marks .page-content p.object-trailing-paragraph.blk-blank::before {
  pointer-events: none;
}
/* 防历史文档的对象伪标记与真实段落标记叠成两枚。 */
body.show-marks .page-content :is(.dyn-block, .attachment-block, .video-block, .html-embed)::after {
  content: none;
}

/* 段落格式刷轻提示 */
#parafmt-toast {
  position: fixed; left: 50%; bottom: 64px; transform: translateX(-50%) translateY(8px);
  z-index: 998; padding: 8px 16px;
  background: rgba(30, 38, 52, .92); color: #fff;
  border-radius: 8px; font: 12.5px "Segoe UI", "Microsoft YaHei", sans-serif;
  opacity: 0; pointer-events: none; transition: all .18s;
}
#parafmt-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---- 查找与替换（Word 式浮动面板） ---- */
#find-panel {
  position: fixed;
  top: 8px; right: 24px;
  z-index: 60;
  background: #fff;
  border: 1px solid var(--ribbon-border);
  border-radius: 6px;
  box-shadow: 0 6px 24px rgba(0,0,0,.18);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
}
#find-panel.hidden { display: none; }
#find-panel .find-row { display: flex; align-items: center; gap: 5px; }
#find-panel input[type="text"] {
  width: 190px;
  padding: 4px 8px;
  border: 1px solid #c4cdd9;
  border-radius: 4px;
  font-size: 13px;
  outline-color: var(--accent);
}
#find-panel button {
  min-width: 26px; height: 26px;
  border: 1px solid transparent;
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  font-size: 12px;
  color: #333;
}
#find-panel button:hover { background: #e8eef8; border-color: #c9d6ea; }
#find-panel button.on { background: #cfdcf3; border-color: #a9c0e8; }
#find-panel #replace-one, #find-panel #replace-all {
  min-width: auto;
  padding: 0 10px;
  background: #f2f5fa;
  border-color: #c9d6ea;
}
#find-count { color: #777; min-width: 52px; text-align: center; white-space: nowrap; }
#find-panel.no-replace #replace-row { display: none; }
/* 匹配高亮（CSS Custom Highlight API，零 DOM 侵入） */
::highlight(unidoc-find) { background: rgba(255, 213, 74, .55); }
::highlight(unidoc-find-current) { background: #ff9632; color: #1a1a1a; }

/* ---- 字数统计对话框 ---- */
#wordcount-dialog {
  position: fixed;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 70;
  width: 300px;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 16px 48px rgba(0,0,0,.28);
  font-size: 13px;
}
#wordcount-dialog.hidden { display: none; }
#wordcount-dialog header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 14px;
  font-weight: 600;
  border-bottom: 1px solid #e7ebf2;
}
#wordcount-dialog header button {
  border: none; background: transparent; cursor: pointer; font-size: 13px; color: #666;
}
#wordcount-dialog table { width: 100%; border-collapse: collapse; }
#wordcount-dialog td, #wordcount-dialog th {
  padding: 6px 14px;
  text-align: left;
  border: none;
}
#wordcount-dialog td:last-child, #wordcount-dialog th:last-child { text-align: right; }
#wordcount-dialog tr:nth-child(even) { background: #f6f8fb; }
#wordcount-dialog .wc-note { padding: 8px 14px 12px; color: #888; font-size: 11px; }
#st-words { cursor: pointer; }
#st-words:hover { text-decoration: underline; }

/* ---- 页面布局组（Word Layout 风格：控件 + 下方小标题） ---- */
.page-setup-tools {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}
.page-setup-col {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 2px;
}
.page-setup-col select {
  min-width: 88px;
}
.page-setup-caption {
  font-size: 10px;
  color: #7a8494;
  text-align: center;
  line-height: 1.1;
}
#btn-pagesetup {
  height: 30px;
  padding: 0 10px;
  font-size: 12px;
  white-space: nowrap;
}

/* ---- 页面设置对话框（Word「页面设置」极简风）----
 * 中性配色、右对齐标签列 + 紧凑控件列，分组只用小号灰标题加一条发丝线；
 * 右侧「预览」窗格按当前纸张比例与四边边距实时描出版心。 */
#page-setup-dialog {
  position: fixed;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 70;
  width: 512px;
  max-width: calc(100vw - 32px);
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 16px 48px rgba(0,0,0,.28);
  font: 12px/1.5 "Segoe UI", "Microsoft YaHei", sans-serif;
  color: var(--ink);
}
#page-setup-dialog.hidden { display: none; }
#page-setup-dialog header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 34px;
  padding: 0 4px 0 14px;
  font-weight: 600;
  color: #1f2429;
  background: #f4f5f7;
  border-bottom: 1px solid #e1e4e9;
}
#page-setup-dialog header button {
  width: 28px; height: 24px;
  border: none;
  border-radius: 2px;
  background: transparent;
  color: #5a6270;
  font-size: 12px;
  cursor: pointer;
}
#page-setup-dialog header button:hover { background: #e3e6ea; color: #1f2429; }
#page-setup-dialog .ps-body {
  display: flex;
  gap: 16px;
  padding: 14px 16px 2px;
  max-height: calc(100vh - 160px);
  overflow-y: auto;
}
#page-setup-dialog .ps-form { flex: 1; min-width: 0; }
#page-setup-dialog .ps-group { margin-bottom: 13px; }
#page-setup-dialog .ps-group:last-child { margin-bottom: 4px; }
#page-setup-dialog .ps-group h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 7px;
  font-size: 11px;
  font-weight: 600;
  color: #6b7480;
}
#page-setup-dialog .ps-group h3::after {
  content: "";
  flex: 1;
  height: 1px;
  background: #e6e9ee;
}
#page-setup-dialog .ps-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}
#page-setup-dialog .ps-label {
  flex: none;
  width: 46px;
  text-align: right;
  color: #454c56;
}
#page-setup-dialog .ps-inline {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
#page-setup-dialog select,
#page-setup-dialog input[type="number"] {
  height: 24px;
  border: 1px solid #c3c9d2;
  border-radius: 2px;
  background: #fff;
  font: inherit;
  color: inherit;
}
#page-setup-dialog select { min-width: 176px; padding: 0 2px; }
#page-setup-dialog input[type="number"] { width: 58px; padding: 0 5px; text-align: right; }
#page-setup-dialog select:focus,
#page-setup-dialog input:focus { outline: none; border-color: var(--accent); }
#page-setup-dialog .ps-num {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: #6b7480;
}
#page-setup-dialog .ps-unit { color: #6b7480; }
#page-setup-dialog .ps-radio {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: #1f2429;
  cursor: pointer;
}
#page-setup-dialog .ps-radio input { margin: 0; }
#page-setup-dialog .ps-ghost {
  height: 24px;
  padding: 0 10px;
  border: 1px solid #c3c9d2;
  border-radius: 2px;
  background: #fff;
  font: inherit;
  color: #1f2429;
  cursor: pointer;
}
#page-setup-dialog .ps-ghost:hover { background: #f0f3f7; border-color: #9fa9b7; }
#page-setup-dialog .is-disabled { opacity: .4; pointer-events: none; }

#page-setup-dialog .ps-preview {
  flex: none;
  width: 124px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding-top: 16px;
}
#page-setup-dialog .ps-preview-frame {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 124px;
  height: 130px;
}
#ps-preview-paper {
  position: relative;
  width: 84px;
  height: 118px;
  background: #fff;
  border: 1px solid #b8bfc9;
  box-shadow: 0 1px 4px rgba(15, 25, 40, .16);
}
#ps-preview-area {
  position: absolute;
  inset: 12px;
  border: 1px dashed #a9b6c8;
  background: repeating-linear-gradient(#eef2f7 0 2px, transparent 2px 5px);
}
#page-setup-dialog .ps-preview-cap {
  font-size: 11px;
  color: #6b7480;
  text-align: center;
}

#page-setup-dialog .ps-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 16px 14px;
}
#page-setup-dialog .ps-actions button {
  min-width: 76px;
  height: 26px;
  padding: 0 14px;
  border: 1px solid #c3c9d2;
  border-radius: 2px;
  background: #fff;
  font: inherit;
  color: #1f2429;
  cursor: pointer;
}
#page-setup-dialog .ps-actions button:hover { background: #f0f3f7; border-color: #9fa9b7; }
#page-setup-dialog #ps-apply {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
#page-setup-dialog #ps-apply:hover { background: var(--accent-dark); border-color: var(--accent-dark); }

/* ---- 段落对话框（Word「段落」：当前段落语义直接可见并可编辑）---- */
#para-dialog {
  position: fixed;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 70;
  width: 640px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - 28px);
  background: #fff;
  border: 1px solid #8f98a5;
  border-radius: 0;
  box-shadow: 0 16px 48px rgba(0,0,0,.28);
  font: 14px/1.45 "Segoe UI", "Microsoft YaHei", sans-serif;
  color: var(--ink);
  overflow: hidden;
}
#para-dialog.hidden { display: none; }
#para-dialog header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 42px;
  padding: 0 5px 0 12px;
  font-weight: 400;
  background: #fff;
  border-bottom: 0;
}
#para-dialog header button {
  width: 32px; height: 30px;
  border: none;
  border-radius: 0;
  background: transparent;
  color: #5a6270;
  font-size: 12px;
  cursor: pointer;
}
#para-dialog header button:hover { background: #e3e6ea; color: #1f2429; }
#para-dialog .pd-tabs {
  display: flex;
  align-items: flex-end;
  height: 38px;
  padding: 0 11px;
  border-bottom: 1px solid #c7cbd1;
  background: #f4f4f4;
}
#para-dialog .pd-tabs button {
  height: 37px;
  margin: 0 0 -1px;
  padding: 0 15px;
  border: 1px solid transparent;
  border-radius: 0;
  background: transparent;
  color: #202124;
  font: inherit;
  cursor: pointer;
}
#para-dialog .pd-tabs button:hover:not(.on) { background: #e9eaec; }
#para-dialog .pd-tabs button:focus-visible { outline: 1px solid var(--accent); outline-offset: -3px; }
#para-dialog .pd-tabs button.on {
  border-color: #c7cbd1 #c7cbd1 #fff;
  background: #fff;
}
#para-dialog .pd-body {
  max-height: calc(100vh - 174px);
  padding: 17px 40px 2px;
  overflow: auto;
}
#para-dialog .pd-panel.hidden { display: none; }
#para-dialog .pd-group { margin-bottom: 15px; }
#para-dialog .pd-group h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
  font-size: 14px;
  font-weight: 400;
  color: #202124;
}
#para-dialog .pd-group h3::after {
  content: "";
  flex: 1;
  height: 1px;
  background: #c7cbd1;
}
#para-dialog .pd-grid {
  display: grid;
  grid-template-columns: 104px minmax(130px, 1fr) 92px minmax(130px, 1fr);
  align-items: center;
  gap: 9px 12px;
}
#para-dialog .pd-label {
  min-width: 0;
  text-align: left;
  color: #202124;
}
#para-dialog select,
#para-dialog input[type="number"] {
  width: 100%;
  height: 32px;
  min-width: 0;
  border: 1px solid #8f98a5;
  border-radius: 0;
  background: #fff;
  font: inherit;
  color: inherit;
}
#para-dialog select { padding: 0 7px; }
#para-dialog input[type="number"] { padding: 0 7px; text-align: right; }
#para-dialog select:focus,
#para-dialog input:focus { outline: none; border-color: var(--accent); }
#para-dialog .pd-num {
  display: grid;
  grid-template-columns: minmax(64px, 1fr) 68px;
  align-items: stretch;
  gap: 0;
  color: #6b7480;
}
#para-dialog .pd-num .pd-unit-sel { border-left: 0; }
#para-dialog #pd-style-name {
  min-height: 32px;
  padding: 5px 8px;
  overflow: hidden;
  border: 1px solid #c7cbd1;
  background: #f7f7f7;
  color: #444;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#para-dialog .pd-hint {
  margin: 9px 0 0 116px;
  color: #68707b;
  font-size: 12px;
}
#para-dialog .pd-check-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 22px;
  padding: 2px 0 8px;
}
#para-dialog .pd-check-grid label {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  min-height: 42px;
  padding: 7px 8px;
  border: 1px solid transparent;
  cursor: pointer;
}
#para-dialog .pd-check-grid label:hover { border-color: #d5d9df; background: #f7f8fa; }
#para-dialog .pd-check-grid input[type="checkbox"] {
  width: 15px;
  height: 15px;
  margin: 2px 0 0;
  accent-color: var(--accent);
}
#para-dialog .pd-check-grid span { display: grid; gap: 2px; }
#para-dialog .pd-check-grid b { font-weight: 400; color: #202124; }
#para-dialog .pd-check-grid small,
#para-dialog .pd-tab-note { color: #68707b; font-size: 12px; line-height: 1.55; }
#para-dialog .pd-tab-note { margin: 0; }
#para-dialog .pd-rule-list { margin: 0 0 10px; border: 1px solid #d5d9df; }
#para-dialog .pd-rule-list div { display: flex; justify-content: space-between; padding: 9px 11px; }
#para-dialog .pd-rule-list div + div { border-top: 1px solid #e5e7eb; }
#para-dialog .pd-rule-list dt { color: #202124; }
#para-dialog .pd-rule-list dd { margin: 0; color: #68707b; }
#para-dialog .pd-preview-group { margin-bottom: 8px; }
#para-dialog .pd-preview {
  height: 154px;
  padding: 13px 38px;
  overflow: hidden;
  border: 1px solid #777;
  background: #fff;
  color: #202124;
  font: 11px/1.45 "Microsoft YaHei", sans-serif;
}
#para-dialog .pd-preview p { margin: 0 0 7px; }
#para-dialog .pd-preview-muted { color: #b3b5b8; }
#para-dialog #pd-preview-current {
  position: relative;
  margin-top: 4px;
  color: #202124;
}
#para-dialog #pd-preview-marker { user-select: none; }
#para-dialog .pd-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 40px 14px;
  border-top: 1px solid #e1e4e9;
}
#para-dialog .pd-actions button {
  min-width: 86px;
  height: 32px;
  padding: 0 14px;
  border: 1px solid #c3c9d2;
  border-radius: 0;
  background: #fff;
  font: inherit;
  color: #1f2429;
  cursor: pointer;
}
#para-dialog .pd-actions button:hover { background: #f0f3f7; border-color: #9fa9b7; }
#para-dialog #pd-apply {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
#para-dialog #pd-apply:hover { background: var(--accent-dark); border-color: var(--accent-dark); }

@media (max-width: 700px) {
  #para-dialog .pd-body { padding-inline: 20px; }
  #para-dialog .pd-grid { grid-template-columns: 96px minmax(130px, 1fr); }
  #para-dialog .pd-hint { margin-left: 108px; }
  #para-dialog .pd-actions { padding-inline: 20px; }
}

/* ---- 编号库面板（Word「编号」下拉同款：卡片网格 + 底部命令）---- */
#num-panel {
  position: fixed;
  z-index: 71;
  width: 318px;
  padding: 8px;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 8px 28px rgba(0,0,0,.22);
  font: 12px/1.4 "Segoe UI", "Microsoft YaHei", sans-serif;
  color: var(--ink);
}
#num-panel.hidden { display: none; }
#num-panel .np-title {
  margin: 2px 4px 7px;
  font-size: 11px;
  font-weight: 600;
  color: #6b7480;
}
#num-panel .np-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
#num-panel .np-card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  height: 72px;
  padding: 7px 9px;
  border: 1px solid #d7dce4;
  border-radius: 2px;
  background: #fff;
  font: 11px/1 "Segoe UI", "Microsoft YaHei", sans-serif;
  color: #1f2429;
  cursor: pointer;
  text-align: left;
  overflow: hidden;
}
#num-panel .np-card:hover { border-color: var(--accent); background: #f3f7fd; }
#num-panel .np-card.on { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
#num-panel .np-card.np-none {
  align-items: center;
  justify-content: center;
  color: #6b7480;
  font-size: 13px;
}
#num-panel .np-row {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
#num-panel .np-row i { font-style: normal; flex: none; }
#num-panel .np-row u {
  flex: 1;
  height: 0;
  border-top: 1.5px solid #cdd4de;
  text-decoration: none;
}
#num-panel .np-sep { height: 1px; margin: 8px 2px; background: #e6e9ee; }
#num-panel .np-cmd {
  display: block;
  width: 100%;
  padding: 5px 8px;
  border: 0;
  border-radius: 2px;
  background: transparent;
  font: inherit;
  color: #1f2429;
  text-align: left;
  cursor: pointer;
}
#num-panel .np-cmd:hover { background: #eef2f8; }

/* ---- 模板库面板（与编号库同一套极简视觉）---- */
#tpl-panel {
  position: fixed;
  z-index: 71;
  width: 392px;
  max-height: calc(100vh - 120px);
  overflow-y: auto;
  padding: 8px;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 8px 28px rgba(0,0,0,.22);
  font: 12px/1.4 "Segoe UI", "Microsoft YaHei", sans-serif;
  color: var(--ink);
}
#tpl-panel.hidden { display: none; }
#tpl-panel .tp-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 2px 4px 7px;
  font-size: 12px;
  font-weight: 600;
}
#tpl-panel .tp-close {
  border: 0; background: transparent; color: #5a6270;
  cursor: pointer; font-size: 12px; padding: 2px 6px; border-radius: 2px;
}
#tpl-panel .tp-close:hover { background: #e3e6ea; }
#tpl-panel .tp-sec {
  margin: 8px 4px 6px;
  font-size: 11px;
  font-weight: 600;
  color: #6b7480;
}
#tpl-panel .tp-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
#tpl-panel .tp-card {
  position: relative;
  min-height: 58px;
  padding: 8px 9px;
  border: 1px solid #d7dce4;
  border-radius: 2px;
  background: #fff;
  cursor: pointer;
}
#tpl-panel .tp-card:hover { border-color: var(--accent); background: #f3f7fd; }
#tpl-panel .tp-name { font-weight: 600; margin-bottom: 3px; }
#tpl-panel .tp-desc { color: #6b7480; font-size: 11px; }
#tpl-panel .tp-del {
  position: absolute;
  right: 3px; top: 3px;
  border: 0; background: transparent; color: #9aa3b0;
  cursor: pointer; font-size: 10px; padding: 2px 4px; border-radius: 2px;
}
#tpl-panel .tp-del:hover { background: #fbe9e9; color: #c00000; }
#tpl-panel .tp-sep { height: 1px; margin: 8px 2px; background: #e6e9ee; }
#tpl-panel .tp-cmd {
  display: block;
  width: 100%;
  padding: 5px 8px;
  border: 0;
  border-radius: 2px;
  background: transparent;
  font: inherit;
  color: #1f2429;
  text-align: left;
  cursor: pointer;
}
#tpl-panel .tp-cmd:hover { background: #eef2f8; }

/* 背景音乐面板 + ▶ 放映模式样式已拆分至 css/app-present.css（PPT 演示层） */

/* ---- AI 助手面板（右侧停靠；底部停在状态栏上方，Word 任务窗格行为）---- */
#ai-panel {
  position: fixed;
  right: 0; top: 0; bottom: 28px;
  z-index: 90;
  width: 400px;
  min-width: 300px;
  max-width: 99vw;
  display: flex;
  flex-direction: column;
  background: #f7f7f5;
  border-left: 1px solid #e6e4de;
  box-shadow: -8px 0 32px rgba(15, 25, 40, .10);
  border-radius: 12px 0 0 12px;
  overflow: hidden;
  font: 13.5px/1.6 "Segoe UI", "Microsoft YaHei", sans-serif;
  color: #1b1c1e;
}
/* 浮动态：脱离右侧停靠，四周留圆角阴影，可拖到任意位置 */
#ai-panel.ai-floating { border-radius: 12px; border: 1px solid #e6e4de; height: min(88vh, 900px); bottom: auto; }
/* 全屏铺满 */
#ai-panel.ai-full {
  left: 0 !important; top: 0 !important; right: 0 !important; bottom: 0 !important;
  width: 100vw !important; height: 100vh; max-width: none; border-radius: 0; border-left: none;
}
#ai-panel.ai-full .ai-resizer { display: none; }
#ai-panel.ai-full .ai-msgs, #ai-panel.ai-full .ai-dock { max-width: 820px; margin-left: auto; margin-right: auto; width: 100%; }
/* 左缘拖拽把手：调整面板宽度 */
#ai-panel .ai-resizer {
  position: absolute; left: -3px; top: 0; bottom: 0; width: 7px;
  cursor: ew-resize; z-index: 2;
}
#ai-panel .ai-resizer:hover { background: linear-gradient(90deg, var(--accent), transparent); opacity: .35; }
body.ai-resizing { cursor: grabbing !important; user-select: none !important; }
#ai-panel.hidden { display: none; }
#ai-panel .ai-head {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 52px;
  padding: 0 10px 0 16px;
  background: transparent;
  cursor: grab;
  flex: none;
}
#ai-panel .ai-head:active { cursor: grabbing; }
#ai-panel .ai-title { flex: 1; display: flex; align-items: center; gap: 9px; font-size: 15px; font-weight: 600; }
#ai-panel .ai-logo {
  width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center;
  background: transparent;
}
#ai-panel .ai-logo img,
#ai-panel .ai-hello-logo img,
#ai-panel .ai-assistant .ai-avatar img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
#ai-panel .ai-name { color: var(--accent); font-weight: 600; }
#ai-panel .ai-head button {
  width: 32px; height: 32px;
  border: none; border-radius: 8px;
  background: transparent; color: #6b6f76;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: background .12s, color .12s;
}
#ai-panel .ai-head button:hover { background: rgba(0,0,0,.06); color: #1b1c1e; }
#ai-panel .ai-cfg {
  padding: 10px 14px;
  border-bottom: 1px solid #eef0f3;
  background: #fafbfc;
}
#ai-panel .ai-cfg.hidden { display: none; }
#ai-panel .ai-cfg label {
  display: block;
  margin-bottom: 6px;
  font-size: 12px;
  color: #6b7480;
}
#ai-panel .ai-cfg input {
  width: 100%;
  height: 26px;
  margin-top: 2px;
  padding: 0 8px;
  border: 1px solid #c3c9d2;
  border-radius: 3px;
  font: inherit;
  box-sizing: border-box;
}
#ai-panel .ai-warn { color: #b06a00; font-size: 11px; margin: 4px 0 8px; }
#ai-panel .ai-save {
  height: 26px; padding: 0 12px;
  border: 1px solid var(--accent); border-radius: 3px;
  background: var(--accent); color: #fff; cursor: pointer;
}
#ai-panel .ai-msgs {
  flex: 1;
  overflow-y: auto;
  padding: 8px 18px 6px;
  background: #f7f7f5;
}
/* Copilot 式问候页：居中大标题 + 副标题 */
#ai-panel .ai-hello {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  padding: 48px 16px 24px;
  gap: 14px;
}
#ai-panel .ai-hello-logo {
  width: 46px; height: 46px;
  display: flex; align-items: center; justify-content: center;
  background: transparent;
}
#ai-panel .ai-hello-h { font-size: 26px; font-weight: 600; color: #24262b; letter-spacing: .3px; }
#ai-panel .ai-hello-sub { max-width: 420px; font-size: 13px; color: #7a7f87; line-height: 1.7; }
#ai-panel .ai-msg {
  display: flex;
  gap: 9px;
  margin-bottom: 16px;
}
#ai-panel .ai-avatar {
  flex: none;
  width: 28px; height: 28px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800;
  color: #fff;
}
#ai-panel .ai-user { flex-direction: row-reverse; }
#ai-panel .ai-user .ai-avatar { background: #d7d3ca; color: #4a4741; }
#ai-panel .ai-assistant .ai-avatar { background: transparent; }
#ai-panel .ai-bubble {
  max-width: 84%;
  padding: 10px 14px;
  border-radius: 16px;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 13.5px;
  line-height: 1.65;
  position: relative;
}
#ai-panel .ai-user .ai-bubble { background: #e8ebf2; color: #1b1c1e; border-bottom-right-radius: 5px; }
#ai-panel .ai-assistant .ai-bubble { background: #fff; color: #1b1c1e; border: 1px solid #eceae4; border-bottom-left-radius: 5px; box-shadow: 0 1px 3px rgba(20,30,50,.04); }
#ai-panel .ai-think {
  margin-bottom: 8px;
  padding: 8px 10px;
  border-left: 2px solid #d7d3ca;
  background: #faf9f6;
  color: #8a8f97;
  font-size: 12px;
  line-height: 1.6;
  border-radius: 6px;
  max-height: 260px;          /* 展开后可滚动回看 */
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-word;
}
/* 思考链完成后自动折叠；一行开关可展开回看 */
#ai-panel .ai-think.collapsed { display: none !important; }
#ai-panel .ai-think-toggle {
  display: flex; align-items: center; gap: 6px; width: 100%;
  border: 0;
  background: transparent;
  color: #8a8f97;
  font-size: 12px;
  cursor: pointer;
  padding: 2px 0 6px;
  text-align: left;
}
#ai-panel .ai-think-toggle .tk-ic { flex: none; }
#ai-panel .ai-think-toggle .tk-live {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: #9096a0; font-style: italic;
}
#ai-panel .ai-think-toggle .tk-caret { flex: none; color: #b3b8c0; }
#ai-panel .ai-think-toggle:hover .tk-live { color: var(--accent); }
/* AI 回复富渲染（Markdown + KaTeX，气泡内隔离） */
#ai-panel .ai-md { white-space: normal; }
#ai-panel .ai-md p { margin: 0 0 8px; }
#ai-panel .ai-md p:last-child { margin-bottom: 0; }
#ai-panel .ai-md h1, #ai-panel .ai-md h2, #ai-panel .ai-md h3 {
  margin: 10px 0 6px; font-size: 14px; font-weight: 700;
}
#ai-panel .ai-md ul, #ai-panel .ai-md ol { margin: 0 0 8px; padding-left: 20px; }
#ai-panel .ai-md li { margin: 2px 0; }
#ai-panel .ai-md pre {
  background: #0f1115; color: #c8d0dc;
  padding: 8px 10px; border-radius: 8px;
  font: 11px/1.5 Consolas, monospace;
  overflow: auto; white-space: pre-wrap; word-break: break-all;
  margin: 6px 0;
  position: relative;
}
#ai-panel .ai-md pre[data-ai-copy-ready="1"],
#ai-panel .ai-src[data-ai-copy-ready="1"] { padding-top: 34px; position: relative; }
#ai-panel .ai-copy-row {
  display: flex; justify-content: flex-end; margin-top: 4px;
}
#ai-panel .ai-copy-answer {
  width: 28px; height: 28px; padding: 0;
  display: inline-grid; place-items: center;
  border: 0; border-radius: 7px;
  background: transparent; color: #7a8391; cursor: pointer;
}
#ai-panel .ai-copy-answer svg {
  width: 17px; height: 17px; fill: none; stroke: currentColor;
  stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
}
#ai-panel .ai-copy-answer:hover {
  background: #eef2f7; color: var(--accent);
}
#ai-panel .ai-copy-answer:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  outline-offset: 1px;
}
#ai-panel .ai-copy-answer.is-copied { color: #178447; background: #edf8f1; }
#ai-panel .ai-copy-answer.is-copy-error { color: #c2413b; background: #fff0ef; }
#ai-panel .ai-code-copy {
  border: 1px solid #d6dae2; border-radius: 6px;
  background: #fff; color: #667085; cursor: pointer;
  font: 11px/1.2 "Segoe UI", "Microsoft YaHei", sans-serif;
  padding: 4px 8px; white-space: nowrap;
}
#ai-panel .ai-code-copy {
  position: absolute; z-index: 2; right: 7px; top: 6px;
  background: #252a33; border-color: #3b4350; color: #d7dde8;
}
#ai-panel .ai-code-copy:hover { background: #303744; color: #fff; }
#ai-panel .ai-md code {
  background: #eef1f6; padding: 1px 4px; border-radius: 3px;
  font-family: Consolas, monospace; font-size: 12px;
}
#ai-panel .ai-md pre code { background: none; padding: 0; color: inherit; }
#ai-panel .ai-md table { border-collapse: collapse; margin: 6px 0; }
#ai-panel .ai-md td, #ai-panel .ai-md th {
  border: 1px solid #dfe3ea; padding: 3px 8px; font-size: 12px;
}
#ai-panel .ai-md blockquote {
  border-left: 3px solid #cdd4de; margin: 6px 0; padding: 2px 10px; color: #6b7480;
}
#ai-panel .ai-md .katex-display { margin: 6px 0; overflow-x: auto; }

/* ---- 目录面板（标题大纲 + 页码 + 跳转）：Word 导航窗格 ---- */
#toc-panel {
  position: fixed;
  left: 0;
  top: 128px;              /* ↑ 与 ribbon 高度一致 */
  bottom: 28px;             /* ↑ 留出状态栏 28px */
  z-index: 60;
  width: 300px;
  display: flex;
  flex-direction: column;
  background: #f7f7f5;      /* ↑ 浅灰背景（ZSSH 风格） */
  box-shadow: 6px 0 24px rgba(0, 0, 0, .15);  /* ↑ 更明显的投影 */
  font: 13px/1.5 "Segoe UI", system-ui, sans-serif;
}
#toc-panel.hidden { display: none; }
#toc-panel header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 14px;
  font-weight: 600;
  font-size: 13.5px;
  color: var(--ink);
  border-bottom: 1px solid var(--line-soft);
  background: transparent;        /* ↑ 去掉灰色标题栏 */
}
#toc-panel header .toc-title { flex: 1; font-size: 14px; }
#toc-panel .toc-close {
  width: 30px; height: 28px; border: 0;
  background: transparent; color: var(--ink-2); cursor: pointer; font-size: 16px;
  border-radius: 6px;
  transition: background .15s, color .15s;
}
#toc-panel .toc-close:hover { background: #e81123; color: #fff; }
#toc-panel .toc-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 8px 4px 12px; }
#toc-panel .toc-body::-webkit-scrollbar { width: 8px; }
#toc-panel .toc-body::-webkit-scrollbar-thumb { background: #c8c6c4; border-radius: 4px; }
#toc-panel .toc-item {
  --toc-depth: 0;
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 6px 12px 6px calc(12px + var(--toc-depth) * 18px);
  cursor: pointer;
  color: var(--ink);
  text-decoration: none;
  border-radius: 6px;
  margin: 2px 0;               /* ↑ 间距 */
  transition: background .15s, transform .08s;
}
#toc-panel .toc-item:hover { background: #edebe9; color: var(--accent); }
#toc-panel .toc-item:active { transform: scale(.98); }
#toc-panel .toc-text {
  flex: 1;
  word-break: break-word;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
#toc-panel .toc-page {
  flex: none;
  font: 10.5px Consolas, monospace;
  color: #a19f9d;
  background: rgba(0, 0, 0, .04);
  padding: 2px 8px;
  border-radius: 4px;
}
#toc-panel .toc-item:hover .toc-page { background: rgba(43, 87, 154, .1); color: var(--accent); }
#toc-panel .toc-l1 { font-weight: 700; }
#toc-panel .toc-l2 { --toc-depth: 1; }
#toc-panel .toc-l3 { --toc-depth: 2; font-size: 12px; color: #4a5568; }
#toc-panel .toc-l4 { --toc-depth: 3; font-size: 12px; color: #6b7480; }
#toc-panel .toc-l5 { --toc-depth: 4; font-size: 12px; color: #6b7480; }
#toc-panel .toc-l6 { --toc-depth: 5; font-size: 12px; color: #7a838e; }
#toc-panel .toc-empty {
  padding: 40px 20px;
  text-align: center;
  color: #a3abb8;
  font-size: 12px;
  line-height: 1.7;
}
#toc-panel .toc-empty::before {
  content: "\2630";
  display: block;
  font-size: 30px;
  color: #d3d9e2;
  margin-bottom: 10px;
}
#ai-panel .ai-prose { margin-bottom: 8px; }
#ai-panel .ai-card {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px;
  border-radius: 8px;
  background: #eaf6ee;
  color: #1f6b3a;
  font-size: 12.5px;
}
#ai-panel .ai-card .ai-ok {
  flex: none;
  width: 18px; height: 18px; border-radius: 50%;
  background: #2f9e57; color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 11px;
}
#ai-panel .ai-actrow { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
/* AI 修改请求卡（人在回路：应用/拒绝） */
#ai-panel .ai-card-ask { background: #fff7e8; color: #8a5a00; }
#ai-panel .ai-card-ask .ai-req {
  flex: none;
  width: 18px; height: 18px; border-radius: 50%;
  background: #e8a13b; color: #fff;
  display: flex; align-items: center; justify-content: center; font-size: 11px;
}
#ai-panel .ai-card-no { background: #f3f4f6; color: #6b7480; }
#ai-panel .ai-mini-primary {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
  color: #fff !important;
}
#ai-panel .ai-mini {
  height: auto; min-height: 28px; padding: 5px 12px;
  border: 1px solid #d0d5dd; border-radius: 6px;
  background: #fff; color: #454c56; font-size: 12px; cursor: pointer;
  white-space: nowrap; line-height: 1.3;
}
#ai-panel .ai-mini:hover { border-color: var(--accent); color: var(--accent); }
#ai-panel .ai-src {
  margin-top: 8px; padding: 8px 10px;
  background: #0f1115; color: #c8d0dc;
  border-radius: 8px; font: 11px/1.5 Consolas, monospace;
  max-height: 220px; overflow: auto; white-space: pre-wrap; word-break: break-all;
}
/* ===== Copilot 式底部区：chips + 圆角输入卡 ===== */
#ai-panel .ai-dock {
  flex: none;
  padding: 6px 18px 16px;
  background: linear-gradient(180deg, rgba(247,247,245,0) 0%, #f7f7f5 22%);
}
#ai-panel .ai-chips {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 6px 0 10px;
}
#ai-panel .ai-chip {
  padding: 7px 14px;
  border: 1px solid #e6e4de; border-radius: 20px;
  background: #fff; color: #4a4f57; font-size: 12.5px; cursor: pointer;
  transition: all .12s;
}
#ai-panel .ai-chip:hover { border-color: #cfd4dc; color: #1b1c1e; background: #fbfbfa; box-shadow: 0 2px 8px rgba(20,30,50,.06); }

/* Cursor 式交互提问气泡 */
#ai-panel .ai-ask {
  margin-top: 8px;
  padding: 10px 12px;
  border: 1px solid #e3e7ee;
  border-radius: 10px;
  background: #fbfcfe;
}
#ai-panel .ai-ask-q { font-weight: 600; margin-bottom: 8px; }
#ai-panel .ai-ask-opts { display: flex; flex-wrap: wrap; gap: 6px; }
#ai-panel .ai-ask-opt {
  padding: 6px 12px;
  border: 1px solid #c9d4e4;
  border-radius: 16px;
  background: #fff;
  color: var(--accent);
  font-size: 12.5px;
  cursor: pointer;
  transition: all .12s;
}
#ai-panel .ai-ask-opt:hover:not(:disabled) { background: var(--accent); border-color: var(--accent); color: #fff; }
#ai-panel .ai-ask-opt:disabled { opacity: .45; cursor: default; }
#ai-panel .ai-ask-opt.ai-ask-picked { opacity: 1; background: var(--accent); border-color: var(--accent); color: #fff; }
#ai-panel .ai-ask-other { color: #6b7480; border-style: dashed; }

/* 圆角输入卡（Copilot 招牌）：textarea 在上，工具行在下 */
#ai-panel .ai-composer {
  background: #fff;
  border: 1px solid #e6e4de;
  border-radius: 22px;
  padding: 12px 14px 8px;
  box-shadow: 0 4px 18px rgba(20,30,50,.07);
  transition: border-color .15s, box-shadow .15s;
}
#ai-panel .ai-composer:focus-within { border-color: #b9c6ea; box-shadow: 0 4px 22px rgba(65,116,224,.15); }
#ai-panel .ai-input {
  width: 100%;
  border: none;
  background: transparent;
  font: inherit;
  resize: none;
  max-height: 200px;
  padding: 2px 4px 6px;
  color: #1b1c1e;
  box-sizing: border-box;
}
#ai-panel .ai-input:focus { outline: none; }
#ai-panel .ai-composer-tools {
  display: flex; align-items: center; gap: 6px;
}
#ai-panel .ai-tools-spacer { flex: 1; }
/* 附件 chips 条 */
#ai-panel .ai-attach-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 0 0 8px;
}
#ai-panel .ai-attach-bar .ai-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 100%;
  padding: 3px 6px 3px 10px;
  border-radius: 20px;
  background: #f2f1ec;
  border: 1px solid #e6e4de;
  font-size: 11.5px;
  color: #3b4350;
}
#ai-panel .ai-chip-ic { flex: none; }
#ai-panel .ai-chip-name {
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#ai-panel .ai-chip-x {
  flex: none;
  width: 16px; height: 16px;
  border: 0; border-radius: 50%;
  background: transparent;
  color: #8a93a0;
  font-size: 10px;
  cursor: pointer;
  line-height: 1;
}
#ai-panel .ai-chip-x:hover { background: #e3e6ea; color: #d23f31; }
#ai-panel .ai-clip, #ai-panel .ai-shot {
  flex: none;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: #6b6f76;
  font-size: 15px;
  cursor: pointer;
  transition: background .12s;
}
#ai-panel .ai-clip:hover, #ai-panel .ai-shot:hover { background: rgba(0,0,0,.06); color: #1b1c1e; }
/* 对话/编排 分段开关 */
#ai-panel .ai-modes {
  display: inline-flex; gap: 0;
  background: #f2f1ec; border-radius: 16px; padding: 2px;
}
#ai-panel .ai-modes label {
  padding: 5px 12px;
  border-radius: 14px;
  color: #6b6f76;
  font-size: 12px; cursor: pointer;
  white-space: nowrap;
  transition: all .12s;
}
#ai-panel .ai-modes input { position: absolute; opacity: 0; width: 0; height: 0; }
#ai-panel .ai-modes label:has(input:checked) {
  background: #fff; color: var(--accent); font-weight: 600;
  box-shadow: 0 1px 4px rgba(20,30,50,.12);
}
#ai-panel .ai-send {
  flex: none;
  width: 36px; height: 36px;
  border: none; border-radius: 50%;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 19V5M5 12l7-7 7 7'/></svg>");
  background-repeat: no-repeat; background-position: center;
  transition: filter .12s, transform .12s;
}
#ai-panel .ai-send:hover { filter: brightness(1.08); transform: translateY(-1px); }
#ai-panel .ai-send.busy {
  background-image: none;
  position: relative;
}
#ai-panel .ai-send.busy::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 12px; height: 12px; border-radius: 3px; background: #fff;
}

/* ---- 链接：只保留「悬停真实 <a> 显示原生手型 + Ctrl+点击 跳转」，不加任何自定义高亮 ----
 * 手型显式打到 #pages 内所有 <a> 及其后代（.ln/.wd 等），压过冻结文本框的 cursor:text，
 * 保证无论链接落在 page-content / 文本框 / pv-page 哪一层都显示手指；跳转在 app.js 的
 * pagesEl click 里要求 Ctrl/⌘+点击。不画背景/描边环——pdf2html 会把整行、大量交叉引用包成 <a>。 */
#pages a[href], #pages a[href] * {
  cursor: pointer;
}

/* ---- 快捷键设置对话框 ---- */
#shortcut-dialog {
  position: fixed; inset: 0; z-index: 95;
  display: flex; align-items: center; justify-content: center;
  background: rgba(15, 20, 30, .38);
}
#shortcut-dialog.hidden { display: none; }
#shortcut-dialog .sk-box {
  width: 420px; max-width: calc(100vw - 32px); max-height: 80vh;
  display: flex; flex-direction: column;
  background: #fff; border: 1px solid var(--line);
  box-shadow: 0 16px 48px rgba(0,0,0,.28);
  font: 13px/1.5 "Segoe UI", "Microsoft YaHei", sans-serif; color: var(--ink);
}
#shortcut-dialog header {
  display: flex; justify-content: space-between; align-items: center;
  height: 40px; padding: 0 8px 0 16px; font-weight: 600;
  border-bottom: 1px solid #eef0f3;
}
#shortcut-dialog header .sk-close {
  width: 28px; height: 26px; border: none; background: transparent;
  color: #5a6270; font-size: 13px; cursor: pointer; border-radius: 4px;
}
#shortcut-dialog header .sk-close:hover { background: #e3e6ea; }
#shortcut-dialog .sk-hint { padding: 10px 16px; color: #6b7480; font-size: 12px; }
#shortcut-dialog .sk-list { flex: 1; overflow-y: auto; padding: 0 16px; }
#shortcut-dialog .sk-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 6px 0; border-bottom: 1px solid #f2f4f7;
}
#shortcut-dialog .sk-label { color: #333; }
#shortcut-dialog .sk-rec {
  min-width: 110px; height: 28px; padding: 0 12px;
  border: 1px solid #c3c9d2; border-radius: 6px;
  background: #f7f9fc; color: #1f2429; font: inherit; cursor: pointer;
}
#shortcut-dialog .sk-rec:hover { border-color: var(--accent); }
#shortcut-dialog .sk-rec.rec { border-color: var(--accent); color: var(--accent); background: #eef4ff; }
#shortcut-dialog .sk-foot {
  display: flex; justify-content: space-between;
  padding: 12px 16px; border-top: 1px solid #eef0f3;
}
#shortcut-dialog .sk-foot button {
  height: 30px; padding: 0 16px; border: 1px solid #c3c9d2; border-radius: 6px;
  background: #fff; font: inherit; cursor: pointer;
}
#shortcut-dialog .sk-foot button:hover { background: #f0f3f7; }
#shortcut-dialog .sk-foot .sk-close { background: var(--accent); border-color: var(--accent); color: #fff; }


/* ---- 分页符标记（Word 式虚线 + 居中文字；不可编辑，打印隐藏） ---- */
.page-break {
  position: relative;
  margin: 0 0 .6em;
  padding: 3px 0;
  text-align: center;
  user-select: none;
  cursor: default;
}
.page-break::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  border-top: 1px dashed #a9c0e8;
}
.page-break span {
  position: relative;
  background: #fff;
  padding: 0 10px;
  font-size: 10px;
  color: #8aa0c0;
  letter-spacing: 4px;
}
.page-break span::after { content: "分页符"; }
/* 特调无损导入（PDF 特调 / OmniDoc 冻结版 / 多页沙箱）的页骨架是纯占位：
   分页符不画蓝色虚线、骨架空段不画 ↴（用户 bug：每页顶部一条蓝色虚线） */
.page-break.pb-quiet { margin: 0; padding: 0; }
.page-break.pb-quiet::before { content: none; }
.page-content sup, .page-content sub {
  position: relative;
  /* Word's automatic superscript/subscript is rendered at exactly half the
     inherited point size (12pt citations become 6pt).  Chromium's UA rule is
     about 83%, which widens citation-heavy CJK paragraphs enough to add lines. */
  font-size: 50%;
  line-height: 0;
  vertical-align: baseline;
}
.page-content sup { top: -.5em; }
.page-content sub { bottom: -.25em; }

/* DOCX-imported paragraphs carry exact OOXML w:spacing inline. Never apply
   document-wide tracking here: -0.4px makes a 467.7pt Word line accept 38
   instead of 37 full-width 12pt glyphs and cascades into wrong pagination. */
.page-content [data-word-layout="1"] {
  /* The Word default for an unspecified before/after value is zero.  UniDoc's
     generic web-block .6em gap must not leak into imported paragraphs. */
  margin-top: 0;
  margin-bottom: 0;
  /* Word punctuation compression is carried by per-character spans emitted
     from settings.xml; never squeeze every business glyph to force a page
     count match. */
  letter-spacing: normal;
  text-spacing-trim: space-all;
  line-break: strict;
  word-break: normal;
  overflow-wrap: anywhere;
}
/* w:t xml:space="preserve" owns significant repeated/edge spaces. Scope the
   browser whitespace behavior to that exact editable source run; normal DOCX
   text keeps ordinary HTML wrapping and no hot-path JS is involved. */
.page-content [data-word-space-preserve="1"] {
  white-space: break-spaces;
}
/* A run made only of preserved Word spaces is a horizontal formatting run.
   break-spaces would split a long trailing underline/spacer into extra
   browser lines even though desktop Word keeps it on the current line. Keep
   every source space while forbidding an internal wrap; surrounding text and
   adjacent runs remain normal wrap opportunities. */
.page-content [data-word-space-preserve="1"][data-word-space-only="1"] {
  white-space: pre;
}
/* Word owns the line pitch at the paragraph level.  Letting every script run
   inherit that full pitch makes Chromium align the KaiTi/Song and Times New
   Roman inline boxes with different ascent/descent metrics; their union then
   grows about .5-.7px beyond the declared line-height on every line.  Keep
   each glyph run at its natural 1em box and let the paragraph strut provide
   the authoritative Word line spacing.  Larger explicit run fonts can still
   expand an automatic line, while ordinary mixed CJK/Latin lines no longer
   accumulate hidden page drift. */
.page-content [data-word-layout="1"][data-word-line-rule="auto"]
  span[data-word-line-box="paragraph"] {
  line-height: 1;
}
/* Desktop Word's East-Asian body line box is taller than Chromium `normal`.
   Keep the calibrated Word body strut on top-level imported blocks only;
   table cells retain their font-dependent browser `normal`, which matches the
   real Word line coordinates once row minimums include the resolved rule. */
.page-content > [data-word-layout="1"]:is(
    [style*="line-height:normal"], [style*="line-height: normal"]),
body.flow-mode .page-content > .flow-chunk > [data-word-layout="1"]:is(
    [style*="line-height:normal"], [style*="line-height: normal"]) {
  line-height: 1.25 !important;
}
.page-content :is(td, th) [data-word-layout="1"][style*="line-height:normal"]
  > span[data-word-script="eastAsia"] {
  /* Word uses the East-Asian font's natural 15pt line box for 11pt Song text;
     Chromium's inline `normal` is only about 12.5pt.  Raise only lines that
     actually contain an East-Asian run, leaving compact Latin rows unchanged. */
  line-height: 1.3636;
}
.page-content .word-punct-compress-end {
  /* Word's compressPunctuation is line-adaptive, not a document-wide fixed
     squeeze.  Keep ordinary lines effectively full-width; cached Word page
     tails receive the smallest required value through this custom property. */
  margin-inline-end: var(--word-punct-compress, 0em);
}
.page-content .word-punct-compress-start {
  margin-inline-start: var(--word-punct-compress, 0em);
}
/* contenteditable 删除标点时，Chromium 可能短暂留下空的 run 壳。
   空壳绝不能继续消费负 advance；JS 会在同一 input 内将它移除，这里保证
   浏览器默认动作到 input 监听器之间也不会出现字符重叠的一帧。 */
.page-content .word-punct-compress-start:empty,
.page-content .word-punct-compress-end:empty {
  margin-inline-start: 0;
  margin-inline-end: 0;
}
/* Word character-unit first-line indents participate in its East-Asian grid
   compression path.  Empirical OOXML→Word-PDF line probes show the matching
   advance at .32em, while twip-indented body text matches at .10em. */
.page-content [data-word-char-indent="1"] {
  --word-punct-compress: -.32em;
}
body.show-marks .page-content .pb-skel.blk-blank::before { content: none; }
@media print {
  .page-break { display: none; }
}
/* ---- 导入加载遮罩（PDF/特调 HTML 无损导入耗时时显示） ---- */
#import-loading {
  position: fixed; inset: 0; z-index: 99999;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 18px; background: rgba(247, 249, 252, .82); backdrop-filter: blur(2px);
  font: 14px/1.5 "Segoe UI", system-ui, sans-serif; color: var(--accent);
}
#import-loading.hidden { display: none; }
#import-loading .il-spinner {
  width: 46px; height: 46px; border-radius: 50%;
  border: 4px solid #d5e0f2; border-top-color: var(--accent);
  animation: il-spin .8s linear infinite;
}
#import-loading .il-text { font-weight: 600; letter-spacing: .5px; }
@keyframes il-spin { to { transform: rotate(360deg); } }

/* ---- 云附件上传：右下角、点击穿透、不阻塞编辑器 ---- */
#attachment-upload-status {
  position: fixed; right: 22px; bottom: 48px; z-index: 99998;
  display: grid; grid-template-columns: 48px minmax(0, 1fr); align-items: center;
  width: min(356px, calc(100vw - 32px)); min-height: 78px; padding: 13px 15px 12px 13px;
  border: 1px solid rgba(31, 91, 156, .16); border-radius: 18px;
  background: rgba(255, 255, 255, .94); box-shadow: 0 16px 48px rgba(34, 54, 78, .2);
  color: #152238; font: 13px/1.35 "Segoe UI", system-ui, sans-serif;
  pointer-events: none; user-select: none; backdrop-filter: blur(14px) saturate(1.12);
  animation: aus-enter 180ms cubic-bezier(.2, .8, .2, 1); contain: layout paint style;
}
#attachment-upload-status.hidden { display: none; }
#attachment-upload-status .aus-icon { width: 42px; height: 42px; }
#attachment-upload-status svg { display: block; width: 100%; height: 100%; overflow: visible; }
#attachment-upload-status .aus-ring-track,
#attachment-upload-status .aus-ring-progress { fill: none; stroke-width: 2.7; }
#attachment-upload-status .aus-ring-track { stroke: #dce8f6; }
#attachment-upload-status .aus-ring-progress {
  stroke: #1478df; stroke-linecap: round; stroke-dasharray: 0 100;
  transform: rotate(-90deg); transform-origin: 24px 24px; transition: stroke-dasharray 140ms ease-out;
}
#attachment-upload-status .aus-cloud {
  fill: rgba(20, 120, 223, .1); stroke: #236cae; stroke-linejoin: round; stroke-width: 1.7;
}
#attachment-upload-status .aus-arrow,
#attachment-upload-status .aus-check {
  fill: none; stroke: #1478df; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2.4;
}
#attachment-upload-status .aus-arrow { animation: aus-arrow-rise 1.05s ease-in-out infinite; }
#attachment-upload-status .aus-check { display: none; }
#attachment-upload-status.is-finalizing .aus-icon,
#attachment-upload-status.is-caching .aus-icon { animation: aus-pulse 1.1s ease-in-out infinite; }
#attachment-upload-status.is-complete .aus-ring-progress { stroke: #159a75; }
#attachment-upload-status.is-complete .aus-cloud,
#attachment-upload-status.is-complete .aus-arrow { display: none; }
#attachment-upload-status.is-complete .aus-check {
  display: block; stroke: #159a75; stroke-dasharray: 24; animation: aus-check 360ms ease-out both;
}
#attachment-upload-status .aus-copy { min-width: 0; padding-left: 10px; }
#attachment-upload-status .aus-head,
#attachment-upload-status .aus-detail { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
#attachment-upload-status .aus-phase { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
#attachment-upload-status .aus-percent { color: #1768ba; font-size: 16px; font-weight: 750; font-variant-numeric: tabular-nums; }
#attachment-upload-status.is-complete .aus-percent { color: #148565; }
#attachment-upload-status .aus-detail { margin-top: 4px; color: #64748b; font-size: 11px; }
#attachment-upload-status .aus-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#attachment-upload-status .aus-bytes { flex: 0 0 auto; font-variant-numeric: tabular-nums; }
#attachment-upload-status .aus-track { height: 3px; margin-top: 8px; overflow: hidden; border-radius: 999px; background: #e5edf6; }
#attachment-upload-status .aus-track > span { display: block; width: 0; height: 100%; border-radius: inherit; background: linear-gradient(90deg, #2769b0, #18a8b5); transition: width 140ms ease-out; }
@keyframes aus-enter { from { opacity: 0; transform: translate3d(0, 10px, 0) scale(.98); } }
@keyframes aus-arrow-rise { 0%, 100% { transform: translateY(1.5px); opacity: .68; } 50% { transform: translateY(-1.5px); opacity: 1; } }
@keyframes aus-pulse { 50% { transform: scale(.94); opacity: .72; } }
@keyframes aus-check { from { stroke-dashoffset: 24; } to { stroke-dashoffset: 0; } }
@media (max-width: 640px) {
  #attachment-upload-status { right: 12px; bottom: 42px; width: min(340px, calc(100vw - 24px)); }
}
@media (prefers-reduced-motion: reduce) {
  #attachment-upload-status,
  #attachment-upload-status .aus-arrow,
  #attachment-upload-status .aus-icon,
  #attachment-upload-status .aus-check { animation: none !important; }
}
/* 分页符/分节符点选态：点击选中 → Delete/Backspace 删除，Esc 取消 */
.page-break.marker-selected,
.section-break.marker-selected {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  background: rgba(43, 87, 154, .07);
  border-radius: 4px;
  cursor: pointer;
}
.page-break, .section-break { cursor: pointer; }
/* 悬停微高亮（配合右侧浮出的删除钮，Word 视觉不变） */
body:not(.flow-mode) .page-break:hover,
body:not(.flow-mode) .section-break:hover {
  background: rgba(43, 87, 154, .05);
  border-radius: 4px;
}
/* UniDoc 友好分页符：悬停删除浮钮（body 级，跟随分隔符右端） */
#pb-del-btn {
  position: fixed;
  z-index: 60;
  width: 22px; height: 22px;
  display: none;
  align-items: center; justify-content: center;
  padding: 0; border: 1px solid #e2b4ad; border-radius: 50%;
  background: #fff; color: #d23f31; font-size: 12px; line-height: 1;
  cursor: pointer; box-shadow: 0 2px 8px rgba(15, 25, 40, .18);
}
#pb-del-btn:hover { background: #d23f31; color: #fff; border-color: #d23f31; }

/* ---- 页面文本框：每页绝对定位的浮动文本框（Word「浮于文字上方」语义）----
 * 视觉与文档设计系统对齐：圆角卡片 + 分层柔和阴影，悬浮微抬升；
 * 选中 = accent 描边环，编辑 = accent 实线 + 聚焦光晕；抓取角默认隐藏、悬浮浮现。 */
.udoc-textbox {
  position: absolute;
  z-index: 5;
  box-sizing: border-box;
  padding: 4px;                       /* 抓取环：点边框拖动/选中，点内部编辑 */
  background: #fff;
  border: 1px solid #c8d2e2;
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(20, 40, 80, .06), 0 4px 14px rgba(20, 40, 80, .10);
  cursor: move;
  user-select: none;
  transition: box-shadow .15s ease, border-color .15s ease;
}
.udoc-textbox:hover {
  border-color: #9fb4d8;
  box-shadow: 0 2px 4px rgba(20, 40, 80, .08), 0 8px 22px rgba(20, 40, 80, .14);
}
.udoc-textbox .tbox-content {
  width: 100%;
  height: 100%;
  /* PPT 溢出语义（用户拍板）：宽度硬约束（横向裁切、文本自动换行），
     高度软约束（内容多了向下溢出照显）。
     关键：用 overflow-x: clip 而非 hidden —— hidden 会把 overflow-y: visible
     强制降级成 auto（CSS 规范陷阱，纵向溢出会失效变滚动）；clip 可与
     visible 合法混用，单轴裁切不影响另一轴。 */
  overflow-x: clip;
  overflow-y: visible;
  scrollbar-width: none;
  outline: none;
  cursor: text;
  user-select: text;
  font-size: 14px;
  line-height: 1.6;
  word-wrap: break-word;
  padding: 0;                        /* 内容内边距全局归零（与导入无损框一致，文字与框矩形对齐） */
  border-radius: 5px;
}
/* Word text-body insets are signed. CSS padding is not, so imported boxes use
   the exact Word content rectangle instead of a padding approximation. The
   shell remains the wp:extent selection/resize geometry; negative insets may
   deliberately extend editable text beyond that shell. */
.udoc-textbox[data-tbox-insets="1"] .tbox-content {
  position: absolute;
  left: var(--tbox-inset-left, 0px);
  top: var(--tbox-inset-top, 0px);
  width: calc(100% + var(--tbox-content-width-adjust, 0px));
  height: calc(100% + var(--tbox-content-height-adjust, 0px));
}
.udoc-textbox .tbox-content::-webkit-scrollbar { width: 0; height: 0; display: none; }
.udoc-textbox .tbox-content > * { margin: 0 0 .35em; }
.udoc-textbox .tbox-resize {
  position: absolute;
  right: 2px;
  bottom: 2px;
  width: 14px;
  height: 14px;
  cursor: nwse-resize;
  border-right: 2px solid #a9b9d4;
  border-bottom: 2px solid #a9b9d4;
  border-bottom-right-radius: 7px;
  opacity: 0;
  transition: opacity .15s ease;
}
.udoc-textbox:hover .tbox-resize,
.udoc-textbox.tbox-selected .tbox-resize,
.udoc-textbox.tbox-editing .tbox-resize { opacity: 1; }
.udoc-textbox.tbox-selected {
  border-color: #1677ff;
  outline: none;
}
.udoc-textbox.tbox-editing {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(43, 87, 154, .12), 0 4px 14px rgba(20, 40, 80, .10);
}
/* 文本框外观写入 UDOC 模型；选中/编辑轮廓属于编辑器瞬态，不改变文档样式。 */
.udoc-textbox[data-tbox-style="borderless"] {
  border-color: transparent;
  box-shadow: none;
  transition: none;
}
.udoc-textbox[data-tbox-style="outline"] {
  border: 1px solid #44546c;
  border-radius: 0;
  box-shadow: none;
  transition: none;
  background: transparent;
}
.udoc-textbox[data-tbox-style="dashed"] {
  border: 1px dashed #6b7c96;
  border-radius: 2px;
  box-shadow: none;
  transition: none;
}
.udoc-textbox[data-tbox-style="transparent"] {
  /* OOXML a:noFill + a:ln/a:noFill means that no shape edge exists at all.
     A transparent-coloured 1px border is visually hidden but still changes
     the content box and therefore Word textbox wrapping/geometry. */
  border-width: 0;
  border-color: transparent;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  transition: none;
}
/* bare：冻结 DOM/网页还原专用 —— 零内边距零装饰，坐标与原页像素对齐
 *（transparent 的 4px/6px 内边距会让每个框文字偏移+可用宽度变窄→折行走样）。
 * 导入内容 = 原页已定稿的绝对布局，必须 overflow:visible 双轴：中文 fallback 字体
 * 比原西文字体略宽时不能被 overflow-x:clip 裁掉（“文本右侧溢出不显示”回归真因）。 */
.udoc-textbox[data-tbox-style="bare"] {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  transition: none;
  border-width: 0;
  padding: 0;                        /* 导入无损框：外层抓取环内边距归零，内容与框矩形精确对齐 */
  overflow: visible;
}
.udoc-textbox[data-tbox-style="bare"] .tbox-content {
  padding: 0;
  border-radius: 0;
  font-size: inherit;
  line-height: inherit;
  overflow: visible;
}
/* overlay：旋转/竖排文本专用 —— 零装饰 + 双轴 visible（旋转内容伸出框外不裁切）；
 * 内元素绝对定位到 (0,0)=旋转支点，transform-origin:left top 复现原页位置。 */
.udoc-textbox[data-tbox-style="overlay"] {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  transition: none;
  border-width: 0;
  overflow: visible;
}
.udoc-textbox[data-tbox-style="overlay"] .tbox-content {
  padding: 0;
  border-radius: 0;
  font-size: inherit;
  line-height: inherit;
  overflow: visible;
  position: relative;
}
/* Explicit Word insets remain authoritative for every appearance variant,
   including overlay/bare shells declared above. */
.udoc-textbox[data-tbox-insets="1"] .tbox-content {
  position: absolute;
}
body.flow-mode .udoc-textbox {
  display: block;
}
@media print {
  .udoc-textbox { box-shadow: none; }
  /* The default frame of an object textbox is editor chrome. On screen it is
     hidden while idle, but Chromium can keep :hover/:focus during Ctrl+P and
     print the pale-blue frame around an otherwise borderless image. Authored
     outline/dashed styles remain untouched; only the transient default frame
     and selection ring are suppressed. */
  .udoc-textbox.tbox-obj:not([data-tbox-style="outline"]):not([data-tbox-style="dashed"]),
  .udoc-textbox.tbox-obj.tbox-selected,
  .udoc-textbox.tbox-obj.tbox-editing {
    border-color: transparent !important;
    outline: none !important;
    box-shadow: none !important;
  }
  .udoc-textbox .tbox-content { overflow-x: clip; overflow-y: visible; }
  .udoc-textbox .tbox-resize { display: none; }
}

/* ---- 分节符：克制的 Word 式编辑标记（不参与打印） ---- */
.section-break {
  position: relative;
  /* Keep the legacy marker's layout footprint so a purely visual redesign
     cannot move Word page boundaries. Only the chrome becomes quieter. */
  min-height: 31px;
  margin: 0 0 .6em;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  user-select: none;
  cursor: default;
}
.section-break::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 15px;
  border-top: 1px solid #d8dde5;
}
.section-break span {
  position: relative;
  display: inline-block;
  z-index: 1;
  padding: 0 7px;
  background: #fff;
  color: #7a8491;
  font: 9.5px/18px "Segoe UI", "Microsoft YaHei", sans-serif;
  letter-spacing: 0;
}
.section-break span::before { content: "分节符 · "; }
.section-break span::after { content: attr(data-sec-label); }
.section-break.marker-selected {
  outline-width: 1px;
  background: rgba(43, 87, 154, .035);
}
@media print {
  .section-break { display: none; }
}

/* ---- 视频块（无边框、无块上工具条）----
 * 旧版 vb-bar 悬浮条正好盖在原生播放控制条上方，把播放按钮的点击全吃掉；
 * 换源/尺寸/样式/全屏已收进「布局选项」面板的「视频」板块（与沙箱同模式）。 */
.video-block {
  position: relative;
  user-select: none;
  text-align: center;
}
.video-block video {
  display: block;
  width: 100%;
  max-height: 70vh;
  background: #000;
}

/* ---- 媒体插入对话框（插入图片/视频，与页面设置同一套极简视觉）---- */
#media-dialog {
  position: fixed;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 72;
  width: 420px;
  max-width: calc(100vw - 32px);
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 16px 48px rgba(0,0,0,.28);
  font: 12px/1.5 "Segoe UI", "Microsoft YaHei", sans-serif;
  color: var(--ink);
}
#media-dialog.hidden { display: none; }
#media-dialog header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 34px;
  padding: 0 4px 0 14px;
  font-weight: 600;
  background: #f4f5f7;
  border-bottom: 1px solid #e1e4e9;
}
#media-dialog header button {
  width: 28px; height: 24px;
  border: none;
  border-radius: 2px;
  background: transparent;
  color: #5a6270;
  font-size: 12px;
  cursor: pointer;
}
#media-dialog header button:hover { background: #e3e6ea; color: #1f2429; }
#media-dialog .md-body { padding: 14px 16px 4px; }
#media-dialog .md-hint { margin-bottom: 8px; color: #6b7480; font-size: 11px; }
#media-dialog .md-url {
  width: 100%;
  height: 28px;
  padding: 0 8px;
  border: 1px solid #c3c9d2;
  border-radius: 2px;
  font: inherit;
  box-sizing: border-box;
}
#media-dialog .md-url:focus { outline: none; border-color: var(--accent); }
#media-dialog .md-file {
  margin-top: 8px;
  height: 26px;
  padding: 0 10px;
  border: 1px dashed #c3c9d2;
  border-radius: 2px;
  background: #fafbfc;
  font: inherit;
  color: #454c56;
  cursor: pointer;
}
#media-dialog .md-file:hover { border-color: var(--accent); color: var(--accent); }
#media-dialog .md-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 12px 16px 14px;
}
#media-dialog .md-actions button {
  min-width: 76px;
  height: 26px;
  padding: 0 14px;
  border: 1px solid #c3c9d2;
  border-radius: 2px;
  background: #fff;
  font: inherit;
  cursor: pointer;
}
#media-dialog .md-actions button:hover { background: #f0f3f7; border-color: #9fa9b7; }
#media-dialog .md-apply {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
  color: #fff;
}

/* ---- 动态 HTML 嵌入块（沙箱 iframe；无边框、无块上工具条）----
 * 代码/高度/重运行/样式/全屏/小窗全部收进「布局选项」面板的「HTML 沙箱」板块，
 * 与动态数据块同一套交互；块本体只剩 iframe，选中后走八向手柄与流内拖拽。 */
.html-embed {
  position: relative;
  user-select: none;
}
.html-embed iframe {
  display: block;
  width: 100%;
  border: none;
  background: #fff;
}
/* Word/Notion 式点击盾：未激活时 iframe 不吃指针 —— 单击选中对象
 * （八向手柄 + ⚙ 布局 + 拖拽），双击才进入沙箱与内容交互 */
.html-embed:not(.he-active) iframe { pointer-events: none; }
/* 全屏时点击盾必须撤掉：否则沙箱内容收不到指针（拖拽旋转全失灵） */
.html-embed iframe:fullscreen { pointer-events: auto !important; }
.html-embed.he-active { outline: 2px solid rgba(43, 87, 154, .45); outline-offset: 1px; }
.html-embed:not(.he-active) { cursor: default; }
/* 可编辑网页模式切换：独立于页面/iframe 的视口级悬浮控件。
 * HTML 再长、画布再滚动都固定在 Ribbon 下方，不再跟着网页内容跑。 */
#html-edit-mode-float {
  position: fixed;
  top: calc(var(--ribbon-h, 128px) + 10px);
  right: 18px;
  z-index: 79;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-width: 92px;
  height: 34px;
  padding: 0 13px;
  border: 1px solid rgba(43, 87, 154, .28);
  border-radius: 17px;
  background: rgba(255, 255, 255, .96);
  color: #245d96;
  font: 600 12.5px/1 "Segoe UI", "Microsoft YaHei", sans-serif;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(25, 48, 83, .18), 0 1px 3px rgba(25, 48, 83, .12);
  backdrop-filter: blur(10px);
  transition: transform .14s, background .14s, color .14s, box-shadow .14s;
}
#html-edit-mode-float::before { content: "✎"; font-size: 14px; }
#html-edit-mode-float[data-mode="edit"]::before { content: "▶"; font-size: 11px; }
#html-edit-mode-float:hover {
  transform: translateY(-1px);
  background: #245d96;
  color: #fff;
  box-shadow: 0 10px 26px rgba(31, 78, 125, .26);
}
#html-edit-mode-float:focus-visible { outline: 2px solid #79aee6; outline-offset: 2px; }
#html-edit-mode-float:active { transform: translateY(0); }
#html-edit-mode-float[hidden],
body.presenting #html-edit-mode-float { display: none !important; }
#html-edit-immersive-enter,
#html-edit-immersive-exit {
  position: fixed;
  z-index: 80;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 34px;
  padding: 0 13px;
  border: 1px solid rgba(43, 87, 154, .28);
  border-radius: 17px;
  background: rgba(255, 255, 255, .96);
  color: #245d96;
  font: 600 12.5px/1 "Segoe UI", "Microsoft YaHei", sans-serif;
  cursor: pointer;
  box-shadow: 0 8px 24px rgba(25, 48, 83, .18), 0 1px 3px rgba(25, 48, 83, .12);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
#html-edit-immersive-enter {
  top: calc(var(--ribbon-h, 128px) + 10px);
  right: 126px;
}
#html-edit-immersive-exit {
  top: max(14px, env(safe-area-inset-top));
  right: max(16px, env(safe-area-inset-right));
  z-index: 2147483646;
  height: 40px;
  width: 40px;
  padding: 0;
  border-color: rgba(255, 255, 255, .5);
  border-radius: 20px;
  background: rgba(20, 31, 48, .82);
  color: #fff;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .28);
}
#html-edit-immersive-enter svg,
#html-edit-immersive-exit svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
#html-edit-immersive-enter:hover { background: #245d96; color: #fff; }
#html-edit-immersive-exit:hover { background: rgba(10, 18, 30, .94); }
#html-edit-immersive-enter:focus-visible,
#html-edit-immersive-exit:focus-visible {
  outline: 3px solid rgba(55, 196, 226, .72);
  outline-offset: 3px;
}
#html-edit-immersive-enter[hidden],
#html-edit-immersive-exit[hidden],
body.presenting #html-edit-immersive-enter,
body.presenting #html-edit-immersive-exit { display: none !important; }

/* Free-HTML immersive mode is editor chrome only. It never changes the
 * textbox model or its persisted geometry: one transient page/shell class
 * removes the paged canvas coordinate system and gives the iframe a native
 * viewport. The restore control remains a body-level sibling above it. */
body.udoc-html-immersive {
  padding: 0 !important;
  overflow: hidden !important;
  background: #fff;
}
body.udoc-html-immersive > :not(#canvas):not(#html-edit-immersive-exit) {
  display: none !important;
}
body.udoc-html-immersive #html-edit-immersive-exit {
  display: inline-flex !important;
}
body.udoc-html-immersive #canvas {
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  padding: 0;
  overflow: hidden;
  scrollbar-gutter: auto;
  background: #fff;
}
body.udoc-html-immersive #pages-sizer,
body.udoc-html-immersive #pages {
  position: static;
  width: 100vw !important;
  height: 100vh !important;
  height: 100dvh !important;
  margin: 0 !important;
  transform: none !important;
}
body.udoc-html-immersive #pages > .page {
  display: none !important;
}
body.udoc-html-immersive #pages > .page.udoc-html-immersive-page {
  position: fixed !important;
  display: block !important;
  inset: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  height: 100dvh !important;
  min-width: 0 !important;
  min-height: 0 !important;
  content-visibility: visible;
  contain: none;
  outline: 0;
  box-shadow: none;
  background: #fff;
}
body.udoc-html-immersive .udoc-html-immersive-page > :not(.udoc-html-immersive-target) {
  display: none !important;
}
body.udoc-html-immersive .udoc-html-immersive-target {
  position: fixed !important;
  display: block !important;
  inset: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  height: 100dvh !important;
  z-index: 2147483001 !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  outline: 0 !important;
  box-shadow: none !important;
  transform: none !important;
  overflow: hidden !important;
  transition: none !important;
}
body.udoc-html-immersive .udoc-html-immersive-target > .tbox-content,
body.udoc-html-immersive .udoc-html-immersive-target .html-edit-island,
body.udoc-html-immersive .udoc-html-immersive-target .html-edit-frame {
  position: static !important;
  display: block !important;
  inset: auto !important;
  width: 100% !important;
  height: 100% !important;
  min-width: 0 !important;
  min-height: 0 !important;
  padding: 0 !important;
  margin: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  transform: none !important;
  overflow: hidden !important;
  visibility: visible !important;
  opacity: 1 !important;
  pointer-events: auto !important;
}
body.udoc-html-immersive .udoc-html-immersive-target > .tbox-h,
body.udoc-html-immersive .udoc-html-immersive-target > .tbox-resize,
body.udoc-html-immersive .udoc-html-immersive-target::after {
  display: none !important;
}
/* 可编辑 HTML 岛：iframe 直接接收指针（designMode 就地点选改字，无需双击点击盾） */
.html-edit-island,
.html-edit-island iframe {
  touch-action: pan-x pan-y;
}
.html-edit-island iframe {
  pointer-events: auto !important;
  /* Avoid accidental compositor hints that freeze a low-resolution iframe
   * surface; crisp HTML zoom is selected by syncEditorZoomRenderMode(). */
  will-change: auto;
  backface-visibility: visible;
}
@media print {
  .html-embed.he-active { outline: none !important; }
  #html-edit-mode-float,
  #html-edit-immersive-enter,
  #html-edit-immersive-exit { display: none !important; }
}

/* ---- 代码编辑对话框（动态块 UI 样式 / HTML 嵌入代码共用） ---- */
#code-editor-dialog {
  position: fixed;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 72;
  width: 640px;
  max-width: calc(100vw - 32px);
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 16px 48px rgba(0,0,0,.28);
  font-size: 13px;
}
#code-editor-dialog.hidden { display: none; }
#code-editor-dialog header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 14px;
  font-weight: 600;
  border-bottom: 1px solid #e7ebf2;
  color: #2b3a4f;
}
#code-editor-dialog header button {
  border: none; background: transparent; cursor: pointer; font-size: 13px; color: #666;
}
#code-editor-dialog .ce-body { padding: 10px 14px 0; }
#ce-hint { font-size: 11px; color: #7a8aa5; margin-bottom: 6px; white-space: pre-wrap; }
#ce-text {
  width: 100%;
  height: 320px;
  box-sizing: border-box;
  resize: vertical;
  font-family: Consolas, "Cascadia Mono", monospace;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink);
  background: #f8fafd;
  border: 1px solid var(--line);
  padding: 8px 10px;
  tab-size: 2;
}
#code-editor-dialog .ce-actions {
  display: flex;
  gap: 8px;
  padding: 10px 14px 12px;
}
#code-editor-dialog .ce-spacer { flex: 1; }
#code-editor-dialog .ce-actions button {
  border: 1px solid var(--line);
  background: #fff;
  padding: 4px 14px;
  cursor: pointer;
  font-size: 12px;
  color: var(--ink);
}
#code-editor-dialog #ce-apply { background: var(--accent); color: #fff; border-color: var(--accent); }
#code-editor-dialog .ce-actions button:hover { filter: brightness(1.06); }

/* 页面设置对话框：应用范围禁用态（仅淡显；点击输入框即自动切到页码范围） */
#page-setup-dialog #ps-range-fields.is-disabled {
  opacity: .45;
}

/* ---- 多级列表（Word 式层级符号） ---- */
.page-content ul { list-style-type: disc; }
.page-content ul ul { list-style-type: circle; }
.page-content ul ul ul { list-style-type: square; }
.page-content ol { list-style-type: decimal; }
.page-content ol ol { list-style-type: lower-alpha; }
.page-content ol ol ol { list-style-type: lower-roman; }

/* ---- Word 编号（numbering）----
 * 编号规则仍是段落属性，但编号本体是可命中的真实 HTML span；悬挂缩进
 * 保持 Word 版式。跨页续片无 marker（编号只在逻辑段首）。 */
.page-content [data-num-id] {
  --udoc-num-left: 2em;
  --udoc-num-hanging: 2em;
  --udoc-num-gap: .5em;
  position: relative;
  margin-left: var(--udoc-num-left);
  padding-left: 0;
  text-indent: 0;
}
.page-content .word-num-marker {
  display: inline-block;
  margin-right: .5em;
  text-indent: 0;
  white-space: pre;
  cursor: default;
  user-select: none;
}
.page-content .word-num-marker.num-marker-selected {
  background: #d9d9d9;
  box-shadow: 0 0 0 2px #d9d9d9;
}
/* The paragraph content box begins at Word's w:ind/@left, so every business
   line starts in one column. The real marker occupies the hanging reserve to
   its left; it never consumes inline width and never changes wrapping. */
.page-content [data-num-id] > .word-num-marker {
  position: absolute;
  top: 0;
  left: calc(-1 * var(--udoc-num-hanging));
  width: max(0px, calc(var(--udoc-num-hanging) - var(--udoc-num-gap)));
  margin-right: 0;
  text-align: right;
  transform: none;
}
/* A continuation fragment keeps the same business-text column and owns no
   marker. It must never replay a logical first-line indent. */
.page-content [data-num-id][data-cont="1"] { text-indent: 0; }
@media print {
  .page-content .word-num-marker.num-marker-selected {
    background: transparent;
    box-shadow: none;
  }
}
/* 级别递进（Word 每级 +2 字符） */
.page-content [data-num-lvl="1"] { --udoc-num-left: 4em; }
.page-content [data-num-lvl="2"] { --udoc-num-left: 6em; }
.page-content [data-num-lvl="3"] { --udoc-num-left: 8em; }
.page-content [data-num-lvl="4"] { --udoc-num-left: 10em; }
.page-content [data-num-lvl="5"] { --udoc-num-left: 12em; }
.page-content [data-num-lvl="6"] { --udoc-num-left: 14em; }
.page-content [data-num-lvl="7"] { --udoc-num-left: 16em; }
.page-content [data-num-lvl="8"] { --udoc-num-left: 18em; }
.page-content li > ul, .page-content li > ol { margin: 0; }

/* ---- 超链接（Ctrl+点击 打开）----
 * 不强加蓝色/下划线（导入 HTML 的链接保留原设计，用户铁律）；
 * 样式完全继承文档自身（编辑器插入的链接由 editHyperlink 写内联样式）。
 * 文本框内同理 —— 导入的冻结/网页内容落在文本框，不能被浏览器默认蓝下划线污染。 */
.page-content a,
.udoc-textbox .tbox-content a {
  color: inherit;
  text-decoration: inherit;
  cursor: text;
}
.page-content a:hover { background: rgba(37, 99, 196, .08); }
body.ctrl-down .page-content a,
body.ctrl-down .udoc-textbox .tbox-content a { cursor: pointer; }

/* ---- .zdoc 面板 ---- */
#zdoc-panel {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  width: 420px;
  background: #1e1e28;
  color: #d8e0ea;
  display: flex;
  flex-direction: column;
  box-shadow: -4px 0 20px rgba(0,0,0,.3);
  z-index: 50;
  transition: transform .25s ease;
}
#zdoc-panel.hidden { transform: translateX(100%); }
#zdoc-panel header {
  padding: 10px 14px;
  font-size: 13px;
  display: flex; justify-content: space-between; align-items: center;
  border-bottom: 1px solid #333344;
}
#zdoc-panel header button { background: none; border: none; color: #aaa; cursor: pointer; font-size: 14px; }
#zdoc-panel textarea {
  flex: 1;
  background: transparent;
  color: #b6d7a8;
  border: none;
  resize: none;
  outline: none;
  padding: 12px 14px;
  font-family: Consolas, monospace;
  font-size: 12px;
  line-height: 1.5;
}

/* ---- 右键菜单（Word/Cursor 极简风） ---- */
#ctx-menu {
  position: fixed;
  z-index: 200;
  min-width: 208px;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 4px 16px rgba(0, 0, 0, .2);
  padding: 3px;
  list-style: none;
  font-size: 12.5px;
  user-select: none;
}
#ctx-menu.hidden { display: none; }
#ctx-menu li {
  min-height: 26px;
  box-sizing: border-box;
  padding: 2px 10px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  position: relative;
  white-space: nowrap;
  color: var(--ink);
}
#ctx-menu li:hover { background: var(--hover); }
#ctx-menu li.disabled { color: #b6bfcd; pointer-events: none; }
#ctx-menu li .key { margin-left: auto; color: #aab3c2; font-size: 11px; letter-spacing: .2px; }
#ctx-menu li.separator {
  height: 1px; min-height: 1px; padding: 0; margin: 3px 8px;
  background: var(--line-soft); pointer-events: none;
}
#ctx-menu li.group-label {
  padding: 3px 10px 1px;
  color: #9aa5b5;
  font-size: 10px;
  letter-spacing: 1px;
  cursor: default;
  pointer-events: none;
}
#ctx-menu li.has-sub::after { content: "\25B8"; margin-left: auto; color: #aab3c2; }
#ctx-menu .submenu {
  display: none;
  position: absolute;
  left: 100%; top: -3px;
  min-width: 132px;
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 4px 16px rgba(0, 0, 0, .2);
  padding: 3px;
  list-style: none;
}
#ctx-menu li.has-sub:hover > .submenu { display: block; }
#ctx-menu .submenu li.checked::before { content: "\2713"; color: var(--accent); }
/* ✨ 问 AI：强调色，与普通菜单项拉开层次 */
#ctx-menu li.ctx-ai { color: var(--accent); font-weight: 600; }
#ctx-menu li.ctx-ai:hover { background: var(--accent-weak); }
#ctx-menu li.ctx-source { color: #24549a; font-weight: 600; }
#ctx-menu li.ctx-source:hover { background: #e8f0fe; }
#ctx-menu li.danger { color: #b3261e; }
#ctx-menu li.danger:hover { color: #8c1d18; background: #fce8e6; }
#ctx-menu li.paste-palette {
  display: block;
  padding: 3px 5px 4px;
  cursor: default;
}
#ctx-menu li.paste-palette:hover { background: transparent; }
#ctx-menu .paste-palette-title {
  display: block;
  padding: 1px 5px 3px;
  color: #9aa5b5;
  font-size: 10px;
  letter-spacing: 1px;
}
#ctx-menu .paste-palette-actions {
  display: flex;
  gap: 4px;
}
#ctx-menu .paste-palette-actions button {
  flex: 1;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--ink);
  height: 28px;
  padding: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
#ctx-menu .paste-palette-actions button:hover,
#ctx-menu .paste-palette-actions button:focus-visible {
  background: var(--accent-weak);
  border-color: var(--accent);
  outline: none;
}
#ctx-menu .paste-palette-actions b {
  font-size: 16px;
  line-height: 1;
  font-weight: 500;
}

/* ---- 网页转文档导入向导（与页面设置同一套极简视觉）---- */
#htmlimport-dialog {
  position: fixed;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 96;
  width: 400px;
  max-width: calc(100vw - 32px);
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 16px 48px rgba(0,0,0,.28);
  font: 12.5px/1.5 "Segoe UI", "Microsoft YaHei", sans-serif;
  color: var(--ink);
}
#htmlimport-dialog.hidden { display: none; }
#htmlimport-dialog header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 36px;
  padding: 0 6px 0 14px;
  font-weight: 600;
  background: #f4f5f7;
  border-bottom: 1px solid #e1e4e9;
}
#htmlimport-dialog header .hi-close {
  width: 28px; height: 24px; border: 0; border-radius: 3px;
  background: transparent; color: #5a6270; cursor: pointer;
}
#htmlimport-dialog header .hi-close:hover { background: #e3e6ea; }
#htmlimport-dialog .hi-body { padding: 12px 14px 14px; }
#htmlimport-dialog .hi-info { margin: 0 0 8px; }
#htmlimport-dialog .hi-size {
  display: flex; align-items: center; gap: 6px;
  margin-bottom: 12px; color: #4a5568;
}
#htmlimport-dialog .hi-size input {
  width: 76px; height: 24px; padding: 0 6px;
  border: 1px solid #d7dce4; border-radius: 3px; font: inherit;
}
#htmlimport-dialog .hi-mode {
  display: block;
  width: 100%;
  margin-bottom: 8px;
  padding: 9px 12px;
  border: 1px solid #d7dce4;
  border-radius: 5px;
  background: #fff;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
#htmlimport-dialog .hi-mode:hover { border-color: var(--accent); background: #f3f7fd; }
#htmlimport-dialog .hi-mode b { display: block; margin-bottom: 2px; }
#htmlimport-dialog .hi-mode span { color: #6b7480; font-size: 11.5px; }

/* 段落对话框单位下拉（pt/px/cm/mm/in） */
#para-dialog .pd-unit-sel {
  height: 32px;
  margin-left: 0;
  border: 1px solid #8f98a5;
  border-left: 0;
  border-radius: 0;
  background: #fff;
  font: inherit;
  color: inherit;
}

/* 导出中心：零散导出按钮隐藏（DOM 保留供回归/快捷键），统一走「⬇ 导出」 */
#ribbon .export-legacy { display: none !important; }
#export-dialog {
  position: fixed;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 96;
  width: 420px;
  max-width: calc(100vw - 32px);
  background: #fff;
  border: 1px solid var(--line);
  box-shadow: 0 16px 48px rgba(0,0,0,.28);
  font: 12.5px/1.5 "Segoe UI", "Microsoft YaHei", sans-serif;
  color: var(--ink);
}
#export-dialog.hidden { display: none; }
#export-dialog header {
  display: flex; justify-content: space-between; align-items: center;
  height: 36px; padding: 0 6px 0 14px; font-weight: 600;
  background: #f4f5f7; border-bottom: 1px solid #e1e4e9;
}
#export-dialog .hi-close {
  width: 28px; height: 24px; border: 0; border-radius: 3px;
  background: transparent; color: #5a6270; cursor: pointer;
}
#export-dialog .hi-close:hover { background: #e3e6ea; }
#export-dialog .hi-body { padding: 12px 14px 14px; }
#export-dialog .hi-namerow {
  display: flex; align-items: center; gap: 8px; margin-bottom: 10px;
  padding-bottom: 10px; border-bottom: 1px solid #eef0f3; font-size: 12.5px; color: #55606f;
}
#export-dialog .hi-name {
  flex: 1; border: 1px solid #cfd6e0; border-radius: 5px; padding: 5px 8px; font: inherit;
}
#export-dialog .hi-name:focus { outline: none; border-color: var(--accent); }
#export-dialog .hi-namehint { color: #98a1ae; font-size: 11px; white-space: nowrap; }
#export-dialog .hi-mode {
  display: block; width: 100%; margin-bottom: 8px; padding: 9px 12px;
  border: 1px solid #d7dce4; border-radius: 5px; background: #fff;
  font: inherit; text-align: left; cursor: pointer;
}
#export-dialog .hi-mode:hover { border-color: var(--accent); background: #f3f7fd; }
#export-dialog .hi-mode b { display: block; margin-bottom: 2px; }
#export-dialog .hi-mode span { color: #6b7480; font-size: 11.5px; }

/* ================= 插入目录（TOC 块 + 插入对话框） ================= */
/* 插入对话框：复用导出对话框外观 */
#toc-insert-dialog {
  position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
  z-index: 96; width: 480px; max-width: calc(100vw - 32px);
  background: #fff; border: 1px solid #b8bfc9; border-radius: 6px;
  box-shadow: 0 12px 40px rgba(15, 25, 40, .22);
  font: 12.5px/1.5 "Segoe UI", "Microsoft YaHei", sans-serif; color: #1f2429;
}
#toc-insert-dialog.hidden { display: none; }
#toc-insert-dialog header {
  display: flex; justify-content: space-between; align-items: center;
  height: 36px; padding: 0 6px 0 14px; font-weight: 600;
  background: #f4f5f7; border-bottom: 1px solid #e1e4e9;
}
#toc-insert-dialog .hi-close {
  width: 28px; height: 24px; border: 0; border-radius: 3px;
  background: transparent; color: #5a6270; cursor: pointer;
}
#toc-insert-dialog .hi-close:hover { background: #e3e6ea; }
#toc-insert-dialog .hi-body { padding: 12px 14px 14px; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
#toc-insert-dialog .hi-mode {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 9px 12px;
  border: 1px solid #d7dce4; border-radius: 5px; background: #fff; font: inherit;
  text-align: left; cursor: pointer;
}
#toc-insert-dialog .hi-mode:hover { border-color: var(--accent); background: #f3f7fd; }
#toc-insert-dialog .hi-mode b { display: block; }
#toc-insert-dialog .toc-mini { display: inline-flex; flex-direction: column; gap: 2px; width: 34px; flex: none; }
#toc-insert-dialog .toc-mini i { height: 3px; border-radius: 1px; background: #c7cfda; }
#toc-insert-dialog .toc-mini i:nth-child(1) { width: 100%; }
#toc-insert-dialog .toc-mini i:nth-child(2) { width: 78%; }
#toc-insert-dialog .toc-mini i:nth-child(3) { width: 60%; }
#toc-insert-dialog .toc-mini[data-toc-style="modern"] i { background: var(--accent); }
#toc-insert-dialog .toc-mini[data-toc-style="formal"] i { background: #444; }

/* ---- 正文内的目录块（多预设 + data-style 自定义） ----
 * 预设/基础选择器均用 :where() 降为零特性，让用户自定义 CSS（@scope 注入、
 * 同特性但 DOM 靠后）总能覆盖；预设之间仍按源序区分。 */
:where(.udoc-toc) { margin: 1em 0; padding: 16px 20px; font-size: 14px; line-height: 2; color: var(--ink); }
:where(.udoc-toc) .toc-title { font-size: 16px; font-weight: 700; margin-bottom: 10px; padding-bottom: 6px; border-bottom: 2px solid var(--accent); color: var(--ink); }
:where(.udoc-toc) .toc-empty { color: var(--ink-2); font-size: 12.5px; }
:where(.udoc-toc) .toc-entry { display: flex; align-items: baseline; gap: 6px; text-decoration: none; color: inherit; cursor: default; padding: 2px 6px; border-radius: 4px; transition: background .12s; }
body.ctrl-down :where(.udoc-toc) .toc-entry { cursor: pointer; }
:where(.udoc-toc) .toc-entry:hover { background: var(--hover); }
:where(.udoc-toc) .toc-entry:hover .toc-t { color: var(--accent); }
:where(.udoc-toc) .toc-t { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 0 1 auto; }
:where(.udoc-toc) .toc-dots { flex: 1 1 auto; border-bottom: 1px dotted #c8c6c4; transform: translateY(-3px); min-width: 16px; }
:where(.udoc-toc) .toc-p { flex: none; color: var(--ink-2); font-variant-numeric: tabular-nums; }
:where(.udoc-toc) .toc-l2 { margin-left: 1.6em; }
:where(.udoc-toc) .toc-l3 { margin-left: 3.2em; }
:where(.udoc-toc) .toc-l4 { margin-left: 4.8em; }
:where(.udoc-toc) .toc-l5 { margin-left: 6.4em; }
:where(.udoc-toc) .toc-l6 { margin-left: 8em; }
:where(.udoc-toc[data-toc-style="classic"]) { background: #faf9f8; border: 1px solid var(--line-soft); }
:where(.udoc-toc[data-toc-style="classic"]) .toc-l1 .toc-t { font-weight: 600; }
:where(.udoc-toc[data-toc-style="formal"]) { border-top: 2px solid #444; border-bottom: 2px solid #444; padding: 16px 4px; }
:where(.udoc-toc[data-toc-style="formal"]) .toc-title { text-align: center; letter-spacing: 4px; }
:where(.udoc-toc[data-toc-style="formal"]) .toc-entry { border-bottom: 1px solid #ececec; padding: 4px 0; }
:where(.udoc-toc[data-toc-style="formal"]) .toc-dots { border-bottom: none; }
:where(.udoc-toc[data-toc-style="modern"]) { background: linear-gradient(180deg, #f5f8ff, #fff); border-left: 4px solid var(--accent); }
:where(.udoc-toc[data-toc-style="modern"]) .toc-title { color: var(--accent); }
:where(.udoc-toc[data-toc-style="modern"]) .toc-l1 .toc-t { font-weight: 700; }
:where(.udoc-toc[data-toc-style="modern"]) .toc-dots { border-bottom-color: #cddaf3; }
:where(.udoc-toc[data-toc-style="simple"]) .toc-dots, :where(.udoc-toc[data-toc-style="simple"]) .toc-p { display: none; }
:where(.udoc-toc[data-toc-style="lines"]) .toc-dots { border-bottom: 1px solid #d0d7e2; }
:where(.udoc-toc[data-toc-style="lines"]) .toc-entry { padding: 3px 0; }
:where(.udoc-toc[data-toc-style="minimal"]) { padding: 6px 0; }
:where(.udoc-toc[data-toc-style="minimal"]) .toc-title { font-size: 15px; font-weight: 600; color: #6b7480; }
:where(.udoc-toc[data-toc-style="minimal"]) .toc-dots, :where(.udoc-toc[data-toc-style="minimal"]) .toc-p { display: none; }
:where(.udoc-toc[data-toc-style="word-standard"]) {
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: #000;
  font-family: "宋体", SimSun, serif;
  font-size: 12pt;
  line-height: 1.55;
}
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-title {
  margin: 0 0 20pt;
  padding: 0;
  border: 0;
  color: #000;
  text-align: center;
  font-family: "黑体", SimHei, sans-serif;
  font-size: 16pt;
  font-weight: 700;
  letter-spacing: .65em;
  text-indent: .65em;
}
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-entry {
  min-height: 1.55em;
  gap: .35em;
  padding: 0;
  border: 0;
  border-radius: 0;
  color: #000;
  background: transparent;
}
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-entry:hover {
  background: transparent;
}
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-entry:hover .toc-t {
  color: #000;
}
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-t {
  overflow: visible;
  text-overflow: clip;
  white-space: nowrap;
}
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-dots {
  border-bottom: 1px dotted #000;
  transform: translateY(-.28em);
}
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-p { color: #000; }
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-l1 { margin-left: 0; }
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-l2 { margin-left: 2em; }
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-l3 { margin-left: 4em; }
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-l4 { margin-left: 6em; }
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-l5 { margin-left: 8em; }
:where(.udoc-toc[data-toc-style="word-standard"]) .toc-l6 { margin-left: 10em; }
body:not(.udoc-export) .udoc-toc { outline: 1px dashed transparent; }
body:not(.udoc-export) .udoc-toc:hover { outline-color: #c7cfda; }

/* ---- 极简输入对话框（替代原生 prompt）---- */
#ui-prompt {
  position: fixed;
  inset: 0;
  z-index: 97;
  background: rgba(15, 25, 40, .18);
  display: flex;
  align-items: center;
  justify-content: center;
}
#ui-prompt.hidden { display: none; }
#ui-prompt .up-box {
  width: 380px;
  max-width: calc(100vw - 32px);
  background: #fff;
  border: 1px solid #b8bfc9;
  border-radius: 6px;
  box-shadow: 0 12px 40px rgba(15, 25, 40, .22);
  font: 12.5px/1.5 "Segoe UI", "Microsoft YaHei", sans-serif;
  color: #1f2429;
}
#ui-prompt header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 36px;
  padding: 0 6px 0 14px;
  font-weight: 600;
  background: #f4f5f7;
  border-bottom: 1px solid #e1e4e9;
}
#ui-prompt .up-close {
  width: 28px; height: 24px; border: 0; border-radius: 3px;
  background: transparent; color: #5a6270; cursor: pointer;
}
#ui-prompt .up-close:hover { background: #e3e6ea; }
#ui-prompt .up-body { padding: 12px 14px 14px; }
#ui-prompt .up-hint { margin: 0 0 8px; color: #6b7480; font-size: 11.5px; }
#ui-prompt .up-input {
  width: 100%;
  height: 28px;
  padding: 0 8px;
  border: 1px solid #d7dce4;
  border-radius: 4px;
  font: inherit;
  box-sizing: border-box;
}
#ui-prompt .up-input:focus { outline: none; border-color: var(--accent); }
#ui-prompt .up-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 12px;
}
#ui-prompt .up-actions button {
  height: 26px;
  padding: 0 14px;
  border: 1px solid #d0d5dd;
  border-radius: 4px;
  background: #fff;
  font: inherit;
  cursor: pointer;
}
#ui-prompt .up-ok {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
  color: #fff;
}
#ui-prompt .up-actions button:hover { filter: brightness(.96); }

/* ---- 沙箱网页加载态：圆圈两侧各一漏点旋转 ---- */
.html-embed { position: relative; }
.html-embed .he-loading {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: #f7f8fa;
  color: #6b7480;
  font: 12px/1.5 "Segoe UI", "Microsoft YaHei", sans-serif;
}
.html-embed .he-spin {
  position: relative;
  width: 44px;
  height: 44px;
  animation: he-spin-rot 1.15s linear infinite;
}
.html-embed .he-spin::before {
  content: '';
  position: absolute;
  inset: 9px;
  border: 3px solid #d9dee6;
  border-radius: 50%;
}
.html-embed .he-spin i {
  position: absolute;
  top: 50%;
  width: 9px;
  height: 9px;
  margin-top: -4.5px;
  background: var(--accent);
  border-radius: 50% 50% 50% 0;   /* 漏点（水滴）形 */
}
.html-embed .he-spin i:first-child { left: -3px; transform: rotate(-45deg); }
.html-embed .he-spin i:last-child { right: -3px; transform: rotate(135deg); }
@keyframes he-spin-rot { to { transform: rotate(360deg); } }
.html-embed .he-loading-blocked { gap: 8px; }
.html-embed .he-blocked { color: #8a5a00; }
.html-embed .he-blocked-actions { display: flex; gap: 8px; }
.html-embed .he-blocked-actions button {
  height: 26px;
  padding: 0 12px;
  border: 1px solid #d0d5dd;
  border-radius: 4px;
  background: #fff;
  font: 12px "Segoe UI", "Microsoft YaHei", sans-serif;
  cursor: pointer;
}
.html-embed .he-blocked-actions button:hover { border-color: var(--accent); color: var(--accent); }

/* ---- 打印 / 导出 PDF ----
 * 参考 OmniDoc generate_bg_translated.py 的 @media print 方案：
 * 隐藏全部界面 chrome，每个 .page 独占一张纸，尺寸与 @page 对齐，
 * 去阴影去缩放，break-after: page 强制分页。
 */
@page {
  size: A4;
  margin: 0;
}
@media print {
  html, body {
    background: #fff !important;
    margin: 0 !important; padding: 0 !important;
    display: block !important; overflow: visible !important;
    height: auto !important;
  }
  #ribbon, #statusbar, #zdoc-panel, #ctx-menu, #formula-editor { display: none !important; }
  #canvas {
    overflow: visible !important;
    padding: 0 !important;
    height: auto !important;
  }
  #pages-sizer {
    position: static !important;
    width: auto !important;
    height: auto !important;
    margin: 0 !important;
  }
  #pages {
    display: block !important;
    position: static !important;
    width: auto !important;
    height: auto !important;
    transform: none !important;      /* 屏幕缩放不带入打印 */
    gap: 0 !important;
  }
  .page {
    /* 恢复文档流逐页分纸；必须是 relative 而非 static ——
       .page-content 是 absolute 定位，static 会让它失去包含块，
       全部页内容叠到打印纸原点（打印全乱的根因） */
    position: relative !important;
    top: auto !important;
    left: auto !important;   /* 分节窄页的屏幕居中偏移不带入命名纸张 */
    margin: 0 !important;
    box-shadow: none !important;
    border: none !important;
    overflow: hidden !important;
    content-visibility: visible !important;
    break-inside: avoid !important;
    page-break-inside: avoid !important;
    break-after: page !important;
    page-break-after: always !important;
  }
  .page:last-child {
    break-after: auto !important;
    page-break-after: auto !important;
  }
  /* ---- 分栏打印：.print-sheet 大页面拼栏（beforeprint 动态包裹）----
   * 外层 grid 把同一逻辑页的各栏容器横向拼回一张整纸，分纸只发生
   * 在 sheet 层；栏容器自身退化成 grid 格子，不再独立分纸。 */
  .print-sheet {
    position: relative !important;
    display: grid !important;
    grid-template-columns: var(--sheet-cols) !important;
    width: var(--sheet-w) !important;
    height: var(--sheet-h) !important;
    background: #fff;
    overflow: hidden !important;
    break-inside: avoid !important;
    page-break-inside: avoid !important;
    break-after: page !important;
    page-break-after: always !important;
  }
  .print-sheet:last-child {
    break-after: auto !important;
    page-break-after: auto !important;
  }
  .print-sheet .page {
    break-after: auto !important;
    page-break-after: auto !important;
    /* 首栏的页眉页脚横跨整张纸，不能被栏容器剪掉；剪裁交给 sheet */
    overflow: visible !important;
  }
  .print-sheet .page.col-first::before { box-shadow: none !important; }
  .page-content {
    overflow: clip !important;
    overflow-clip-margin: 8px !important;
  }
  /* 屏幕专用元素不上纸 */
  .latex-src:hover { background: transparent !important; outline: none !important; }
  body.show-marks .page-content .para-mark { display: none !important; }
    body.show-marks .page-content :is(.dyn-block, .attachment-block, .video-block, .html-embed)::after { display: none !important; }
}

/* ---- 状态栏 ---- */
#statusbar {
  background: var(--accent);
  color: #fff;
  font-size: 12px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 3px 14px;
  flex-shrink: 0;
  user-select: none;
}
#statusbar .st-sep { opacity: .4; }
#statusbar .st-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }
#statusbar input[type="range"] { vertical-align: middle; width: 110px; }

/* ---- 自定义缩放滑杆（渐变手柄 + 细轨道 + 数值气泡） ---- */
#zoom-slider {
  position: relative;
  display: inline-block;
  width: 120px; height: 18px;
  cursor: pointer;
  touch-action: none;
  user-select: none;
}
#zoom-track {
  position: absolute; left: 0; right: 0; top: 7px; height: 4px;
  border-radius: 2px;
  background: rgba(255,255,255,.28);
}
#zoom-fill {
  position: absolute; left: 0; top: 0; bottom: 0; width: 33%;
  border-radius: 2px;
  background: rgba(255,255,255,.75);
}
#zoom-handle {
  position: absolute; top: 1px; left: 33%; width: 16px; height: 16px;
  margin-left: -8px;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.4);
  cursor: grab;
}
#zoom-handle:active { cursor: grabbing; }
#zoom-bubble {
  position: absolute; left: 50%; bottom: 22px; transform: translateX(-50%);
  background: #fff;
  color: var(--ink);
  font: 700 11px Consolas, Menlo, monospace;
  padding: 3px 8px;
  white-space: nowrap;
  box-shadow: 0 2px 8px rgba(0,0,0,.3);
  opacity: 0;
  transition: opacity .2s;
  pointer-events: none;
}
#zoom-slider:hover #zoom-bubble,
#zoom-slider.dragging #zoom-bubble { opacity: 1; }
#zoom-val { cursor: pointer; min-width: 38px; display: inline-block; }
#statusbar button {
  background: transparent;
  border: 1px solid transparent;
  color: #fff;
  padding: 2px 10px;
  font-size: 12px;
  cursor: pointer;
}
#statusbar button:hover { background: rgba(255,255,255,.15); }

/* ================= Word 式对象布局（环绕 / 浮动 / 拖拽 / 八向缩放） =================
 * 七种布局：嵌入型(inline) / 四周型(square) / 紧密型(tight) / 穿越型(through) /
 * 上下型(topbottom) / 浮于文字上方(front) / 衬于文字下方(behind)。
 * 前五种是流内块（data-wrap 属性驱动，float + shape-outside 实现环绕）；
 * 后两种脱离块流，挂到页家具层（复用 .udoc-textbox 浮动对象模型）。 */

/* 图片独立块（从段内 img 升格出的可布局对象） */
.img-block {
  position: relative;
  margin: 0 0 .6em;
  line-height: 0;                 /* 图片下方不留基线缝隙 */
}
.img-block > img,
.img-block > .wrap-rotation-content > img {
  max-width: 100%; height: auto; display: block;
}

.dyn-block { position: relative; }

/* ---- Unified rich-object shell ----
 * The shell is the only pagination/wrap/selection box.  Images, SVG-backed
 * images, video, dynamic data and sandbox HTML stay in the zero-gap payload
 * and can rotate without escaping the shell's axis-aligned layout bounds. */
.wrap-object-shell {
  position: relative;
  display: block;
  padding: 0;
  border: 0;
  box-sizing: border-box;
  line-height: normal;
}
.wrap-object-shell > .wrap-object-content {
  display: block;
  width: 100%;
  margin: 0;
  box-sizing: border-box;
  float: none !important;
  clear: none !important;
}
/* 附件载荷保留横向卡片 Grid；统一外壳的通用 block 规则不能把它降级成纵向流。
 * 宽度由外壳拥有，保证嵌入型把整张卡片当作一个随文字移动的原子字符。 */
.wrap-object-shell[data-wrap-kind="attachment"] {
  width: min(100%, 560px);
}
.wrap-object-shell[data-wrap-kind="attachment"] > .wrap-object-content.attachment-block {
  display: grid;
  width: 100%;
}
.wrap-object-shell[data-wrap-kind="image"] { margin: 0 0 .6em; line-height: 0; }
.page-content [data-anchored="1"].wrap-object-shell[data-wrap-kind="image"] {
  margin-bottom: 0;
}

/* ---- 段内锚定对象（Word <wp:anchor>）----
 * 外壳是 <span>（只有行内元素能安全地活在 <p> 里，见 app.js 锚定小节），
 * 这里把它还原成盒模型：不环绕时是行内块（真·嵌入型，跟着文字走），
 * 一旦有 data-wrap 就是块盒，float / shape-outside 照常生效。 */
.page-content [data-anchored="1"] {
  display: inline-block;
  vertical-align: text-bottom;
  max-width: 100%;
}
.page-content [data-anchored="1"][data-wrap] { display: block; }
.page-content [data-anchored="1"].img-block { margin-bottom: 0; }
/* 锚点提示：选中锚定对象时，在宿主段落一侧点一个 Word 式船锚 */
#wrap-anchor-mark {
  position: fixed;
  width: 16px; height: 16px;
  margin-left: -20px;
  font-size: 13px;
  line-height: 16px;
  color: var(--accent);
  opacity: .75;
  pointer-events: none;
  z-index: 61;
  display: none;
}

/* ---- 环绕布局（float 系）----
 * 四周型按矩形外框排斥文字；紧密/穿越优先使用 JS 注入的图片透明轮廓，
 * 非图片对象退回圆角轮廓。--wrap-gap-* 由「布局选项」实时控制。 */
.page-content :is(.wrap-object-shell, .dyn-block, .attachment-block, .video-block, .html-embed, .img-block)[data-wrap="square"],
.page-content :is(.wrap-object-shell, .dyn-block, .attachment-block, .video-block, .html-embed, .img-block)[data-wrap="tight"],
.page-content :is(.wrap-object-shell, .dyn-block, .attachment-block, .video-block, .html-embed, .img-block)[data-wrap="through"] {
  float: left;
  clear: none;
  position: relative;
  z-index: 2;
  box-sizing: border-box;
  min-width: 80px;
  max-width: calc(100% - 1px);
  margin-block: var(--wrap-gap-y);
  margin-inline: 0 var(--wrap-gap-x);
}
.page-content [data-wrap="square"] {
  --wrap-gap-x: 14px;
  --wrap-gap-y: 6px;
  shape-outside: margin-box;
  shape-margin: 0;
}
.page-content [data-wrap="tight"] {
  --wrap-gap-x: 7px;
  --wrap-gap-y: 3px;
  shape-outside: var(--wrap-shape, inset(0 round 8px));
  shape-image-threshold: .12;
  shape-margin: 0;
}
.page-content [data-wrap="through"] {
  --wrap-gap-x: 2px;
  --wrap-gap-y: 1px;
  shape-outside: var(--wrap-shape, inset(0 round 2px));
  shape-image-threshold: .75;
  shape-margin: 0;
}
.page-content [data-wrap][data-wrap-side="right"] { float: right; }
.page-content :is(.wrap-object-shell, .dyn-block, .attachment-block, .video-block, .html-embed, .img-block)[data-wrap][data-wrap-side="right"] {
  margin-inline: var(--wrap-gap-x) 0;
}

/* ---- 真·两侧环绕（Word 四周型完全体）----
 * float 只能单侧排字；对象停在段中时（data-wrap-dx 存在）改走打洞层：
 * 对象在宿主段内绝对定位，JS 逐行往文字里插零高行内占位（.wrap-hole），
 * 浏览器自然断行就绕出左右两列 —— CSS 没有中缝排斥原语（Exclusions 无实现），
 * 这是浏览器里唯一能达到 Word 行为的路径。 */
.page-content .wrap-channel-host { position: relative; }
.page-content [data-anchored="1"].wrap-channel {
  position: absolute;          /* 绝对定位后 float 自动失效 */
  display: block;
  margin: 0 !important;        /* float 系环距 margin 改由洞带几何承担 */
  z-index: 2;
}
.wrap-hole {
  display: inline-block;
  height: 0;                   /* 零高：占行宽不加行高 */
  pointer-events: none;
  user-select: none;
}

/* 上下型：独占横带，两侧不排文字 */
.page-content [data-wrap="topbottom"] {
  --wrap-gap-y: 10px;
  float: none !important;
  clear: both;
  display: block;
  max-width: 100%;
  margin-top: var(--wrap-gap-y);
  margin-bottom: var(--wrap-gap-y);
  margin-left: auto;
  margin-right: auto;
  shape-outside: none;
}

/* ---- UniPPT selection overlay: dashed frame + eight screen-sized handles ---- */
.wrap-selected { outline: none; }
.wrap-selected iframe { pointer-events: none; }   /* 选中态拖动优先，双击/工具条再交互 */
.wrap-handles {
  position: absolute;
  inset: 0;
  z-index: 8;
  box-sizing: border-box;
  border: calc(1px * var(--selection-ui-scale, 1)) dashed #686868;
  background: transparent;
  pointer-events: none;
  transform-origin: center;
}
.wrap-handles .wh {
  position: absolute;
  z-index: 9;
  width: 10px;
  height: 10px;
  padding: 0;
  background: #fff;
  border: 1.5px solid #686868;
  border-radius: 50%;
  pointer-events: auto;
  touch-action: none;
  transform: translate(-50%, -50%) scale(var(--selection-ui-scale, 1));
  transform-origin: center;
}
.wh-nw { left: 0; top: 0; cursor: nwse-resize; }
.wh-n  { left: 50%; top: 0; cursor: ns-resize; }
.wh-ne { left: 100%; top: 0; cursor: nesw-resize; }
.wh-e  { left: 100%; top: 50%; cursor: ew-resize; }
.wh-se { left: 100%; top: 100%; cursor: nwse-resize; }
.wh-s  { left: 50%; top: 100%; cursor: ns-resize; }
.wh-sw { left: 0; top: 100%; cursor: nesw-resize; }
.wh-w  { left: 0; top: 50%; cursor: ew-resize; }

/* 选中的段内嵌入图片（未升格）：临时包一层定位壳挂手柄 */
.img-inline-shell {
  position: relative;
  display: inline-block;
  line-height: 0;
  /* The wrapper is injected only while an inline image is selected.  It must
     not inherit the host paragraph's first-line indent, otherwise the image
     jumps right by that indent until it is deselected. */
  text-indent: 0;
}
#object-rotate-handle {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 404;
  width: 24px;
  height: 24px;
  padding: 0;
  box-sizing: border-box;
  border: 1.5px solid #686868;
  border-radius: 50%;
  display: none;
  place-items: center;
  color: #555;
  background: #fff;
  box-shadow: 0 1px 2px #0002;
  pointer-events: auto;
  touch-action: none;
  cursor: grab;
  font-size: 18px;
  line-height: 1;
  transform: translate(-50%, -50%);
  transform-origin: center;
}
#object-rotate-handle::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 100%;
  z-index: -1;
  width: 1px;
  height: 31px;
  background: #686868;
  transform: translateX(-50%);
  pointer-events: none;
}
#object-rotate-handle.inside-object::before {
  top: auto;
  bottom: 100%;
}
#object-rotate-handle:active {
  cursor: grabbing;
}
/* Rotation stays in the body overlay so page clipping can never crop it. */
.wrap-handles .wh-rotate,
.wrap-handles .wh-rot,
.udoc-textbox.tbox-obj .tbox-h.wh-rotate,
.udoc-textbox.tbox-obj .tbox-h.wh-rot { display: none !important; }
.page-content :is(.wrap-object-shell, .img-block, .dyn-block, .attachment-block, .video-block, .html-embed, .img-inline-shell).wrap-rotation-frame {
  width: var(--ud-rotation-aabb-w) !important;
  height: var(--ud-rotation-aabb-h) !important;
  min-width: 0 !important;
  min-height: 0 !important;
  max-width: none !important;
  box-sizing: border-box;
  overflow: visible;
  transform: none !important;
}
.page-content .wrap-rotation-frame > :is(.wrap-object-content, .wrap-rotation-content) {
  position: absolute;
  left: var(--ud-rotation-content-left);
  top: var(--ud-rotation-content-top);
  width: var(--ud-rotation-source-w);
  height: var(--ud-rotation-source-h);
  box-sizing: border-box;
  transform: rotate(var(--ud-rotation, 0deg));
  transform-origin: center center;
  overflow: visible;
}
.page-content .wrap-rotation-frame > :is(.wrap-object-content, .wrap-rotation-content) > :is(iframe, video) {
  max-width: none;
}

/* 拖动重排：源块半透明 + 目标插入线；全程四向移动光标（Word 语义） */
.wrap-dragging { opacity: .45; }
body.udoc-obj-dragging, body.udoc-obj-dragging * { cursor: move !important; }
.page-content :is(.wrap-object-shell, .dyn-block, .attachment-block, .video-block, .html-embed, .img-block).wrap-selected { cursor: move; }
#wrap-drop-line {
  position: fixed;
  height: 3px;
  background: var(--accent);
  border-radius: 2px;
  box-shadow: 0 0 6px rgba(43,87,154,.55);
  pointer-events: none;
  z-index: 400;
  display: none;
}
/* 落在文字上：插入线转成字位光标（Word 拖对象进段落时的锚点提示） */
#wrap-drop-line.at-caret {
  height: auto;
  border-radius: 1px;
  animation: udoc-caret-blink .9s steps(2, start) infinite;
}
@keyframes udoc-caret-blink { 50% { opacity: .35; } }
#wrap-drag-ghost {
  position: fixed;
  border: 2px dashed var(--accent);
  border-radius: 4px;
  background: rgba(43,87,154,.08);
  pointer-events: none;
  z-index: 399;
  display: none;
}

/* ---- 布局选项浮动按钮 + 面板（Word「布局选项」弹窗） ---- */
#wrap-fab {
  position: fixed;
  width: 30px; height: 30px;
  border: 1px solid #c4d2ea;
  border-radius: 6px;
  background: #fff;
  color: var(--accent);
  font-size: 15px;
  line-height: 28px;
  text-align: center;
  cursor: pointer;
  box-shadow: 0 2px 10px rgba(0,0,0,.22);
  z-index: 402;
  user-select: none;
}
#wrap-fab:hover { background: #eef4fd; }
#wrap-panel {
  position: fixed;
  width: 286px;
  max-height: calc(100vh - 64px);
  background: #fff;
  border: 1px solid #d0d9e8;
  border-radius: 10px;
  box-shadow: 0 10px 34px rgba(0,0,0,.28);
  z-index: 403;
  font-size: 12px;
  color: #1a2b45;
  user-select: none;
  overflow: auto;
}
#wrap-panel header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 12px;
  font-weight: 700;
  color: var(--accent);
  border-bottom: 1px solid #e7edf7;
}
#wrap-panel header button {
  border: none; background: none; cursor: pointer;
  font-size: 14px; color: #8a97ab;
}
#wrap-panel .wp-sec {
  padding: 6px 12px 2px;
  font-size: 10px;
  color: #8a97ab;
  letter-spacing: 1px;
}
#wrap-panel .wp-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  padding: 4px 12px 8px;
}
#wrap-panel .wp-opt {
  border: 1px solid #dbe4f2;
  border-radius: 6px;
  background: #fff;
  cursor: pointer;
  padding: 4px 0 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  color: #44546c;
}
#wrap-panel .wp-opt:hover { background: #eef4fd; border-color: #b7c9e6; }
#wrap-panel .wp-opt.on {
  background: #e2ecfc;
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 700;
}
#wrap-panel .wp-opt svg { width: 30px; height: 24px; display: block; }
#wrap-panel .wp-opt .wp-name { font-size: 10px; transform: scale(.9); white-space: nowrap; }
#wrap-panel .wp-row {
  display: flex;
  gap: 8px;
  padding: 4px 12px 10px;
}
#wrap-panel .wp-row button {
  flex: 1;
  border: 1px solid #dbe4f2;
  border-radius: 6px;
  background: #fff;
  color: #44546c;
  font-size: 11px;
  padding: 4px 0;
  cursor: pointer;
}
#wrap-panel .wp-row button:hover { background: #eef4fd; }
#wrap-panel .wp-row button.on { background: #e2ecfc; border-color: var(--accent); color: var(--accent); }
#wrap-panel .wp-row button:disabled { opacity: .42; cursor: default; }
#wrap-panel .wp-row button.wp-danger { color: #c0392b; border-color: #ecc; }
#wrap-panel .wp-row button.wp-danger:hover { background: #fdf0ee; }
#wrap-panel .wp-distance {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 10px;
  padding: 4px 12px 9px;
}
#wrap-panel .wp-distance label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  color: #64748b;
  font-size: 11px;
}
#wrap-panel .wp-distance input {
  width: 58px;
  height: 24px;
  border: 1px solid #d5dfed;
  border-radius: 5px;
  padding: 0 5px;
  color: #26364d;
  font-size: 11px;
}
#wrap-panel .wp-dynamic,
#wrap-panel .wp-attachment,
#wrap-panel .wp-embed {
  margin: 0 12px 8px;
  padding: 8px;
  border: 1px solid #e0e8f4;
  border-radius: 7px;
  background: #f8faff;
}
#wrap-panel .wp-dyn-url {
  overflow: hidden;
  margin-bottom: 3px;
  color: #405270;
  font: 10px/1.4 Consolas, monospace;
  text-overflow: ellipsis;
  white-space: nowrap;
}
#wrap-panel .wp-dyn-status {
  min-height: 14px;
  margin-bottom: 6px;
  color: #8a97ab;
  font-size: 10px;
}
#wrap-panel .wp-dyn-actions {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5px;
}
#wrap-panel .wp-dyn-actions button {
  min-width: 0;
  height: 26px;
  border: 1px solid #d5dfed;
  border-radius: 5px;
  background: #fff;
  color: #405270;
  cursor: pointer;
  font-size: 10px;
}
#wrap-panel .wp-dyn-actions button:hover { background: #eaf1fd; border-color: #b7c9e6; }

/* ---- 文本框 / 浮动对象八向手柄（复用 .wh-* 方位定位） ---- */
.udoc-textbox .tbox-h {
  position: absolute;
  width: 11px;
  height: 11px;
  padding: 0;
  background: #fff;
  border: 1.5px solid #1677ff;
  border-radius: 0;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .9);
  pointer-events: auto;
  touch-action: none;
  transform: translate(-50%, -50%) scale(var(--selection-ui-scale, 1));
  transform-origin: center;
  opacity: 0;
  z-index: 6;
}
.udoc-textbox.tbox-selected .tbox-h { opacity: 1; }
.udoc-textbox.tbox-selected {
  outline: none;
}
.udoc-textbox.tbox-selected::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 5;
  box-sizing: border-box;
  border: calc(1.5px * var(--selection-ui-scale, 1)) solid #1677ff;
  background: rgba(22, 119, 255, .035);
  box-shadow: 0 0 0 calc(1px * var(--selection-ui-scale, 1)) rgba(255, 255, 255, .7);
  pointer-events: none;
}
.udoc-textbox.tbox-obj.tbox-selected {
  border-color: transparent;
  box-shadow: none;
}
/* The legacy corner grip is replaced by UniPPT's eighth circular handle. */
.udoc-textbox .tbox-resize { display: none !important; }
@media print { .udoc-textbox .tbox-h { display: none !important; } }

/* 按住 Ctrl：隐去 8 个缩放点与右下角 grip；光标落在文本框范围内即变「四向移动」
 * 光标（拖拽移动），无需固定图标。重叠时最上层文本框接管光标与拖拽（DOM 堆叠决定）。 */
body.tbox-ctrl-move .udoc-textbox .tbox-h,
body.tbox-ctrl-move .udoc-textbox .tbox-resize { display: none !important; }
body.tbox-ctrl-move .udoc-textbox,
body.tbox-ctrl-move .udoc-textbox .tbox-content,
body.tbox-ctrl-move .udoc-textbox .tbox-content * { cursor: move !important; }
/* Ctrl 态：浮动对象（图片/数据/音视频/沙盒 HTML/动态）内的 iframe/视频/媒体不吃指针，
 * 事件落到外壳 → 与文本框一致的四箭头整体拖拽（否则 iframe/视频会拦截拖拽与光标）。 */
body.tbox-ctrl-move .udoc-textbox.tbox-obj iframe,
body.tbox-ctrl-move .udoc-textbox.tbox-obj video,
body.tbox-ctrl-move .udoc-textbox.tbox-obj img,
body.tbox-ctrl-move .udoc-textbox.tbox-obj .tbox-content * { pointer-events: none !important; }
body.tbox-ctrl-move .udoc-textbox.tbox-obj { cursor: move !important; }

/* ---- 浮动对象（浮于文字上方 / 衬于文字下方；复用文本框浮层） ---- */
/* 衬底对象选中态临时抬升到正文之上：否则选中后拖拽/手柄仍被正文层拦截（拖不动根源） */
.udoc-textbox.tbox-behind.tbox-selected { z-index: 7 !important; }
.udoc-textbox.tbox-behind { z-index: 0; }
.udoc-textbox.tbox-obj { background: transparent; padding: 0; overflow: visible; }
.udoc-textbox.tbox-obj .tbox-content {
  padding: 0;
  height: 100%;
  overflow: hidden;
  cursor: default;
}
.udoc-textbox.tbox-obj.tbox-rotation-frame .tbox-content {
  position: absolute;
  left: var(--tbox-content-left, 0px);
  top: var(--tbox-content-top, 0px);
  width: var(--tbox-source-w, 100%);
  height: var(--tbox-source-h, 100%);
  box-sizing: border-box;
  transform: rotate(var(--tbox-rotation, 0deg));
  transform-origin: center center;
}
.udoc-textbox.tbox-obj .tbox-content > * { margin: 0; height: 100%; }
.udoc-textbox.tbox-obj .tbox-content .attachment-block {
  width: 100%;
  min-height: 100%;
  border-radius: 0;
}
.udoc-textbox.tbox-obj .tbox-content img {
  width: 100%; height: 100%;
  object-fit: contain;
  display: block;
}
.udoc-textbox.tbox-obj .tbox-content video { width: 100%; height: 100%; object-fit: contain; }
.udoc-textbox.tbox-obj .tbox-content iframe { width: 100%; height: 100%; border: none; }
/* 选中态：沙箱 iframe 暂停吃指针，块体任意处可拖动；取消选中即恢复交互 */
.udoc-textbox.tbox-obj.tbox-selected .tbox-content iframe { pointer-events: none; }
.udoc-textbox.tbox-obj .tbox-content .html-embed iframe { height: calc(100% - 0px); }
.udoc-textbox.tbox-obj:not(.tbox-selected):not(:hover) { box-shadow: none; border-color: transparent; }
@media print {
  .wrap-handles, #object-rotate-handle, #wrap-fab, #wrap-panel,
  #wrap-drop-line, #wrap-drag-ghost { display: none !important; }
  .wrap-selected { outline: none !important; }
}
body.presenting #object-rotate-handle,
body.presenting #wrap-fab,
body.presenting #wrap-panel { display: none !important; }
