/*!
 * sneditor.css — 零依赖极简富文本编辑器样式 v1.0.0
 * ------------------------------------------------------------------
 * 全部类名以 .sne 前缀命名；内容区样式通过 .sne-content 作用域隔离，
 * 不会污染宿主页面，也不会被宿主页面的 p/h/ul 全局样式反向污染。
 *
 * 结构分区：
 *   1. 设计令牌（Design Tokens）
 *   2. 外壳 / 工具栏 / 按钮
 *   3. 内容区（含作用域 reset）
 *   4. 状态栏 / 占位符
 *   5. 弹出面板（下拉 / 颜色 / 表格网格 / 表单）
 *   6. 模态框（预览）
 *   7. 媒体节点 / 表格 / 代码块 / 附件
 *   8. 上传进度 / 提示
 *   9. AI 面板
 *  10. 深色主题
 *  11. 全屏 / 只读 / 响应式
 * ------------------------------------------------------------------
 */

/* ==================================================================
 * 1. 设计令牌
 * ================================================================== */
/* 设计令牌的作用域要同时覆盖三类节点：
 *   1) .sne          —— 编辑器本体
 *   2) .sne-layer    —— 浮层（预览框 / 地图弹窗…），由 registerLayer() 打标，
 *                       它们被挂在 document.body 上，不在 .sne 内部
 *   3) .sne--light / [data-theme="light"]
 *                      —— 经典白是「基准主题」，变量原本只声明在 .sne 上；
 *                        浮层拿不到 → var(--sne-bg) 解析失败 → 弹窗整片透明。
 * 把三者并在同一条规则里，light 主题的浮层才能继承到同一组变量。
 * 深色/其它主题由后面 10.x 节覆盖（同权重、位置更靠后 → 生效）。 */
.sne,
.sne-layer,
.sne--light,
.sne[data-theme="light"] {
  /* 尺寸 */
  --sne-radius: 12px;
  --sne-radius-sm: 8px;
  --sne-radius-xs: 6px;
  --sne-btn: 30px;
  --sne-space: 8px;
  --sne-font: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
             "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
  --sne-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --sne-z: 2000;

  /* 颜色 */
  --sne-bg: #ffffff;
  --sne-bg-soft: #fafbfc;
  --sne-bg-hover: #f4f5f7;
  --sne-bg-active: #eef2ff;
  --sne-border: #e7e9ee;
  --sne-border-soft: #f0f1f4;
  --sne-text: #1f2329;
  --sne-text-sub: #5c6370;
  --sne-text-muted: #8b909a;
  --sne-text-faint: #b3b8c2;
  --sne-primary: #2563eb;
  --sne-primary-soft: #eff4ff;
  --sne-danger: #e11d48;
  --sne-warning: #d97706;

  --sne-shadow-sm: 0 1px 2px rgba(16, 24, 40, .04);
  --sne-shadow: 0 8px 24px -6px rgba(16, 24, 40, .12), 0 2px 6px rgba(16, 24, 40, .06);
  --sne-shadow-lg: 0 24px 60px -12px rgba(16, 24, 40, .22);
}

/* 编辑器本体的布局（浮层不需要铺这些，单独一条，避免污染 .sne-layer） */
.sne {
  position: relative;
  display: flex;
  flex-direction: column;
  font-family: var(--sne-font);
  font-size: 14px;
  line-height: 1.6;
  color: var(--sne-text);
  background: var(--sne-bg);
  border: 1px solid var(--sne-border);
  border-radius: var(--sne-radius);
  box-shadow: var(--sne-shadow-sm);
  transition: border-color .18s ease, box-shadow .18s ease;
  -webkit-font-smoothing: antialiased;
}

/* 浮层基础：字体与正文色跟随主题（此前浮层只能靠各自规则零散设置） */
.sne-layer {
  font-family: var(--sne-font);
  font-size: 14px;
  line-height: 1.6;
  color: var(--sne-text);
}
.sne.is-focused {
  border-color: #cfd6e4;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, .08), var(--sne-shadow-sm);
}
.sne *, .sne *::before, .sne *::after { box-sizing: border-box; }

/* ==================================================================
 * 2. 工具栏
 * ================================================================== */
.sne-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 7px 8px;
  background: var(--sne-bg);
  border-bottom: 1px solid var(--sne-border-soft);
  border-radius: var(--sne-radius) var(--sne-radius) 0 0;
  user-select: none;
}
.sne-toolbar--sticky {
  position: sticky;
  top: 0;
  z-index: 2;
}
.sne-group { display: flex; align-items: center; gap: 2px; }
.sne-sep {
  width: 1px;
  height: 18px;
  margin: 0 3px;
  background: var(--sne-border);
  flex: none;
}

.sne-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--sne-btn);
  height: var(--sne-btn);
  padding: 0;
  border: 0;
  border-radius: var(--sne-radius-xs);
  background: transparent;
  color: var(--sne-text-sub);
  cursor: pointer;
  transition: background .15s ease, color .15s ease, transform .1s ease;
  -webkit-tap-highlight-color: transparent;
}
.sne-btn:hover { background: var(--sne-bg-hover); color: var(--sne-text); }
.sne-btn:active { transform: scale(.94); }
.sne-btn.is-active,
.sne-btn.is-open { background: var(--sne-bg-active); color: var(--sne-primary); }
.sne-btn:disabled { opacity: .34; cursor: not-allowed; }
.sne-btn:disabled:hover { background: transparent; }
.sne-btn:focus-visible { outline: 2px solid var(--sne-primary); outline-offset: 1px; }
.sne-btn--icon { width: 30px; height: 30px; }
/* 文字按钮（MD / 高德 / 百度 / {}…）：宽度自适应，别把两个字挤在 30px 里 */
.sne-btn--text { width: auto; min-width: var(--sne-btn); padding: 0 8px; }

/* ------------------------------------------------------------------
 * 图标基样式：iconHtml() 产出的 <svg> 都带 .sne-ico
 * 没有这条时，只有 viewBox 的 svg 在「没被更具体的容器规则覆盖」的地方会退化：
 * 尺寸变成默认 300×150、路径默认 fill:黑 stroke:none → 纯描边图标直接看不见。
 * 放在这里是为了让 .sne-btn / .sne-code-tool / .sne-map-ph 等更具体的规则
 * （都在后面）按源码顺序继续覆盖尺寸。
 * ------------------------------------------------------------------ */
