/* 知未言提示词 · 页面样式（场景页 / 登录 / 投稿 / 后台）
 * 与首页同一套规则：灰底白卡、无边框靠阴影分层、Apple 式柔和缓动与上浮反馈
 */

/* ---------- 页头 ---------- */
/* ⚠ 面包屑已按用户要求删除（2026-09-23）—— 页首那段留白原来是 .crumb 的 padding-top 撑起来的，
   现在改由 .page-top（挂在 sub.html / detail.html 的 <main> 上）提供。
   别把 .page-top 删了：删了内容会顶到吸附顶栏底下、被盖住一截。 */
.page-top { padding-top: 24px; }
/* 游客提示条与正文之间留一口气（提示条 hidden 时不算，免得凭空多出空白） */
.page-top > .notice:not([hidden]) { margin-bottom: 16px; }
/* 2026-09-23 用户要求删掉列表页的页面标题（首页那一排 + 场景页的场景名大标题）。
   现在 #sceneHead 只有「场景找不到」这种错误态才有内容（sub.js 的 notFound 往里面写 h1 + .sub），
   :empty 时整块不占位 —— 否则正常路径下会凭空多出一段 18px 空白。
   ⚠ 下面 h1 / .sub 两条规则是给 notFound 用的，别当死代码删了。 */
.scene-head { padding: 0 0 var(--head-gap); }
.scene-head:empty { display: none; }
.scene-head h1 { font-size: var(--fs-h1); font-weight: 600; line-height: 1.3; letter-spacing: var(--ls-tight); display: flex; align-items: center; gap: 10px; }
.scene-head .sub { color: var(--ink-3); font-size: var(--fs-xs); margin-top: 6px; }

/* ---------- 面板（白卡，靠阴影分层，不用边框） ---------- */
.panel { background: var(--panel); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-1); }
/* ⭐⭐ 2026-09-29 同日第十三轮：用户要求「投稿页面中，左右框对齐」。
   实测右栏比左栏低 **18px**（左栏顶 y=224、右栏顶 y=242）—— 真因就是下面这条：
   `.panel + .panel` 本意是"**竖着堆的**两个面板之间留 18px"，但它管的是**任何**
   相邻兄弟，于是在 `.up-grid` 这种**两列网格**里，右列那个 `.panel` 也算"第二个
   面板"，被平白顶下去 18px（同理 `.cat-cols` 等网格容器也会中招）。
   ⇒ 修法：让这条**只在网格之外**生效 —— 网格里的面板间距一律交给 grid 的 gap。
      ⚠️ 写法上有讲究：`@supports selector()` 里虽然可以写 `:not(组合器)`，但为了最大化
        兼容、也为了好懂，这里用**更朴素**的办法 —— 在网格容器上把面板的上边距显式归零。
        就地清掉比"用复杂选择器去躲"更直白，而且一眼能看出意图。
      ⚠️ 目前只有 `.up-grid` 需要（admin.html 的 `.cat-cols` 里装的不是 `.panel`，
        别顺手把它也写进来 —— 那是永远不会命中的死规则）。 */
.panel + .panel { margin-top: 18px; }
.up-grid > .panel + .panel { margin-top: 0; }
.panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 15px clamp(16px, 1.8vw, 22px); border-bottom: 1px solid var(--line-2); flex-wrap: wrap; }
.panel-title { font-size: var(--fs-base); font-weight: 600; display: flex; align-items: center; gap: 8px; }
.panel-title small { font-weight: 400; color: var(--ink-3); font-size: var(--fs-2xs); }
.panel-body { padding: clamp(16px, 1.8vw, 22px); }
.panel-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* ---------- 配方 / 模板 ---------- */
.recipe {
  background: var(--surface-2); border: 1px dashed var(--line); border-radius: var(--radius);
  padding: 15px 17px; font: 14px/1.9 ui-monospace, SFMono-Regular, Menlo, "Microsoft YaHei", monospace;
  white-space: pre-wrap; word-break: break-word; color: var(--ink);
}
.recipe-line { display: block; }
.recipe mark { background: var(--ink); }
.model-row { display: flex; flex-wrap: wrap; gap: 7px; margin: 14px 0 4px; }
.chip {
  border: 1px solid var(--line); background: var(--panel); border-radius: var(--radius-pill);
  padding: 10px 14px; font-size: var(--fs-xs); color: var(--ink-2);
  transition: transform .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.chip:hover { border-color: var(--line-strong); box-shadow: var(--shadow-1); }
.chip:active { transform: scale(.96); }
.chip.is-on { background: var(--brand); border-color: var(--brand); color: var(--ink-invert); }
.mode-line { display: flex; align-items: center; gap: 10px; font-size: var(--fs-xs); color: var(--ink-3); margin-top: 10px; flex-wrap: wrap; }
.sibling { display: flex; flex-wrap: wrap; gap: 7px; }
.sibling a {
  font-size: var(--fs-xs); padding: 12px 12px; border-radius: var(--radius-pill); background: var(--surface-3); color: var(--ink-2);
  transition: background .2s var(--ease), color .2s var(--ease), transform .2s var(--ease);
}
.sibling a:hover { background: var(--brand-soft); color: var(--brand-dark); }
.sibling a:active { transform: scale(.96); }
.sibling a.is-now { background: var(--brand); color: var(--ink-invert); }

/* ---------- 瀑布流 ---------- */
.wall-head { display: flex; align-items: center; gap: 10px; padding: 0 0 14px; flex-wrap: wrap; }
.wall-head .grow { flex: 1; }
.wall { display: grid; grid-template-columns: repeat(auto-fill, minmax(clamp(240px, 21vw, 320px), 1fr)); gap: clamp(12px, 1.3vw, 18px); }
.p-card {
  background: var(--panel); border-radius: var(--radius-lg); overflow: hidden;
  border: 1px solid var(--line-soft);      /* 与首页 .card 同一套，理由见 style.css 的 .card */
  display: flex; flex-direction: column;   /* 同样：默认无阴影 */
  transition: transform .32s var(--ease), box-shadow .32s var(--ease);
}
.p-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); }
.p-card:active { transform: translateY(-1px) scale(.995); }        /* 和首页 .card 同一套按压语言 */
/* ⭐ 2026-09-25 封面不再裁成 4:3。原来 object-fit: cover 会把 9:16 / 1:1 的 AI 出图裁掉上下，
   而「看图」正是这个产品的核心；首页的 .card-cover 一直是保原比例的，两页不一致。
   min-height 是图片没加载出来时先占位，避免整墙跳动。 */
.p-media { background: var(--surface-3); overflow: hidden; cursor: zoom-in; position: relative; display: grid; place-items: center; min-height: 120px; }
.p-media img { width: 100%; height: auto; display: block; transition: transform .5s var(--ease); }
.p-card:hover .p-media img { transform: scale(1.03); }
.p-media.is-locked {
  cursor: default; display: grid; place-items: center; color: var(--ink-3); font-size: var(--fs-xs);
  /* ⚠️ #F1F1F1 与 --line-2 **是同一个值**，替换只是让它回到体系里（改主题/调灰阶时不会再漏掉这一处） */
  background: repeating-linear-gradient(45deg, var(--surface-2), var(--surface-2) 8px, var(--line-2) 8px, var(--line-2) 16px);
}
.p-body { padding: 13px 15px 15px; display: flex; flex-direction: column; gap: 8px; flex: 1; }
.p-title { font-size: var(--fs-base); font-weight: 600; display: flex; align-items: center; gap: 6px; }
.p-text { font-size: var(--fs-xs); color: var(--ink-2); white-space: pre-wrap; word-break: break-word; max-height: 108px; overflow: hidden; position: relative; }
.p-text.is-open { max-height: none; }
.p-text.is-clamp::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 30px; background: linear-gradient(transparent, var(--ink-invert)); }
/* 标签行：左边模型 / 生成方式标签，右边收藏 / 复制（靠右贴边，字号与图标都缩一档）。
   同样允许换行兜底，margin-left:auto 保证统计始终靠右。 */
