/* editor.css — Typora 式所见即所得编辑器（编辑视图 = 阅读页渲染镜像）
 * 正文排版复用 reader.css 的 .reader-title / .reader-meta / .para-* / .reader-body
 */

#view-editor {
  /* 容器随主体卡片挂载：布局由 .card-overlay 提供 */
}
/* 编辑器视图：整卡改为 flex 列（滚动区 + 底部工具栏），覆盖 .card-overlay 的整卡滚动与底部避让留白
   ④ 内边距上下左右一致 1.2rem：顶部 1.2rem 写在卡片上（在滚动容器外部，所以是“钉住”的）；
   左右 1.2rem 交给 .editor-scroll；卡片左右 padding 保持 0，使底部工具栏仍能通栏 */
#view-editor.card-overlay {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 1.2rem 0 0;
}
/* 正文滚动区触点触底不串滚到下层列表 */
.editor-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 0 1.2rem 1.2rem;
}
/* 移动端键盘余量：iOS 聚焦 contenteditable 时系统触发 reveal 滚动，
   只有内部滚动容器有足够余量时 iOS 才滚动它（而非视觉视口/文档），
   否则光标会被滚到键盘后面——这是 iOS 键盘遮挡的官方一线解法 */
@media (max-width: 768px) {
  .editor-scroll {
    padding-bottom: 40vh;
  }
}
.editor-loading {
  text-align: center;
  color: #94a3b8;
  font-size: 0.7rem;
  padding: 2rem 0;
}
.editor-cancel {
  border: 1px solid #e2e8f0;
  background: #fff;
  border-radius: 0.3rem;
  padding: 0.4rem 0.8rem;
  font-size: 0.65rem;
  color: #64748b;
  cursor: pointer;
  margin-bottom: 0.6rem;
}

/* ---------- 头部（标题 + 元信息，与阅读页同款居中排版） ---------- */
.editor-head {
  text-align: center;
  padding-top: 0; /* ④ 顶部留白统一由 #view-editor.card-overlay 的 1.2rem 承担 */
  margin-bottom: 1.2rem; /* 更贴近正文 */
}
.editor-title-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
}
.editor-title-row .reader-title {
  margin: 0;
  min-width: 2rem;
  outline: none;
}
.editor-title-row .reader-title:empty::before {
  content: "文章总标题";
  color: #cbd5e1;
}

/* 置顶 / 加密 只读状态 tag：无背景无边框，icon + 文本 */
.editor-flag-tag {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0;
  border: none;
  background: transparent;
  font-size: 0.78rem; /* 原 0.6rem，副标题行所有元素放大 30% */
  color: #94a3b8;
  line-height: 1;
  user-select: none;
}
.editor-flag-tag .icon {
  display: block; /* 消除 svg 行内基线占位，保证与文本上下中心对齐 */
  flex-shrink: 0;
  width: 0.806rem;
  height: 0.806rem;
}
.editor-flag-tag span {
  display: inline-flex;
  align-items: center;
  line-height: 1;
}
.editor-flag-tag.pin.on {
  color: #2563eb;
}
.editor-flag-tag.secret.on {
  color: #15803d;
}

