/* ─────────────────────────────────────────────
   文档页：接口条；模型管理页：模型表格 + 映射弹窗；网关 Key 页：Key 表格

   三个页面的样式同住一个文件，是因为它们共用同一套表格与面板骨架
   （.models-table 是模型管理与网关 Key 共用，见下方注释）。
   **接口条（.ep-*）R8 起住在「文档」页**：它原来在「网关 Key」页，
   整块搬走后这些规则一字未改 —— 它们没有按 [data-page] 收窄（CSS 本来就是
   全局加载的），所以换页面不需要动样式。这里只更正文件头的描述。
   ───────────────────────────────────────────── */

/* ─── 接口条：纵向列表，一行一条端点 ───
   （Base URL / 三种对话协议 / 模型列表；替代原「一行三段」布局 ——
   端点从 3 条涨到 5 条后，横排会把每条压到放不下完整 URL）
   每行两排：上排「名字 + 用途」，下排「方法+URL + 复制」。
   URL 独占一行才放得下完整地址，也不与说明抢宽度。 */
.ep-panel .panel-head { padding-bottom: 12px; }

/* 内部横线用 --hairline（比 --border 淡一档）：面板头用的也是它，
   整块看起来才是「一个面板里的分行」而不是几条独立边框叠在一起 */
.ep-list { border-top: 1px solid var(--hairline); }

.ep-row {
  padding: 12px 16px;
  border-bottom: 1px solid var(--hairline);
}
.ep-row:last-child { border-bottom: 0; }
/* 悬停整行淡底：复制按钮在行尾，行够宽时眼球容易跟丢是哪一条 */
.ep-row:hover { background: var(--surface-inset); }

.ep-head { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }

.ep-name { color: var(--text); font-size: 12.5px; font-weight: 600; }

.ep-note { color: var(--text-3); font-size: 11.5px; }

.ep-line { display: flex; align-items: center; gap: 9px; margin-top: 5px; }

.ep-value {
  flex: 0 1 auto;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  /* 值可选中：想手动挑一段比复制整条更常见（比如只拿路径） */
  user-select: text;
}

/* 分组小标题：把「地址 / 对话协议 / 模型清单」三块视觉上分开，
   否则五条同构的行读起来是一整片 */
.ep-group {
  padding: 7px 16px 6px;
  border-bottom: 1px solid var(--hairline);
  background: var(--surface-inset);
  color: var(--text-3);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
}
/* 工具栏：提供商分段 + 状态分段 + 搜索，排成一行。
   它挂在 .panel-body 上（那条规则是 flex 纵向），这里必须显式改回横向，
   否则三个控件会各占一行并居中 */
/* 状态筛选与搜索框（都住在面板头里，见 index.html 的说明）。
   「搜索框 + 那排按钮」包成一个整体靠右：auto 外边距只给这个整体，不给搜索框自己
   —— 给它自己的话那个 auto 会吃掉全部剩余空间，右边那排按钮被挤到第二行。
   搜索框 240px（模型 ID / 别名一般十几个字符，再宽是白占地方），窄窗口下可压缩到 150px。 */
/* 右侧那排按钮（列设置 + 三颗操作）：不压缩、不内部换行 —— 允许压缩或折行的后果
   是它把自己拆开（按钮分两行），面板头就散了。空间不够时由 .panel-head 自己的
   flex-wrap 把整排挪到下一行。靠右由 .head-actions 自带的 margin-left:auto 完成。 */
.page[data-page="gateway"] .panel-head .head-actions { flex: 0 0 auto; flex-wrap: nowrap; }
/* 搜索框紧跟状态筛选（同为「看这张表」的控件），靠左；240px 是模型 ID / 别名
   能完整显示的宽度，这一页放得下 —— 曾为挤进同一行收到 180，不必了 */
#models-search { flex: 0 0 auto; width: 240px; }