.p-metas { display: flex; align-items: center; gap: 8px; row-gap: 6px; flex-wrap: wrap; }
.p-tags { flex: none; max-width: 100%; display: flex; flex-wrap: wrap; gap: 6px; }
.p-stats { flex: none; margin-left: auto; display: flex; align-items: center; gap: 10px; }
/* 作者行：头像 + 昵称 + 已上传时长 */
.p-by { display: flex; align-items: center; gap: 6px; min-width: 0; font-size: var(--fs-xs); color: var(--ink-3); }
.p-by .avatar { width: 20px; height: 20px; font-size: var(--fs-2xs); }
.p-by .by-name { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.p-by .by-time { flex: none; }
.p-meta { display: flex; align-items: center; gap: 8px; font-size: var(--fs-xs); color: var(--ink-3); flex-wrap: wrap; }
.author { display: flex; align-items: center; gap: 6px; }
.author .avatar { width: 20px; height: 20px; font-size: var(--fs-2xs); }
.p-actions { display: flex; align-items: center; gap: 8px; margin-top: auto; padding-top: 4px; }
.p-actions .btn { flex: 1; }
/* 后台表格里的小标记：置顶 / 重新提交（`.re-flag` 是 2026-09-24 加的，
   用来把"作者改过稿又重提"的行标出来，否则它跟刚提交的新稿长得一模一样）。
   两者都用 `--accent*` 变量：公众页是灰的（符合"公众页只许黑白灰"那条硬规矩，pair-check 会扫），
   后台被 admin-theme.css 重新着色 → 彩色只在后台出现。 */
.pinned-flag, .re-flag { font-size: var(--fs-2xs); background: var(--accent-soft); color: var(--accent); border-radius: var(--radius-xs); padding: 1px 6px; }
.re-flag { margin-bottom: 2px; }
.lightbox { position: fixed; inset: 0; background: var(--overlay); display: grid; place-items: center; z-index: 180; padding: 24px; cursor: zoom-out; -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.lightbox img { max-width: 96vw; max-height: 92vh; border-radius: var(--radius); }
.toggle-more { background: none; border: 0; color: var(--brand); font-size: var(--fs-xs); padding: 0; text-align: left; }
.load-more { display: flex; justify-content: center; padding: 20px 0 0; }

/* ---------- 登录 ---------- */
.auth-wrap { max-width: 420px; margin: clamp(40px, 7vh, 76px) auto 100px; padding: 0 var(--pad); }
.auth-card { background: var(--panel); border-radius: var(--radius-lg); padding: 26px; box-shadow: var(--shadow-2); }
.auth-card h1 { font-size: var(--fs-lg); font-weight: 600; margin-bottom: 6px; }
.auth-card .lead { color: var(--ink-3); font-size: var(--fs-xs); margin-bottom: 18px; }
.tabs { display: flex; gap: 3px; background: var(--field-bg); padding: 3px; border-radius: var(--radius); margin-bottom: 18px; }
.tab {
  flex: 1; border: 0; background: none; padding: 8px 6px; border-radius: var(--radius-sm);
  font-size: var(--fs-sm); color: var(--ink-2);
  transition: background .25s var(--ease), color .25s var(--ease), box-shadow .25s var(--ease);
}
.tab.is-active { background: var(--panel); color: var(--ink); font-weight: 500; box-shadow: var(--shadow-1); }
/* ⭐ 页签实测 37px；命中区补到 45。⚠️ 同样用 ::before（::after 没被占，但统一口径更好查） */
.tab { position: relative; }
.tab::before { content: ''; position: absolute; inset: -4px 0; }
/* 按下去有个即时反馈（原来只有 hover 换底色，点完那一下是"空"的） */
.tab:active { transform: scale(.985); }
.auth-note { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line-2); font-size: var(--fs-xs); color: var(--ink-3); }

/* ---------- 投稿 ---------- */
.up-grid { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: clamp(16px, 1.6vw, 22px); align-items: start; padding: 20px 0 60px; }
.drop {
  border: 1.5px dashed var(--line); border-radius: var(--radius); padding: 24px 16px; text-align: center;
  color: var(--ink-3); font-size: var(--fs-xs); background: var(--surface-2); cursor: pointer;
  transition: border-color .25s var(--ease), background .25s var(--ease), color .25s var(--ease);
}
.drop:hover, .drop.is-over { border-color: var(--brand); background: var(--brand-soft); color: var(--brand-dark); }
.thumb { position: relative; display: inline-block; }
.thumb img { max-height: 150px; border-radius: var(--radius); }
.thumb-x {
  position: absolute; right: -6px; top: -8px; border: 0; border-radius: var(--radius-pill);
  padding: 9px 12px; background: var(--bad); color: var(--ink-invert); font-family: inherit; font-size: var(--fs-2xs);
  cursor: pointer; line-height: 1.5;
}
.editing-bar { display: flex; align-items: center; gap: 10px; background: var(--brand-soft); color: var(--brand-dark); border-radius: var(--radius); padding: 10px 14px; font-size: var(--fs-xs); margin-bottom: 14px; }
.my-list { display: flex; flex-direction: column; gap: 10px; max-height: 70vh; overflow: auto; }
.my-item {
  background: var(--surface-4); border-radius: var(--radius); padding: 13px 14px;
  transition: background .25s var(--ease);
}
.my-item:hover { background: var(--surface-hover); }
.my-item .head { display: flex; align-items: center; gap: 8px; justify-content: space-between; margin-bottom: 6px; flex-wrap: wrap; }
.my-item .txt { font-size: var(--fs-xs); color: var(--ink-2); max-height: 62px; overflow: hidden; white-space: pre-wrap; }
.my-item .acts { display: flex; gap: 8px; margin-top: 9px; }
/* --bad-soft 现在是纯白（驳回 = 白底描边），所以要自己带边框，否则在白卡上看不出边界 */
.reason { font-size: var(--fs-xs); color: var(--bad); background: var(--bad-soft); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 6px 10px; margin-top: 8px; }

/* ---------- 后台 ---------- */
.admin-wrap { padding: 20px 0 60px; }
/* ⭐ 2026-09-29 同日第十三轮：用户要求「文章页 / 模板标签页 / 投稿页中，分栏与下面框的
   距离都统一并增大为 1.4 倍」。实测三页原本是 18 / 16 / 18（并不统一），
   追问后确认：以最大的 18px 为基准 ×1.4 ≈ 25px，三页**全部改成 25px**。
   ⚠️ 这一条改的是 `.tabs.app` 的**下外边距**（页签下划线 → 面板顶），
      它同时服务文章页与投稿页（两页共用这套页签）—— 改一处两页一起变，正是要的。
   ⚠️ 同行首那个 `margin-top: 0` 别动：位置统一靠的是上面 .page-head / .t-head 的
      padding-bottom: 14px，这里再加 margin 会让页签整体下沉（第十一轮踩过）。
   ⚠️ 窄屏那一段（<=900px）不覆盖 margin-bottom，别在那里收窄。 */
.tabs.app { background: none; padding: 0; gap: 4px; border-bottom: 1px solid var(--line); border-radius: 0; margin: 0 0 25px; }
.tabs.app .tab { flex: none; padding: 10px 15px; border-radius: var(--radius-sm) var(--radius-sm) 0 0; font-size: var(--fs-title-sm); }
.tabs.app .tab:hover { background: var(--hover-1); }
.tabs.app .tab.is-active { box-shadow: none; background: none; color: var(--brand-dark); font-weight: 600; border-bottom: 2px solid var(--brand); border-radius: 0; }
.filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.filters .input, .filters .select { width: auto; min-width: 130px; }
.filters .grow { flex: 1; min-width: 180px; }
.stat-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(clamp(140px, 11vw, 180px), 1fr)); gap: 12px; }
.stat { background: var(--panel); border: 1px solid var(--line-2); border-radius: var(--radius); padding: 15px; }
.stat b { display: block; font-size: var(--fs-stat); line-height: 1.2; font-weight: 600; font-variant-numeric: tabular-nums; }
.stat span { font-size: var(--fs-xs); color: var(--ink-3); }
/* ⚠️ 这一段原来是三张条形图的样式（`.bars` / `.bar-row` / `.bar-track` / `.bar-fill` / `.bar-row .n`）。
   2026-09-28 轮次 Z 用户要求「分布内容以数字展示就行」→ 换成数字表格（见下面的 `.dist-*`），
   整套条形图样式连 `style.css` 里的 `bar-grow` 动画、`admin-theme.css` 里的 `.bar-track` 覆盖
   **一起删干净了**。**别再往回加** —— 要展示分布就用 `.dist-*` + `tbl()`。 */

/* ---------- 看板分组 / 顶部两个用户数 / 折线图 / 分布（2026-09-28 轮次 X 加、轮次 Z 改）----------
   ⚠️ .stat-grid / .stat 还是原来那一套，**没动** —— 冒烟是按 `#statGrid .stat`
      数格子的，改了选择器就会连带把那几条断言废掉。
   ⚠️ 颜色只走语义变量：pages.css 是**公众页也在加载**的文件，pair-check 的 [H] 段
      会把它按"公众界面文件"扫一遍，写死任何非灰颜色都会报红。 */
.stat-group + .stat-group { margin-top: 18px; }
.stat-group-h { font-size: var(--fs-xs); font-weight: 600; color: var(--ink-2); margin-bottom: 8px; }

/* 看板**最上面**那两个用户数字（新增用户 / 总用户数）。两格均分，下面再隔开一组。 */
.stat-top { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; margin-bottom: 18px; }
.stat-top .stat b { font-size: var(--fs-stat-lg); }

/* 近 14 天折线图（一张图一条线，各自缩放）。
   ⚠️ SVG 用 `preserveAspectRatio="none"` 横向填满容器 → **横向被拉伸**，
      所以线在 JS 里带了 `vector-effect="non-scaling-stroke"`，否则线宽会跟着变粗。
   ⚠️ 日期标签放在图**外面**（HTML flex 均分 14 份）：既能和折线点中心对齐
      （点的 x 也是 (i+0.5)/N），字号又不跟着 SVG 一起缩 —— 手机上才看得清。 */