/* 背景音乐按钮：无背景无边框，icon + 文本 */
.editor-music-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0;
  border: none;
  background: transparent;
  font-size: 0.806rem; /* 原 0.62rem，副标题行所有元素放大 30% */
  color: #475569;
  cursor: pointer;
  font-family: inherit;
  transition: all 0.15s;
}
.editor-music-btn.active,
.editor-music-btn:hover {
  color: #2563eb;
}
.editor-music-btn .icon {
  width: 0.91rem;
  height: 0.91rem;
  vertical-align: middle;
}
.editor-icon-btn {
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 50%;
  border: 1px solid #e2e8f0;
  background: #fff;
  font-size: 0.8rem;
  cursor: pointer;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: all 0.15s;
}
.editor-icon-btn:hover,
.editor-icon-btn.active {
  background: #eff6ff;
  border-color: #93c5fd;
}
.editor-icon-btn.tiny {
  width: 1.625rem; /* 原 1.25rem，副标题行所有元素放大 30% */
  height: 1.625rem;
  border: none;
  background: transparent;
  opacity: 0.5;
  font-size: 0.806rem;
}
.editor-icon-btn .icon {
  width: 0.7rem;
  height: 0.7rem;
}
.editor-icon-btn.tiny .icon {
  width: 0.91rem;
  height: 0.91rem;
}
.editor-icon-btn.tiny:hover {
  opacity: 1;
  background: #eff6ff;
  border-radius: 50%;
}
/* 元信息行组合容器：组内 gap 小，组间 gap 大（4 组统一） */
.meta-group {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}
.editor-head .reader-meta {
  margin-top: 0.7rem;
  align-items: center;
  /* 组间间距连续自适应：宽屏 18px(=0.9rem)，320px 最低 5.6px——防窄屏副标题行换行（总宽超容器时音乐组被挤到第二行） */
  gap: 0.5rem; /* 老内核兑底（X5 不支持 flex gap 属性） */
  gap: clamp(5.6px, calc(5.7vw - 12.6px), 18px);
}
/* 音乐按钮组（最后一组）与阅读量组间距加倍（视觉 2×）；窄屏随 gap 同步收缩防换行 */
.editor-head .reader-meta .meta-group:last-child {
  margin-left: clamp(5.6px, calc(5.7vw - 12.6px), 18px);
}
/* 阅读量数字固定宽度槽：编辑态数字↔input 互换零位移 */
.meta-count-slot {
  display: inline-block;
  min-width: 3.4rem; /* 原 2.7rem，字号放大 30% 后预留 5 位等宽数字位宽 */
  text-align: center;
  font-variant-numeric: tabular-nums;
}
/* 阅读量组可点击（数字/icon/编辑态重建的 span 均在组内冒泡） */
.meta-read {
  cursor: pointer;
}
.meta-read:hover .meta-count-val {
  color: #2563eb;
}
.meta-count-val {
  color: #64748b;
  cursor: pointer; /* 阅读量数字与 icon 同样可点击进入编辑 */
}
.meta-date-wrap {
  position: relative;
  display: inline-flex;
  width: 1.625rem; /* 原 1.25rem，副标题行放大 30% */
  height: 1.625rem;
  flex-shrink: 0;
}
.meta-date-picker {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
  border: none;
  padding: 0;
  margin: 0;
  width: 100%;
  height: 100%;
}
.meta-count-input {
  width: 3.4rem; /* 与 .meta-count-slot 同宽，编辑不跳动 */
  height: 1.6rem; /* 与行高对齐 */
  padding: 0 0.1rem;
  border: none;
  border-bottom: 1px solid #93c5fd;
  background: transparent;
  border-radius: 0;
  text-align: center;
  font-size: 0.845rem; /* 原 0.65rem，与元信息行字号一致 */
  outline: none;
  color: #334155;
  font-family: inherit;
  -moz-appearance: textfield;
  -webkit-appearance: none;
}
.meta-count-input::-webkit-inner-spin-button,
.meta-count-input::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* ---------- 正文块流（同阅读页 reader-body） ---------- */
.editor-body {
  display: flex;
  flex-direction: column;
  gap: 0.225rem; /* 段落间距：0.9→0.45→0.225（各缩 1/2） */
}
.block {
  position: relative;
  border-radius: 0.5rem;
  border: 1px dashed transparent;
  transition: border-color 0.15s, background 0.15s;
}
/* 非文字块禁用原生长按菜单（图片/视频等）；文字段保留系统自由选择+复制粘贴剪切 */
.block.non-text {
  -webkit-touch-callout: none;
}
.block:focus-within {
  border-color: #cbd5e1;
  background: #f8fafc;
}
.block.active {
  border-color: #cbd5e1;
  background: #f8fafc;
}
.para-text[contenteditable="true"] {
  outline: none;
  white-space: pre-wrap; /* 段首空格真实渲染（与阅读页镜像一致），缩进由空格驱动 */
  -webkit-touch-callout: none; /* 抑制 iOS 长按系统菜单，改由自绘富文本工具条接管 */
  -webkit-user-select: text;
  user-select: text;
}
/* 空段占位提示：JS 以 .p-empty 同步（空段可能含无可见文本的 <br>，:empty 不匹配） */
.para-text[contenteditable="true"].p-empty::before {
  content: "输入文字段落…";
  color: #cbd5e1;
}
/* 聚焦态隐藏占位：消除“光标在占位符后面删不动”的视觉误导（光标本就位于真实文本节点，
   占位只是 ::before 伪元素，新输入文字顶格位置正确）。失焦后恢复提示。 */