/* 刷新说明与逐家结果：常驻在表格下方，不随 toast 消失；有失败才标红 */
/* ─── 「获取模型」弹窗的样式已随迁移移除 ───────────────
   弹窗迁到组件库后（ui-islands/src/islands/models-fetch-modal.tsx），这里原先那套
   .fm-tools / .fm-search / .fm-wrap / #fm-table-* .f-* 列宽 / .fm-table .detail /
   .modal-narrow 全部失去消费者，一并删除。搬走的口径（都是逐字照抄的，改之前先读
   岛里对应的注释）：

   · 列宽百分数：从「按 id 写的 CSS」搬到岛里 `<col>` 的 Tailwind 类上（列宽层
     table-columns.js 仍按表 id + col 的 data-col 定位，所以表 id 保留了）；
     六列 15/25/10/7/24/19、三列 8/74/18 —— 「更新日期」要给足 19% 才装得下完整
     时间戳（只给日期会在同一天两次刷新间分不出先后），「模型来源」25% 由邮箱长度
     定（emailAsName 的家以邮箱为主名）。
   · 滚动盒高度上限 min(48vh, 460px)、工具行「汇总在左、动作在右」的分工、
     窄形态 552px / 宽形态 920px：都改由岛里的 Tailwind 类表达。
   · 「模型来源」下拉：旧实现靠原生 select 当宽度锚（.select-shell 撑满单元格），
     新实现直接用组件库的 Select，宽度由单元格自己管。 */

/* 表格（模型管理 / 网关 Key 共用）：贴面板左右边缘，表头粘顶。
   overflow-anchor 同 .page.active：tbody 重建时不做锚定补偿，行内点开关视口不动 */
/* 表格滚动盒（模型管理 / 网关 Key 共用）。max-height 是**内容撑高、超过才收**的
   语义，网关 Key 页就按这个来（那页没有自己的高度骨架）。模型管理页要的是固定
   高度（与账号页一致），由 `.mm-main > .models-table-wrap` 覆盖成 flex 吃满剩余。 */
.models-table-wrap { overflow: auto; overflow-anchor: none; max-height: min(62vh, 720px); border-top: 1px solid var(--border); }

.models-table {
  width: 100%;
  border-collapse: collapse;
  table-layout: fixed;
  font-size: 12.5px;
}

/* 单元格内边距统一 8px（上下左右同值）：列宽本来就紧（七列分 100%），
   14px 会从每列吃掉 12px 的内容宽度。表头与表体用同一档，两者才对得齐；
   列宽拖动（table-columns.js）的可用宽度从 computed style 现读 padding，
   跟着这条生效，不需要另改。 */
.models-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 8px;
  border-bottom: 1px solid var(--border);
  background: var(--table-head-bg);
  color: var(--text-3);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .05em;
  text-align: left;
  white-space: nowrap;
}

.models-table td { padding: 8px; border-bottom: 1px solid var(--hairline); vertical-align: middle; }
.models-table tbody tr:last-child td { border-bottom: 0; }
.models-table tbody tr:hover td { background: var(--row-hover); }
.models-table th.r, .models-table td.r { text-align: right; }
.models-table td.empty { padding: 26px 8px; text-align: center; color: var(--text-3); }

/* 列宽（合计 100%，table-layout: fixed 下按 colgroup 分配） */
.models-table .c-model { width: 22%; }
.models-table .c-rate { width: 6%; }
.models-table .c-source { width: 7%; }
/* 能力位两列：数值一格（上下文 / 最大输出）、三枚布尔徽章一格。
   并入映射列的宽度从这里来 —— 五列会把它挤到装不下 chips（见 models-page
   文件头的列数取舍） */
.models-table .c-budget { width: 11%; }
.models-table .c-caps { width: 13%; }
.models-table .c-alias { width: 29%; }
.models-table .c-act { width: 12%; }
.keys-table .k-name { width: 22%; }
.keys-table .k-key { width: 44%; }
.keys-table .k-time { width: 16%; }
.keys-table .k-state { width: 8%; }
.keys-table .k-act { width: 10%; }

/* 禁用 / 已删除的行整体压淡，开关与操作列保持可点 */
.models-table tr.off td { opacity: .5; }
.models-table tr.off td.state, .models-table tr.off td.r { opacity: 1; }

/* 提供商分组行：表内的一条分组带。取 --surface-2，只比表体差一档 ——
   它仍是「表里的一行」，不该用卡内凹槽那档深色（那会把表切成几块）。 */