.line-wrap { display: grid; gap: 22px; }
.line-h { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.line-t { font-size: var(--fs-xs); font-weight: 600; color: var(--ink-2); }
.line-n { font-size: var(--fs-2xs); color: var(--ink-3); }
.line-n b { color: var(--ink); font-variant-numeric: tabular-nums; }
.line-plot svg { display: block; width: 100%; height: 150px; }
.ln-area { fill: var(--shade-light); }
.ln-line { fill: none; stroke: var(--shade-mid); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.line-x { display: flex; margin-top: 6px; }
.line-x span { flex: 1 1 0; min-width: 0; text-align: center; font-size: var(--fs-2xs); color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* 分布：数字表格（三块并排，窄屏自动落成一列）。
   ⚠️ 数量那一列右对齐 + 等宽数字，一眼能比大小 —— 这也是"以数字展示"的意义所在。 */
.dist-wrap { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px; align-items: start; }
.dist-t { font-size: var(--fs-xs); font-weight: 600; color: var(--ink-2); margin-bottom: 8px; }
.dist-n { text-align: right; font-variant-numeric: tabular-nums; }

.table-wrap { overflow: auto; }
/* ⭐ 2026-09-26：把**操作列钉在表格右边**。
   起因：用户报「后台管理在删除分类和卡片时无法删除」。实测窄窗口下
   .table-wrap 的 scrollWidth（390px 视口时 522）大于可视宽度，操作列被推到
   x=462 起 —— 完全在可视区外，而且 4 个按钮还各自换行；用户根本够不着「删除」。
   钉住之后横向滚动时这一列一直贴右边，任何宽度下都点得到。
   ⚠ 必须给**不透明**底色（sticky 单元格透明的话，滚过去的表体会从底下透出来）。
      td 用 --panel（和行底同色，看不出接缝）、th 用 --surface-4（和其余表头同色）；
      hover 时后台主题的 tr:hover td 优先级更高，会盖成 hover 底色，同样是实色。
   ⚠ 表格是 border-collapse: collapse，个别浏览器在 sticky 单元格上会丢底边框（纯装饰，可接受）。 */
.table th:last-child, .table td:last-child {
  position: sticky; right: 0;
  box-shadow: var(--shadow-edge);
}
.table th:last-child { background: var(--surface-4); }
.table td:last-child { background: var(--panel); }
.table { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); }
.table th, .table td { text-align: left; padding: 12px 12px; border-bottom: 1px solid var(--line-2); vertical-align: middle; }
.table th { font-size: var(--fs-xs); color: var(--ink-3); font-weight: 500; white-space: nowrap; background: var(--surface-4); }
.table tr { transition: background .2s var(--ease); }
.table tbody tr:hover td { background: var(--surface-4); }
.table .mini { font-size: var(--fs-xs); color: var(--ink-3); max-width: 340px; }
.thumb-xs { width: 46px; height: 46px; object-fit: cover; border-radius: var(--radius-sm); background: var(--surface-3); }
.row-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.row-actions .btn { padding: 4px 10px; font-size: var(--fs-xs); }

/* ---------- 后台：提示词「详情 / 编辑」弹窗（2026-09-26 轮次 H 加） ----------
   用户要求「后台预览尽可能详细、有分类信息，并且能直接改」→ 弹窗做成两栏表单。
   · 弹窗本身用 `UI.dialog({ wide: true })`（`style.css` 的 `.modal-box.is-wide`）拉宽到 920px；
   · ⚠ 图片格子先给 1:1 占位块再填图 —— 不然读图那几百毫秒里弹窗会跳一下高度；
   · 窄屏回落单列，且不许横向溢出。 */
.pv-head {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding-bottom: 12px; margin-bottom: 14px; border-bottom: 1px solid var(--line-2);
}
.pv-grid { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 22px; }
.pv-col { min-width: 0; }
.pv-sec {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin: 18px 0 9px; padding-bottom: 6px;
  font-size: var(--fs-xs); font-weight: 600; color: var(--ink-2);
  border-bottom: 1px solid var(--line-2);
}
.pv-col > .pv-sec:first-child { margin-top: 0; }
.pv-data { list-style: none; margin: 0; padding: 0; }
.pv-data li {
  display: flex; justify-content: space-between; gap: 10px;
  padding: 6px 0; font-size: var(--fs-xs); border-bottom: 1px dashed var(--line-2);
}
.pv-data li:last-child { border-bottom: 0; }
.pv-data li span { color: var(--ink-3); flex: 0 0 auto; }
.pv-data li b { font-weight: 500; text-align: right; word-break: break-all; }
.pv-note {
  margin-top: 12px; padding: 10px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--line-2); border-left: 3px solid var(--bad);
  background: var(--surface-4); font-size: var(--fs-xs);
}
.pv-note b { display: block; margin-bottom: 4px; }
.pv-imgs-title { font-size: var(--fs-2xs); color: var(--ink-3); margin: 10px 0 6px; }
.pv-imgs { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; }
.pv-img { display: block; aspect-ratio: 1 / 1; border-radius: var(--radius-sm); background: var(--surface-3); overflow: hidden; }
.pv-img img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (max-width: 760px) {
  .pv-grid { grid-template-columns: minmax(0, 1fr); gap: 4px; }
}
.cat-cols { display: grid; grid-template-columns: 240px minmax(0, 1fr); gap: 16px; align-items: start; }
.cat-item {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: var(--radius);
  cursor: pointer; transition: background .2s var(--ease), color .2s var(--ease);
}
.cat-item:hover { background: var(--surface-hover); }
.cat-item.is-on { background: var(--brand-soft); color: var(--brand-dark); }
.cat-item .nm { flex: 1; font-size: var(--fs-sm); }
.cat-item .g-count { font-size: var(--fs-2xs); color: var(--ink-3); }
.dv-preview { background: var(--panel); border-radius: var(--radius); padding: 17px; box-shadow: var(--shadow-1); }
.dv-preview b { display: block; font-size: var(--fs-md); font-weight: 600; }
.dv-preview span { font-size: var(--fs-xs); color: var(--ink-3); }
.legend { display: flex; gap: 14px; font-size: var(--fs-xs); color: var(--ink-3); flex-wrap: wrap; }
.legend i { display: inline-block; width: 10px; height: 10px; border-radius: var(--radius-xs); margin-right: 5px; vertical-align: -1px; }

@media (max-width: 900px) {
  .up-grid, .cat-cols { grid-template-columns: minmax(0, 1fr); }
  /* ⚠️ 这里原来给 `.bar-row` 收窄列宽的（条形图），2026-09-28 轮次 Z 条形图整块删了。
     折线图那一块窄屏不用特殊处理：`.line-x` 是 flex 均分，`.dist-wrap` 是 auto-fit。 */
  .wall { grid-template-columns: minmax(0, 1fr); }
  /* ⭐ 同日第十轮：窄屏时「页签 + 搜索框」一条排不下 → 换行，
     搜索框占满整行（比被挤成一小条好用）。 */
  .t-bar { flex-wrap: wrap; }
  .t-bar .t-search { flex: 1 1 100%; max-width: none; }
  .tabs.app { overflow-x: auto; scrollbar-width: none; }
  .tabs.app::-webkit-scrollbar { display: none; }
  .tabs.app .tab { padding: 9px 12px; font-size: var(--fs-xs); }
  .auth-wrap { margin-top: 26px; }
}

/* ---------- 后台：用户建议（2026-09-26 加） ----------
 * 一条建议 = 一张卡（不用表格）：建议正文可能有好几行，塞进 <td> 里会被挤成一竖条。
 * ⚠ 卡片里的文字色**只走语义变量**（--ink / --ink-3 / --warn / --ok），不写死颜色 ——
 *   这个文件在 pair-check 的 [H] 灰阶扫描范围内（公众页 + 公共样式必须黑白灰），
 *   真要上色只能靠 admin-theme.css 重定义那几个变量（三档状态徽章就是这么做的）。 */
.sg-item { margin-bottom: 10px; }
.sg-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sg-head b { font-size: var(--fs-sm); }
.sg-kind {
  font-size: var(--fs-2xs); font-weight: 500; padding: 2px 8px;
  border-radius: var(--radius-sm); background: var(--brand-soft); color: var(--brand-dark);
}
.sg-badge { font-size: var(--fs-2xs); padding: 2px 9px; border-radius: var(--radius-pill); }
.sg-new      { background: var(--warn-soft); color: var(--warn); border: 1px solid var(--line-mid); }
.sg-accepted { background: var(--ok); color: var(--ink-invert); }
.sg-ignored  { background: var(--line-2); color: var(--ink-2); }
/* ⚠ pre-wrap 是这条样式存在的**唯一理由**：用户分条写的「1. … 2. …」必须原样断行显示，
   压成一行等于把人家排的版废掉（后端 clean() 也特意只归一化换行符、不压成单行）。 */
.sg-body {
  margin-top: 8px; font-size: var(--fs-sm); line-height: 1.75;
  white-space: pre-wrap; word-break: break-word;
}
.sg-contact, .sg-note { margin-top: 7px; font-size: var(--fs-xs); color: var(--ink-3); }
.sg-note { border-left: 2px solid var(--line-strong); padding-left: 9px; }

/* ---------- 提示词详情页：左边大图 + 右边信息 ----------
 * 图片三条硬规矩（用户定的）：宽度不超过屏幕 2/3、高度不超过一屏、按图片原始比例。
 * 做法：左列占 2fr（= 屏宽 2/3），图片只给 max-width / max-height，尺寸由图片自己决定
 * （width:auto + height:auto），于是既不裁也不变形，也不会超出这两条上限。 */
.detail {
  display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: clamp(16px, 1.8vw, 26px); align-items: start; padding-bottom: 60px;
}
/* 左边图区：最上面一张「生成图」大图；多余的**生成图**一张张往下叠；
   **参考图不管几张，都只占一排**（2026-09-24 用户要求：「提示词详情页中，参考图放为一排」）。
   ⚠ 2026-09-24 起上限是「生成图 3 张 + 参考图 3 张」—— 原来那条「两张加起来不超过一屏」的规矩
     是按最多 3 张定的；两组都填满时左列会比一屏高，这是新上限带来的必然结果，不是 bug。 */
.d-media { min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.d-shot, .d-ref { margin: 0; min-width: 0; }
/* 参考图那一排：等宽平分左列、整排高度封在 150px 以内（一行最多 3 张）。
   `min-height` 是**图还没加载出来时先占住位置**的（跟 .d-img 的 320px 同一个道理）——
   不然这一排会先塌成 0 高、图片到了再撑开，整页会跳一下。 */
.d-refs { display: flex; gap: 10px; min-width: 0; }
.d-refs .d-ref { display: flex; flex: 1 1 0; }
.d-refs .d-img { flex: 1; min-height: 96px; max-height: 150px; }
.d-refs .d-img img { max-width: 100%; max-height: 150px; }
/* ⚠ 图片小标题（.d-cap）已按用户要求删除（2026-09-23）—— 「生成图」「参考图」都不再显示文字，
   图片区只有图（原名留在 img 的 alt 里，读屏还能读到）。别再往 figure 里加 figcaption：
   加回来冒烟会红（有「小标题数量 = 0」的断言）。 */
/* ⭐ 生成图：**每一张都是同样的大图**（2026-09-24 用户要求「所有的生成图显示方式一样，都是大图」）。
   单张上限 = 一屏减掉顶栏与上下留白 —— 看完一张还能露出下一张的边，不会"一张图霸占一整屏"。
   ⚠ 原来那两条 `.d-media.is-multi .d-shot …`（"多张就把首图压到 calc(100vh - 430px)"）**已删除**：
     生成图之间是并列关系、不是主次关系，不再有大图/小图之分。
   ⚠ 于是"左列图区整组不超过一屏"这条老规矩对生成图不再成立（3 张生成图 = 3 个大图，会超一屏）。
     这是新规则的必然结果，**不是 bug**，别再想办法把它压回一屏。
   ⚠ `.d-media.is-multi` 这个类 detail.js 还在挂（信息性），但 CSS 里已经没有规则依赖它了。 */
.d-shot .d-img, .d-shot .d-img img { max-height: calc(100vh - 200px); }
.d-img.is-small { min-height: 0; max-height: 150px; background: var(--surface-2); }
.d-img.is-small img { max-height: 150px; }
.d-img {
  background: var(--panel); border-radius: var(--radius-lg); overflow: hidden;
  display: grid; place-items: center;
  min-height: 320px;                    /* 图还没加载出来时先占住位置，避免页面跳动 */
  max-height: calc(100vh - 140px);      /* 不超过一屏（扣掉顶栏与上下留白） */
}
.d-img img {
  display: block; margin: 0 auto;
  max-width: 100%;                      /* 最多铺满左列 = 屏宽 2/3 */
  max-height: calc(100vh - 140px);      /* 最多一屏高 */
  width: auto; height: auto;            /* 关键：让图片按自己的比例走 */
  object-fit: contain; cursor: zoom-in;
}
.d-img.is-locked {
  color: var(--ink-3); font-size: var(--fs-xs);
  /* ⚠️ #F1F1F1 与 --line-2 **是同一个值**，替换只是让它回到体系里（改主题/调灰阶时不会再漏掉这一处） */
  background: repeating-linear-gradient(45deg, var(--surface-2), var(--surface-2) 8px, var(--line-2) 8px, var(--line-2) 16px);
}
.d-img.is-empty { color: var(--ink-3); font-size: var(--fs-xs); background: var(--panel); }

/* ⭐ 图生图成对版式（2026-09-26 用户要求：「同一栏中左边展示参考图、右边展示生成图」）。
   左列参考图、右列生成图，两列等宽平分左列；每列内部各自竖着叠（每组最多 IMG_EACH_MAX 张）。
   ⚠ 两条老规矩没变：宽不超过屏宽 2/3（由上面 .detail 的 2fr 列保证）、单张高不超过一屏。
   ⚠ 这几条**必须排在本文件 .d-img.is-small 之后** —— 特异性一样（两个类），靠"后写的赢"
     覆盖掉那个 150px 的小图上限；挪到前面去，参考图那一列又会缩成 150px 的小图。
   ⚠ 用 flex 而不是两层 grid：列数会随"只有参考图 / 只有生成图"退化，flex 更好兜。
   ⚠ 别给它加 aspect-ratio：详情页图区一律"按图片自己的比例"（用户定的三条硬规矩之一）。 */
.d-pair { display: flex; gap: 10px; min-width: 0; align-items: flex-start; }
.d-pair .d-col { display: flex; flex-direction: column; gap: 10px; flex: 1 1 0; min-width: 0; }
.d-pair .d-shot, .d-pair .d-ref { margin: 0; min-width: 0; }
.d-pair .d-img {
  min-height: 140px;                    /* 图还没加载出来时先占位，避免左右两列先后跳一下 */
  max-height: calc(100vh - 200px);
  background: var(--surface-2);
}
.d-pair .d-img img { max-width: 100%; max-height: calc(100vh - 200px); }

/* ⭐ 右栏 = 提示词卡片 + 评论区（2026-09-26 用户要求「评论区位于右侧卡面下面」）。
   原来是"两栏网格 + 评论区整幅铺在下面"，评论区因此不受右栏 1fr 那种窄宽度限制；
   现在按用户要求收进右栏 —— 窄是必然的（约等于一个手机屏宽），换来的是详情页只剩一条纵向阅读线。
   ⚠ 这一层是 .detail 网格的**第二个格子**：.d-media / .d-info 必须留在它里面，
     别把它们直接提到 .detail 下面，否则右侧那两块会被摆到下一行的第一格去。 */
.d-side { display: flex; flex-direction: column; gap: clamp(14px, 1.4vw, 20px); min-width: 0; }

.d-info {
  background: var(--panel); border-radius: var(--radius-lg);
  padding: clamp(20px, 2vw, 30px); min-width: 0;
  display: flex; flex-direction: column; gap: 15px;
}
.d-title { font-size: var(--fs-h1); font-weight: 600; line-height: 1.3; letter-spacing: var(--ls-tight); }
.d-by { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; color: var(--ink-3); font-size: var(--fs-xs); }
.d-by .avatar { width: 28px; height: 28px; font-size: var(--fs-xs); }
.d-name { color: var(--ink-2); font-weight: 500; }

.d-line3 { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* 第 3 行的收藏量 / 复制量：图标与首页卡片同一套（UI.icon('fav') / UI.icon('copy')）。
   2026-09-23 用户要求：把「浏览量」换成「复制量」并带上图标 → 随后又把「收藏量 / 复制量」
   这几个字也删了，只剩图标 + 数字（含义靠图标本身和 title 表达），所以现在是窄药丸。 */
/* ⭐ 2026-09-29 同日第十一轮：用户要求「详情页中的收藏和复制的边框和其他的标签统一大小」，
   追问确认方向 =「只统一边框细节」。同一行里躺着 .tag（圆角 8px / 内边距 2px 8px），
   而这两个原本是全圆药丸（980px）+ 12px 内边距，明显是两个家族。
   现在往 .tag 那一派收：圆角 --radius-sm、内边距 4px 8px、字号 --fs-2xs（与 .tag 同档）。
   ⚠️ padding-block 只能是 4px：再往下压控件高度会掉到 24px 以下（WCAG 2.5.8 AA 触控下限），
      与 .d-site 那条注释同一个道理。改小之前先看 design-audit 的触控那一节。
   ⚠️ 保留 border: 0 —— 这几个是"计数药丸"，靠灰底与标签区分，不描边；
      用户说的是"边框大小"（即圆角与外形），不是要加一圈描边。 */
.metric {
  display: inline-flex; align-items: center; gap: 5px;
  border: 0; padding: 4px 8px; border-radius: var(--radius-sm); font-family: inherit; font-size: var(--fs-2xs);
  color: var(--ink-3); background: var(--hover-1); cursor: pointer;
  transition: background .2s var(--ease), color .2s var(--ease), transform .2s var(--ease);
}
.metric .i { flex: none; width: 13px; height: 13px; opacity: .82; }
/* ⭐ 同步收档：原来数字是 --fs-sm(14px)、比同排 .tag 的 12px 大一档，
   于是 .metric 比 .tag 高 7px（30.4 vs 23.2），一排里"一高一矮"。
   现在与 .tag 同档（--fs-2xs）。⚠️ 仍保留 600 字重 —— 数字是这一排里唯一要"读得清"的。 */
.metric b { font-size: var(--fs-2xs); font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.metric:active { transform: scale(.96); }
.metric:hover { background: var(--hover-2); }
.metric.is-static { cursor: default; }
.metric.is-static:hover { background: var(--hover-1); }
.metric.is-on { background: var(--hover-2); color: var(--brand); }
.metric.is-on b { color: var(--brand); }

/* ⭐ 2026-09-25 去掉 max-height: 340px / overflow: auto。
   原来超过约 12 行（340px ÷ 28.5px 行高）正文就变成「页面里的小滚动框」，
   而正文正是这一页要卖的东西；顶部的阅读进度条读的是整页滚动，正文在小框里滚时它不动，
   指示也会骗人。现在正文随页面走，页面滚多少进度条就画多少。
   overflow-wrap 是为了长串（网址 / 无空格英文）不撑破右侧栏。 */
.d-content {
  white-space: pre-wrap; line-height: 1.9; font-size: var(--fs-base); color: var(--ink);
  background: var(--surface-2); border-radius: var(--radius-lg); padding: 16px 18px;
  overflow-wrap: break-word;
}
/* ⭐ 2026-09-26（用户要求）游客：正文照样看得见，但**拖不出选区、右键没有"复制"**，
   鼠标也不给文本光标（I 形）—— 光标形状是在暗示"这里可以选"，退成箭头才对得上实际行为。
   ⚠️ 判据是 detail.js 在 `!me` 时给 #detail 挂的 `.is-guest`；**登录后这条不生效**，照旧能选能复制。
   ⚠️ 这只是手感层：文本仍在 HTML 里，防不住开发者工具；真闸门是后端 `A.requireUser`。
   ⚠️ 不涉及任何颜色，纯灰阶扫描（pair-check [H]）不受影响。 */
#detail.is-guest .d-content {
  user-select: none; -webkit-user-select: none;
  cursor: default; -webkit-touch-callout: none;
}
/* 第 4.5 行：图片风格标签（投稿时选的/自己写的，没填就整行不出现） */
.d-tags { display: flex; flex-wrap: wrap; gap: 6px; }

/* 第 5 行分两行：上行是「复制提示词」主按钮（自然宽度、不拉满），
   下行是缩小的站外生图入口（2026-09-24 用户要求「把这几个网站按钮缩小，放到复制提示词按钮的下面」）。
   `align-items: flex-start` 是关键 —— 不加的话主按钮会被拉伸成一整行宽。 */
.d-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.d-sites { display: flex; flex-wrap: wrap; gap: 8px; }
/* 详情页「打开 XX」按钮：比主按钮小一档（内边距与字号都收），鼠标悬浮时冒出
   「将跳转到其它网站！」的气泡（2026-09-24 用户要求）。
   ⚠ 站点全站去图标、公众页只许黑白灰 —— 这里气泡用纯灰（var(--tip-bg) / 白），不引入彩色。
   用 data-tip 属性 + ::after 渲染，正文按钮里不写提示文字。 */
/* ⭐ 2026-09-26（用户要求）「详情页中的各个跳转网页按钮全部缩小一倍」。
   实测改前 **78×47**（字号 13px / 内边距 12px），比「复制提示词」主按钮（108×44）还高一头 ——
   8 个站排下来在右栏要占 3 行 156px，压得提示词正文没地方站。
   改后 **66×27**（约原来的一半面积）：字号收到 --fs-2xs（12px，与徽章/标签同一档）、
   内边距收到 3px 8px。⚠️ 高度**不能再往下压**：27px 是留给"手指能点中"的余量，
   再小就掉到 24px（WCAG 2.5.8 的 AA 下限）以下了 —— design-audit 的触控那一节会从
   🟡AA 变 ❌不合格。想改小先看那一段的输出。 */
.d-site { position: relative; padding: 3px 8px; font-size: var(--fs-2xs); }
.d-site:hover::before, .d-site:hover::after { opacity: 1; visibility: visible; }
.d-site::before, .d-site::after {
  position: absolute; left: 50%; transform: translateX(-50%);
  opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .15s var(--ease);
  z-index: 6;
}
.d-site::after {
  content: attr(data-tip);
  bottom: calc(100% + 9px);
  background: var(--tip-bg); color: var(--ink-invert); font-size: var(--fs-2xs); line-height: 1.4; white-space: nowrap;
  padding: 5px 9px; border-radius: var(--radius-sm); box-shadow: var(--shadow-pop);
}
.d-site::before {
  content: ''; bottom: calc(100% + 3px);
  border: 6px solid transparent; border-top-color: var(--tip-bg);
}
/* ⚠️ 「.d-scene」（详情页尾部「所属场景：…」那一行）2026-09-26 随那一块 HTML 一起删除（用户要求），
   .d-scene / .d-scene a 两条规则已清掉。别再按 .d-scene 去找样式，也别把它加回来。 */

@media (max-width: 900px) {
  .detail { grid-template-columns: minmax(0, 1fr); }
  .d-img { max-height: 62vh; }
  .d-img img { max-height: 62vh; }
  .d-shot .d-img, .d-shot .d-img img { max-height: 54vh; }
  .d-img.is-small, .d-img.is-small img { max-height: 110px; }
  .d-refs .d-img, .d-refs .d-img img { max-height: 110px; }
  /* 成对版式在窄屏**仍然是左右两列**（用户要的就是"同一栏里左右并排"），
     只是把每张图的上限再收一档，免得一张图吃掉大半个屏。 */
  .d-pair .d-img { min-height: 96px; max-height: 54vh; }
  .d-pair .d-img img { max-height: 54vh; }
  .d-content { max-height: none; font-size: var(--fs-base); }
}

.p-title a { color: inherit; text-decoration: none; }
.p-title a:hover { color: var(--brand); }

/* ⚠️ 详情页「第六行 提示词模板」的样式（`.d-tpl-row` / `.d-tpl` / `.d-tpl-head` /
   `.d-tpl-title` / `.d-tpl-body`）已于 2026-09-24 随那一块 HTML 一起删除（用户要求
   「在详情页中，删除提示词模板」）。场景页与写作指南页的模板用的是**另一套类名**，未受影响。
   别再往这个区块里加东西、也别指望详情页还有 `.d-tpl*` 元素。 */

/* ---------- 提示词模板页（guide.html；2026-09-24 新增，此后两次整页重做）----------
   2026-09-28 **本轮**用户原话「提示词模板页面中，删所有的提示词，把实例内容改为卡片形式……
   提示词页面设计的更符合人性化，符合操作习惯、浏览习惯」。追问后定了四条：
     ① 可点的词标签**全部保留**；② 末尾那三套演练改成**成套示例卡**；
     ③ 页面上的**说明性灰字全删**（所以这一节里没有 .t-sub、也没有 .t-box-hint 了）；
     ④ 后台 ⑦ 改成**分块编辑**（后台的样式在 admin 那一段 / admin-theme.css）。
   这一页现在是：页头（只有标题）· 搜索 · 两个页签 · 成套示例 / 词表速查 · 吸顶文本框。

   ⚠️ 跟着被删掉的样式（别因为别处见过就往回加）：
      .g-hero / .g-search / .g-filt / .g-frow / .g-flabel / .g-fchips .tag-all /
      .g-scenes / .g-scene* / .g-ftag / .g-detail / .g-tpl / .g-dacts / .g-sibs* /
      .g-empty-act / .g-note
      —— 这些只服务旧的「四维筛选条 + 77 张场景卡 + 页内展开模板 + 同方向快切」。
      （.g-note 那条注释原来写着"admin.js 也在用"，实际全站只有指南页在用 ——
        2026-09-28 核实过，后台用的是 .sg-note，所以这个类一起删了。）
      .t-sub / .t-box-hint —— 这两个是"页面上的说明性灰字"，同日按用户要求删掉；
        别再往 HTML 里加回这两个类名（加了也没有样式，会变成一坨默认黑字）。
      .t-tabs / .t-tabc —— 上一版那两个页签的样式，同日按用户要求"解散"，
        HTML 里的 #tTabs / #tExPane / #tDictPane 也一起删了。

   ⚠️ 两个「不动」的实现不一样，别合成一套：
      · 桌面（> 900px）：右栏 position: sticky —— 跟着滚，但永远停在顶栏下面；
      · 窄屏（≤ 900px）：右栏 position: fixed 吸在**视口底部** —— 一列排不下两栏，
        再 sticky 只能排到卡片后面去，"不动"这条要求会直接失效。
        吸底必须配 body { padding-bottom: … }（同一段媒体查询里），
        不配的话页面最底下那块内容会被永久盖住：点不到、也读不到。
   ⚠️ 词卡复用站上既有的 .chip（胶囊），只把内边距压小 —— 几百个词用默认尺寸是一堵墙。
   ⚠️ 页签直接复用站上既有的 .tabs.app（文章页「热门 / 最新」同一套），别另造一套。
  ⭐ 2026-09-29 同日第九轮：用户发截图要求「页签字更大更粗」→
     `.tabs.app .tab` 字号 --fs-sm(14px) → --fs-title-sm(16px)，
     选中态 font-weight: 600、未选中 500（原来都是 400）。
     ⚠️ 这套是**全站共用**的（文章页「热门 / 最新」、我的收藏都吃它）——
        用户这次是**明确要更大更粗**，所以那两页一起变是预期内的，不是误伤。
   颜色一律走语义变量（pair-check 的 [H] 段会扫死颜色，公众页必须 R=G=B）。 */

/* ⭐ 2026-09-29 同日第十一轮：与 .page-head 统一（原来 6px 0 18px，顶多出 6px 且底部多 4px，
   同一屏里跟文章页/投稿页并排看就是"标题高一截、离页签远一点"）。
   现在上下完全同款：padding: 0 0 14px；字号两边都是 --fs-h1-lg（32px）。
   ⚠️ 这一页没有 .page-head 那个 <p> 说明句（09-28 按用户要求删了），别再补。 */
.t-head { padding: 0 0 var(--head-gap); }
/* ⭐⭐ 页标题的**完整规格**（2026-09-29 同日第十五轮定，六处必须一字不差）：
     字号 var(--fs-h1) · 字重 600 · 行高 1.3 · 字间距 var(--ls-tight)
   ⚠️ 之前这四项在六个类里各写各的：字重 600/650 两种、行高 1.3/1.32/1.4 三种、
      字间距 normal/-0.01em 两种 —— 单看一页没问题，两页并排就是"哪里怪怪的"。
   ⚠️ 要调这一档**只改 --fs-h1 令牌**，别去逐个类改数值。 */
.t-h1 { font-size: var(--fs-h1); font-weight: 600; line-height: 1.3; letter-spacing: var(--ls-tight); }

/* 两列：左边卡片（可宽），右边文本框（固定 340px）。
   ⚠️ align-items: start 是 sticky 能生效的前提（拉伸的话右栏没有可滚动的余量）。 */
.t-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 22px; align-items: start; }
.t-main { min-width: 0; }
.t-search { max-width: 460px; }
/* ⚠️ 这里原来有 .t-note（模板标签页顶部那行灰字反馈的样式），
   2026-09-29 同日第十二轮随 #tHint 整行删除 —— **别再补回来**。 */

/* ---- 页签（2026-09-29 本轮回来了，但**不是老的那两个**）----
   用户原话：「提示词模板页面，分为模板和标签两个可切换的内容」。
   ⚠️ 复用的是站上既有的 `.tabs.app`（文章页「热门 / 最新」、收藏页同一套），
      这里只加一个 `.t-tabs` 做间距微调 —— **别再另造一套页签样式**。
   ⚠️ 老的 `.t-tabs / .t-tabc`（2026-09-28 那版的页签）是另一回事：那是两屏内容
      （成套示例 / 词表速查），已按用户要求删干净。现在这两个页签是新语义，别混。
   ⚠️ 面板显隐**只有一处**判据 = guide.js 的 setPane()（靠 hidden 属性）。
      这里**不要**再写 `.t-pane { display: none }` 之类的规则跟它打架 ——
      作者样式一旦给了 display，UA 的 `[hidden]{display:none}` 就被盖掉。 */
/* ⭐ 2026-09-29 同日第十轮：页签与搜索框并成一条（页签左、搜索右）。
   用户原话：「大标题的模板标签，改为模板和标签两栏，右面跟着搜索栏」。
   ⚠️ 这一条以前自己带 14px 上边距（因为它是独立一行）—— 现在并进 .t-bar 了，
      上边距交给 .t-bar 统一管，否则会和搜索框对不齐（搜索框没有那个 margin）。
   ⭐ 同日第十一轮：用户要求「搜索框左移到标签旁边」→ justify-content 从 space-between
      改成 flex-start，搜索框不再被顶到最右，而是紧跟在页签右边（间距 = 下面那个 gap）。
   ⚠️ 窄屏（≤900px）那一段会把搜索框整行铺满（flex: 1 1 100%），
      那时 flex-start 与 space-between 没差别，不用另写一条覆盖。
   ⚠️ margin-top 必须是 0：上面的 .page-head / .t-head 已经用 padding-bottom: 14px
      给了留白，这里再加 margin 就会比文章页/投稿页的页签低 10px（同一屏并排看就是错位）。
      页签顶边要与那两页的 .tabs.app 完全对齐（都是紧接页头下留白）。 */
.t-bar {
  display: flex; align-items: flex-end; justify-content: flex-start;
  gap: 16px; flex-wrap: wrap; margin-top: 0;
}
/* 搜索框原来自己占满一行（max-width: 460px），并排后改成可伸缩、跟在页签右边。
   ⚠️ 要 align-items: flex-end 才能让搜索框底边与页签的下划线对齐（页签有 padding）。
   ⚠️ flex-basis 460px 只是"上限再配 min-width"的组合：空间不够会先缩，缩到 180px 才换行。 */
.t-bar .t-search { flex: 0 1 460px; max-width: 460px; min-width: 180px; }
/* 页签在 .t-bar 里：去掉自己的上边距，让它跟搜索框齐。 */
.t-bar .t-tabs { margin-top: 0; margin-bottom: 0; flex: none; }
/* 面板那两屏本身是"一条流"，页签切换只是换里面显示什么 */
.t-pane[hidden] { display: none; }

/* ---- ⭐ 标签页签的「左菜单 + 右内容」（2026-09-29 同日第四轮）----
   用户原话：「标签栏做侧边菜单栏」，追问确认范围是**只改标签内部**（顶部那两个页签不动）。
   左列 = 模块菜单（6 个模块），右列 = 选中的那个模块的小节与词。
   ⚠️ 菜单栏是 sticky 的，top 走 --topbar-h（顶栏高度由 JS 量出来写回这个变量）——
      写死像素会在顶栏高度变化时被盖住一截，而且那种错"只是看着有点别扭"，不会报错。
   ⚠️ 菜单列固定 216px：模块名最长是「画质与构图」这种 5 字，216px 一行放得下；
      再窄会把名字挤成两行。窄屏（620px 以下）整块收成一列横滑，见下面那段媒体查询。 */
/* ⭐ 2026-09-29 同日第十三轮：margin-top 16px → 25px。
   这是「标签」页签下（左菜单 + 右词表）与上面那条 `.t-bar` 之间的距离 ——
   必须与 `.t-tpls` / `.tabs.app` 的 25px 同值，三页才会看着一样高。 */
.t-tagwrap { display: grid; grid-template-columns: 216px minmax(0, 1fr); gap: 18px; align-items: start; margin-top: 25px; }
.t-tagmain { min-width: 0; }
.t-menu {
  position: sticky; top: calc(var(--topbar-h, 64px) + 12px);
  display: flex; flex-direction: column; gap: 2px;
  background: var(--panel); border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg); padding: 8px;
  /* 模块多了也能滚，别让菜单比视口还高 */
  max-height: calc(100vh - var(--topbar-h, 64px) - 32px); overflow: auto;
}
/* 菜单项：整行可点，左编号 + 模块名 + 右侧命中词数。
   ⚠️ 触达区 ≥44px 用 min-height + 伪元素补（站上统一补法），不自增 padding 让行变胖。 */
.t-mi {
  position: relative; display: flex; align-items: center; gap: 8px; width: 100%;
  font: inherit; font-size: var(--fs-xs); color: var(--ink-2); text-align: left;
  background: none; border: 0; border-radius: var(--radius-sm);
  padding: 9px 10px; min-height: 40px; cursor: pointer; line-height: 1.45;
  transition: background .22s var(--ease), color .22s var(--ease);
}
.t-mi::before { content: ''; position: absolute; inset: -2px 0; }
.t-mi:hover { background: var(--surface-2); color: var(--ink); }
/* 选中态：黑底白字（与站上"选中项"的既有表达一致，别另造一套） */
.t-mi.is-active { background: var(--brand); color: var(--ink-invert); font-weight: 600; }
.t-mi-no { flex: none; font-size: var(--fs-2xs); opacity: .7; }
.t-mi-t { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.t-mi-n { flex: none; font-size: var(--fs-2xs); opacity: .7; }

/* ---- 模板卡（「模板」页签；一张卡 = 标题 + 文本内容 + 复制）----
   ⚠️ 正文用 <pre>：模板里换行、空格、`--ar 16:9` 这类参数都可能是有意义的排版，
      用 <p> 会把换行折掉。所以要显式重置 pre 的默认等宽字体与 margin。 */
/* ⭐ 2026-09-29 同日第四轮：用户要求「这个卡片宽 500px，自适应横排，后台管理也是这样」。
   ⭐⭐ 2026-09-29 同日第十五轮：用户改口「卡片变窄四分之一，可以根据窗口自适应**小幅**调节宽度」。
      追问确认：① 基准 500 → **375px 左右**；② 要**小幅伸缩**（约 ±20%），不是写死。
   ── 实现（两处配合，缺一不可）──
     ① 网格列 = `repeat(auto-fill, minmax(min(100%, 330px), 1fr))`
     ② 卡片本体 = `.t-tpl { max-width: 450px }`（见下面那条规则）
   ⚠️⚠️ 为什么上界不能写在 minmax 里（这是本轮最关键的坑）：
      `repeat(auto-fill, minmax(330px, 450px))` 看着最直观，**实际是死的** ——
      CSS 规范里 auto-fill / auto-fit 算"能放几列"时，**若 max 是确定值就用 max 当除数**
      （§7.2.3.1；只有 max 不确定才用 min）。于是列数按 450 算，每列又被 max 顶到 450，
      结果**每张卡恒等于 450px**，完全失去"自适应"。
      实测证据（改前那版 minmax(360,450)）：窗口 1680/1440 → 卡宽全是 450，
      1280 起直接掉成 1 列 450 —— 既不跟随窗口，也不整齐。
      ⇒ 上界必须改成 **`1fr`**（不确定值）→ 列数按 min(330) 算、轨道再把行**填满**；
        真正的"上界 450"交给卡片自身的 `max-width`。
   ⚠️ min 取 330（不是 360）是**算出来的**，不是拍的：
      本页正文列 `.t-main` 在 1440 窗口下只有 **1032px**，
      330×3 + 16×2 = 1022 ≤ 1032 → 恰好排下 **3 列（每列 333）**；
      若 min 取 360，则 3 列要 1112 > 1032，只能退成 2 列 → 每列被拉到 508、
      再被 max 截成 450 并**剩 116px 空档**，正是要避免的"右边缺一块"。
   ⚠️ `min(100%, 330px)` 不可省：不写 min(100%) 时手机（390px）容器虽够，
      但更窄的机型上会横向溢出 —— 冒烟那条"窄屏无横向溢出"会当场红。
   ⚠️ 不用 flex + flex-wrap：flex 的 flex-grow 会把**最后一行**几张拉得比别的行宽，
      出现"此行与彼行宽度不一致"；网格的轨道算法天然保证每列等宽。 */
/* 空态（还没有模板 / 搜索 0 命中）：退回普通块流，别被网格当成一格。 */
.t-tpls.is-empty { display: block; }
/* ⭐ 2026-09-29 同日第十三轮：margin-top 16px → 25px（与 .tabs.app 的下外边距同值）。
   这就是用户截图里红框圈的那段「页签/搜索栏 → 白卡」的竖直距离。
   ⚠️ 这个 25px 必须与 `.tabs.app { margin: 0 0 25px }` 以及下面的 `.t-tagwrap`
      三处同值 —— 它们分别是"模板页签下""标签页签下""文章/投稿页签下"的同一样东西，
      任何一处单独改都会让三页看着又不一样（这就是这一轮要修的病）。 */
.t-tpls {
  display: grid; gap: 16px; margin-top: 25px;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 330px), 1fr));
  justify-content: start;
}
.t-tpl {
  background: var(--panel); border-radius: var(--radius-lg); box-shadow: var(--shadow-1);
  padding: 18px clamp(16px, 1.8vw, 22px) 16px;
  /* ⚠️ 卡内原来靠 .t-tpls 的 margin-top 撑开，进网格后 margin 会跟 gap 叠加 → 去掉。
     卡片自身也不该有上外边距，间距一律交给父容器的 gap。 */
  /* ⭐ 2026-09-29 同日第十五轮：卡片宽度的**上界 450px** 落在这里（不是网格的 minmax 里）。
     理由见上面 `.t-tpls` 那段长注释：auto-fill 算列数时若 max 是确定值就按 max 当除数，
     网格会被钉死成"每张卡恒 450"；所以把上界从网格挪到卡片本体，
     网格那边用 `1fr` 让轨道填满，卡片再用 max-width 收在 450 以内。
     ⇒ 效果：卡宽随窗口在 **约 333 ~ 450px** 之间小幅变化，永不回到 500（那是改前的老宽度）。 */
  width: 100%; max-width: 450px; min-width: 0;
}
.t-tpl-h { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
/* ⭐ 2026-09-29 同日第八轮：用户发了两张截图说「标题部分不一样」→ 确认要的是
   **模板卡标题更小更轻**（16px / 500）。
   ⚠️⚠️ 千万别直接改 `--fs-md` —— 那个变量是**首页卡片标题**在用的，
      而首页 17px/600 是用户 2026-09-24 明确要求「放大 2 号」的，动了就把他那条改回去了。
      模板卡要的是**另一档** `--fs-title-sm`（16px），所以这里换变量，不动共享值。
   ⚠️ 后台「模板管理」用的是同一个 `.t-tpl-t`（admin.js 里渲染的），
      所以改这一处，公开页与后台**同时**生效 —— 这正是用户要的「后台也同步」。
   实测依据：用户图2 里 标题字高÷正文字高 = 1.28（图1 现在是 1.50），
   且标题区黑像素密度 14%（图1 是 28%）→ 字号降一档 + 字重降一档，
   正好落在 --fs-title-sm (16px) / 500 上。 */
.t-tpl-t { flex: 1 1 auto; min-width: 0; font-size: var(--fs-title-sm); font-weight: 500; }
.t-tpl-acts { display: flex; gap: 8px; margin-left: auto; }
/* 折叠容器：卡内高度统一。
   ⚠️ 折叠只许用 max-height（反向锁盯着这件事，别换写法）：
      `<pre>` 里的换行是**真换行**，任何依赖 -webkit-box 的多行截断写法
      都会把 pre 的空白折叠规则一起干掉，正文的真换行全挤成一行、模板卡就废了。
   ⚠️ 计算式：6 行 × 1.85 行高 = 11.1em，再加 padding 上下 12px×2 = 1.5rem。
      改行数就改这两个数（别忘了 620px 窄屏那段也要跟着改）。 */
.t-tpl-fold { max-height: calc(11.1em + 1.5rem); overflow: hidden; position: relative; }
.t-tpl.is-open .t-tpl-fold { max-height: none; }
.t-tpl-body {
  margin: 11px 0 0; padding: 12px 13px;
  background: var(--surface-2); border-radius: var(--radius-sm);
  font: inherit; font-size: var(--fs-xs); line-height: 1.85; color: var(--ink);
  white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere;
}
.t-tpl-body mark { background: transparent; font-weight: 600; }
/* 折起来时底部压一层渐隐，明示"下面还有"（公众页只能黑白灰：用 --panel，不带色）。
   ⚠️ 不挡点击（pointer-events:none），否则鼠标停在最后一行点不动。 */
.t-tpl-fold::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 26px;
  background: linear-gradient(to bottom, transparent, var(--surface-2));
  pointer-events: none; opacity: 1;
}
.t-tpl.is-open .t-tpl-fold::after { opacity: 0; }
/* 「展开 / 收起」：细边框小按钮，跟卡里其它按钮不是一个层级，不抢眼。
   ⚠️ 触达区 ≥44px 用伪元素内衬补（这是站上统一的补法，别改成真 padding）。 */