.para-text[contenteditable="true"].p-empty:focus::before {
  content: "";
}

/* ---------- 底部合并工具栏（3 行 × 7 列，无框无底扁平） ---------- */
.editor-toolbar {
  flex-shrink: 0;
  border-top: 1px solid #e2e8f0;
  background: #fafbfc;
  padding: 0.4rem 0.5rem 0.2rem; /* 底部 0.45→0.2：消除 R3 下方视觉双重留白（按钮 pad + 容器 pad） */
  user-select: none;
  -webkit-user-select: none;
}
.tb-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr); /* 7 列等宽轨道，三行纵向对齐 */
  align-items: center;
}
/* 行间灰色分割线 */
.tb-row + .tb-row {
  border-top: 1px solid #e2e8f0;
  margin-top: 0.13rem; /* 原 0.26rem 缩小 1/2 */
  padding-top: 0.13rem;
}
.tb-btn {
  border: none;
  background: transparent;
  color: #475569;
  font-family: inherit;
  font-size: 0.62rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
  transition: color 0.15s;
}
.tb-btn:hover:not(:disabled) {
  color: #2563eb;
}
.tb-btn:active:not(:disabled) {
  color: #2563eb;
}
/* 输入样式激活态（加粗/下划/颜色）：点击后进入该样式，后续键入继承；蓝字提示 */
.tb-btn.tb-on {
  color: #2563eb;
}
.tb-btn.tb-on .tb-swatch-name {
  color: #2563eb;
}
.tb-btn.tb-on .tb-chip {
  box-shadow: 0 0 0 2px #93c5fd; /* 色块外侧蓝色标示环 */
}
.tb-btn:disabled {
  opacity: 0.32;
  cursor: default;
}

/* R1：单行文字操作；上下 padding 再缩 1/2（1.63→1.42rem），字号 -10%（1.2→1.08rem）
   line-height 1.12：字形 ink 视觉中心在 line box 中略偏低，微抬使视觉居中 */
.tb-row1 .tb-btn {
  height: 1.42rem;
  font-size: 1.08rem;
  font-weight: 500;
  line-height: 1.12;
}

/* R2：色块 + 名称；与 R1 同步再缩（1.63→1.5rem，仅收上下 padding） */
.tb-swatch {
  flex-direction: row;
  gap: 0.16rem;
  height: 1.5rem;
}
/* 色块：尺寸保持（1.36rem 高，不随 padding 缩放），圆角=主体卡片下边缘圆角（.content 0.4rem），宽=图标视觉宽 */
.tb-chip {
  width: 1.67rem;
  height: 1.36rem;
  border-radius: 0.4rem;
  border: 1px solid rgba(15, 23, 42, 0.14); /* 包边 */
  box-sizing: border-box;
  flex-shrink: 0;
}
.tb-swatch-name {
  font-size: 0.44rem;
  color: #64748b;
  line-height: 1;
}
.tb-btn:hover:not(:disabled) .tb-swatch-name {
  color: #2563eb;
}

/* R3：icon（左 6 图 / 右 2 图+字）；上下 padding 再缩 1/2（3.35→3.15rem）
   ③ 本行比 R1/R2 多一个「文本」按钮，单独改 8 列（R1/R2 仍 7 列）：
   行间有灰色分割线，两行间的列不对齐肉眼不可见；避免改动 R1/R2 后各留一个空轨道。 */
.tb-row3 {
  grid-template-columns: repeat(9, 1fr);
}
.tb-row3 .tb-btn {
  flex-direction: column;
  gap: 0.055rem; /* 原 0.22→0.11，再缩小 1/2 */
  height: 3.15rem;
  position: relative; /* 竖向分割线定位锚点 */
  /* 「应用」加入后单格 = 容器/9，320px 窄屏下小于 ic-image/ic-link 的盒宽（2.5rem）。
     这两个图标多出来的只是透明盒边（着色墨迹都是 ~2.18rem），min-width:0 让 1fr 不再被
     min-content（图标盒）撑开，于是不会横向溢出；图标居中、盒边压到邻格空白处，视觉无差。 */
  min-width: 0;
}
/* 发布按钮左侧竖向分割线：隔离插入组与发布组，不顶满整行高。
   锚在 data-op 而非列号：插入组按钮顺序调整（如「应用」「链接」互换）时自动跟随。 */