.models-table .tr-group td {
  padding: 5px 8px;
  background: var(--surface-2);
  color: var(--text-2);
  font-size: 11.5px;
  font-weight: 600;
}
.models-table .tr-group td:hover { background: var(--surface-2); }
.models-table .prov-tag {
  display: inline-block;
  margin-right: 8px;
  padding: 0 8px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-pill);
  background: var(--surface);
  font-weight: 700;
}
.models-table .tr-more td { padding: 4px 8px; text-align: center; }

/* 模型 id：等宽加粗。名字本身就是复制入口（上游模型列与映射别名 chip 的
   `.t` 都带 data-copy，点击走 clipboard.js 的全局委托）—— 曾经另挂一颗
   悬浮才显形的 ⧉ 按钮（.mid .cp），已去掉：点名字更省事，也少一个控件。
   可点样式只给带 data-copy 的名字：`.mid .t` 是模型管理 / 网关 Key 两页
   共用的，Key 页的名字不可复制，别把指针样式串过去。 */
.mid { display: flex; align-items: center; gap: 6px; min-width: 0; }
.mid .t { font-family: var(--font-mono); font-size: 12px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.keys-table .mid .t { font-family: var(--font-sans); }
.models-table .mid .t[data-copy],
.models-table .alias .t[data-copy] { cursor: pointer; }
.models-table .mid .t[data-copy]:hover,
.models-table .alias .t[data-copy]:hover {
  color: var(--text);
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}
/* 点击瞬间压淡一下：复制没有可见的落点（toast 之外），这一下是「点到了」的凭据 */
.models-table .mid .t[data-copy]:active,
.models-table .alias .t[data-copy]:active { opacity: .55; }
.mname { color: var(--text-3); font-size: 11.5px; }
.rate { font-family: var(--font-mono); font-size: 11.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* ── 能力位两列（「上下文 / 输出」与「能力」）─────────────────────────
   cell 内容是一个按钮：点开「模型能力」弹窗。两列的入口语义相同（能力是一个
   整体，没必要各开一个弹窗），所以共用 .caps-open 外壳 —— 无样式按钮、hover
   给一层浅底、focus 有圈（键盘可达）。数值与徽章的三态样式只定义在这里；
   弹窗里用的是组件库控件，不复用这一套。

   负外边距 4px：hover 底比内容外扩一圈，又不会顶到列边界上（td 左右 8px 的
   内边距减掉 4px 外扩，还剩 4px 呼吸）。 */
.caps-open {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  margin: -3px -4px;
  padding: 3px 4px;
  border: 0;
  border-radius: 6px;
  background: none;
  box-shadow: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.caps-open:hover { background: var(--surface-2); }
.caps-open:focus-visible { outline: 2px solid var(--primary); outline-offset: -1px; }

/* 数值格：上下文 / 最大输出（等宽、按位数对齐，两行的两个数能上下比） */
.cap-num {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  color: var(--text-2);
}
/* 未声明：压淡而不是换成文字 —— 与「明确声明了 0 / 不支持」一眼可分 */
.cap-num.unset { color: var(--text-3); opacity: .6; }
.cap-sep { color: var(--text-3); font-size: 11px; }

/* 三枚布尔徽章：支持 = 品牌淡底实心；不支持 = 描边压淡；未声明 = 虚线。
   窄窗口下列宽会被压小，允许换行 —— 不换行只会让第三枚压到映射列上 */
.caps-open.caps-badges { gap: 4px; flex-wrap: wrap; }
.cap-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 1px 6px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-size: 10.5px;
  line-height: 16px;
  white-space: nowrap;
}
.cap-badge.on { border-color: var(--primary-bd); background: var(--primary-soft); color: var(--primary-fg); font-weight: 600; }
.cap-badge.off { border-color: var(--border); color: var(--text-3); }
.cap-badge.unset { border-style: dashed; border-color: var(--border-strong); color: var(--text-3); opacity: .8; }

/* 覆盖标记：被用户改过的那一项挂一枚小点（title 说明「已覆盖上游值」） */
.cap-mark { flex: 0 0 auto; display: block; width: 4px; height: 4px; border-radius: 50%; background: var(--primary); }

/* 映射名药丸：品牌色浅底；行禁用时随行压淡并加删除线。
   纵向排列（每条绑定独占一行，参照账号页模型管理弹窗）——映射一多条，
   横向 wrap 会挤成变宽的迷宫，竖着读每行一条才对得上「绑定列表」的心智。
   第一行是例外：默认那条与「＋ 映射」并排（.alias-row）—— 入口按钮不是绑定，
   让它独占一行会把每个模型行都撑高三行。 */
.aliases { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
/* 默认 chip + 「＋ 映射」。max-width: 100% 让这一行在最宽处收住，放不下时
   按钮自己折到第二行，而不是把 chip 挤扁或把列顶宽（.mm 是 minmax(0,1fr)，
   列一被顶宽，横向滚动条就挂到面板上了）。 */
.alias-row { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; max-width: 100%; }
.alias {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  height: 22px;
  padding: 0 3px 0 8px;
  border: 1px solid var(--primary-bd);
  border-radius: var(--r-pill);
  background: var(--primary-soft);
  color: var(--primary-fg);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
}
.alias.off { border-color: var(--border); background: var(--surface-inset); color: var(--text-3); text-decoration: line-through; }
/* 关闭的映射（chip 上自己的开关关着）：整体灰化弱化并加删除线，但仍可点
   （开关就在 chip 里）。与行级压淡的 .off 互相独立 —— 「行开着、某条映射
   关着」的状态要一眼可辨，所以另起一个类名。 */
.alias.map-off { border-color: var(--border); background: var(--surface-inset); color: var(--text-3); }
.alias.map-off .t { text-decoration: line-through; }
.alias .t { min-width: 0; overflow-wrap: anywhere; }
.alias { height: auto; min-height: 26px; max-width: 100%; padding-top: 3px; padding-bottom: 3px; gap: 5px; }
.binding-default { flex: 0 0 auto; padding: 0 4px; border: 1px solid var(--border); border-radius: var(--r-xs); background: var(--surface); color: var(--text-3); font-family: var(--font-sans); font-size: 10px; font-weight: 500; }
.alias .switch { flex: 0 0 auto; }
.alias .alias-level, .alias .x { flex: 0 0 auto; }

/* chip 内的小号开关：复用 .switch 的结构与交互（components.css），只在这里
   收尺寸 —— 药丸高 22px，滑块压到 24×14 才放得下；滑块位移同步缩放 */
.alias .switch { gap: 0; margin-right: 2px; }
.alias .switch .track { width: 24px; height: 14px; }
.alias .switch .track::after { top: 2px; left: 2px; width: 10px; height: 10px; }
.alias .switch input:checked + .track::after { transform: translateX(10px); }
.alias .x {
  height: 16px;
  width: 16px;
  padding: 0;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  box-shadow: none;
  color: inherit;
  opacity: .6;
  font-size: 12px;
  line-height: 1;
}
.alias .x:hover:not(:disabled) { opacity: 1; background: color-mix(in srgb, var(--text) 10%, transparent); color: inherit; border-color: transparent; }
/* 行内操作：默认略淡，悬浮行时恢复 */
.row-actions { display: flex; gap: 4px; justify-content: flex-end; }
.row-actions button { opacity: .75; }
.models-table tr:hover .row-actions button { opacity: 1; }

/* 网关 Key 页：key 单元格 */
.keycell { display: flex; align-items: center; gap: 6px; min-width: 0; }
.keycell .kv { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: var(--font-mono); font-size: 12px; }

/* 新建 / 编辑 Key 弹窗里的两个多选（可用提供商 / 可用模型）。
   原生 select 留在壳里当宽高锚，给它一个「够放下两个中文名」的下限、上界收在
   260px —— 勾多了由触发器里的文案自己省略号收住，这一行保持等高。`.field-row`
   是 flex 行，不设 flex:1 就会按内容宽度塌成很窄的一条。 */
#key-allowed-providers, #key-allowed-models {
  flex: 1 1 auto;
  min-width: 180px;
  max-width: 260px;
}
/* 弹窗里这两行之间的间距已经由行内 style 给了，这里只补「标签与控件不同基线」
   带来的视觉偏移（.field-row 是 align-items:center，多选外壳比 input 略高） */
#key-modal .field-row > label { align-self: center; }
/* 摘要行：与上面的说明同款小字，首行前留一点空隙（它是「当前选择」而不是
   「使用说明」，视觉上要分得开） */
#key-restrict-summary { margin-top: 2px; }

/* ─────────────────────────────────────────────
   模型管理页：占满剩余高度，滚动只发生在列表内部

   与账号页（layout.css 的 .page.active[data-page="accounts"]）同一套骨架：
   页面本身不滚，面板吃满剩余高度，面板里只有「列表」那一块滚 —— 表格高度因此
   与窗口绑定，而不是随模型条数伸缩（模型少时表格矮成一条、多时把整页顶长，
   两种都不该发生）。同一页里的左栏是列表，所以它也自己滚。
   ───────────────────────────────────────────── */
.page.active[data-page="gateway"] {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding-bottom: var(--pad);
}
.page[data-page="gateway"] .panel {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  margin-bottom: 0;
}

/* ─────────────────────────────────────────────
   左栏（提供商导航）+ 右栏（选中那家的模型表）

   左栏是**页面内的一段侧边栏**：分组标题、导航项、选中态全部沿用全局侧边栏
   （layout.css 的 .nav-group-label / .nav-item）那一套变量与形态 —— 同一个应用里
   只该有一种「列表导航」的语言，用户在左侧栏认得出的行高、字号、选中底色，
   在这里应当原样成立。差别只有两处：这里的项多一个计数（模型数），
   以及「＋ 新建自定义提供商」是动作而不是选项（虚线框）。

   两栏用 grid 而不是 flex：右栏必须能收缩到 0 宽以下（minmax(0, 1fr)），
   否则「模型映射」那一列的 chips 会把整行顶宽，横向滚动条挂到 panel 上。
   ───────────────────────────────────────────── */
.mm {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 218px minmax(0, 1fr);
  /* 行高必须显式吃满容器：grid 的行高默认按内容算，不写这条时左栏与右栏
     都只有内容高，下面的「表格区 flex:1」就没有可分配的剩余空间 */
  grid-template-rows: minmax(0, 1fr);
}
.mm-main {
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}
/* 面板头 / 表尾：都是固定高度的两块，不参与压缩 */
.mm-main > .panel-head,
.mm-main > .panel-foot { flex: 0 0 auto; }
/* 表格区：吃掉剩余高度。内容少时它照旧占满（表格下方是空白，不是滚动条），
   内容多时自己滚 —— 「固定高度」的判据是**它不随内容变**，而不是永远出滚动条 */
.mm-main > .models-table-wrap {
  flex: 1 1 auto;
  min-height: 0;
  /* 清掉共用的内容上限：这一页的高度由上面那条 flex 链给，不由内容给 */
  max-height: none;
}

.prov-rail {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 8px 12px;
  border-right: 1px solid var(--sidebar-border);
  /* 比全局侧栏浅一档（--rail-bg，见 tokens.css）：它是面板内的一段内嵌导航，
     用侧栏同款底色会被读成侧栏的延伸，和右边的模型表也不成一块 */
  background: var(--rail-bg);
  /* 高度由 grid 行高给（= 面板高度），家数多了自己滚 —— 它是列表，不是内容。
     这里**不能**加 scrollbar-gutter: stable：预留的槽仍在 padding box 内，
     分组标题条的负外边距一旦铺进去（见 .rail-label）就是 11px 的横向溢出，
     栏底立刻挂一条横向滚动条。原生滚动条的出现/消失只让内容宽跳 11px，
     而这一栏的家数远不到一屏，实际几乎见不到滚动条。 */
  overflow-y: auto;
}

/* 分组标题：做成一条**通栏的分组条**，而不是一行小字。
   原先它逐条照搬侧边栏的 .nav-group-label（同样字号、字距、muted 色），结果是
   它和条目同色系、只淡一档，混在列表里根本看不出「这里是两组」—— 而内置与
   自定义的分界恰恰是这一页最要紧的一次分类，看错组就会在错的家上改模型。
   现在：底色用 --surface-inset 抬起一层（与文档页 .ep-group 同一个手法），
   文字提到 --sidebar-fg 并加粗，负外边距让底色通到栏边（.prov-rail 内边距 8px）。
   字号仍压在 11px：它是标题，不能比 .pv 条目更抢眼；左右内边距取 18px
   （= 栏内边距 8 + 条目内边距 10），标题文字与条目文字左对齐。 */
.rail-label {
  flex: none;
  /* 左右各 -8px 抵消 .prov-rail 的内边距，底色通到栏边（右缘正好落在
     padding box 右边缘；有纵向滚动条时落在滚动条左缘，都不会溢出） */
  margin: 8px -8px 4px -8px;
  padding: 6px 18px 5px;
  background: var(--surface-inset);
  color: var(--sidebar-fg);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .09em;
}
.rail-label:first-child { margin-top: 0; }
.rail-empty { padding: 2px 10px 6px; color: var(--sidebar-muted); font-size: 11.5px; }

/* 一家一行：与 .nav-item 同一形态（行高、圆角、字号、字重、选中态配色、
   过渡曲线都取自那一份），差异只有右侧那个计数 */
.pv {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 8px 10px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  /* 通用 button 规则会带上 --shadow-1，与「平铺的导航列表」冲突（.nav-item 同样清掉） */
  box-shadow: none;
  color: var(--sidebar-fg);
  font-size: 12.5px;
  font-weight: 500;
  text-align: left;
  transition: background .15s ease, color .15s ease;
}
.pv:hover:not(:disabled) { background: var(--nav-hover); color: var(--text); border-color: transparent; }
.pv.on,
.pv.on:hover:not(:disabled) {
  color: var(--nav-selected-fg);
  background: var(--nav-selected-bg);
  border-color: var(--nav-selected-border);
  font-weight: 600;
}

.pv .n { flex: 0 0 auto; color: var(--sidebar-muted); font-size: 10.5px; font-variant-numeric: tabular-nums; }
.pv.on .n { color: inherit; }

/* 自定义家条目外层的定位容器（.pv 是 button，删除按钮不能嵌在它里面 ——
   button 套 button 会被解析器拆开，绝对定位也跟着失去参照，见 models-panel 的
   renderRail）。宽高都交给里面的 .pv，这一层只负责给 × 当坐标原点。 */
.pv-row { position: relative; flex: none; }

/* 条目上的删除按钮：与右侧那个计数**占同一个位置**，hover / 键盘聚焦时互换
   —— 计数在「要删它」这一刻没有用，让位给按钮既不用加宽左栏，也不会让
   12.5px 的名字被挤掉一截。默认隐藏（opacity 而非 display：显隐不动布局，
   鼠标扫过一排条目时不会有跳动）。 */
.pv-del {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  box-shadow: none;
  color: var(--sidebar-muted);
  font-size: 15px;
  line-height: 1;
  opacity: 0;
  cursor: pointer;
  transition: opacity .12s ease, color .12s ease, background .12s ease;
}
.pv-row:hover .pv-del,
.pv-del:focus-visible { opacity: 1; }
/* hover 时把计数让出来（两者都在右缘，不藏计数就会叠字） */
.pv-row:hover .pv .n { visibility: hidden; }
/* :not(:disabled) 是为了压过 components.css 的 `button:hover:not(:disabled)`
   —— 那条的特异性是 (0,2,1)，比单类 + :hover 高一级，不写就抢不回来 */
.pv-del:hover:not(:disabled) {
  color: var(--danger);
  background: var(--nav-hover);
  border-color: transparent;
}
/* 窄窗口（约 900px 以下）改成上下堆叠：左栏在上一行，横向铺满、自己滚 */
@media (max-width: 900px) {
  /* 窄窗口改成上下两行：左栏一行（自己的高度上限），表格区吃掉剩下的 */
  .mm {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
  }
  .prov-rail {
    max-height: 210px;
    border-right: 0;
    border-bottom: 1px solid var(--sidebar-border);
  }
}