.t-tpl-more {
  margin-top: 10px; position: relative;
  font: inherit; font-size: var(--fs-2xs); color: var(--ink-2);
  background: none; border: 0; padding: 0; cursor: pointer;
}
.t-tpl-more::before { content: ''; position: absolute; inset: -13px -8px; }
.t-tpl-more:hover { color: var(--ink); }
.t-tpl-more[hidden] { display: none; }
/* 点「复制 / 填进去」的即时反馈（只动 background / transform，符合站上的动效规矩） */
.t-tpl-copy.is-hit, .t-tpl-fill.is-hit { transform: scale(.96); }


/* ---- 示例区（页面最下面那一块；2026-09-28 本轮从"页签的第二屏"挪到页尾）----
   ⚠️ 上一版那两个页签（`.t-tabs` / `.t-tabc` 连同 `#tTabs` / `#tExPane` / `#tDictPane`）
      用户明确要求"解散"，已经整块删掉 —— 别再往回加。
   分隔靠一条上边框 + 大一点的上留白：它是"另一类内容"（成套示例 vs 词表），
   不该和上面的词表卡长得一模一样，否则一眼看不出这是另一块。 */
.t-exsec { margin-top: 34px; padding-top: 22px; border-top: 1px solid var(--line); }
/* ⚠️ 这条必须写：`hidden` 属性靠的是 UA 样式表里的 `[hidden]{display:none}`，
   只要作者样式给这个元素写了任何 `display`，它就被盖掉了 —— 写一行保险。 */