.tb-row3 .tb-btn[data-op="publish"]::before {
  content: "";
  position: absolute;
  left: -0.06rem; /* 骑在发布组与插入组的分界线上（grid 单元格即按钮宽度） */
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 56%;
  background: #e2e8f0;
}
.tb-ico .icon {
  width: 1.7rem;
  height: 1.7rem;
  flex-shrink: 0;
}
/* 插入/发布按钮图标：按各 symbol 实测“墨迹占 viewBox 的比例”反算盒子尺寸，
   使左侧 6 个插入图标（text/image/video/space/audio-eq/link）的**可见墨迹等大**（约 2.18rem）。
   依据：Playwright getBBox() 实测 inkW% —— text 97.25 / image 84(几何，含 stroke 为 86.9) /
   video 97.5 / space 97.6 / audio-eq 100 / link 87.5；盒子尺寸 = 2.18rem ÷ 着色墨迹%。
   右侧发布/放弃为「icon+文本」双行，保持原设计的小一号（与标签整体上下对齐） */
.tb-ico .icon[data-ic="ic-text"]    { width: 2.24rem; height: 2.24rem; } /* 97.25%（圆角方框 + T） */
.tb-ico .icon[data-ic="ic-image"]   { width: 2.51rem; height: 2.51rem; } /* 几何 84% + stroke-width 30 → 着色墨迹 86.9% */
.tb-ico .icon[data-ic="ic-video"]   { width: 2.24rem; height: 2.24rem; } /* 97.5% */
.tb-ico .icon[data-ic="ic-space"]   { width: 2.24rem; height: 2.24rem; } /* 97.6% */
.tb-ico .icon[data-ic="ic-audio-eq"] { width: 2.18rem; height: 2.18rem; } /* 100% */
.tb-ico .icon[data-ic="ic-link"]    { width: 2.50rem; height: 2.50rem; } /* 87.5% */
.tb-ico .icon[data-ic="ic-app"]     { width: 2.18rem; height: 2.18rem; } /* 100%（方框满 viewBox） */
.tb-ico .icon[data-ic="ic-publish"] { width: 1.78rem; height: 1.78rem; } /* 88.2% */
.tb-ico .icon[data-ic="ic-discard"] { width: 1.72rem; height: 1.72rem; } /* 90.9% */
.tb-lbl {
  font-size: 0.55rem;
  line-height: 1;
  color: inherit;
}

/* 窄屏：三行文字标签收起只留图标/字形，行高等比下调不压挤 */
@media (max-width: 520px) {
  .editor-toolbar {
    padding: 0.2rem 0.2rem 0.18rem; /* 底部同步压缩（原 0.3） */
  }
  .tb-row1 .tb-btn {
    height: 1.19rem; /* 桌面 1.42 等比（1.37 对应关系） */
    /* 字号 1.05 覆盖已删：统一桌面 1.08rem，连续缩放（字号断点禁令） */
  }
  .tb-swatch-name {
    display: none;
  }
  .tb-chip {
    width: 1.52rem;
    height: 1.22rem; /* 原尺寸等比（桌面 1.36/1.67） */
  }
  .tb-row3 .tb-btn {
    height: 2.61rem; /* 桌面 3.15 等比 */
  }
  .tb-ico .icon {
    width: 1.5rem;
    height: 1.5rem;
  }
}