svg.sne-ico {
  width: 17px; height: 17px; display: block; flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
svg.sne-ico [fill="currentColor"] { fill: currentColor; }
svg.sne-ico [fill="currentColor"][stroke="none"] { stroke: none; }

.sne-btn svg { width: 17px; height: 17px; display: block; }
.sne-btn svg [fill="currentColor"] { fill: currentColor; }
.sne-btn svg path, .sne-btn svg rect, .sne-btn svg circle {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.sne-btn svg [fill="currentColor"][stroke="none"] { stroke: none; }
.sne-ico-text {
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.02em;
  font-family: var(--sne-font);
}

/* ==================================================================
 * 3. 内容区
 * ================================================================== */
.sne-body { position: relative; display: flex; flex: 1 1 auto; min-height: 0; overflow: hidden; }

.sne-content {
  flex: 1 1 auto;
  padding: 18px 20px;
  overflow-y: auto;
  overflow-x: hidden;
  outline: none;
  word-break: break-word;
  overflow-wrap: anywhere;
  font-size: 15px;
  line-height: 1.78;
  color: var(--sne-text);
  background: var(--sne-bg);
  min-height: 100%;
}
.sne-content:empty::before { content: ""; }

/* ---- 作用域 reset：不被宿主页面样式污染 ---- */
.sne-content > *:first-child { margin-top: 0 !important; }
.sne-content > *:last-child { margin-bottom: 0 !important; }
.sne-content p { margin: 0 0 12px; }
.sne-content div { line-height: inherit; }
.sne-content h1 { font-size: 24px; font-weight: 650; line-height: 1.35; margin: 22px 0 12px; }
.sne-content h2 { font-size: 20px; font-weight: 650; line-height: 1.4; margin: 20px 0 10px; }
.sne-content h3 { font-size: 17px; font-weight: 650; line-height: 1.45; margin: 18px 0 8px; }
.sne-content h4 { font-size: 15.5px; font-weight: 650; margin: 16px 0 8px; }
.sne-content h5 { font-size: 15px; font-weight: 650; margin: 14px 0 6px; }
.sne-content h6 {
  font-size: 13px; font-weight: 650; margin: 14px 0 6px;
  color: var(--sne-text-sub); text-transform: uppercase; letter-spacing: .04em;
}
.sne-content ul, .sne-content ol { margin: 0 0 12px; padding-left: 26px; }
.sne-content ul { list-style: disc; }
.sne-content ol { list-style: decimal; }
.sne-content li { margin: 4px 0; }
.sne-content li::marker { color: var(--sne-text-muted); }
.sne-content ul ul { list-style: circle; }
.sne-content ul ul ul { list-style: square; }
.sne-content a { color: var(--sne-primary); text-decoration: none; border-bottom: 1px solid rgba(37, 99, 235, .3); }
.sne-content a:hover { border-bottom-color: var(--sne-primary); }
.sne-content b, .sne-content strong { font-weight: 650; }
.sne-content mark { background: #fff3bf; padding: 1px 3px; border-radius: 3px; }
.sne-content small { font-size: 12.5px; color: var(--sne-text-muted); }
.sne-content code {
  font-family: var(--sne-mono);
  font-size: .88em;
  padding: 2px 5px;
  border-radius: 5px;
  background: var(--sne-bg-hover);
  border: 1px solid var(--sne-border-soft);
  color: #c22d5c;
}
.sne-content blockquote {
  margin: 0 0 14px;
  padding: 4px 0 4px 14px;
  border-left: 3px solid var(--sne-primary);
  color: var(--sne-text-sub);
  background: linear-gradient(90deg, var(--sne-primary-soft), transparent 60%);
  border-radius: 0 6px 6px 0;
}
.sne-content pre,
.sne-mdprev pre {
  position: relative;
  margin: 0 0 14px;
  padding: 13px 15px;
  background: #f7f8fa;
  border: 1px solid var(--sne-border-soft);
  border-radius: var(--sne-radius-sm);
  overflow-x: auto;
  font-family: var(--sne-mono);
  font-size: 13px;
  line-height: 1.62;
  white-space: pre;
  tab-size: 2;
}
.sne-content pre code,
.sne-mdprev pre code { padding: 0; background: none; border: 0; color: inherit; font-size: inherit; }
.sne-content hr {
  height: 0; border: 0; border-top: 1px dashed #dfe3e8;
  margin: 20px 0;
}
.sne-content img { max-width: 100%; height: auto; border-radius: var(--sne-radius-xs); vertical-align: bottom; }
.sne-content img[data-align="left"] { float: left; margin: 4px 14px 10px 0; }
.sne-content img[data-align="right"] { float: right; margin: 4px 0 10px 14px; }
.sne-content img[data-align="center"] { display: block; margin: 12px auto; }
.sne-content video { max-width: 100%; border-radius: var(--sne-radius-sm); background: #000; display: block; margin: 0 0 14px; }
.sne-content audio { width: 100%; margin: 0 0 14px; display: block; }
.sne-content iframe { max-width: 100%; border: 0; border-radius: var(--sne-radius-sm); }

/* ==================================================================
 * 6.1 代码块：外壳 + 顶部工具条（macOS 圆点 / 语言下拉 / 行号 / 复制）
 *   外壳 .sne-code 里的工具条与行号槽是「瞬态装饰」——
 *   保存时被 stripChrome 剥掉，渲染时由 decorateCodeBlocks() 重建，
 *   所以它们不会出现在存库的 HTML / 导出的 Markdown 里。
 * ================================================================== */
.sne-code {
  --sne-code-bar-h: 34px;
  position: relative;
  margin: 0 0 16px;
  border: 1px solid var(--sne-border-soft);
  border-radius: 10px;
  background: #f7f8fa;
  overflow: hidden;
}
.sne-code > pre {
  margin: 0;
  border: 0;
  border-radius: 0;
  padding: 13px 15px;
}
.sne-code--lines > pre { padding-left: 48px; }

.sne-code-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  height: var(--sne-code-bar-h, 34px);
  padding: 0 8px 0 13px;
  border-bottom: 1px solid var(--sne-border-soft);
  background: var(--sne-bg-hover);
  font-family: var(--sne-font);
  font-size: 12px;
  user-select: none;
}
.sne-code-dots { display: inline-flex; gap: 6px; flex: none; }
.sne-code-dots i { display: block; width: 10px; height: 10px; border-radius: 50%; }
.sne-code-dots i:nth-child(1) { background: #ff5f57; }
.sne-code-dots i:nth-child(2) { background: #febc2e; }
.sne-code-dots i:nth-child(3) { background: #28c840; }

.sne-code-lang {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 22px;
  padding: 0 9px;
  border: 1px solid var(--sne-border);
  border-radius: 11px;
  background: var(--sne-bg);
  color: var(--sne-text-sub);
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .02em;
  cursor: pointer;
  transition: color .14s ease, border-color .14s ease;
}
.sne-code-lang::after { content: '▾'; font-size: 9px; opacity: .65; }
.sne-code-lang:hover { color: var(--sne-primary); border-color: var(--sne-primary); }
.sne-code-lang.is-plain { font-weight: 500; opacity: .74; }

.sne-code-gap { flex: 1 1 auto; }

.sne-code-tool {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 22px;
  padding: 0 8px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: transparent;
  color: var(--sne-text-muted);
  font: inherit;
  font-size: 11.5px;
  cursor: pointer;
  transition: color .14s ease, background .14s ease, border-color .14s ease;
}
.sne-code-tool:hover { color: var(--sne-primary); background: var(--sne-bg); border-color: var(--sne-border); }
.sne-code-lines { font-family: var(--sne-mono); font-size: 12px; padding: 0 7px; }
.sne-code-lines.is-on { color: var(--sne-primary); background: var(--sne-primary-soft); border-color: transparent; }
.sne-code-copy.is-done { color: #15803d; background: #f0fdf4; border-color: #bbf7d0; }
.sne-code-tool svg { width: 13px; height: 13px; flex: none; }
.sne-code-tool svg path, .sne-code-tool svg rect, .sne-code-tool svg circle {
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}

/* 行号槽：挂在外壳上（不在 <pre> 里），所以不会干扰 pre 的排版和导出 */
.sne-code-gutter {
  position: absolute;
  left: 0;
  top: calc(var(--sne-code-bar-h, 34px) + 1px);
  width: 40px;
  padding: 13px 9px 13px 0;
  text-align: right;
  color: var(--sne-text-faint);
  font-family: var(--sne-mono);
  font-size: 13px;
  line-height: 1.62;
  white-space: pre;
  pointer-events: none;
  user-select: none;
  border-right: 1px solid var(--sne-border-soft);
}

/* ==================================================================
 * 4. 状态栏 / 占位符 / 源码模式
 * ================================================================== */
.sne-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: 30px;
  padding: 0 12px;
  border-top: 1px solid var(--sne-border-soft);
  background: var(--sne-bg-soft);
  border-radius: 0 0 var(--sne-radius) var(--sne-radius);
  font-size: 12px;
  color: var(--sne-text-muted);
}
.sne-status .sne-path { display: none; font-family: var(--sne-mono); font-size: 11px; color: var(--sne-text-faint); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.sne-status .sne-statusright { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.sne-status .sne-savestate { color: var(--sne-text-faint); }
.sne-status .sne-count.is-warn { color: var(--sne-warning); }
.sne-status .sne-count.is-over { color: var(--sne-danger); font-weight: 600; }

.sne-placeholder {
  position: absolute;
  top: 18px;
  left: 20px;
  right: 20px;
  color: var(--sne-text-faint);
  font-size: 15px;
  line-height: 1.78;
  pointer-events: none;
  user-select: none;
}

/* ---- 源码列（HTML 源码 / Markdown 源码）----
   说明：早先靠「源码 class 的兄弟选择器」隐藏内容区是错的（content 在 source 之前），
   源码模式其实一直和内容区并排显示。现在显隐关系只由根节点上的 sne--mode-* 类决定，
   下面是全站唯一一处定义模式显隐关系的地方。 */
.sne-md {
  display: flex;
  flex-direction: column;
  /* ⚠️ flex-basis 必须是 0，不能是 auto。
     用 auto 时会拿「内容宽度」当基准，而栏目头里的语法工具栏是整整一行按钮
     （约 500px+），会把源码列撑到占满大半宽度，右侧预览列被挤扁。 */
  flex: 1 1 0;
  min-width: 0;
  border-right: 1px solid var(--sne-border-soft);
  background: var(--sne-bg);
}
.sne-md[hidden] { display: none; }
.sne-md-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
  min-height: 34px;
  padding: 4px 10px;
  border-bottom: 1px solid var(--sne-border-soft);
  background: var(--sne-bg-soft);
  font-size: 12px;
  color: var(--sne-text-muted);
}
.sne-md-title { font-weight: 600; white-space: nowrap; }
.sne-md-tools {
  display: flex;
  align-items: center;
  gap: 3px;
  row-gap: 3px;
  margin-left: auto;
  flex: 0 1 auto;
  min-width: 0;          /* 允许工具栏在窄栏里换行，不要反过来撑宽整列 */
  flex-wrap: wrap;
  justify-content: flex-end;
}
.sne-md-tools[hidden] { display: none; }
.sne-md-tool {
  height: 22px;
  min-width: 22px;
  padding: 0 6px;
  border: 1px solid transparent;
  border-radius: 5px;
  background: transparent;
  color: var(--sne-text-sub);
  font: inherit;
  font-size: 12px;
  line-height: 1;
  cursor: pointer;
  transition: background .14s ease, color .14s ease, border-color .14s ease;
}
.sne-md-tool:hover { background: var(--sne-bg-hover); border-color: var(--sne-border); color: var(--sne-primary); }
.sne-md-tool:active { transform: scale(.94); }
.sne-md-sep { width: 1px; height: 12px; margin: 0 1px; background: var(--sne-border); }

.sne-source {
  display: block;
  flex: 1 1 auto;
  width: 100%;
  min-height: 0;
  padding: 14px 16px;
  border: 0;
  outline: none;
  resize: none;
  background: var(--sne-bg);
  color: var(--sne-text);
  font-family: var(--sne-mono);
  font-size: 13px;
  line-height: 1.7;
  tab-size: 2;
}

/* ---- Markdown 实时预览（同样是 contenteditable，可直接改）---- */
.sne-mdprev {
  display: none;
  flex: 1 1 0;
  min-width: 0;
  padding: 18px 20px;
  overflow-y: auto;
  outline: none;
  background: var(--sne-bg);
  color: var(--sne-text);
  font-size: 15px;
  line-height: 1.78;
  word-break: break-word;
  overflow-wrap: anywhere;
}
.sne-mdprev[hidden] { display: none; }

/* ---- 源码列 / 预览列之间的拖拽分隔条（只在 Markdown 分栏下出现）----
   预览宽度不够时，用户可以自己往右拖；没拖过就是默认 1:1。 */
.sne-mdsplit {
  display: none;
  position: relative;
  flex: none;
  width: 9px;
  background: transparent;
  cursor: col-resize;
  z-index: 2;
  touch-action: none;
}
.sne-mdsplit::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--sne-border-soft);
  transition: background .14s ease;
}
.sne-mdsplit:hover::before,
.sne-mdsplit.is-dragging::before { background: var(--sne-primary); }

/* ---- 三种模式的显隐关系（唯一定义处）---- */
.sne--mode-wysiwyg .sne-md,
.sne--mode-wysiwyg .sne-mdprev,
.sne--mode-wysiwyg .sne-mdsplit,
.sne--mode-wysiwyg .sne-sourcetag { display: none; }

.sne--mode-html .sne-content,
.sne--mode-html .sne-mdprev,
.sne--mode-html .sne-mdsplit { display: none; }
.sne--mode-html .sne-md { border-right: 0; }

.sne--mode-markdown .sne-content { display: none; }
.sne--mode-markdown .sne-md { border-right: 0; }
.sne--mode-markdown .sne-mdsplit { display: block; }
.sne--mode-markdown .sne-mdprev { display: block; }
.sne--mode-markdown.sne--md-nosplit .sne-mdprev { display: none; }
.sne--mode-markdown.sne--md-nosplit .sne-mdsplit { display: none; }
.sne--mode-markdown.sne--md-nosplit .sne-md { border-right: 0; }

/* 用户拖过分隔条后，按 --sne-mdw 记录的比例分栏；预览列吃掉剩下的宽度 */
.sne--mode-markdown.sne--md-resized .sne-md { flex: 0 0 var(--sne-mdw, 50%); }
.sne--mode-markdown.sne--md-resized .sne-mdprev { flex: 1 1 0; }

.sne--mode-html .sne-placeholder,
.sne--mode-markdown .sne-placeholder { display: none; }

.sne-sourcetag {
  display: none;
  position: absolute;
  top: 8px;
  right: 10px;
  z-index: 2;
  padding: 2px 8px;
  font-size: 11px;
  color: var(--sne-primary);
  background: var(--sne-primary-soft);
  border-radius: 20px;
  pointer-events: none;
}
.sne-sourcetag--on { display: block; }
/* Markdown 模式下左侧栏目头已经标了「Markdown 语法」，角标就多余了 */
.sne--mode-markdown .sne-sourcetag { display: none; }

/* ---- 插件侧栏容器（AI 助手等）：编辑器内部左右分栏 ---- */
.sne-side { display: flex; flex: none; min-width: 0; }
.sne-side[hidden] { display: none; }
.sne-pane {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: none;
  min-width: 0;
  border-left: 1px solid var(--sne-border-soft);
  background: var(--sne-bg-soft);
}
.sne-pane--left { order: -1; border-left: 0; border-right: 1px solid var(--sne-border-soft); }
.sne-pane[hidden] { display: none; }
.sne-pane-head {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
  height: 36px;
  padding: 0 8px 0 12px;
  border-bottom: 1px solid var(--sne-border-soft);
  background: var(--sne-bg);
}
.sne-pane-head svg { width: 15px; height: 15px; flex: none; stroke: var(--sne-primary); fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.sne-pane-title { font-size: 13px; font-weight: 600; color: var(--sne-text); }
.sne-pane-actions { display: flex; align-items: center; gap: 2px; margin-left: auto; }
.sne-pane-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 12px; }
.sne-pane-foot { flex: none; border-top: 1px solid var(--sne-border-soft); }
.sne-pane-resizer {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -2px;
  width: 5px;
  cursor: col-resize;
  z-index: 2;
}
.sne-pane--left .sne-pane-resizer { left: auto; right: -2px; }
.sne-pane-resizer:hover, body.sne-resizing .sne-pane-resizer { background: var(--sne-primary-soft); }
body.sne-resizing, body.sne-resizing * { cursor: col-resize !important; user-select: none !important; }

/* ==================================================================
 * 5. 弹出面板
 * ================================================================== */
.sne-pop {
  position: absolute;
  z-index: calc(var(--sne-z) + 2);
  min-width: 120px;
  padding: 6px;
  background: var(--sne-bg);
  border: 1px solid var(--sne-border);
  border-radius: 10px;
  box-shadow: var(--sne-shadow);
  animation: sne-pop-in .14s ease;
}
@keyframes sne-pop-in {
  from { opacity: 0; transform: translateY(-4px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

.sne-listpanel { display: flex; flex-direction: column; gap: 1px; min-width: 148px; max-height: 320px; overflow-y: auto; }
.sne-listitem {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  padding: 7px 10px;
  border: 0;
  border-radius: var(--sne-radius-xs);
  background: transparent;
  color: var(--sne-text);
  font: inherit;
  font-size: 13.5px;
  text-align: left;
  cursor: pointer;
}
.sne-listitem:hover { background: var(--sne-bg-hover); }
.sne-listitem.is-active { background: var(--sne-bg-active); color: var(--sne-primary); font-weight: 600; }
.sne-listitem-hint { font-size: 11.5px; color: var(--sne-text-faint); font-family: var(--sne-mono); }

.sne-colorpanel { width: 216px; }
.sne-colorgrid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 4px; margin-bottom: 8px; }
.sne-colorcell {
  width: 100%;
  aspect-ratio: 1 / 1;
  border: 1px solid rgba(0, 0, 0, .1);
  border-radius: 4px;
  cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease;
}
.sne-colorcell:hover { transform: scale(1.14); box-shadow: 0 0 0 2px var(--sne-primary-soft); }
.sne-colorfoot { display: flex; align-items: center; gap: 6px; padding-top: 6px; border-top: 1px solid var(--sne-border-soft); }
.sne-colorinput {
  width: 30px; height: 28px; padding: 0; border: 1px solid var(--sne-border);
  border-radius: var(--sne-radius-xs); background: none; cursor: pointer;
}
.sne-input {
  height: 30px;
  min-width: 0;
  padding: 0 9px;
  border: 1px solid var(--sne-border);
  border-radius: var(--sne-radius-xs);
  background: var(--sne-bg);
  color: var(--sne-text);
  font: inherit;
  font-size: 13px;
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.sne-input::placeholder { color: var(--sne-text-faint); }
.sne-input:focus { border-color: var(--sne-primary); box-shadow: 0 0 0 3px rgba(37, 99, 235, .1); }
.sne-input--hex { flex: 1 1 auto; font-family: var(--sne-mono); text-transform: uppercase; }
select.sne-input { padding-right: 22px; appearance: none;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5 6 7.5 9 4.5' fill='none' stroke='%238b909a' stroke-width='1.4' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 6px center; background-size: 12px;
}

.sne-panel-group { display: flex; align-items: center; gap: 2px; }
.sne-panel-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border: 0; border-radius: var(--sne-radius-xs);
  background: transparent; color: var(--sne-text-sub); cursor: pointer;
}
.sne-panel-btn:hover { background: var(--sne-bg-hover); color: var(--sne-text); }
/* 对齐 / 缩进这些面板图标：显式定尺寸 + 描边，别指望 svg 自己撑开 */
.sne-panel-btn svg { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.sne-panel-btn svg [fill="currentColor"] { fill: currentColor; stroke: none; }
.sne-panel-btn.is-on { background: var(--sne-primary-soft); color: var(--sne-primary); }
.sne-panel-sep { width: 1px; height: 18px; margin: 0 4px; background: var(--sne-border); }

/* 表格网格选择器 */
.sne-gridpanel { width: 210px; }
.sne-gridhint { font-size: 12px; color: var(--sne-text-muted); text-align: center; margin-bottom: 7px; min-height: 17px; }
.sne-gridpicker { display: grid; grid-template-columns: repeat(10, 1fr); gap: 2px; }
.sne-gridcell {
  aspect-ratio: 1 / 1;
  border: 1px solid var(--sne-border);
  border-radius: 3px;
  background: var(--sne-bg-soft);
  cursor: pointer;
  transition: background .1s ease, border-color .1s ease;
}
.sne-gridcell.is-on { background: var(--sne-primary-soft); border-color: #b9cdfb; }
.sne-gridacts { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--sne-border-soft); }
.sne-gridopts {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-top: 9px; padding-top: 8px;
  border-top: 1px solid var(--sne-border-soft);
  font-size: 12px;
}
.sne-gridopts select.sne-input { height: 26px; width: 116px; font-size: 12px; }

/* 表格悬浮操作条 */
.sne-tablebar {
  position: absolute;
  z-index: calc(var(--sne-z) + 2);
  display: flex;
  align-items: center;
  gap: 1px;
  max-width: calc(100% - 16px);
  padding: 4px 6px;
  background: var(--sne-bg);
  border: 1px solid var(--sne-border);
  border-radius: 20px;
  box-shadow: var(--sne-shadow);
  overflow-x: auto;
  animation: sne-pop-in .14s ease;
}
.sne-tbbtn {
  flex: none;
  height: 24px;
  padding: 0 8px;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--sne-text-sub);
  font: inherit;
  font-size: 12px;
  white-space: nowrap;
  cursor: pointer;
  transition: background .14s ease, color .14s ease;
}
.sne-tbbtn:hover { background: var(--sne-bg-hover); color: var(--sne-primary); }
.sne-tbsep { flex: none; width: 1px; height: 14px; margin: 0 3px; background: var(--sne-border); }

/* 通用按钮 */
.sne-btn-ghost, .sne-btn-primary {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  height: 30px; padding: 0 11px;
  border-radius: var(--sne-radius-xs);
  border: 1px solid var(--sne-border);
  background: var(--sne-bg);
  color: var(--sne-text-sub);
  font: inherit; font-size: 13px; cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
  white-space: nowrap;
}
.sne-btn-ghost:hover { background: var(--sne-bg-hover); color: var(--sne-text); }
.sne-btn-primary { background: var(--sne-primary); border-color: var(--sne-primary); color: #fff; }
.sne-btn-primary:hover { background: #1d4fd8; border-color: #1d4fd8; }
.sne-btn-primary:disabled { opacity: .5; cursor: not-allowed; }
.sne-btn-ghost svg, .sne-btn-primary svg { width: 15px; height: 15px; }
.sne-btn-ghost svg path, .sne-btn-primary svg path, .sne-btn-primary svg circle, .sne-btn-primary svg rect {
  fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}

/* 表单 */
.sne-form { width: 300px; padding: 4px; }
.sne-form-row { margin-bottom: 10px; }
.sne-form-row--inline { display: flex; gap: 14px; align-items: center; }
.sne-form-label { display: block; margin-bottom: 5px; font-size: 12px; color: var(--sne-text-muted); }
.sne-form-row .sne-input { width: 100%; }
.sne-form-foot { display: flex; justify-content: flex-end; gap: 8px; padding-top: 8px; border-top: 1px solid var(--sne-border-soft); }
.sne-check { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; color: var(--sne-text-sub); cursor: pointer; }
.sne-check input { accent-color: var(--sne-primary); }

/* 媒体面板：标签页 / 拖放区 */
.sne-form--media { width: 324px; }
.sne-tabs {
  display: flex; gap: 2px; padding: 3px; margin-bottom: 10px;
  background: var(--sne-bg-hover); border-radius: 8px;
}
.sne-tab {
  flex: 1 1 0; height: 28px;
  border: 0; border-radius: 6px; background: transparent;
  color: var(--sne-text-sub); font: inherit; font-size: 13px; cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.sne-tab:hover { color: var(--sne-text); }
.sne-tab.is-active { background: var(--sne-bg); color: var(--sne-text); font-weight: 600; box-shadow: var(--sne-shadow-sm); }
.sne-tabpane[hidden] { display: none; }
.sne-dropzone {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 22px 12px;
  border: 1px dashed var(--sne-border); border-radius: var(--sne-radius-sm);
  background: var(--sne-bg-soft); color: var(--sne-text-sub);
  font: inherit; font-size: 13px; cursor: pointer;
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
.sne-dropzone svg { width: 20px; height: 20px; stroke: var(--sne-primary); fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.sne-dropzone:hover { border-color: #b9cdfb; background: var(--sne-primary-soft); color: var(--sne-primary); }
.sne-hint { margin-top: 8px; font-size: 11.5px; line-height: 1.65; color: var(--sne-text-faint); }
.sne-form--media .sne-form-foot { margin-top: 10px; padding-top: 0; border-top: 0; }
.sne-form--media .sne-form-row--inline .sne-check { font-size: 12px; color: var(--sne-text-muted); gap: 4px; }
.sne-form--media select.sne-input { height: 28px; width: 84px; }

/* ==================================================================
 * 6. 模态框
 * ================================================================== */
/* ------------------------------------------------------------------
 * 6.1 对话框骨架
 * head / body / foot 是 .sne-modal 的三个「直接子元素」，它们共用同一个
 * max-width，视觉上才拼成"一个对话框"。
 *   早先的问题：没有 max-width，三块被拉到 94vw 铺满整屏；栏目头又用
 *   space-between 把「标题 / 切换 / 关闭」撒到两端；body 还因为一条
 *   "head 相邻即补底部圆角"的规则，在中间段错加了圆角
 *   —— 这三条叠加起来就是「点击地图时页面错乱」的原因。
 * ------------------------------------------------------------------ */
.sne-modal {
  position: fixed;
  inset: 0;
  z-index: calc(var(--sne-z) + 10);
  display: flex;
  flex-direction: column;
  align-items: center;        /* 对话框水平居中，不再被拉伸铺满屏 */
  justify-content: center;
  background: rgba(15, 23, 42, .35);
  backdrop-filter: blur(2px);
  padding: 4vh 20px;
  font-family: var(--sne-font);
  animation: sne-fade .16s ease;
  overflow: hidden;
}
@keyframes sne-fade { from { opacity: 0; } to { opacity: 1; } }

/* 三段共用宽度 → 拼成一个整体对话框（各弹窗按需覆盖 max-width） */
.sne-modal-head,
.sne-modal-body,
.sne-modal-foot {
  width: 100%;
  max-width: 720px;
}

.sne-modal-head {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: none;
  padding: 12px 14px 12px 20px;
  background: var(--sne-bg);
  border-bottom: 1px solid var(--sne-border-soft);
  border-radius: var(--sne-radius) var(--sne-radius) 0 0;
}
/* 标题吃掉剩余空间 → 右侧操作区自然靠右（替代 space-between 的撒开效果） */
.sne-modal-title {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--sne-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sne-modal-body {
  flex: 1 1 auto;
  min-height: 0;              /* 允许在 flex 列里正确收缩，否则内容会顶破视口 */
  overflow-y: auto;
  padding: 24px 28px;
  background: var(--sne-bg);
  border-radius: 0;           /* 中间段不圆角（后面还有 .sne-modal-foot） */
  color: var(--sne-text);
  font-size: 15px;
  line-height: 1.78;
}
/* 只有「最后一段」才补底部圆角：预览弹窗是 head + body 两段，就命中这条 */
.sne-modal-body:last-child { border-radius: 0 0 var(--sne-radius) var(--sne-radius); }
.sne-modal .sne-btn { color: var(--sne-text-muted); }
.sne-modal .sne-btn:hover { background: var(--sne-bg-hover); color: var(--sne-text); }
.sne-preview-body { max-width: 860px; margin: 0 auto; width: 100%; }
.sne-preview-body img { max-width: 100%; height: auto; border-radius: var(--sne-radius-xs); }
.sne-preview-body pre { padding: 13px 15px; background: #f7f8fa; border-radius: var(--sne-radius-sm); overflow-x: auto; font-family: var(--sne-mono); font-size: 13px; }
.sne-preview-body blockquote { margin: 0 0 14px; padding-left: 14px; border-left: 3px solid var(--sne-primary); color: var(--sne-text-sub); }
.sne-preview-body table { border-collapse: collapse; width: 100%; margin-bottom: 14px; }
.sne-preview-body th, .sne-preview-body td { border: 1px solid var(--sne-border); padding: 7px 11px; }
.sne-preview-body video { max-width: 100%; border-radius: var(--sne-radius-sm); }
.sne-preview-body audio { width: 100%; }

/* ==================================================================
 * 7. 内容内的结构化节点
 * ================================================================== */
.sne-content table, .sne-table { border-collapse: collapse; width: 100%; margin: 0 0 14px; font-size: 14px; }
.sne-content th, .sne-content td, .sne-table th, .sne-table td {
  border: 1px solid var(--sne-border);
  padding: 7px 11px;
  min-width: 40px;
  vertical-align: top;
}
.sne-content th, .sne-table th { background: var(--sne-bg-soft); font-weight: 600; text-align: left; }
.sne-content td:focus, .sne-content th:focus { outline: 2px solid var(--sne-primary-soft); }

.sne-attachment {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 7px 12px 7px 10px;
  margin: 2px 0;
  border: 1px solid var(--sne-border);
  border-radius: 20px;
  background: var(--sne-bg-soft);
  color: var(--sne-text) !important;
  text-decoration: none !important;
  font-size: 13.5px;
  vertical-align: middle;
}
.sne-attachment:hover { border-color: #cfd6e4; background: var(--sne-bg-hover); }
.sne-attachment svg { width: 15px; height: 15px; flex: none; stroke: var(--sne-primary); fill: none; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.sne-attachment .sne-att-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }
.sne-attachment .sne-att-size { color: var(--sne-text-faint); font-size: 12px; flex: none; }
.sne-attachment .sne-att-del {
  border: 0; background: none; color: var(--sne-text-faint); cursor: pointer;
  font-size: 15px; line-height: 1; padding: 0 0 0 2px; flex: none;
}
.sne-attachment .sne-att-del:hover { color: var(--sne-danger); }

.sne-figure { margin: 0 0 14px; }
.sne-figure figcaption {
  margin-top: 6px; font-size: 12.5px; color: var(--sne-text-muted); text-align: center;
}

/* ==================================================================
 * 8. 上传进度 / 轻提示
 * ================================================================== */
.sne-toasts {
  position: absolute;
  right: 12px;
  bottom: 42px;
  z-index: calc(var(--sne-z) + 3);
  display: flex;
  flex-direction: column;
  gap: 8px;
  pointer-events: none;
}
.sne-toast {
  min-width: 208px;
  max-width: 300px;
  padding: 9px 12px;
  background: var(--sne-bg);
  border: 1px solid var(--sne-border);
  border-radius: 10px;
  box-shadow: var(--sne-shadow);
  font-size: 13px;
  color: var(--sne-text);
  pointer-events: auto;
  animation: sne-pop-in .16s ease;
}
.sne-toast--error { border-color: rgba(225, 29, 72, .35); }
.sne-toast--success { border-color: rgba(22, 163, 74, .35); }
.sne-toast-head { display: flex; align-items: center; gap: 8px; }
.sne-toast-name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; }
.sne-toast-msg { margin-top: 3px; font-size: 12px; color: var(--sne-text-muted); }
.sne-toast--error .sne-toast-msg { color: var(--sne-danger); }
.sne-progress { margin-top: 7px; height: 4px; border-radius: 4px; background: var(--sne-bg-hover); overflow: hidden; }
.sne-progress-bar { height: 100%; width: 0; background: var(--sne-primary); border-radius: 4px; transition: width .18s ease; }

.sne.is-dragover::after {
  content: "松开以上传文件";
  position: absolute;
  inset: 0;
  z-index: calc(var(--sne-z) + 4);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  color: var(--sne-primary);
  background: rgba(239, 244, 255, .82);
  border: 2px dashed #9dbcfb;
  border-radius: var(--sne-radius);
  pointer-events: none;
}

/* 内容内联占位（上传中） */
.sne-pending {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: 14px;
  background: var(--sne-primary-soft); color: var(--sne-primary);
  font-size: 12.5px; vertical-align: middle;
}
.sne-pending::before {
  content: ""; width: 10px; height: 10px; border-radius: 50%;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: sne-spin .7s linear infinite;
}
@keyframes sne-spin { to { transform: rotate(360deg); } }

/* ==================================================================
 * 9. AI 面板
 * ================================================================== */
.sne-aipanel { width: 380px; padding: 4px; }
.sne-ai-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.sne-ai-head svg { width: 16px; height: 16px; stroke: var(--sne-primary); fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.sne-ai-title { font-size: 13.5px; font-weight: 600; }
.sne-ai-scope { margin-left: auto; font-size: 11.5px; color: var(--sne-text-muted); background: var(--sne-bg-hover); padding: 2px 8px; border-radius: 20px; }
/* ---- AI 引擎标识（只读） ----
   接口参数（服务商 / Key / 模型 / Base URL）全部在实例化编辑器时
   通过 options.ai 传入，面板上不再有任何设置输入框。 */
.sne-ai-enginebar { display: flex; align-items: center; margin-bottom: 9px; }
.sne-ai-engine-tag {
  display: inline-flex; align-items: center;
  max-width: 100%;
  padding: 3px 9px;
  border: 1px solid var(--sne-border);
  border-radius: 20px;
  background: var(--sne-bg-soft);
  color: var(--sne-text-muted);
  font-size: 11.5px; line-height: 1.5;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sne-ai-engine-tag[hidden] { display: none; }
.sne-ai-engine-tag.is-ready { color: #15803d; border-color: #bbf7d0; background: #f0fdf4; }
.sne-ai-engine-tag.is-unready { color: var(--sne-danger); border-color: #fecdd3; background: #fff1f2; }

/* ---- 代码块语言下拉菜单（工具栏「代码块 / {}」与代码块语言按钮共用） ---- */
.sne-langmenu { display: flex; flex-direction: column; gap: 8px; width: 306px; }
.sne-langhead { font-size: 12px; line-height: 1.6; color: var(--sne-text-muted); }
.sne-langhead b { color: var(--sne-primary); font-weight: 600; }
.sne-langsearch { flex: none; }
.sne-langsearch .sne-langkb { width: 100%; height: 30px; padding: 0 10px; font-size: 12.5px; }
.sne-langlist {
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-height: 254px;
  overflow-y: auto;
  margin: 0 -4px;
  padding: 1px 4px;
}
.sne-langitem {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  height: 30px;
  padding: 0 8px 0 5px;
  border: 0;
  border-radius: var(--sne-radius-xs);
  background: transparent;
  color: var(--sne-text);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.sne-langitem:hover { background: var(--sne-bg-hover); }
.sne-langitem.is-cursor { background: var(--sne-bg-hover); box-shadow: inset 0 0 0 1px var(--sne-border); }
.sne-langitem.is-active { background: var(--sne-primary-soft); color: var(--sne-primary); font-weight: 600; }
.sne-langcheck { display: inline-flex; align-items: center; justify-content: center; width: 15px; flex: none; }
.sne-langcheck svg { width: 14px; height: 14px; }
.sne-langcheck svg path { fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.sne-langname { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sne-langcode {
  flex: none;
  font-family: var(--sne-mono);
  font-size: 10.5px;
  color: var(--sne-text-faint);
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--sne-bg-hover);
}
.sne-langitem.is-active .sne-langcode { color: var(--sne-primary); background: var(--sne-bg); }
.sne-langempty { padding: 16px 10px; text-align: center; font-size: 12.5px; color: var(--sne-text-faint); }
.sne-langfoot { font-size: 11px; line-height: 1.6; color: var(--sne-text-faint); }
.sne-langfoot code { padding: 1px 4px; border-radius: 3px; background: var(--sne-bg-hover); font-family: var(--sne-mono); font-size: 10.5px; }

/* ---- 代码块右上角的语言角标（来自 data-lang 属性，不进正文文本） ---- */
.sne-content pre[data-lang]::before,
.sne-mdprev pre[data-lang]::before {
  content: attr(data-lang);
  position: absolute; top: 0; right: 0;
  padding: 1px 8px 2px;
  border-radius: 0 var(--sne-radius-sm) 0 var(--sne-radius-xs);
  background: var(--sne-bg-hover);
  color: var(--sne-text-muted);
  font-family: var(--sne-font);
  font-size: 10.5px; line-height: 1.7;
  letter-spacing: .03em;
  pointer-events: none;
  user-select: none;
}
/* 套了外壳的代码块，语言改由顶部工具条展示 → 关掉旧角标，避免双份 */
.sne-code > pre[data-lang]::before { display: none; }

/* ---- 导入 Markdown 面板 ---- */
.sne-mdimport { display: flex; flex-direction: column; gap: 9px; width: 384px; }
.sne-mdimp-title { font-size: 13px; font-weight: 600; }
.sne-mdimp-drop {
  display: flex; align-items: center; gap: 10px;
  padding: 12px;
  border: 1px dashed var(--sne-border);
  border-radius: var(--sne-radius-sm);
  background: var(--sne-bg-soft);
  transition: border-color .15s ease, background .15s ease;
}
.sne-mdimport.is-drag .sne-mdimp-drop { border-color: var(--sne-primary); background: var(--sne-primary-soft); }
.sne-mdimp-hint { font-size: 11.5px; color: var(--sne-text-muted); }
.sne-mdimp-text {
  min-height: 98px;
  padding: 8px 9px;
  font-family: var(--sne-mono); font-size: 12px; line-height: 1.65;
  resize: vertical;
}
.sne-mdimp-row { display: flex; align-items: center; gap: 7px; }
.sne-mdimp-row .sne-input { flex: 1 1 auto; min-width: 0; height: 30px; padding: 0 9px; font-size: 12.5px; }
.sne-mdimp-foot { display: flex; align-items: center; gap: 8px; }
.sne-mdimp-foot .sne-check { font-size: 12px; }
.sne-mdimp-msg { font-size: 11.5px; line-height: 1.6; color: var(--sne-text-muted); }
.sne-mdimp-msg:empty { display: none; }
.sne-mdimp-msg.is-error { color: var(--sne-danger); }
.sne-mdimp-msg.is-info { color: var(--sne-primary); }

.sne-ai-funcs { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 9px; }
.sne-ai-chip {
  padding: 5px 10px;
  border: 1px solid var(--sne-border);
  border-radius: 20px;
  background: var(--sne-bg);
  color: var(--sne-text-sub);
  font: inherit; font-size: 12.5px; cursor: pointer;
  transition: all .15s ease;
}
.sne-ai-chip:hover { border-color: #b9cdfb; color: var(--sne-primary); background: var(--sne-primary-soft); }
.sne-ai-chip.is-active { background: var(--sne-primary); border-color: var(--sne-primary); color: #fff; }
.sne-ai-prompt { width: 100%; min-height: 56px; resize: vertical; padding: 8px 10px; line-height: 1.6; }
.sne-ai-out {
  margin-top: 8px;
  max-height: 220px;
  overflow-y: auto;
  padding: 10px 12px;
  border: 1px solid var(--sne-border-soft);
  border-radius: var(--sne-radius-sm);
  background: var(--sne-bg-soft);
  font-size: 13.5px;
  line-height: 1.7;
  white-space: pre-wrap;
  word-break: break-word;
  display: none;
}
.sne-ai-out.is-on { display: block; }
.sne-ai-out.is-error { color: var(--sne-danger); border-color: rgba(225, 29, 72, .3); }
.sne-ai-caret {
  display: inline-block; width: 6px; height: 14px; margin-left: 1px;
  background: var(--sne-primary); vertical-align: -2px;
  animation: sne-blink .9s steps(2, start) infinite;
}
@keyframes sne-blink { to { visibility: hidden; } }
.sne-ai-foot { display: flex; align-items: center; gap: 6px; margin-top: 9px; padding-top: 9px; border-top: 1px solid var(--sne-border-soft); }
.sne-ai-foot .sne-spacer { flex: 1 1 auto; }

/* ==================================================================
 * 10. 内置主题（5 套）
 *     · 换主题 = 换一组 CSS 变量，不需要改 JS，也不需要重渲染工具栏
 *     · 自定义主题：Sneditor.registerTheme(name, { vars: {...} })
 *       由 theme 插件在运行时注入 <style>，规则形如
 *         .sne--<name>, [data-theme="<name>"] { --sne-primary: …; }
 *     · 本节里的两套写法都要保留：.sne--x 给编辑器本体，
 *       [data-theme="x"] 给浮层（预览框）——浮层不在 .sne 内部
 * ================================================================== */

/* ---------- 10.1 dark 暗夜（深色） ---------- */
.sne--dark, .sne[data-theme="dark"], .sne-layer[data-theme="dark"] {
  --sne-bg: #16181d;
  --sne-bg-soft: #1b1e24;
  --sne-bg-hover: #23262e;
  --sne-bg-active: #1e2a44;
  --sne-border: #2b2f38;
  --sne-border-soft: #23262e;
  --sne-text: #e8eaed;
  --sne-text-sub: #b6bcc7;
  --sne-text-muted: #8b909a;
  --sne-text-faint: #666c78;
  --sne-primary: #6b9bff;
  --sne-primary-soft: #1b2740;
  --sne-shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
  --sne-shadow: 0 8px 24px -6px rgba(0, 0, 0, .55), 0 2px 6px rgba(0, 0, 0, .35);
}
.sne--dark .sne-content code, .sne[data-theme="dark"] .sne-content code { color: #ff9db5; }
.sne--dark .sne-content pre, .sne[data-theme="dark"] .sne-content pre,
.sne--dark .sne-mdprev pre, .sne[data-theme="dark"] .sne-mdprev pre { background: #101216; }
.sne--dark .sne-content mark, .sne[data-theme="dark"] .sne-content mark { background: #4a3b12; color: inherit; }
.sne--dark .sne-content hr, .sne[data-theme="dark"] .sne-content hr { border-top-color: #33373f; }
.sne--dark .sne-btn svg [fill="#fde68a"], .sne[data-theme="dark"] .sne-btn svg [fill="#fde68a"] { fill: #b45309; }
/* 弹窗遮罩：浮层自身就带 data-theme，所以必须同时命中 .sne-layer[data-theme]，
   否则「后代选择器」永远匹配不到（浮层不在 .sne 里面）。 */
.sne--dark .sne-modal, .sne[data-theme="dark"] .sne-modal,
.sne-layer[data-theme="dark"] { background: rgba(0, 0, 0, .55); }
.sne--dark .sne-video, .sne[data-theme="dark"] .sne-video { background: #000; }

/* ---------- 10.2 starry 星空（深色 + 渐变） ---------- */
.sne--starry, .sne[data-theme="starry"], .sne-layer[data-theme="starry"] {
  --sne-bg: #0f1024;
  --sne-bg-soft: #161734;
  --sne-bg-hover: #1e2044;
  --sne-bg-active: #2a2564;
  --sne-border: #2c2c5e;
  --sne-border-soft: #212148;
  --sne-text: #e9eafb;
  --sne-text-sub: #bbbee4;
  --sne-text-muted: #8b8ec0;
  --sne-text-faint: #686c9e;
  --sne-primary: #8b7cf6;
  --sne-primary-soft: #241f4f;
  --sne-danger: #fb7185;
  --sne-warning: #fbbf24;
  --sne-shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --sne-shadow: 0 10px 28px -8px rgba(0, 0, 0, .62), 0 2px 8px rgba(0, 0, 0, .42);
}
/* 星空底：两团柔光 + 细星点（写成 .sne.sne--x：浮层也带 sne--x 类，不能被底图覆盖） */
.sne.sne--starry, .sne[data-theme="starry"] {
  background:
    radial-gradient(900px 320px at 8% -12%, rgba(139, 124, 246, .22), transparent 62%),
    radial-gradient(700px 260px at 108% 2%, rgba(56, 189, 248, .16), transparent 60%),
    var(--sne-bg);
}
.sne--starry .sne-content, .sne--starry .sne-mdprev { background: transparent; }
.sne--starry .sne-toolbar,
.sne--starry .sne-status,
.sne--starry .sne-md-head { background: color-mix(in srgb, var(--sne-bg) 72%, transparent); }
.sne--starry .sne-content code { color: #f8a5d1; }
.sne--starry .sne-content pre, .sne--starry .sne-mdprev pre { background: #0a0b1a; border-color: #26264f; }
.sne--starry .sne-content blockquote { border-left-color: var(--sne-primary); background: linear-gradient(90deg, rgba(139, 124, 246, .18), transparent 62%); }
.sne--starry .sne-content a, .sne--starry .sne-mdprev a { color: #b9aeff; border-bottom-color: rgba(185, 174, 255, .35); }
.sne--starry .sne-modal, .sne[data-theme="starry"] .sne-modal,
.sne-layer[data-theme="starry"] { background: rgba(6, 6, 20, .62); }

/* ---------- 10.3 paper 纸张（暖色浅底 + 衬线正文） ---------- */
.sne--paper, .sne[data-theme="paper"], .sne-layer[data-theme="paper"] {
  --sne-radius: 6px;
  --sne-radius-sm: 5px;
  --sne-radius-xs: 4px;
  --sne-bg: #fdfbf6;
  --sne-bg-soft: #f7f2e7;
  --sne-bg-hover: #f1eadd;
  --sne-bg-active: #f8e8ce;
  --sne-border: #e6dcc7;
  --sne-border-soft: #efe8d9;
  --sne-text: #3b3226;
  --sne-text-sub: #6b5f4c;
  --sne-text-muted: #8d8170;
  --sne-text-faint: #b5a995;
  --sne-primary: #b45309;
  --sne-primary-soft: #fbf1e0;
  --sne-danger: #b91c1c;
  --sne-shadow-sm: 0 1px 2px rgba(120, 100, 70, .06);
  --sne-shadow: 0 10px 28px -10px rgba(120, 100, 70, .22), 0 2px 6px rgba(120, 100, 70, .08);
}
.sne--paper .sne-content, .sne--paper .sne-mdprev {
  font-family: Georgia, "Songti SC", "Source Han Serif SC", "Noto Serif SC", "SimSun", serif;
  font-size: 15.5px;
  line-height: 1.9;
}
.sne--paper .sne-content pre, .sne--paper .sne-mdprev pre { background: #f5efe2; border-color: #e8dfcc; }
.sne--paper .sne-content blockquote { background: linear-gradient(90deg, #fbf1e0, transparent 62%); }
.sne--paper .sne-md-tool:hover { color: var(--sne-primary); }

/* ---------- 10.4 mint 薄荷（清爽浅色 + 大圆角） ---------- */
.sne--mint, .sne[data-theme="mint"], .sne-layer[data-theme="mint"] {
  --sne-radius: 16px;
  --sne-radius-sm: 12px;
  --sne-radius-xs: 9px;
  --sne-btn: 32px;
  --sne-bg: #ffffff;
  --sne-bg-soft: #f3fbf9;
  --sne-bg-hover: #eaf7f3;
  --sne-bg-active: #d9f2ea;
  --sne-border: #d6ebe4;
  --sne-border-soft: #e8f5f1;
  --sne-text: #16302b;
  --sne-text-sub: #4c6b64;
  --sne-text-muted: #78958e;
  --sne-text-faint: #a9c1bb;
  --sne-primary: #0d9488;
  --sne-primary-soft: #effaf7;
  --sne-shadow-sm: 0 1px 3px rgba(13, 148, 136, .08);
  --sne-shadow: 0 10px 26px -8px rgba(13, 148, 136, .18), 0 2px 6px rgba(13, 148, 136, .08);
}
.sne--mint .sne-toolbar { background: linear-gradient(180deg, var(--sne-bg-soft), var(--sne-bg)); }
.sne--mint .sne-content code { color: #0f766e; background: var(--sne-bg-soft); }
.sne--mint .sne-content blockquote { background: linear-gradient(90deg, #e6f7f2, transparent 62%); }
.sne--mint .sne-btn:hover { background: var(--sne-bg-active); }
.sne--mint .sne-md-tool:hover { background: var(--sne-bg-active); }

/* ---------- 10.5 ocean 海盐蓝（浅色 · 清透蓝） ---------- */
.sne--ocean, .sne[data-theme="ocean"], .sne-layer[data-theme="ocean"] {
  --sne-bg: #ffffff;
  --sne-bg-soft: #f4f9fd;
  --sne-bg-hover: #eaf3fb;
  --sne-bg-active: #dceafa;
  --sne-border: #d5e6f5;
  --sne-border-soft: #e6f0f9;
  --sne-text: #0f2430;
  --sne-text-sub: #3f5c6e;
  --sne-text-muted: #6d8798;
  --sne-text-faint: #a3b8c6;
  --sne-primary: #0284c7;
  --sne-primary-soft: #eff8ff;
  --sne-danger: #dc2626;
  --sne-warning: #ea8a00;
  --sne-shadow-sm: 0 1px 3px rgba(2, 132, 199, .08);
  --sne-shadow: 0 10px 26px -8px rgba(2, 132, 199, .18), 0 2px 6px rgba(2, 132, 199, .07);
}
/* 注意：浮层也会带上 sne--<name> 类，所以「编辑器本体背景」必须写成
   .sne.sne--x（要求同时具备 .sne），否则弹窗遮罩会被主题背景覆盖。 */
.sne.sne--ocean { background: linear-gradient(180deg, #f7fbff, var(--sne-bg) 220px); }
.sne--ocean .sne-toolbar { background: linear-gradient(180deg, #eef7fe, var(--sne-bg)); }
.sne--ocean .sne-content code { color: #0369a1; background: var(--sne-bg-soft); }
.sne--ocean .sne-content blockquote { background: linear-gradient(90deg, #e6f3fd, transparent 62%); }

/* ---------- 10.6 sunset 晚霞橙（浅色 · 暖调） ---------- */
.sne--sunset, .sne[data-theme="sunset"], .sne-layer[data-theme="sunset"] {
  --sne-radius: 14px;
  --sne-radius-sm: 9px;
  --sne-radius-xs: 6px;
  --sne-bg: #fffdfb;
  --sne-bg-soft: #fff6f0;
  --sne-bg-hover: #ffece0;
  --sne-bg-active: #ffe0cc;
  --sne-border: #f6dcc9;
  --sne-border-soft: #fbeade;
  --sne-text: #3a2318;
  --sne-text-sub: #6d4a35;
  --sne-text-muted: #97785f;
  --sne-text-faint: #c2a992;
  --sne-primary: #ea580c;
  --sne-primary-soft: #fff4ec;
  --sne-danger: #dc2626;
  --sne-warning: #d97706;
  --sne-shadow-sm: 0 1px 3px rgba(234, 88, 12, .08);
  --sne-shadow: 0 10px 26px -8px rgba(234, 88, 12, .2), 0 2px 6px rgba(234, 88, 12, .08);
}
.sne.sne--sunset { background: linear-gradient(180deg, #fff8f3, var(--sne-bg) 240px); }
.sne--sunset .sne-toolbar { background: linear-gradient(180deg, #fff2e8, var(--sne-bg)); }
.sne--sunset .sne-content code { color: #c2410c; background: var(--sne-bg-soft); }
.sne--sunset .sne-content blockquote { border-left-color: #fb923c; background: linear-gradient(90deg, #ffeedd, transparent 62%); }
.sne--sunset .sne-content h1, .sne--sunset .sne-content h2 { color: #9a3412; }

/* ---------- 10.7 ink 墨韵（浅色 · 素雅衬线） ---------- */
.sne--ink, .sne[data-theme="ink"], .sne-layer[data-theme="ink"] {
  --sne-radius: 4px;
  --sne-radius-sm: 3px;
  --sne-radius-xs: 3px;
  --sne-bg: #fdfdfc;
  --sne-bg-soft: #f5f5f3;
  --sne-bg-hover: #eeeeeb;
  --sne-bg-active: #e6e6e2;
  --sne-border: #dcdcd8;
  --sne-border-soft: #ebebe8;
  --sne-text: #1a1a19;
  --sne-text-sub: #4a4a47;
  --sne-text-muted: #787872;
  --sne-text-faint: #a8a8a0;
  --sne-primary: #40403c;
  --sne-primary-soft: #f0f0ed;
  --sne-danger: #b91c1c;
  --sne-warning: #a16207;
  --sne-shadow-sm: 0 1px 2px rgba(0, 0, 0, .05);
  --sne-shadow: 0 8px 22px -10px rgba(0, 0, 0, .2), 0 2px 6px rgba(0, 0, 0, .05);
}
.sne--ink .sne-content, .sne--ink .sne-mdprev {
  font-family: Georgia, "Songti SC", "Source Han Serif SC", "Noto Serif SC", "SimSun", serif;
  font-size: 15.5px;
  line-height: 1.92;
}
.sne--ink .sne-toolbar { background: var(--sne-bg-soft); border-bottom-color: var(--sne-border); }
.sne--ink .sne-content code { color: #444; background: #f2f2ef; }
.sne--ink .sne-content blockquote { border-left: 3px double var(--sne-primary); color: var(--sne-text-sub); background: transparent; }
.sne--ink .sne-content h1 { border-bottom: 2px solid var(--sne-border); padding-bottom: 6px; }
.sne--ink .sne-content hr { border-top: 3px double var(--sne-border); }

/* ---------- 10.8 cyber 赛博霓虹（深色 · 高饱和） ---------- */
.sne--cyber, .sne[data-theme="cyber"], .sne-layer[data-theme="cyber"] {
  --sne-radius: 10px;
  --sne-radius-sm: 7px;
  --sne-radius-xs: 5px;
  --sne-bg: #0b0f1a;
  --sne-bg-soft: #101828;
  --sne-bg-hover: #16203a;
  --sne-bg-active: #1d2a4d;
  --sne-border: #24324f;
  --sne-border-soft: #1a2438;
  --sne-text: #dff3ff;
  --sne-text-sub: #a7c6dd;
  --sne-text-muted: #7c9ab3;
  --sne-text-faint: #5b7690;
  --sne-primary: #22d3ee;
  --sne-primary-soft: #0d2b38;
  --sne-danger: #ff4d94;
  --sne-warning: #fbbf24;
  --sne-shadow-sm: 0 1px 3px rgba(0, 0, 0, .5);
  --sne-shadow: 0 10px 30px -8px rgba(34, 211, 238, .22), 0 2px 8px rgba(0, 0, 0, .5);
}
.sne.sne--cyber, .sne[data-theme="cyber"] {
  background:
    radial-gradient(760px 300px at 0% -10%, rgba(34, 211, 238, .16), transparent 60%),
    radial-gradient(680px 280px at 106% 4%, rgba(255, 77, 148, .14), transparent 60%),
    var(--sne-bg);
}
.sne--cyber .sne-content, .sne--cyber .sne-mdprev { background: transparent; }
.sne--cyber .sne-toolbar { border-bottom-color: #1d3b52; box-shadow: inset 0 -1px 0 rgba(34, 211, 238, .18); }
.sne--cyber .sne-content code { color: #7df9ff; background: #0c1c26; }
.sne--cyber .sne-content pre, .sne--cyber .sne-mdprev pre { background: #070b12; border-color: #1d3b52; }
.sne--cyber .sne-content blockquote { border-left-color: #22d3ee; background: linear-gradient(90deg, rgba(34, 211, 238, .16), transparent 62%); }
.sne--cyber .sne-content a, .sne--cyber .sne-mdprev a { color: #ff8ec4; border-bottom-color: rgba(255, 142, 196, .4); }
.sne--cyber .sne-primary, .sne--cyber .sne-btn-primary { color: #04202a; }
.sne--cyber .sne-modal, .sne-layer[data-theme="cyber"] { background: rgba(4, 8, 18, .68); }

/* ---------- 10.9 forest 松林绿（深色 · 自然） ---------- */
.sne--forest, .sne[data-theme="forest"], .sne-layer[data-theme="forest"] {
  --sne-radius: 10px;
  --sne-radius-sm: 7px;
  --sne-radius-xs: 5px;
  --sne-bg: #0f1a14;
  --sne-bg-soft: #14231b;
  --sne-bg-hover: #1a2e23;
  --sne-bg-active: #21382b;
  --sne-border: #24402f;
  --sne-border-soft: #1b2f23;
  --sne-text: #e2f3e8;
  --sne-text-sub: #b0cdbc;
  --sne-text-muted: #83a894;
  --sne-text-faint: #5f8271;
  --sne-primary: #34d399;
  --sne-primary-soft: #10301f;
  --sne-danger: #f87171;
  --sne-warning: #fbbf24;
  --sne-shadow-sm: 0 1px 3px rgba(0, 0, 0, .45);
  --sne-shadow: 0 10px 28px -8px rgba(52, 211, 153, .16), 0 2px 8px rgba(0, 0, 0, .45);
}
.sne.sne--forest, .sne[data-theme="forest"] {
  background:
    radial-gradient(700px 280px at 4% -12%, rgba(52, 211, 153, .14), transparent 62%),
    var(--sne-bg);
}
.sne--forest .sne-content, .sne--forest .sne-mdprev { background: transparent; }
.sne--forest .sne-content code { color: #86efac; background: #10241a; }
.sne--forest .sne-content pre, .sne--forest .sne-mdprev pre { background: #0a1410; border-color: #1e3a2a; }
.sne--forest .sne-content blockquote { border-left-color: #34d399; background: linear-gradient(90deg, rgba(52, 211, 153, .14), transparent 62%); }
.sne--forest .sne-content a, .sne--forest .sne-mdprev a { color: #7dd3a8; border-bottom-color: rgba(125, 211, 168, .35); }
.sne--forest .sne-primary, .sne--forest .sne-btn-primary { color: #04211a; }
.sne--forest .sne-modal, .sne-layer[data-theme="forest"] { background: rgba(4, 12, 8, .66); }

/* ==================================================================
 * 11. 全屏 / 只读 / 响应式
 * ================================================================== */
.sne--fullscreen {
  position: fixed;
  inset: 0;
  z-index: var(--sne-z);
  border-radius: 0;
  border: 0;
}
.sne--fullscreen .sne-toolbar { border-radius: 0; }
.sne--fullscreen .sne-status { border-radius: 0; }
.sne-noscroll, .sne-noscroll body { overflow: hidden !important; }

.sne--readonly { background: var(--sne-bg-soft); }
.sne--readonly .sne-toolbar { opacity: .82; }
.sne--readonly .sne-content { cursor: default; }

/* ==================================================================
 * 12. AI 侧栏（编辑器内左右分栏）
 * ================================================================== */
.sne-aipanel--side {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  padding: 0;
}
.sne-aipanel--side .sne-ai-head { flex: none; }
.sne-aipanel--side .sne-ai-enginebar { flex: none; }
.sne-aipanel--side .sne-ai-funcs { flex: none; }
.sne-aipanel--side .sne-ai-prompt { flex: none; }
.sne-aipanel--side .sne-ai-out {
  flex: 1 1 auto;
  min-height: 90px;
  max-height: none;
}
.sne-aipanel--side .sne-ai-foot { flex: none; flex-wrap: wrap; row-gap: 6px; }
.sne-ai-scope.is-sel { color: var(--sne-primary); background: var(--sne-primary-soft); }
.sne-spacer { flex: 1 1 auto; }

/* ==================================================================
 * 13. 地图卡片（插入到内容里的地点节点）
 * ================================================================== */
.sne-map {
  display: flex;
  align-items: center;
  gap: 12px;
  max-width: 100%;
  margin: 10px 0;
  padding: 10px 12px;
  border: 1px solid var(--sne-border);
  border-radius: var(--sne-radius-sm);
  background: var(--sne-bg-soft);
  font-size: 13px;
  vertical-align: top;
}
.sne-map-main { display: flex; align-items: center; gap: 11px; min-width: 0; flex: 1 1 auto; }
.sne-map-thumb {
  flex: none;
  width: 86px;
  height: 62px;
  border-radius: 6px;
  object-fit: cover;
  background: var(--sne-bg-hover);
  display: block;
}
.sne-map-thumb--ph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background:
    radial-gradient(60px 40px at 30% 20%, rgba(255, 255, 255, .28), transparent 70%),
    linear-gradient(135deg, var(--sne-map-color, #0a84ff), #1f2a44);
}
.sne-map-thumb--ph svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linejoin: round; }
.sne-map-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sne-map-name { font-weight: 600; color: var(--sne-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sne-map-addr { color: var(--sne-text-sub); font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sne-map-coord { color: var(--sne-text-faint); font-size: 11.5px; font-family: var(--sne-mono); }
.sne-map-acts { display: flex; align-items: center; gap: 4px; margin-left: auto; flex: none; }
.sne-map-act {
  display: inline-flex;
  align-items: center;
  height: 24px;
  padding: 0 9px;
  border: 1px solid var(--sne-border);
  border-radius: 12px;
  background: var(--sne-bg);
  color: var(--sne-text-sub) !important;
  font-size: 12px;
  text-decoration: none !important;
  cursor: pointer;
  user-select: none;
}
.sne-map-act:hover { color: var(--sne-primary) !important; border-color: var(--sne-primary); }
.sne-map-act--del:hover { color: var(--sne-danger) !important; border-color: var(--sne-danger); }
.sne-map-replace { display: none; }

/* ---- 卡片 / 完整地图 两种展示形态 ---- */
/* ⚠️ 修饰类由 JS 按 data-show 拼出来：show='map' → .sne-map--map、show='card' → .sne-map--card。
   这里曾经写成 .sne-map--full，跟 JS 生成的名字对不上 —— 完整地图拿不到这块样式，
   画布 .sne-map-stage 就没有高度，插进去以后只看得见下面那条信息栏，像是「没渲染成地图」。
   --full 作为早期命名的别名一起保留，免得旧内容掉样式。 */
/* 卡片形态：横向「缩略图 + 信息 + 操作组」，基础 .sne-map 就是这套布局。
   这里显式再写一条，让 JS 生成的 .sne-map--card 在样式表里真实存在 ——
   免得重蹈「JS 拼出来的类名在 CSS 里根本没规则」的覆辙。 */
.sne-map--card { align-items: center; }

.sne-map--map,
.sne-map--full {
  display: block;
  position: relative;      /* 完整地图里的浮层（信息胶囊 + 操作组）靠它定位 */
  padding: 0;
  overflow: hidden;
  border-radius: 12px;
  background: var(--sne-bg-soft);
}
/* 完整地图的「画布」：装饰器把实时地图 / 大静态图 / 占位图塞进来
   （挂载容器是瞬态装饰，存库时会被剥掉，只留 data-* 让渲染时重建） */
.sne-map-stage {
  position: relative;
  display: block;
  height: 248px;
  background: var(--sne-bg-hover);
  overflow: hidden;
}
/* 画布里的「图层」铺满整块；角标除外 ——
   它要待在右下角，被 inset:0 一起拉伸的话会变成一整块半透明遮罩。 */
.sne-map-stage > :not(.sne-map-ph-badge) { position: absolute; inset: 0; }
.sne-map-shot { display: block; cursor: pointer; }
.sne-map-bigshot { width: 100%; height: 100%; object-fit: cover; display: block; }
.sne-map-ph {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 16px;
  text-align: center;
  color: #fff;
  background:
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .07) 0 1px, transparent 1px 44px),
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .07) 0 1px, transparent 1px 44px),
    radial-gradient(120% 90% at 20% 0%, var(--sne-map-color, #0a84ff) 0%, #223052 58%, #131a2b 100%);
  cursor: pointer;
}
.sne-map-ph svg { width: 34px; height: 34px; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linejoin: round; }
.sne-map-ph-name { font-size: 14px; font-weight: 600; }
.sne-map-ph-hint { font-size: 11.5px; opacity: .82; line-height: 1.6; max-width: 320px; }
.sne-map-ph-badge {
  position: absolute; right: 10px; bottom: 10px;
  padding: 3px 9px; border-radius: 12px;
  background: rgba(0, 0, 0, .42);
  color: #fff; font-size: 11px;
  backdrop-filter: blur(4px);
}
/* 完整地图的浮层：左上信息胶囊 + 右上操作组。
   都是瞬态装饰（.sne-map-hud 已登记为 chrome），不进存库 HTML。
   —— 以前这里是画布下面的一条信息栏（.sne-map-fullfoot），看着就是「地图下面又挂了张卡片」，
   而且它当时没被登记成装饰，名称/地址整条写进了存库 HTML，等于第二份真源。 */
.sne-map-hud {
  position: absolute;
  top: 10px;
  left: 10px;
  right: 10px;
  z-index: 2;
  display: flex;
  align-items: flex-start;
  gap: 8px;
  pointer-events: none;    /* 浮层不挡地图拖拽，只有按钮自己可点 */
}
.sne-map-hud .sne-map-acts {
  pointer-events: auto;
  margin-left: auto;
  padding: 3px;
  border-radius: 14px;
  background: var(--sne-bg);
  box-shadow: 0 3px 12px rgba(15, 23, 42, .18);
  opacity: .92;
  transition: opacity .16s ease;
}
.sne-map--map:hover .sne-map-hud .sne-map-acts { opacity: 1; }
.sne-map-hud .sne-map-act { border-color: transparent; background: transparent; }
.sne-map-hud .sne-map-act:hover { background: var(--sne-bg-hover); }
.sne-map-chip {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  max-width: min(56%, 340px);
  padding: 7px 12px 7px 8px;
  border: 1px solid var(--sne-border);
  border-radius: 11px;
  background: var(--sne-bg);
  box-shadow: 0 3px 12px rgba(15, 23, 42, .16);
}
.sne-map-chip .sne-map-pin {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; flex: none;
  border-radius: 8px;
  color: #fff;
  background: var(--sne-map-color, #0a84ff);
}
.sne-map-chip .sne-map-pin svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linejoin: round; }
.sne-map-chip .sne-map-info { min-width: 0; }
/* 占位图自己已经把名称 / 地址写在大字里了，胶囊再叠一份就成双份了 */
.sne-map-stage[data-mode="placeholder"] ~ .sne-map-hud .sne-map-chip { display: none; }
.sne-map-act.is-on { color: var(--sne-primary) !important; border-color: var(--sne-primary); background: var(--sne-primary-soft); }

/* 完整地图在存库 HTML 里是「只有 data-* 的空壳」（画布 / 浮层都是瞬态装饰，会被剥掉）。
   正常渲染由装饰流水线重建，但万一有人把内容直接丢到一个没挂 Sneditor 的展示页上，
   空壳就会变成一个洞 —— 这里用纯 CSS 兜一句，把名称 / 地址 / 坐标印出来。 */
.sne-map--map:empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 132px;
  padding: 16px;
  text-align: center;
  background:
    repeating-linear-gradient(90deg, rgba(120, 132, 156, .1) 0 1px, transparent 1px 42px),
    repeating-linear-gradient(0deg, rgba(120, 132, 156, .1) 0 1px, transparent 1px 42px),
    var(--sne-bg-hover);
}
.sne-map--map:empty::before { content: attr(data-name); font-weight: 600; color: var(--sne-text-sub); }
.sne-map--map:empty::after {
  content: attr(data-address) "\A" attr(data-lng) ", " attr(data-lat);
  white-space: pre-line;
  font-size: 12px;
  line-height: 1.7;
  color: var(--sne-text-muted);
}

/* ==================================================================
 * 14. 地图选点弹窗
 * ================================================================== */
/* 地图弹窗要更宽一些：三段的 max-width 一起提上去，才不会挤成一团 */
.sne-modal--map { padding: 3vh 20px; }
.sne-modal--map .sne-modal-head,
.sne-modal--map .sne-modal-body,
.sne-modal--map .sne-modal-foot { max-width: 1120px; }
.sne-modal--map .sne-modal-body { padding: 16px; }
.sne-mapbody { display: flex; gap: 14px; align-items: stretch; }
.sne-mapbody .sne-mapleft { display: flex; flex-direction: column; gap: 10px; flex: 1 1 0; min-width: 0; }
.sne-mapbody .sne-mapright { display: flex; flex-direction: column; gap: 10px; flex: none; width: 322px; min-height: 0; }
.sne-mapcanvas {
  position: relative;
  flex: 1 1 auto;
  min-height: min(380px, 46vh);   /* 视口矮的时候不硬撑，交给 body 滚动 */
  border: 1px solid var(--sne-border);
  border-radius: var(--sne-radius-sm);
  background: var(--sne-bg-soft);
  overflow: hidden;
}
.sne-mapmount { position: absolute; inset: 0; }
.sne-maploading, .sne-mapmanual {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 20px;
  text-align: center;
  color: var(--sne-text-muted);
  font-size: 13px;
  line-height: 1.7;
}
.sne-mapmanual svg { width: 30px; height: 30px; fill: none; stroke: var(--sne-primary); stroke-width: 1.5; }
.sne-mapmanual p { margin: 0; color: var(--sne-text-sub); }
.sne-mapmanual-hint { font-size: 12px; color: var(--sne-text-muted); max-width: 380px; }
.sne-mapnote { font-size: 11.5px; line-height: 1.6; color: var(--sne-text-faint); }
.sne-mapnote a { color: var(--sne-primary); }
.sne-mapsearch { display: flex; gap: 6px; flex: none; }
.sne-mapsearch .sne-mapkw { flex: 1 1 auto; min-width: 0; }
.sne-mapresults {
  flex: 1 1 auto;
  min-height: 120px;
  max-height: 240px;
  overflow-y: auto;
  border: 1px solid var(--sne-border-soft);
  border-radius: var(--sne-radius-sm);
  background: var(--sne-bg-soft);
  padding: 4px;
}
.sne-mapresult {
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 100%;
  padding: 7px 9px;
  border: 0;
  border-radius: var(--sne-radius-xs);
  background: transparent;
  color: var(--sne-text);
  font: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.sne-mapresult:hover { background: var(--sne-bg-hover); }
.sne-mapresult.is-active { background: var(--sne-bg-active); color: var(--sne-primary); }
.sne-mapresult b { font-weight: 600; }
.sne-mapresult i { font-style: normal; font-size: 11.5px; color: var(--sne-text-muted); }
.sne-mapempty { padding: 14px 10px; text-align: center; font-size: 12.5px; color: var(--sne-text-faint); }
.sne-mappicked {
  flex: none;
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-top: auto;                 /* 右栏内容少时，表单贴底，不留突兀空档 */
  padding-top: 10px;
  border-top: 1px solid var(--sne-border-soft);
}
.sne-mapform-row { display: flex; align-items: center; gap: 8px; }
.sne-mapform-row--2 { gap: 8px; }
.sne-mapform-row--2 > span { display: flex; align-items: center; gap: 6px; flex: 1 1 0; min-width: 0; }
.sne-mapform-row label { flex: none; width: 62px; font-size: 12px; color: var(--sne-text-muted); }
.sne-mapform-row--2 label { width: auto; }
.sne-mapform-row .sne-input { flex: 1 1 auto; min-width: 0; font-size: 13px; }
.sne-mapform-row--2 .sne-input { width: 100%; }

/* ---- 展示形态（卡片 / 完整地图）分段选择 ---- */
.sne-mapshot {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
}
.sne-mapshot > label { flex: none; width: 62px; font-size: 12px; color: var(--sne-text-muted); }
.sne-mapshows {
  display: inline-flex;
  flex: 1 1 auto;
  padding: 2px;
  border: 1px solid var(--sne-border);
  border-radius: 9px;
  background: var(--sne-bg-soft);
}
.sne-mapshow {
  flex: 1 1 0;
  height: 26px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--sne-text-sub);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  transition: background .14s ease, color .14s ease;
}
.sne-mapshow:hover { color: var(--sne-primary); }
.sne-mapshow.is-active { background: var(--sne-bg); color: var(--sne-primary); font-weight: 600; box-shadow: 0 1px 3px rgba(15, 23, 42, .12); }

/* ---- 地址 → 坐标（正/逆地理编码） ---- */
.sne-mapgeo { display: flex; align-items: center; gap: 6px; }
.sne-mapgeo .sne-input { flex: 1 1 auto; min-width: 0; }
.sne-mapgeo .sne-btn-ghost { flex: none; height: 30px; padding: 0 10px; font-size: 12px; }
.sne-mapgeo.is-busy .sne-btn-ghost { opacity: .55; pointer-events: none; }
.sne-mapauto { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--sne-text-muted); }
.sne-mapauto .sne-check { font-size: 11.5px; }
.sne-mapsource { font-size: 11.5px; color: var(--sne-text-faint); }
.sne-mapprov { display: flex; align-items: center; gap: 4px; margin-left: 14px; }
.sne-mapprovtab {
  height: 26px;
  padding: 0 12px;
  border: 1px solid var(--sne-border);
  border-radius: 13px;
  background: var(--sne-bg);
  color: var(--sne-text-sub);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}
.sne-mapprovtab:hover { color: var(--sne-primary); border-color: var(--sne-primary); }
.sne-mapprovtab.is-active { background: var(--sne-primary); border-color: var(--sne-primary); color: #fff; }
.sne-mapstatus { font-size: 12px; color: var(--sne-text-muted); }
.sne-mapstatus.is-ok { color: var(--sne-primary); }
.sne-mapstatus.is-error { color: var(--sne-danger); }

/* ==================================================================
 * 15. 主题面板（色板）
 * ================================================================== */
.sne-themepanel { width: 322px; padding: 4px; }
.sne-themepanel-head { margin: 4px 0 8px; font-size: 12px; color: var(--sne-text-muted); }
.sne-themelist {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 308px;          /* 10 套主题 → 超出滚动，避免面板顶破视口 */
  overflow-y: auto;
  padding-right: 2px;
}
.sne-themeitem {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 7px 8px;
  border: 1px solid transparent;
  border-radius: var(--sne-radius-xs);
  background: transparent;
  color: var(--sne-text);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.sne-themeitem:hover { background: var(--sne-bg-hover); }
.sne-themeitem.is-active { border-color: var(--sne-primary); background: var(--sne-bg-active); }
.sne-themeswatch {
  display: inline-flex;
  flex: none;
  width: 46px;
  height: 26px;
  border: 1px solid var(--sne-border);
  border-radius: 6px;
  overflow: hidden;
}
.sne-themeswatch i { flex: 1 1 0; }
.sne-themeinfo { display: flex; flex-direction: column; min-width: 0; line-height: 1.35; }
.sne-themeinfo b { font-size: 13px; font-weight: 600; }
.sne-themeinfo i { font-style: normal; font-size: 11px; color: var(--sne-text-muted); }
.sne-themecode { margin-left: auto; font-family: var(--sne-mono); font-size: 10.5px; color: var(--sne-text-faint); }
.sne-themeform { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--sne-border-soft); }
.sne-themerow { display: flex; align-items: center; gap: 6px; margin-bottom: 7px; }
.sne-themerow .sne-input { flex: 1 1 auto; min-width: 0; }
.sne-themeform .sne-hint { margin-top: 2px; }

/* ==================================================================
 * 16. 模态框补充（预览的多视图切换 / 底部操作条）
 * ================================================================== */
.sne-modal-tabs { display: flex; align-items: center; gap: 2px; margin-left: 16px; padding: 3px; background: var(--sne-bg-hover); border-radius: 8px; }
/* 预览弹窗偏「阅读」用途，比默认 720px 放宽一些，好让正文排到 860px */
.sne-modal--preview .sne-modal-head,
.sne-modal--preview .sne-modal-body { max-width: 920px; }
.sne-modal-foot {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
  padding: 12px 16px;
  border-top: 1px solid var(--sne-border-soft);
  background: var(--sne-bg);
  border-radius: 0 0 var(--sne-radius) var(--sne-radius);
}
.sne-preview-md, .sne-preview-text {
  margin: 0;
  padding: 14px 16px;
  background: var(--sne-bg-soft);
  border: 1px solid var(--sne-border-soft);
  border-radius: var(--sne-radius-sm);
  font-family: var(--sne-mono);
  font-size: 13px;
  line-height: 1.7;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ==================================================================
 * 17. 响应式 / 打印
 * ================================================================== */
@media (max-width: 1024px) {
  .sne-pane { flex-basis: 320px !important; width: 320px !important; }
}
@media (max-width: 900px) {
  /* 窄屏：侧栏改为整体下移，不再挤压内容 */
  .sne-body { flex-wrap: wrap; }
  .sne-pane, .sne-side { flex-basis: 100% !important; width: 100% !important; }
  .sne-side { border-top: 1px solid var(--sne-border-soft); }
  .sne-pane { border-left: 0; max-height: 46vh; }
  .sne-pane-resizer { display: none; }
  .sne-pane-body { padding: 10px; }
}
@media (max-width: 760px) {
  /* 窄屏 Markdown 分栏：上下堆叠，两块都保留可输入（此时分隔条不再可拖） */
  .sne--mode-markdown .sne-body { flex-wrap: nowrap; flex-direction: column; }
  .sne--mode-markdown .sne-md { flex: 0 0 42%; border-right: 0; border-bottom: 1px solid var(--sne-border-soft); }
  .sne--mode-markdown.sne--md-resized .sne-md { flex: 0 0 42%; }   /* 窄屏忽略拖拽比例 */
  .sne--mode-markdown .sne-mdprev { flex: 1 1 0; }
  .sne--mode-markdown .sne-mdsplit { display: none; }
  .sne-mapbody { flex-direction: column; }
  .sne-mapbody .sne-mapright { width: 100%; }
  .sne-mapcanvas { min-height: 280px; }
  .sne-mappicked { margin-top: 0; }
}
@media (max-width: 720px) {
  .sne-toolbar { gap: 4px; padding: 6px; }
  .sne-btn { width: 28px; height: 28px; }
  .sne-content { padding: 14px 15px; }
  .sne-placeholder { top: 14px; left: 15px; right: 15px; }
  .sne-aipanel, .sne-form, .sne-themepanel { width: min(340px, calc(100vw - 40px)); }
  .sne-gridpanel { width: 190px; }
  .sne-mdprev { padding: 14px 15px; }
  .sne-map { flex-wrap: wrap; }
  .sne-map-acts { margin-left: 0; }
}

@media print {
  .sne-toolbar, .sne-status, .sne-pop, .sne-toasts, .sne-side, .sne-md, .sne-sourcetag { display: none !important; }
  .sne { border: 0; box-shadow: none; }
  .sne-body { height: auto !important; }
  .sne-content, .sne-mdprev { overflow: visible; padding: 0; }
}