.t-exsec[hidden] { display: none; }
.t-exsec-h { display: flex; align-items: baseline; gap: 9px; }
.t-exsec-t { font-size: var(--fs-md); font-weight: 600; }
.t-exsec-n { font-size: var(--fs-2xs); color: var(--ink-3); }

/* ---- 成套示例卡（一张卡 = 一个完整场景，点一段抄一段、也能整套抄走）---- */
.t-ex {
  background: var(--panel); border-radius: var(--radius-lg); box-shadow: var(--shadow-1);
  padding: 18px clamp(16px, 1.8vw, 22px) 16px; margin-top: 16px;
}
.t-ex-h { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.t-ex-no {
  font-size: var(--fs-2xs); color: var(--ink-2); background: var(--surface-2);
  border-radius: var(--radius-sm); padding: 2px 7px;
}
.t-ex-t { flex: 1 1 auto; min-width: 0; font-size: var(--fs-md); font-weight: 600; }
.t-ex-n { margin-left: auto; font-size: var(--fs-2xs); color: var(--ink-3); }
.t-ex-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; }
.t-ex-tag {
  font-size: var(--fs-2xs); color: var(--ink-3);
  border: 1px solid var(--line-2); border-radius: var(--radius-pill); padding: 1px 9px;
}

/* 段落：一行一段；段名占固定一列，值从同一条竖线开始，扫起来快。
   ⚠️ 整段是一个 <button>（点一下 = 把这一段加进右边那个框），所以 reset 要写全：
      appearance / font / text-align / width / border 少写一个，浏览器的按钮默认底纹就会冒出来。
   ⚠️ 只动 background-color / transform（站上的动效规矩：不动布局属性，不用回弹缓动）。 */