/* ---------- 媒体块三态（空态占位 / 已上传渲染 / 更换） ---------- */
.media-empty {
  border: 1px dashed #cbd5e1;
  border-radius: 0.5rem;
  background: #fafbfc;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45rem;
  padding: 1.4rem 1rem;
  text-align: center;
}
.media-empty.image {
  min-height: 9rem;
  justify-content: center;
}
.media-empty.video {
  min-height: 11rem;
  justify-content: center;
}
.media-empty-icon {
  font-size: 1.4rem;
  opacity: 0.55;
}
.media-empty-icon .icon {
  width: 1.4rem;
  height: 1.4rem;
}
.media-empty-hint {
  font-size: 0.62rem;
  color: #94a3b8;
}
.upload-wrap {
  display: inline-flex;
}
.upload-btn {
  border: 1px solid #cbd5e1;
  background: #f8fafc;
  border-radius: 0.35rem;
  padding: 0.35rem 0.8rem;
  font-size: 0.65rem;
  color: #475569;
  cursor: pointer;
}
.upload-btn:hover:not(:disabled) {
  border-color: #2563eb;
  color: #2563eb;
  background: #eff6ff;
}
.upload-btn:disabled {
  opacity: 0.6;
  cursor: default;
}
.media-preview {
  text-align: center;
  color: #94a3b8;
  font-size: 0.65rem;
  padding: 0.5rem;
}
.media-view {
  max-width: 100%;
  border-radius: 0.4rem;
  display: block;
  margin: 0.1rem auto;
}
img.media-view {
  /* ⑤ 去掉内文图片浅灰描边（原先 1px #f1f5f9）；旋转盒样式见 reader.css .img-rot */
  border: none;
}
/* 编辑页媒体间距沿用改造前的 0.1rem（旋转盒 .img-rot 基础值是 0.3rem，与阅读页一致）：
   编辑页正文块间距本就比阅读页紧（.editor-body gap 0.225 vs .reader-body 0.45），不因换盒而变松 */
.media-block .img-rot {
  margin: 0.1rem auto;
}
audio.media-view {
  width: min(21rem, 100%);
}
video.media-view {
  width: auto;
  max-width: 100%;
}
/* ---------- 媒体块两态 ---------- */
.media-block {
  position: relative;
  width: fit-content;
  max-width: 100%;
  margin: 0 auto;
}
/* 悬浮操作钮：盖在媒体右下角，仅选中态可见（更换 + 删除） */
.media-ops {
  position: absolute;
  right: 0.35rem;
  bottom: 0.35rem;
  display: none;
  z-index: 3;
}
.block.active .media-ops {
  display: flex;
  gap: 0.4rem;
}
.block.active .media-ops .upload-btn {
  background: #fff;
  border: 1px solid #e2e8f0;
  border-radius: 0.35rem;
  box-shadow: 0 0.2rem 0.6rem rgba(0, 0, 0, 0.18);
  padding: 0.3rem 0.65rem;
}
.block.active .media-ops .upload-btn.del {
  color: #dc2626;
}
.block.active .media-ops .upload-btn.del:hover {
  border-color: #dc2626;
  background: #fef2f2;
}
/* 空态占位：上传按钮仅选中态显示 */
.media-empty .upload-btn {
  display: none;
}
.block.active .media-empty .upload-btn {
  display: inline-flex;
}
/* ---------- 文件块 ---------- */
.file-block {
  text-align: center;
}
.file-content {
  position: relative;
  width: fit-content;
  max-width: 100%;
  margin: 0 auto;
}
.file-card {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  border: 1px solid #e2e8f0;
  background: #f8fafc;
  border-radius: 0.4rem;
  padding: 0.6rem 1rem;
  font-size: 0.7rem;
  color: #334155;
  font-weight: 500;
  cursor: default;
}
.file-label-input {
  border: 1px solid #93c5fd;
  border-radius: 0.25rem;
  padding: 0.2rem 0.4rem;
  font-size: 0.7rem;
  width: 11rem;
  outline: none;
  font-family: inherit;
}