.t-ex-parts { margin-top: 12px; display: grid; gap: 4px; }
.t-seg {
  display: grid; grid-template-columns: 52px minmax(0, 1fr); gap: 10px; align-items: start;
  width: 100%; text-align: left; font: inherit;
  appearance: none; -webkit-appearance: none;
  background: none; border: 0; border-radius: var(--radius-sm);
  padding: 6px 8px; cursor: pointer;
  transition: background-color .16s ease, transform .16s ease;
}
.t-seg:hover { background: var(--surface-2); }
.t-seg:focus-visible { outline: 2px solid var(--ink-3); outline-offset: 1px; }
.t-seg.is-hit { background: var(--brand); transform: scale(.995); }
.t-seg.is-hit .t-seg-l, .t-seg.is-hit .t-seg-v, .t-seg.is-hit mark { color: var(--ink-invert); }
.t-seg-l { font-size: var(--fs-xs); color: var(--ink-2); padding-top: 3px; line-height: 1.5; }
.t-seg-v { font-size: var(--fs-xs); color: var(--ink); line-height: 1.75; }
.t-seg mark { background: transparent; font-weight: 600; }
.t-ex-f { display: flex; justify-content: flex-end; margin-top: 12px; }

/* ---- 卡片（词表：一个模块一张）---- */
.t-card {
  background: var(--panel); border-radius: var(--radius-lg); box-shadow: var(--shadow-1);
  padding: 18px clamp(16px, 1.8vw, 22px) 16px; margin-top: 16px;
}
/* ⭐ 2026-09-29 同日第十四轮：用户截图指出「标签页中，两边没对齐」。
   实测：左菜单 `.t-menu` 顶 = 211，右卡 `.t-card` 顶 = 227 —— **差 16px**，
   真因就是上面那条 `margin-top: 16px`。
   ⚠️ 那个 16px 本意是「竖着排的多张词表卡之间留缝」（模板页签 / 后台模板列表都是多张连排，
      确实需要）。但**标签页签里 `#tCards` 一次只渲染"当前选中模块"这一张卡** ——
      单张卡的 margin-top 不构成"卡间距"，只把**整列内容**平白推下去 16px，
      于是与左侧菜单的顶边错开（`.t-tagwrap` 是 align-items: start，两列顶边本该齐平）。
   ⇒ 修法：只把 `#tCards` 里的**首张**卡上边距归零（多张卡时后续卡仍有 16px 缝，不受影响）。
   ⚠️ 用 `#tCards > .t-card:first-child` 压住作用域：**不能**写通用 `.t-card:first-child` ——
      `#tCards` 里首张卡之后紧跟的是 `.t-exsec`（示例区），那是另一类内容、有自己的 34px 上边距，
      而模板页签的 `#tTpls` 是纯卡片网格，首张卡本来就该吃网格的 gap。 */
#tCards > .t-card:first-child { margin-top: 0; }
.t-card-h { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
.t-card-no {
  font-size: var(--fs-2xs); color: var(--ink-2); background: var(--surface-2);
  border-radius: var(--radius-sm); padding: 2px 7px;
}
.t-card-t { font-size: var(--fs-md); font-weight: 600; }
.t-card-en { font-size: var(--fs-2xs); color: var(--ink-3); letter-spacing: var(--ls-wide); }
.t-card-n { margin-left: auto; font-size: var(--fs-2xs); color: var(--ink-3); }
.t-card-note { margin-top: 7px; font-size: var(--fs-xs); color: var(--ink-3); line-height: 1.7; }

.t-sec { margin-top: 15px; padding-top: 13px; border-top: 1px solid var(--line-2); }
.t-sec:first-of-type { border-top: 0; padding-top: 0; }
.t-sec-h { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); margin-bottom: 8px; }

/* 一行 = 左边行名 + 右边一串词。行名那一列固定窄一点，词都从同一条竖线开始，扫起来快。 */
.t-row { display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: 10px; align-items: start; padding: 5px 0; }
.t-row-h { font-size: var(--fs-xs); color: var(--ink-2); padding-top: 5px; line-height: 1.5; }
.t-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.t-chip { padding: 4px 10px; font-size: var(--fs-2xs); line-height: 1.5; }
/* 点一下的即时反馈（只动 background / transform，符合站上的动效规矩） */
.t-chip.is-hit { background: var(--brand); border-color: var(--brand); color: var(--ink-invert); transform: scale(.94); }
.t-chip mark { background: transparent; font-weight: 600; }
.t-empty-act { margin-top: 10px; font-size: var(--fs-xs); }