/* ---------- 链接组 ---------- */
.link-block {
  text-align: left;
  position: relative; /* 模式切换钮定位锚点 */
}
/* 布局模式宽度：1=单卡占½行、2=双卡占⅔行、3=三卡占90%，均居中 */
.link-block .para-link-group {
  padding: 0.5rem; /* 左右上下留白统一 0.5rem：上下与左右一致（原仅左右留白） */
  margin: 0.5rem auto; /* 上下留出切换钮空间，水平居中 */
}
.link-block .para-link-group.mode-1 {
  width: 50%;
}
.link-block .para-link-group.mode-2 {
  width: calc(200% / 3);
}
.link-block .para-link-group.mode-3 {
  width: 90%;
}
/* 布局切换钮：选中态显示，圆形数字，骑在组件顶缘中间 */
.link-mode-btn {
  position: absolute;
  top: -0.75rem;
  left: 50%;
  transform: translateX(-50%);
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  border: 1px solid #bfdbfe;
  background: #fff;
  color: #2563eb;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 1px 0.2rem rgba(37, 99, 235, 0.18);
  z-index: 3;
}
.link-mode-btn:hover {
  background: #eff6ff;
  border-color: #93c5fd;
}
.link-block .para-link-card {
  flex: 0 0 auto;
  justify-content: flex-start;
}
.block.active .link-block .para-link-card {
  flex: 1 1 0;
  min-width: 0;
  justify-content: center;
}
.link-block .para-link-card.editable:hover {
  border-color: #93c5fd;
}
/* 空占位卡片（未填 url）：与引导条一致的灰虚线风格；高度 = 编辑态卡片高度 */
.para-link-card.editable.placeholder {
  border: 1px dashed #cbd5e1;
  background: #fafbfc;
  color: #94a3b8;
  cursor: pointer;
}
.para-link-card.editable.placeholder:hover {
  border-color: #93c5fd;
  background: #f8fafc;
}
/* 编辑/占位卡统一高度：min-height 2.9rem + padding 0.5rem×2 + border = 表单卡（input 1.8rem + padding 0.5rem×2 + border）同高 58px（root 20px）；点击编辑不跳变 */
.para-link-card.editable {
  position: relative;
  cursor: pointer;
  min-height: 2.9rem;
  padding: 0.5rem; /* 四边一致，与 .link-edit 内边距、主卡片留白统一（覆盖阅读页继承的 0.9rem） */
}
.para-link-card.editable:hover {
  border-color: #93c5fd;
}
/* 预览态全空链接：静态占位提示（已废弃：预览态恒渲染 3 张占位卡） */
/* （link-preview-empty 样式移除） */
.link-edit {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
  border: 1px solid #93c5fd;
  border-radius: 0.45rem;
  background: #f8fafc;
  padding: 0.5rem;
  margin: 0.5rem; /* 上下左右留白统一：与主卡片内边距 0.5rem 一致 */
}
.link-input {
  flex: 1 1 10rem;
  height: 1.8rem;
  border: 1px solid #e2e8f0;
  border-radius: 0.3rem;
  padding: 0 0.5rem;
  font-size: 0.65rem;
  outline: none;
  font-family: inherit;
  min-width: 0;
}
.link-input:focus {
  border-color: #93c5fd;
}
.link-edit-ok,
.link-edit-cancel {
  width: 1.8rem;
  height: 1.8rem;
  border-radius: 0.3rem;
  border: 1px solid #e2e8f0;
  background: #fff;
  font-size: 0.7rem;
  cursor: pointer;
  flex-shrink: 0;
}
.link-edit-ok {
  color: #16a34a;
}
.link-edit-cancel {
  color: #dc2626;
}
/* 窄屏：表单折两行时用网格固定布局——icon 占两行成方形，
   展示文案（行2）与跳转地址（行1）左对齐，✓✕ 保持行2 右侧原位 */
@media (max-width: 30rem) {
  .link-edit {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-rows: auto auto;
    grid-template-areas:
      "icon url  .    ."
      "icon text ok   cancel";
    align-items: center;
    gap: 0.45rem 0.4rem;
  }
  .link-edit .upload-wrap {
    grid-area: icon;
  }
  .link-edit .upload-btn {
    width: 2.9rem;
    height: 2.9rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.15rem;
    text-align: center;
    line-height: 1.1;
  }
  .link-edit .link-url-input {
    grid-area: url;
    width: 100%;
  }
  .link-edit .link-text-input {
    grid-area: text;
    width: 100%;
  }
  .link-edit .link-edit-ok {
    grid-area: ok;
  }
  .link-edit .link-edit-cancel {
    grid-area: cancel;
  }
}

/* 3D 空间卡：占位卡 + 右下角删除按钮 */
.space-block {
  position: relative;
  width: fit-content;
  max-width: 100%;
  margin: 0 auto;
}

/* ---------- 轻提示 ---------- */
.editor-toast {
  position: fixed;
  left: 50%;
  bottom: 3.5rem;
  transform: translateX(-50%) translateY(0.6rem);
  background: rgba(15, 23, 42, 0.92);
  color: #fff;
  font-size: 0.65rem;
  padding: 0.45rem 0.9rem;
  border-radius: 0.4rem;
  opacity: 0;
  pointer-events: none;
  transition: all 0.2s;
  z-index: 99999;
}
.editor-toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ---------- 编辑器确认模态（放弃 / 草稿恢复） ---------- */
.editor-modal {
  position: fixed;
  inset: 0;
  z-index: 9990;
  background: rgba(15, 23, 42, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}
.editor-modal-card {
  width: min(20rem, 100%);
  background: #fff;
  border-radius: 0.7rem;
  padding: 1.2rem 1.3rem;
  box-shadow: 0 0.8rem 2rem rgba(0, 0, 0, 0.18);
}
.editor-modal-title {
  font-size: 0.85rem;
  font-weight: 700;
  color: #0f172a;
  margin-bottom: 0.5rem;
}
.editor-modal-text {
  font-size: 0.7rem;
  line-height: 1.7;
  color: #64748b;
  margin-bottom: 1.1rem;
}
.editor-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
}
/* ---------- 内嵌 HTML 应用块 ---------- */
/* 块内只有应用本体：占满整块、无标题条/预览按钮（阅读页同排版）。
   选中 = 实时可交互（所见即所得）；未选中 = 透明承接层接住点击以完成选中
   （iframe 内的事件不会冒泡到父文档，没有承接层就"点卡片选不中块"）。 */
.app-block {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.app-shield {
  position: absolute;
  inset: 0;
  z-index: 2;
  /* 不再写 border-radius：应用外壳已无外框/圆角（见 reader.css 的 .app-frame），
     罩子是纯透明层，圆角是死属性，留着只会误导"应用有圆角卡片"。 */
  cursor: pointer;
  /* 它是 div：主站"button/a/[role=button] 双击放大防护"覆盖不到，
     手机上连点两下（先选中、再操作）会被当成双击放大 → 表现为"点卡片没反应"。 */
  touch-action: manipulation;
}
.block.active .app-shield {
  display: none;
}
/* 双保险：JS 也会在切换选中态时同步 hidden 属性（见 editor.js 的 syncShield）。
   万一 .active 没落在同一元素上（历史脏 DOM / 别的样式覆盖），应用也不会被罩死。 */
.app-shield[hidden] {
  display: none;
}
/* 应用块的操作钮只有 🗑删除，浮在卡面右上角：absolute 不占位、不撑高卡片
   （应用右上角是留白区：应用自己的标题在左上、撑开箭头在第二行右侧）。 */
.app-block .media-ops {
  top: 0.4rem;
  right: 0.4rem;
  bottom: auto;
}

/* 应用选择器：复用编辑器模态外框（.editor-modal*），内部换成应用卡片列表 */
.editor-modal-card.app-pick {
  width: min(22rem, 100%);
}
.app-pick-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-bottom: 1rem;
  max-height: 52vh;
  overflow-y: auto;
}
.app-pick-empty {
  font-size: 0.65rem;
  color: #94a3b8;
  padding: 0.6rem 0;
}
.app-pick-item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-align: left;
  border: 1px solid #e2e8f0;
  background: #fff;
  border-radius: 0.5rem;
  padding: 0.7rem 0.8rem;
  font-family: inherit;
  cursor: pointer;
}
.app-pick-item:hover {
  border-color: #2563eb;
  background: #f8fafc;
}
.app-pick-icon {
  display: inline-flex;
  align-items: center;
  color: #2563eb;
  flex-shrink: 0;
}
.app-pick-icon .icon {
  display: block;
  width: 1.2rem;
  height: 1.2rem;
}
.app-pick-text {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.app-pick-name {
  font-size: 0.7rem;
  font-weight: 700;
  color: #0f172a;
}
.app-pick-desc {
  font-size: 0.6rem;
  color: #94a3b8;
}

.editor-modal-btn {
  border: none;
  border-radius: 0.4rem;
  padding: 0.45rem 1rem;
  font-size: 0.7rem;
  font-weight: 600;
  cursor: pointer;
  background: #2563eb;
  color: #fff;
}
.editor-modal-btn.ghost {
  background: #fff;
  color: #64748b;
  border: 1px solid #e2e8f0;
}
.editor-modal-btn.ghost:hover {
  border-color: #94a3b8;
}