/* ---- 右侧「你的提示词」（桌面吸顶）---- */
.t-side { position: sticky; top: calc(var(--topbar-h, 60px) + 14px); }
.t-box {
  background: var(--panel); border-radius: var(--radius-lg); box-shadow: var(--shadow-2);
  padding: 14px; display: flex; flex-direction: column; gap: 10px;
}
.t-box-h { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.t-box-t { font-size: var(--fs-sm); font-weight: 600; }
.t-box-n { font-size: var(--fs-2xs); color: var(--ink-3); }
/* 高度跟着视口走，但留上下限：减掉 340px 是给顶栏 + 页头 + 按钮行 + 提示那句的余量 ——
   不留的话，800px 高的笔记本上框底会被顶出屏幕，「复制」就点不到了。 */
.t-box-ta {
  height: clamp(200px, calc(100vh - 340px), 460px);
  min-height: 0; margin: 0; font-size: var(--fs-xs); line-height: 1.8;
}
.t-box-acts { display: flex; gap: 8px; }
.t-box-acts .btn { flex: 1; }
/* ⚠️ 这里原来有一条 .t-box-hint（"不会自动保存，刷新就清空"那句灰字），
   2026-09-28 本轮按用户要求删掉 —— 别再往 HTML 里加回这个类名。 */

/* 窄屏：两列排不下 → 单列；右栏改成**吸在视口底部**的横条
   （竖着排到卡片下面 = 跟着滚走了，"不动"这条要求会失效）。
   ⚠️ body 的 padding-bottom 是给它留的高度，两者必须一起改：条子长高了不加 padding，
      页面最底下的内容会被永久盖住。 */
@media (max-width: 900px) {
  .t-wrap { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .t-side { position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 40; }
  .t-box {
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    box-shadow: var(--shadow-up);
    padding: 10px 12px 12px; gap: 8px;
  }
  .t-box-ta { height: 74px; }
  /* ⚠️ 吸底条的高度直接决定下面这个 padding-bottom 要留多少：条子里少一行
     （原来这里还有一条 .t-box-hint 被隐藏）不会让条子变矮，量的时候务必**实测**条子高度。 */
  /* ⚠️ 这个数必须 ≥ 吸底条的实际高度（实测 390×844 下是 179px）：
       条子高过它，页面最底下的页脚就会被永久盖住一截（点不到、也读不到）。
       改条子里的行高 / 内边距之后，这里要跟着重量（`v3` 那张手机截图能看到页脚）。 */
  body { padding-bottom: 186px; }
}
/* 行名那一列在窄屏收到词上面（84px 固定列会把词挤成竖排）；
   示例卡里的段名同理收窄一点，别把段名本身挤成两行。 */
@media (max-width: 620px) {
  .t-row { grid-template-columns: minmax(0, 1fr); gap: 5px; padding: 3px 0; }
  .t-row-h { padding-top: 0; }
  .t-card { padding: 15px 14px 13px; }
  .t-exsec { margin-top: 26px; padding-top: 18px; }
  .t-ex { padding: 15px 14px 13px; }
  .t-seg { grid-template-columns: 44px minmax(0, 1fr); gap: 8px; padding: 6px 4px; }
  /* 模板卡：窄屏上标题与两个按钮的宽度都紧张 —— 标题占满一行、按钮换到下一行。 */
  .t-tpl { padding: 15px 14px 13px; }
  /* 窄屏一律单列（第十五轮起卡宽上界 450px，390px 屏上本来就只排得下 1 张，
     但显式收成 1fr 更稳：minmax 的下界会随容器算，偶发情形下可能排成两个迷你列）。 */
  .t-tpls { grid-template-columns: minmax(0, 1fr); }

  /* 标签页签的左菜单：窄屏改成顶部横向一条，可左右滑。
     ⚠️ 不能保留 216px 的侧栏 —— 手机 390px 下剩给内容的只有 150px 出头，
        词会被挤成一列竖排的字。
     ⚠️ 取消 sticky：横向条在窄屏粘住会占掉不少高度，本来就没什么竖向空间。 */
  .t-tagwrap { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  .t-menu {
    position: static; flex-direction: row; flex-wrap: nowrap;
    overflow-x: auto; overflow-y: hidden; max-height: none; padding: 6px;
    -webkit-overflow-scrolling: touch;
  }
  .t-mi { flex: 0 0 auto; min-height: 36px; padding: 7px 11px; white-space: nowrap; }
  .t-mi-t { overflow: visible; text-overflow: clip; }
  /* 折叠高度**不用在这里重算**：上面写的是 em + rem（跟字号 / 内边距同步），
     而字号和 padding 本段又没改 —— 6 行还是 6 行。改了字号才需要动。 */
  .t-tpl-h { display: block; }
  .t-tpl-acts { margin: 10px 0 0; }
  .t-tpl-acts .btn { flex: 1; }
}


/* ---------- 后台：提示词模板 · 分块编辑器（panel-t，2026-09-28 本轮改成"左列表 + 右单块"）----------
   用户要求「后台管理中提示词模板设计为更容易管理的展现形式」——
   原来是一整个大文本框（整份正文塞进去改），现在改成：
     左 = 正文结构（页头 / 模块 / 小节，按正文顺序）；右 = 单独编辑选中的那一块。

   要件与理由：
     · 等宽字体 —— 四种写法全靠 ## / ### / * 这些符号对齐，比例字体下看不齐；
       字体栈里**不要**把自托管的 HarmonyOS 放第一（它是比例字体，装了等于没写等宽）。
     · 左边列表给 max-height + 滚动：这份正文有 6 个模块 22 个小节，
       不滚的话会把右边的编辑器顶到屏幕外面，"点一块编辑一块"就废了。
     · 窄屏（≤ 900px）两列排不下，落回单列：列表在上、编辑器在下。

   ⚠️ 颜色一律走语义变量：pages.css 是**公众页也在加载**的文件，pair-check 的 [H] 段
      会把它按"公众界面文件"扫一遍，出现任何非灰硬编码颜色都会报红。
      后台那一点品牌色放在 admin-theme.css 里（比如左边列表的选中底色）。
   ⚠️ 上一版那个 `#gdMd`（一整个大文本框）已随本轮改造删掉，别再把它加回来。 */
.gd-wrap { display: grid; grid-template-columns: 264px minmax(0, 1fr); gap: 14px; align-items: start; }

.gd-side {
  background: var(--surface-2); border: 1px solid var(--line-2);
  border-radius: var(--radius); padding: 10px; position: sticky; top: 12px;
}
.gd-side-h { font-size: var(--fs-2xs); color: var(--ink-3); padding: 2px 6px 8px; }
.gd-list { display: flex; flex-direction: column; gap: 2px; max-height: 58vh; overflow: auto; }
.gd-addmod { width: 100%; margin-top: 8px; }

/* 列表里的三种行：页头（最上面一条）、模块（粗体、带徽章）、小节（缩进、细体） */
.gd-item {
  display: flex; align-items: center; gap: 6px; width: 100%; text-align: left;
  font: inherit; font-size: var(--fs-xs); color: var(--ink-2);
  background: none; border: 0; border-radius: var(--radius-sm);
  padding: 6px 8px; cursor: pointer; line-height: 1.5;
}
.gd-item:hover { background: var(--panel); }
.gd-item.is-sel { background: var(--panel); color: var(--ink); font-weight: 600; box-shadow: var(--shadow-1); }
.gd-item-m { font-size: var(--fs-sm); color: var(--ink); font-weight: 600; margin-top: 6px; }
.gd-item-s { padding-left: 18px; }
.gd-item-t { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gd-badge {
  flex: none; font-size: var(--fs-2xs); font-weight: 400;
  color: var(--ink-3); border: 1px solid var(--line-2); border-radius: var(--radius-pill); padding: 0 6px;
}

/* 右：单块编辑器 */
.gd-edit { background: var(--panel); border: 1px solid var(--line-2); border-radius: var(--radius); padding: 14px; }
.gd-eh { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.gd-et { font-size: var(--fs-sm); font-weight: 600; flex: 1 1 auto; min-width: 0; }
.gd-eacts { display: flex; gap: 6px; flex-wrap: wrap; }
.gd-ta {
  width: 100%; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Courier New", monospace;
  font-size: var(--fs-xs); line-height: 1.75; tab-size: 2;
}
.gd-kids { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.gd-blank { font-size: var(--fs-xs); color: var(--ink-3); padding: 18px 4px; line-height: 1.7; }

@media (max-width: 900px) {
  .gd-wrap { grid-template-columns: minmax(0, 1fr); }
  .gd-side { position: static; }
  .gd-list { max-height: 36vh; }
}
/* ---------- 详情页评论区（2026-09-26 加）----------
   ⚠ 2026-09-26 用户要求「评论区位于右侧卡面下面」：原来整幅铺在详情两栏下面（因此不受右栏窄宽度限制），
     现在收进右栏 .d-side、做成和提示词卡片同款的白卡，贴在它下面。
     好处是详情页只剩一条纵向阅读线；代价是评论栏宽度 ≈ 右栏（比手机屏略宽），
     窄栏里长评论会多折几行 —— 这是用户明确要的版式，不是 bug，别再"顺手"铺回整幅。
   ⚠ 上下间距改由 .d-side 的 gap 管，所以这里 margin-top 归零（铺在下面时用的是 --sp-7）。
   配色遵守公众页「只有黑白灰」：底 --surface-*、线 --line-*、字 --ink / --ink-2 / --ink-3。 */
.comments { margin-top: var(--sp-7); }
/* 收进右栏之后：跟着 .d-side 的 gap 排、同款白卡（特异性 0,2,0 > 上面那条 0,1,0，稳赢） */
.d-side > .comments {
  margin-top: 0;
  background: var(--panel); border-radius: var(--radius-lg);
  padding: clamp(20px, 2vw, 30px); min-width: 0;
}

.cm-head {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: var(--fs-lg); font-weight: 600; margin: 0 0 var(--sp-4);
}
.cm-count { font-size: var(--fs-xs); font-weight: 400; color: var(--ink-3); }

/* ⭐ 2026-09-29 同日第十二轮：用户截图圈出「整个评论输入区外面那层灰底卡片」（红框）要求删掉。
   那层就是下面这条的 background + border + border-radius + padding。
   现在整条去掉 —— 文本框与「发表评论」按钮**直接落在 `.comments` 白卡上**，
   不再套一层"卡片里的卡片"（详情页右栏本来就是一张白卡，再套一层灰卡视觉上很碎）。
   ⚠️ 保留 .cm-form 这个类名与 <form> 元素本身：JS 靠 `#cmForm` 取表单、
      submit 事件挂在他身上（改名会静默失效）。
   ⚠️ 不要再给 .cm-form 加 padding —— 用户要的就是"没有框"。 */
.cm-form { margin: 0; }
.cm-input {
  box-sizing: border-box; width: 100%; min-height: 76px; resize: vertical;
  padding: var(--sp-3); border: 1px solid var(--line-mid); border-radius: var(--radius);
  background: var(--panel); color: var(--ink); font-size: var(--fs-base); line-height: 1.7;   /* #FFF → var(--panel)（同值） */
}
.cm-input:focus { outline: 2px solid var(--ink); outline-offset: -1px; border-color: transparent; }
/* ⚠️ 这一条的上边距原来是"卡片内边距 + 这条 margin"两层给的；上层卡片删了之后
   只剩这一层，所以从 --sp-3 提到 --sp-4，免得按钮贴着文本框。
   窄屏那一段（<=600px）会把按钮拉成整行宽，照旧。 */
.cm-foot { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-3); margin-top: var(--sp-4); }

.cm-login {
  padding: var(--sp-4); border: 1px solid var(--line-soft); border-radius: var(--radius);
  background: var(--surface-2); color: var(--ink-2); font-size: var(--fs-sm);
}
.cm-login a { margin-left: var(--sp-2); text-decoration: underline; }

.cm-list { list-style: none; margin: var(--sp-5) 0 0; padding: 0; }
.cm-item { display: flex; gap: var(--sp-3); padding: var(--sp-4) 0; border-top: 1px solid var(--line-2); }
.cm-item:first-child { border-top: 0; }
/* ⭐ min-width:0 必须写：不写的话长字符串（一串英文、长链接）会把整行撑破，横向溢出 */
.cm-main { flex: 1; min-width: 0; }
.cm-meta { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.cm-name { font-size: var(--fs-sm); font-weight: 600; }
.cm-tag {
  padding: 0 5px; border: 1px solid var(--line-mid); border-radius: var(--radius-xs);
  color: var(--ink-2); font-size: var(--fs-2xs);
}
.cm-time { font-size: var(--fs-2xs); color: var(--ink-3); }
/* 删除按钮平时不抢眼：靠 hover / 键盘聚焦才显形。触屏没有 hover，所以常显。 */
.cm-del {
  margin-left: auto; padding: 2px 4px; border: 0; background: none; cursor: pointer;
  color: var(--ink-3); font-family: inherit; font-size: var(--fs-2xs);
  opacity: 0; transition: opacity .2s var(--ease), color .2s var(--ease);
}
.cm-item:hover .cm-del, .cm-del:focus-visible { opacity: 1; }
.cm-del:hover { color: var(--ink); text-decoration: underline; }
.cm-text {
  margin: var(--sp-2) 0 0; color: var(--ink); font-size: var(--fs-base);
  line-height: 1.75; overflow-wrap: break-word;
}
.cm-empty { padding: var(--sp-5) 0; color: var(--ink-3); font-size: var(--fs-sm); text-align: center; }

@media (max-width: 600px) {
  /* .comments 的 margin-top 已由 .d-side > .comments 归零接管（特异性更高），这里不再管间距 */
  .d-side { gap: 14px; }
  .cm-foot { flex-direction: column; align-items: stretch; }
  .cm-foot .btn { width: 100%; }
}
@media (hover: none) {
  .cm-del { opacity: 1; }          /* 触屏设备：常显，否则永远点不到 */
}

/* ==========================================================================
   文章分享（2026-09-27 加）—— 三处用到：
     ① 站内文章页 article.html（`.art-*`）—— 用户要求**内容区固定 1200px**
     ② 文章**列表**页 articles.html 的卡片流（`.a-card`）—— 2026-09-28 从指南页底部整块搬过来的
     ③ 「我的收藏」页里文章那一栏（复用 `.a-card`）
   ⚠️ ②③ 是同一套卡片，改样式一次全生效；改一处请两处都看一遍。
   ⚠️ 公众页只有黑白灰：这一段只许用语义变量与纯黑 rgba，不引入任何彩色
      `node tools/pair-check.mjs` 的 [H] 灰阶扫描盯着这条。
   ⚠️ 「1200px 固定宽」在窄屏必须降级成 100% —— 真按 1200 硬撑，
      手机上会出现横向滚动条，整页没法看。所以是 width:1200px + max-width:100%。
   ========================================================================== */

/* ---------- ① 站内文章页 ---------- */
.art-page { width: 1200px; max-width: 100%; margin: 0 auto; padding: 26px 0 48px; }
.art-top { margin-bottom: 14px; }
.art-back { color: var(--ink-3); font-size: var(--fs-xs); text-decoration: none; }
.art-back:hover { color: var(--ink); }
.art-card {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-1); padding: 44px 64px 40px;
}
.art-title { font-size: var(--fs-h1); font-weight: 600; line-height: 1.3; letter-spacing: var(--ls-tight); }
.art-title .badge { margin-left: 10px; vertical-align: middle; }
.art-by { display: flex; align-items: center; gap: 8px; margin-top: 16px; color: var(--ink-3); font-size: var(--fs-xs); }
.art-name { color: var(--ink-2); }
.art-dot { color: var(--line-strong); }
.art-note { margin-top: 16px; }
/* 互动行：收藏 / 点赞 / 看原文 / 作者操作。收起态是描边药丸，选中/激活是纯黑实底 */
.art-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin: 20px 0 0; }
.art-sep { width: 1px; height: 20px; background: var(--line); margin: 0 4px; }
.art-btn {
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-size: var(--fs-xs); color: var(--ink-2);
  background: var(--panel); border: 1px solid var(--line-mid); border-radius: var(--radius-pill);
  padding: 7px 14px; cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background .18s var(--ease), color .18s var(--ease), border-color .18s var(--ease);
}
.art-btn:hover { border-color: var(--line-strong); color: var(--ink); }
.art-btn b { font-weight: 600; color: var(--ink); }
.art-btn.is-on { background: var(--brand); border-color: var(--brand); color: var(--ink-invert); }
.art-btn.is-on b { color: var(--ink-invert); }
/* 正文：文章页的阅读区比全站正文大一档（长文要能读），行高放宽 */
.art-body { margin-top: 26px; font-size: var(--fs-md); line-height: 1.95; color: var(--ink); }
.art-body p { margin: 0 0 18px; overflow-wrap: break-word; }
.art-fig { margin: 22px 0; }
.art-fig img {
  display: block; width: 100%; height: auto; border-radius: var(--radius);
  background: var(--surface-3); border: 1px solid var(--line-2);
}
/* 图片淡入（见 ui.js 的 setImg）：基础态可见，等图期间才挂 .is-loading —— fail-safe */
.art-fig img.is-loading { opacity: 0; }
.art-fig img { transition: opacity .32s var(--ease); }

/* ---------- ② 文章卡片（文章列表页 / 我的收藏）----------
   用户要求：**跟提示词卡片长得不一样**，卡上是「第一张图 + 作者头像昵称 + 收藏量 + 点赞量」。
   ⚠️ 这份样式被 `articles.html`（列表页）与 `favs.html`（收藏的文章）共用，别只改一处。 */
.a-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; }
.a-card {
  display: flex; flex-direction: column; overflow: hidden; text-decoration: none; color: inherit;
  background: var(--panel); border: 1px solid var(--line-soft); border-radius: var(--radius-lg);
  transition: transform .22s var(--ease), box-shadow .22s var(--ease), border-color .22s var(--ease);
}
.a-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); border-color: var(--line-mid); }
.a-card:active { transform: translateY(0) scale(.995); }
.a-cover { display: block; aspect-ratio: 16 / 9; background: var(--surface-3); overflow: hidden; }
.a-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.a-cover img.is-loading { opacity: 0; }
.a-cover img { transition: opacity .32s var(--ease); }
.a-cover.is-none { display: grid; place-items: center; color: var(--ink-3); font-size: var(--fs-2xs); }
.a-body { display: flex; flex-direction: column; gap: 10px; padding: 14px 16px 16px; flex: 1; }
.a-title { font-size: var(--fs-md); font-weight: 600; line-height: 1.45; color: var(--ink);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.a-by { display: flex; align-items: center; gap: 6px; font-size: var(--fs-2xs); color: var(--ink-3); }
.a-by .avatar { width: 20px; height: 20px; font-size: var(--fs-2xs); }
.a-stats { display: flex; align-items: center; gap: 14px; margin-top: auto; font-size: var(--fs-2xs); color: var(--ink-3); }
.a-stats b { color: var(--ink-2); font-weight: 600; }
.a-empty { color: var(--ink-3); font-size: var(--fs-sm); }

@media (max-width: 900px) {
  .art-card { padding: 28px 22px 26px; }
  .art-body { font-size: var(--fs-base); line-height: 1.85; }
}
@media (max-width: 600px) {
  .a-list { grid-template-columns: minmax(0, 1fr); }
}


/* ---------- ④ 文章编辑器：格式工具条 + 编辑/预览（2026-09-27 加）----------
   照用户给的站酷发布页参考做的：H1 / H2 / H3 / 加粗 / 上传图片。
   ⚠️ 公众页只有黑白灰：这一段只用语义变量与纯黑 rgba（pair-check 的 [H] 灰阶扫描盯着）。 */
.art-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.art-tabs { display: inline-flex; gap: 2px; background: var(--field-bg); padding: 2px; border-radius: var(--radius-sm); }
.art-tab {
  font: inherit; font-size: var(--fs-2xs); color: var(--ink-2);
  background: none; border: 0; cursor: pointer; padding: 5px 12px; border-radius: var(--radius-xs);
  transition: background .18s var(--ease), color .18s var(--ease);
}
.art-tab:hover { color: var(--ink); }
.art-tab.is-on { background: var(--panel); color: var(--ink); font-weight: 600; box-shadow: var(--shadow-1); }
.art-tools {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
  padding: 6px 8px; margin-bottom: 8px;
  background: var(--surface-4); border: 1px solid var(--line); border-radius: var(--radius-sm);
}
/* 工具按钮要 ≥24px（WCAG AA 的点击下限）：padding 6px + 12px 行高 ≈ 30px */
.art-tool {
  font: inherit; font-size: var(--fs-2xs); font-weight: 600; color: var(--ink-2);
  background: var(--panel); border: 1px solid var(--line-mid); border-radius: var(--radius-xs);
  padding: 6px 10px; cursor: pointer; line-height: 1.2;
  transition: background .16s var(--ease), color .16s var(--ease), border-color .16s var(--ease);
}
.art-tool:hover { border-color: var(--line-strong); color: var(--ink); background: var(--surface-hover); }
.art-tool-b { font-weight: 800; }
.art-tool-sep { width: 1px; height: 18px; background: var(--line); margin: 0 4px; }
/* 预览区：与文章页共用 .art-body 的正文样式，这里只补"它是个框" */
.art-preview {
  margin-top: 0; padding: 16px 18px; min-height: 150px;
  background: var(--surface-4); border: 1px solid var(--line); border-radius: var(--radius);
}
.art-preview:empty::after { content: '（还没写正文）'; color: var(--ink-3); }

/* 文章页的标题级别（正文渲染出来的 h1/h2/h3）——
   ⚠️ 必须显式写：全站的 h1/h2/h3 是给"页面标题"用的，字号和间距都不适合正文里的小标题。 */
.art-body .art-h1 { font-size: var(--fs-c-h1); line-height: 1.4; margin: 30px 0 14px; }
.art-body .art-h2 { font-size: var(--fs-c-h2); line-height: 1.45; margin: 26px 0 12px; }
.art-body .art-h3 { font-size: var(--fs-c-h3); line-height: 1.5; margin: 22px 0 10px; }
.art-body .art-h1:first-child, .art-body .art-h2:first-child, .art-body .art-h3:first-child { margin-top: 0; }
.art-body b { font-weight: 700; }
@media (max-width: 900px) {
  .art-body .art-h1 { font-size: var(--fs-c-h1-sm); }
  .art-body .art-h2 { font-size: var(--fs-c-h2-sm); }
  .art-body .art-h3 { font-size: var(--fs-md); }
}

/* ---------- ③ 「我的收藏」页（2026-09-27 加）----------
   用户第二轮要求：**收藏的提示词也改成卡片**，并且和收藏的文章**并列**
   （做法与投稿页一致 —— 两个页签并排，不是左右两栏硬挤）。
   ⚠️ 卡片本身不在这里定义：提示词用全站的 .card（ui.js 的 UI.workCard 生成）、
      文章用 .a-card。这里只负责"把它们排成网格 + 右上角挂一个取消收藏"。 */
.fav-grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  align-items: start;
}
/* 一格 = 一张卡 + 一个浮在右上角的「取消收藏」。
   ⚠️ 按钮必须是卡片**外面**的元素：<a class="card"> 里再塞 <button> 是无效嵌套。 */
.fav-cell { position: relative; min-width: 0; }
.fav-x {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  font: inherit; font-size: var(--fs-2xs); line-height: 1.2;
  color: var(--ink-2); background: var(--panel);
  border: 1px solid var(--line-mid); border-radius: var(--radius-pill);
  padding: 5px 10px; cursor: pointer;
  box-shadow: var(--shadow-1);
  transition: background .18s var(--ease), color .18s var(--ease), border-color .18s var(--ease);
}
.fav-x:hover { background: var(--brand); border-color: var(--brand); color: var(--ink-invert); }
.fav-x:disabled { opacity: .55; cursor: default; }
@media (max-width: 600px) {
  .fav-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
}

/* ---------- 登录页的「忘记密码」（2026-09-27 加）----------
   .auth-alt = 登录按钮下面那一行次要入口（忘记密码 / 返回登录）
   .link-btn = 长得像链接的按钮（用 <button> 而不是 <a>，语义才对：它不跳页）
   .rs-row   = 验证码 + 「发送验证码」并排（窄屏自动叠成两行） */
.auth-alt { margin-top: 12px; text-align: center; }
.link-btn {
  font: inherit; font-size: var(--fs-xs); color: var(--ink-2);
  background: none; border: 0; padding: 5px 6px; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: var(--line-strong);
  transition: color .18s var(--ease), text-decoration-color .18s var(--ease);
}
.link-btn:hover { color: var(--brand); text-decoration-color: var(--brand); }
.rs-row { display: flex; align-items: flex-end; gap: 10px; }
.rs-row .field { flex: 1; min-width: 0; margin-bottom: 14px; }
.rs-row .btn { flex: none; margin-bottom: 14px; white-space: nowrap; }
@media (max-width: 420px) {
  /* 窄屏：验证码框和按钮并排会把两边都挤扁 → 让它各占一行 */
  .rs-row { display: block; }
  .rs-row .btn { width: 100%; margin-bottom: 14px; }
}

/* ==========================================================================
   账号设置（settings.html，2026-09-28 加）
   ==========================================================================
   用户要求：顶栏头像下拉里的「改昵称」改成「账号设置」，点进去能改昵称 / 头像 / 密码。
   · .set-wrap   = 这一页的容器（比登录页宽一点：里面要放头像预览）
   · .set-card   = 一张白卡 = 一件事（昵称 / 头像 / 邮箱 / 退出…），彼此独立
   · .set-info   = 只读信息（用户名 / 邮箱 / 身份 / 注册时间）的键值列表
   ⚠️ 预置头像色块那一套样式（8 个 56px 圆的选项）**2026-09-28 第二轮按用户要求已删**，
      头像只剩"上传自己的图"这一条路 —— 别再把那套选择器加回来。
   ⚠️ 全站公众页只有黑白灰：这里**没有**彩色装饰，唯一的颜色来自头像本身（用户内容）。
   ⚠️ 动效只用 transform / opacity / box-shadow —— 与 style.css 末尾那套约定一致；
      这里没有新增 transition，所以不用改 prefers-reduced-motion 白名单。 */
.set-wrap { max-width: 720px; margin: 0 auto; padding: clamp(24px, 4vh, 44px) var(--pad) 90px; }
.set-head { margin-bottom: var(--head-gap); }
.set-head h1 { font-size: var(--fs-h1); font-weight: 600; line-height: 1.3; letter-spacing: var(--ls-tight); }
.set-head .lead { color: var(--ink-3); font-size: var(--fs-sm); margin-top: 6px; }
.set-card { background: var(--panel); border: 1px solid var(--line-2); border-radius: var(--radius-lg); padding: 20px 20px 18px; margin-bottom: 16px; }
.set-card h2 { font-size: var(--fs-md); font-weight: 600; margin-bottom: 6px; }
.set-card > .hint { margin-bottom: 12px; }
.set-card .field { margin-bottom: 12px; }
.set-card .field:last-of-type { margin-bottom: 14px; }
.set-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.set-row .input { flex: 1 1 240px; min-width: 0; }
.set-row-tight { margin-top: 10px; }
.hint-inline { margin: 0; }
.set-info { display: grid; gap: 8px; margin-bottom: 12px; }
.set-info > div { display: flex; align-items: baseline; gap: 12px; font-size: var(--fs-sm); }
.set-info .k { flex: none; width: 9.5em; color: var(--ink-3); font-size: var(--fs-xs); }
.set-info .v { color: var(--ink); word-break: break-all; }
.set-info .muted { color: var(--ink-3); font-style: normal; }
.set-av { display: flex; align-items: flex-start; gap: 18px; flex-wrap: wrap; }
.set-av-now { flex: none; }
.set-av-side { flex: 1 1 300px; min-width: 0; }
/* 卡片底部那一颗单独的动作按钮（2026-09-28 加）：
   目前只有「账号信息」卡里的「修改密码」用它 —— 用户要求把改密码从一整块表单
   收成"注册时间下面的一颗按钮"。⚠️ 同一天删掉的那 8 个预置头像色块，别再加回来。 */
.set-act { margin-top: 14px; }
@media (max-width: 560px) {
  .set-av { gap: 14px; }
  .set-info .k { width: 6.5em; }
}
