/* ============ A股实时盯盘 · 样式 ============
 * 设计语言：Apple（iOS / macOS）HIG
 *
 * 【2026-10-17 全页一致性重构】改前的实测审计（1440 视口 / 1164 个可见元素）：
 *   圆角 9 种、阴影 5 种、字号字重 24 种组合、背景色 16 种、描边色 13 种、
 *   按钮语言 5 套（白底描边胶囊 / 灰底填充胶囊 / 白底描边小方块 / 灰底圆形 /
 *   白底描边方角）。这不是"风格不统一"，是五套语言在同一屏里抢注意力。
 *
 *   收口原则（也是判据：以后新增控件先问它属于哪一族）：
 *   ① 形状只有三种 —— 胶囊（文本/下拉控件）、圆形（纯图标按钮）、圆角矩形（卡片/面板），
 *      圆角矩形三档 8/12/16；logo 容器 11px 是按 bull.png 宽高比定制的例外（.brand-mark）
 *   ② 控件只有一族 —— 灰底填充三档（--g4 默认 / --g5 悬停 / --g6 按压），
 *      **不再有"白底 + 描边"页面控件**（唯一例外：弹窗 sheet 的输入字段，
 *      走 macOS 表单约定"灰底行 + 白字段"，见 .rule-sel 一节）
 *   ③ 阴影三档 —— 卡片 / 浮层 / 模态，同一色基 rgba(15,22,36,.x)；
 *      同色基的状态变体（卡片悬停抬升 / 分段控件激活块 / 导航栏细线）只做不列档
 *   ④ 字号两套刻度 —— 整档 11/12/13/14/15/20/24（Apple 阶梯）+
 *      半档 11.5/12.5/13.5（chip 与数据行的微调档，2026-10-16/17 逐处与用户确认后固化）；
 *      标题另有 19（页头）/ 22（宽度条成交额）/ 24（指数价）三档大字号
 *   ⑤ 金色只有一个值 #c9a54c，派生两个角色：选中态 tint（--gold-tint 底 + --gold-ink 字）、
 *      实底主按钮上的深字（--on-gold）
 *   ⑥ 品牌金只做"小面积锚点"：顶栏 2px 线 + focus 环 + 选中态 tint；
 *      不用 Web 后台那套"左侧竖条标题 / 左侧彩条卡片"（已在下方逐条移除）
 *
 * 【2026-10-17 二轮：整页 UI 审计收尾】一轮重构后仍有"文档宣称 ≠ 代码事实"的残留，
 *   按 audit-ui.cjs 的频次表逐项对账（1932 个可见元素），本轮修正：
 *   · 控件底色：--g4 只有 20 个元素在用，而行内控件（换组下拉 / ↑↓ / × / 组工具）
 *     223 个用的还是 #eef1f6（恰是页面底色 --bg，"胶囊等于没做"的老病）→ 全部归入
 *     --g4 族；悬停 #e2e8f1 → --g5；按压 #cfd8e6 → 新令牌 --g6
 *   · 阴影：搜索浮层 / toast 仍是一轮重构点名要消除的 (6,15,33) 黑 → --sh-pop
 *   · 三条提示条：注释写"无重描边"、代码却都带着 1px 彩边 → 删掉
 *   · 阶外灰 9 处（行悬停 #f5f8fc / 表头悬停 #f0f4f9 / 行分割线 #f0f3f8 /
 *     状态点 #9aa5b8 ×2 / 搜索图标 #94a0b0 / .dd-item:hover / 表头底 / .dd-type 底）
 *     → 归入 --g1 / --g2 / --line-soft / --ink-3 令牌
 *   · 琥珀两套（#fdf6e3+#8a5a00 与 #faf3e0+#8a6d1f）→ --amber-bg / --amber-ink 一对
 *   · 涨跌幅胶囊三种规格（idx-pill 12px/2px9px、pct-badge 13px/3px10px、
 *     sec-pct 12.5px/700）→ 统一 12.5px / 3px 10px / 600
 *   · 指数卡网格（gap 12 + padding 14/16/12）与板块卡网格（gap 10 + padding 11/14/10）
 *     → 同一规格
 *   · 圆角 6px（换组下拉 / 组工具，106 个元素）与 7px（组工具条）→ --r-sm 8px
 *   · 页头 🔔 / ⚙ 两个 emoji 图标 → 与锁、异动铃铛同族的内联 SVG（currentColor 驱动）
 */
:root {
  --bg: #eef1f6;
  --card: #ffffff;
  --ink: #1a2233;
  --ink-2: #5b6478;
  --ink-3: #98a1b3;
  --line: #e6eaf1;          /* 发丝线：卡片边、输入框、分隔 */
  --line-soft: #eff2f7;     /* 更弱一层：表格行分割线 */
  --up: #d93025;
  --up-bg: #fdeceb;
  --down: #0a9d5a;
  --down-bg: #e7f7ef;
  --flat: #6b7280;
  /* 中性淡底。⚠️ 2026-10-18 整站统一：旧值 #eef1f6 **与页面底色 --bg 完全相同**，
     于是「平盘」胶囊落在页面上就是一块看不见的底（用户截图里五颗胶囊只有四颗有壳）。
     这与历史上 .chips / .count-badge / 行内控件踩的是同一个坑，判据也同一个：
     **填充胶囊可不可见只取决于填充色与所在底色的亮度差**。
     新值 #e3e8f0 与 --bg(#eef1f6) 差 11 阶、与白卡差 28 阶，两处都成立；
     它同时是伪装态下 --up-bg/--down-bg 的替换值（见文件末尾），那儿也要求"看得见"。 */
  --flat-bg: #e3e8f0;
  /* ⛔ `--navy: #0d1f3c` 已删（2026-10-18）：它唯一的引用是 `.btn-mv:hover` 的深色悬停，
     那条已改成灰底加深（--g5）。深色导航栏时代留下的最后一个深底色，现在没有消费者，
     留着下次有人会拿它去做"深色按钮"，把刚统一的浅色控件族又劈成两套。 */
  /* 品牌金：全站唯一强调色。旧值 #d8b25f 与散落各处的硬编码 #c9a54c 是两套，
     统一取用户既有的品牌辅色 #c9a54c（与 oscoteam 站同一支金）。
     派生角色（2026-10-17 二轮从硬编码提为令牌）：
     --gold-tint / --gold-ink = 选中态（.notify-btn.on / .lock-btn.on：淡金底 + 深金字）；
     --on-gold = 实底主按钮（.mbtn.primary：金底上的深褐字，保证对比度）。 */
  --gold: #c9a54c;
  --gold-tint: rgba(201, 165, 76, .16);
  --gold-ink: #7d6219;
  --on-gold: #3d2f08;

  /* 灰阶：收敛到 5 档（此前 12 个近似灰各自为政，肉眼分不出但让页面"发脏"） */
  --g1: #f7f9fc;   /* 表头底 / 行悬停 */
  --g2: #f2f5fa;   /* 组头行 */
  --g3: #eef1f6;   /* 页面底 */
  --g4: #e9edf4;   /* 控件填充（默认态）—— 全站唯一控件底色 */
  --g5: #dbe2ed;   /* 控件填充（悬停态） */
  --g6: #cfd8e6;   /* 控件填充（按压态，:active）—— 二轮补：此前是阶外字面量 */

  /* 语义色板的"印在淡底上的加深字"档：淡底（--up-bg 等）上的文字若直接用 --up，
     对比度只差一点，小字发虚；各板式因此都有一只更深字的规格（二轮提为令牌）。 */
  --up-ink: #a32d2d;      /* 红字印红底：异动 high chip / 文件损坏提示 / 弹窗错误 */
  /* 绿字印绿底：异动下跌 chip（2026-10-18）。直接用 --down 印在 --down-bg 上
     对比度只有 3.2:1，12px 小字发虚 —— 与 --up-ink 同理需要加深一档。
     取值 #0a7a4a 是此前 .mkt-status.open 用过、二轮已归一的同族绿，不是新颜色。 */
  --down-ink: #0a7a4a;
  --amber-bg: #faf3e0;    /* 琥珀淡底：三条提示条 / 集合竞价状态 / 异动 warn chip */
  --amber-ink: #8a5a00;   /* 琥珀字：与 --amber-bg 配对（旧值 #8a6d1f 是另一只，已归一） */
  --info-bg: #eef4fb;     /* 信息淡底：异动 info chip */
  --info-ink: #185fa5;    /* 信息字：与 --info-bg 配对 */

  /* 半透明前景层与动画底色（2026-10-21 深色模式新增）。
     为什么单独立令牌、而不是在暗色段里重写 .topbar/.modal-mask/.toast：
     这三处的**透明度本身也要跟着变**（深色遮罩要更重、toast 要与深底拉开亮度差），
     写在两处等于同一个值存在两份，将来改浅色时漏改一份就是"深色对、浅色错"。
     @keyframes 里的颜色**不能**按选择器覆盖 —— 同名 keyframes 是全局的，
     后定义的会整条替换，`html[data-theme=dark] @keyframes` 这种写法根本不存在。
     所以跳动闪现的颜色只能提成变量，让 keyframes 去引用。 */
  --topbar-bg: rgba(250, 251, 253, .86);   /* 页头毛玻璃底 */
  --mask: rgba(15, 22, 36, .38);           /* 弹窗遮罩 */
  --toast-bg: rgba(13, 31, 60, .92);       /* toast 底（深蓝 + 白字） */
  --tick-up: rgba(217, 48, 37, .22);       /* 报价跳动闪现：涨 */
  --tick-down: rgba(10, 157, 90, .22);     /* 报价跳动闪现：跌 */
  /* 分时图的昨收基准虚线。它是**画布**用的（app.js 的 drawTrend 读出来画），
     所以既不是给 DOM 的背景也不是文字色 —— 单独一只，暗色下要提亮否则看不见。 */
  --trend-ref: rgba(120, 130, 150, .5);

  /* 圆角：三档 + 胶囊（旧版有 2/6/9/10/12/14 六种圆角矩形） */
  --r-sm: 8px;     /* 表格内的块状小控件（下拉） */
  --r-md: 12px;    /* 提示条、浮层、toast */
  --r-lg: 16px;    /* 卡片、弹窗 */
  --r-pill: 999px;

  /* 阴影：三档、同一色基。旧版 5 套阴影用 3 种不同的黑（16,24,40 / 15,22,36 / 6,15,33），
     同屏出现时深浅对不上，是"卡片发灰"的来源之一。
     两个状态变体（二轮从字面量提为令牌，色基不变、只列不档）：
     --sh-card-hover = 卡片悬停抬升一档（.idx-card:hover）；
     --sh-tab = 分段控件灰槽里的激活块（.slide-tab.active，"浮在槽里的小卡"）。 */
  --sh-card: 0 1px 2px rgba(15, 22, 36, .04), 0 4px 16px rgba(15, 22, 36, .05);
  --sh-card-hover: 0 2px 4px rgba(15, 22, 36, .05), 0 10px 28px rgba(15, 22, 36, .08);
  --sh-tab: 0 1px 2px rgba(15, 22, 36, .08);
  --sh-pop: 0 8px 32px rgba(15, 22, 36, .16);
  --sh-modal: 0 24px 64px rgba(15, 22, 36, .24);
  --shadow: var(--sh-card);   /* 兼容旧引用（.idx-card / .table-card） */
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  /* 2026-10-18 整站统一：去掉 body 上那层 `radial-gradient(1200px 500px at 70% -10%, …)`
     装饰性打光。Apple 的浅色界面是**平底色**，层次全部由白色卡片与发丝线建立；
     一层斜照的深色渐变会同时压低右上角的卡片白度，让整页"发脏"（这是 Web 后台的
     常见做法，不是 iOS/macOS 的做法）。 */
  background: var(--bg);
  color: var(--ink);
  font-size: 14px;
  line-height: 1.5;
  /* Apple 观感的半条命在字重渲染：Windows 默认的次像素抗锯齿会把细体糊成"发胖"，
     macOS 走的是灰度抗锯齿。这一行让 Chrome/Edge 在浅底上更接近 SF 的瘦利感。 */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.hidden { display: none !important; }
.num { font-variant-numeric: tabular-nums; }
button { font-family: inherit; }

/* ---------- 顶栏（Apple 浅色毛玻璃导航栏）----------
   2026-10-16 重构：原深蓝渐变 + 白字与浅色页面明暗断层，改为 iOS/macOS 的
   navigation bar 语言 —— 半透明浅底 + backdrop-filter 模糊 + 底部发丝线，
   滚动时页面内容透出形成层次；重投影（.25 黑影）是深底时代的遗留，一并去掉。
   所有子控件同步迁到浅色系（原 rgba(255,255,255,.x) 白系全部换成深字浅底）。 */
.topbar {
  background: var(--topbar-bg);
  -webkit-backdrop-filter: saturate(180%) blur(20px);
  backdrop-filter: saturate(180%) blur(20px);
  color: var(--ink);
  position: sticky;
  top: 0;
  z-index: 50;
  border-bottom: 1px solid var(--line);
  /* 2026-10-18 整站统一：删掉 `box-shadow: 0 1px 3px rgba(15,22,36,.04)`。
     它是全站第 6 种阴影（既不在 :root 的三档里，也不是任何令牌的状态变体），
     而且与下面那条 1px 发丝线叠在同一个位置 —— 视觉上等于把同一条边画了两遍。
     macOS 的工具栏停在顶部时只有一根发丝线，投影是"浮起来"才有的语言。 */
}
.topbar-inner {
  max-width: 1440px;
  margin: 0 auto;
  padding: 12px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 12px; }
.brand-mark {
  /* 2026-10-17 第四轮：40×40 正方形 → 52×44（用户在对比图里最终选 D 版，此前 C 47×40 为中间稿）。
     原因：边框去掉后那个方格已无视觉意义，却仍在限制高度 —— bull.png 是 317×270
     （宽高比 1.174）的横图，放进正方形只能按宽度受限，金牛实际只画到 40px 宽，
     周围一圈是空占位。按 ratio 撑满高度后再整体放大一档：宽 52 ≈ 44 × 1.174。
     ⚠️ 页头高度三版都是 77px（标题 h1 19px + 副标题 11px 共占 44px < 容器 50px，
     topbar-inner 上下各 12px 内边距），所以放大容器不会把页头撑高。 */
  width: 52px; height: 44px;
  border-radius: 11px;
  /* 2026-10-17 用户反馈①：logo 区域原来填 --g4(#e9edf4) 灰底，跟导航栏的
     近白半透明底(rgba(250,251,253,.86))不一致、显出一块灰。改透明 —— 直接透出
     导航栏背景，与顶栏融为一体。
     用户反馈②（同一轮，更彻底）：「logo的容器边框去掉」—— 连那道 inset 描边也不要了。
     现在容器彻底无色无框，只剩占位与圆角裁剪作用（overflow:hidden 仍在，
     保证金牛的角不会溢出）。 */
  background: transparent;
  box-shadow: none;
  display: flex; align-items: center; justify-content: center;
  /* 二轮删掉 font-size:21px —— 容器里早已没有文字（金牛是 <img>），是 emoji 时代的残留，
     还让它以 21px/400 的身份出现在字号频次表里。 */
  overflow: hidden;
}
/* 页头 logo 双图标切换（2026-10-16 用户确认"网站图标换金牛"，2026-10-17 用户
   二次给图"Logo换成这个"——金牛改为用户给的原图的 <img>（现用去背景版
   public/bull.png；原场景图 bull.jpg 零引用，2026-10-20 已归档清理），按
   "给什么图用什么图"纪律不重绘；中性列表图仍是内联 SVG）：
   默认显示金牛、藏起中性列表图；伪装态的反向规则在文件末尾 html.disguise 块里。
   用 CSS 而不是 JS 切：brand-mark 是静态 HTML，两条 display 规则就够了，
   还顺带覆盖"JS 还没跑起来"的那一小段（金牛先显示，与 favicon 的默认值一致）。
   ⚠️ 末尾 html.disguise 规则特异性(0-2-2)高于本条 img 规则(0-2-1)，伪装态照样藏得住。 */
.brand-mark .mark-list { display: none; color: var(--ink); }
/* ↑ color 是给内部 rect 的 fill="currentColor" 用的（2026-10-21 深色模式）：
   index.html 里两条横杠原本写死 fill="#33415c"，在深底 #0e1218 上对比度约 1.9:1，
   伪装态 + 深色同时成立时这行图等于消失。改成 currentColor 后颜色回到 CSS 手里，
   深色下自动跟着 --ink 变亮，不必再写一条暗色专用规则。 */
.brand-mark img.mark-bull {
  width: 100%; height: 100%;
  /* 2026-10-17 换透明抠图（public/bull.png，已裁到牛体紧边界）：contain 完整撑满、
     不裁腿尾；2px padding 留一口气，避免牛角/蹄尖顶到圆角边缘。
     （旧版是场景图 cover 裁左右保中间，已随去背景改掉。） */
  object-fit: contain;
  padding: 2px;
  border-radius: 11px;    /* 与容器同一半径：容器已 overflow:hidden，这里只是消除 img 自身的矩形角 */
  display: block;
}
.brand-text h1 { font-size: 19px; font-weight: 600; letter-spacing: 0; color: var(--ink); }
/* 副标题从 2.5px 字距收到 1.4px：过宽的字距是"Web 2.0 装饰"，Apple 的小字标签靠字重和灰度区分层级。
   字号 10.5px → 11px（2026-10-17 二轮）：10.5 不在任何刻度上，而 11 是整档最小值；
   行盒只高 1px，页头 77px 不变（h1 29 + 副标题 15 < 容器 50）。 */
.brand-sub { font-size: 11px; letter-spacing: 1.4px; font-weight: 500; color: var(--ink-3); }
.topbar-right { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }

/* 搜索框
   ⚠️ 2026-10-17 从「白底 + 1px 描边」改为「灰底填充 + 无描边」—— 这是 iOS 搜索栏
   的本来样子（UISearchBar 就是 systemGray6 填充、无边框），也是全站控件统一的关键一处：
   改完之后顶栏这一行与下方工具区（.btn-sort / .sel-inline）终于是同一族语言。
   focus 才回到白底 + 金环 —— 与 macOS 的「激活态反白」一致。 */
.searchbox { position: relative; }
.searchbox input {
  width: 300px;
  height: 36px;
  padding: 0 14px 0 36px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  background: var(--g4) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24' fill='none' stroke='%2398a1b3' stroke-width='2.2'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.5-3.5'/%3E%3C/svg%3E") no-repeat 13px center;
  color: var(--ink);
  font-size: 13px;
  outline: none;
  transition: background-color .18s, border-color .18s, box-shadow .18s;
}
.searchbox input::placeholder { color: var(--ink-3); }
.searchbox input:hover { background-color: var(--g5); }
.searchbox input:focus {
  background-color: var(--card);
  border-color: var(--gold);
  box-shadow: 0 0 0 3px rgba(201, 165, 76, .18);
}
.search-dropdown {
  position: absolute;
  top: 44px; left: 0;
  width: 340px;
  max-height: 340px;
  overflow-y: auto;
  background: var(--card);
  border-radius: var(--r-md);
  /* 2026-10-17 二轮：0 12px 40px rgba(6,15,33,.28) → --sh-pop。
     (6,15,33) 正是首轮重构文档点名要消除的三种黑之一，浮层与卡片/模态不是一套色基。 */
  box-shadow: var(--sh-pop);
  padding: 6px;
  z-index: 60;
}
.dd-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px;
  border-radius: var(--r-sm);
  cursor: pointer;
  color: var(--ink);
}
.dd-item:hover { background: var(--g2); }   /* 二轮：#f2f5fa 字面量 → 令牌（值与 --g2 相同） */
.dd-name { font-weight: 600; font-size: 13.5px; }
.dd-code { color: var(--ink-3); font-size: 12px; font-variant-numeric: tabular-nums; }
.dd-type {
  margin-left: auto;
  /* 同 .count-badge / .grp-count 那颗计数胶囊（2026-10-18 统一 11.5/500/2×8）。 */
  font-size: 11.5px;
  font-weight: 500;
  color: var(--ink-2);
  background: var(--g4);
  padding: 2px 8px;
  border-radius: var(--r-pill);
}
.dd-empty { padding: 14px 12px; color: var(--ink-3); font-size: 12.5px; text-align: center; }

/* 市场状态
   与搜索框同一族：灰底填充、无描边。四种状态只在「填充色 + 文字色」上分叉，
   不再给 .open 加绿色描边 —— 描边+填充+文字三层同时变色，在浅底上会显得花。
   2026-10-17 二轮：.open 的 #0a7a4a/#e8f5ee 是 --down/--down-bg 之外的第四只绿 →
   归入 --down 系（全站只有一只绿：跌/绿，与 A股口径一致）；
   .auction/.break 的 #8a6d1f → --amber-ink（与三条琥珀提示条同一只字）。
   状态点 #9aa5b8 → var(--ink-3)（此前是 --ink-3 之外的第五只灰）。 */
.mkt-status {
  display: flex; align-items: center; gap: 7px;
  font-size: 12px;
  height: 30px;
  padding: 0 13px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  background: var(--g4);
  color: var(--ink-2);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.mkt-status .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-3); }
.mkt-status.open { color: var(--down); background: var(--down-bg); }
.mkt-status.open .dot { background: #34d399; animation: pulse 1.6s infinite; }
.mkt-status.auction { color: var(--amber-ink); background: var(--amber-bg); }
.mkt-status.auction .dot { background: var(--gold); animation: pulse 1s infinite; }
.mkt-status.break { color: var(--amber-ink); }
.mkt-status.break .dot { background: var(--gold); }
.mkt-status.closed { color: var(--ink-3); }

/* 信号点专用亮绿（#34d399）：与"跌/绿"语义无关，是"活着"的指示灯 ——
   开盘点 / 连接正常点共用一只，配 pulse 呼吸环。 */
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(52, 211, 153, .5); }
  70% { box-shadow: 0 0 0 6px rgba(52, 211, 153, 0); }
  100% { box-shadow: 0 0 0 0 rgba(52, 211, 153, 0); }
}

/* 时钟 */
.clock { text-align: right; line-height: 1.25; }
.clock-time { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: 0; color: var(--ink); }
.clock-date { font-size: 11px; color: var(--ink-3); }

/* 连接状态 */
.conn { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-2); }
.conn-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-3); }
.conn.ok .conn-dot { background: #34d399; animation: pulse 1.6s infinite; }
.conn.bad .conn-dot { background: #f87171; }

/* ---------- 桌面通知开关 ----------
   与搜索框 / 市场状态同一族：灰底填充、无描边、30px 高。 */
.notify-btn {
  display: inline-flex; align-items: center; gap: 5px;
  height: 30px; padding: 0 12px; border-radius: var(--r-pill);
  border: 1px solid transparent;
  background: var(--g4);
  color: var(--ink-2);
  font: inherit; font-size: 12px; font-weight: 600;
  cursor: pointer; white-space: nowrap;
  transition: background-color .18s, color .18s;
}
.notify-btn:hover { background: var(--g5); color: var(--ink); }
/* 图标改内联 SVG（2026-10-17 二轮）：原来是 🔔 / ⚙ 两个 emoji —— 同一页里锁与异动
   铃铛都是 SVG 线图标，emoji 的彩色字形+平台差异（Windows/Apple 两套绘法）与它们
   不是一种语言。SVG 用 currentColor 描边，颜色跟着按钮的 color 走，无需 filter  hack。
   ⚠️ 尺寸必须写死：SVG 不设宽高会按 viewBox 把 30px 高的按钮撑爆（本项目老坑）。 */
.notify-btn .notify-icon { width: 14px; height: 14px; flex: 0 0 14px; display: block; }
/* 已开启：金色 tint 填充（Apple 的选中态是"同色淡填充 + 同色文字"，
   旧版 #fdf8ea + 金描边会与页面其他淡黄提示条撞脸）。
   二轮：rgba(201,165,76,.16) 与 #7d6219 两个字面量 → --gold-tint / --gold-ink 令牌
   （.lock-btn.on 同一对，页头两个"开着的开关"从此是同一种金）。 */
.notify-btn.on {
  background: var(--gold-tint);
  color: var(--gold-ink);
}
/* 权限被拒：弱化，提示需回浏览器站点设置里改 */
.notify-btn.denied { opacity: .62; }

/* ---------- 写保护锁（页头右侧的图标按钮）----------
   与 .notify-btn 同一族的胶囊按钮，但**只有图标没有文字** —— 页头已经排了 5 个元素，
   再加一个带字的按钮会把搜索框挤窄。状态靠图标形状区分（闭锁 = 未登录 / 开锁 = 已登录），
   语义写在 title 里（伪装态会经 dtitle() 换中性说法）。 */
.lock-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  /* `font: inherit` 是补一个真空档：按钮没写 font-size 时会落回浏览器默认的
     13.3333px，在整页的字号频次表里就是一条**阶外值**（2026-10-18 审计抓到的唯一一条）。
     本按钮只有图标、字号不参与渲染，但"没声明的就继承"比"留个怪数字"干净。 */
  font: inherit;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  background: var(--g4);
  color: var(--ink-2);
  cursor: pointer; flex: 0 0 auto;
  transition: background-color .18s, color .18s;
}
.lock-btn:hover { background: var(--g5); color: var(--ink); }
/* SVG 必须写死尺寸 —— 不写会按 24×24 的 viewBox 把按钮撑爆（本项目踩过的老坑）。
   另外这里两根都要写：内联 SVG 的 width/height 属性在 flex 容器里不一定被尊重。 */
.lock-btn svg { width: 15px; height: 15px; display: block; flex: 0 0 15px; }
/* 已登录：金色 tint，与 .notify-btn.on 完全同一套视觉语言（"这个开关当前是开着的"）。
   二轮：两个字面量 → --gold-tint / --gold-ink（与 .notify-btn.on 共用同一对令牌）。 */
.lock-btn.on {
  background: var(--gold-tint);
  color: var(--gold-ink);
}
/* 显式压过上面的 display —— `.lock-btn` 与 `.hidden` 同为单类选择器，
   靠"谁写在后面"决定胜负太脆弱（本项目在 .td-op 上吃过这个亏）。 */
.lock-btn.hidden { display: none; }

/* ---------- 深色模式开关（页头最右，2026-10-21）----------
   与 .notify-btn 同族的胶囊按钮，但**只有图标**：页头已经排了 5 个元素，
   带字会把搜索框挤窄（与 .lock-btn 同一条理由）。宽度按 .lock-btn 收成 30px 方形。
   月亮/太阳两枚图标都写在 HTML 里，靠 display 切换 —— `display:none` 的元素**不占位**，
   所以两枚叠放不会把按钮撑成 72px 宽。
   ⚠️ `.theme-btn .ico-sun` 必须写成两级：`.notify-btn .notify-icon` 的
      `display:block` 也是 (0,2,0)，单写 `.ico-sun`(0,1,0) 会被它压过去 —— 结果就是
      月亮太阳一起显示、按钮变成 52px。这类"看起来没生效"的规则先数特异性，别加 !important。 */
.theme-btn {
  width: 30px; padding: 0; justify-content: center;
  flex: 0 0 auto;
}
.theme-btn .ico-sun { display: none; }
html[data-theme="dark"] .theme-btn .ico-moon { display: none; }
html[data-theme="dark"] .theme-btn .ico-sun { display: block; }

/* ---------- 登录框（写保护）----------
   2026-10-17 统一到 Apple 的 alert / sheet 语言：
   遮罩用更深的 .38 + 2px 模糊（旧版 .48 纯色，页面完全消失，缺少"浮在内容之上"的层次），
   卡片 16px 圆角 + 三档里最重的 --sh-modal，标题 17px/600（iOS alert 标题的规格），
   按钮从 8px 方角改成胶囊 —— 全站最后一个方角按钮族在这里消失。

   ⚠️ z-index:200 只是**基准**，浮层之间的上下关系由 JS 的 raiseModal() 按"谁最后打开"
   分配（200 + 序号）。别为了"让登录框浮上来"在这里加更大的 z-index —— 三个浮层同值时
   由 DOM 顺序决定，而登录框排在条件预警、添加持仓之前，2026-10-21 就是这么被盖住的。 */
.modal-mask {
  position: fixed; inset: 0; z-index: 200;
  background: var(--mask);
  -webkit-backdrop-filter: blur(2px);
  backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.modal-mask.hidden { display: none; }
.modal-card {
  width: 100%; max-width: 340px; box-sizing: border-box;
  background: var(--card); border-radius: var(--r-lg);
  padding: 24px 24px 20px;
  box-shadow: var(--sh-modal);
}
.modal-title { margin: 0 0 6px; font-size: 17px; font-weight: 600; letter-spacing: -.1px; color: var(--ink); }
.modal-desc { margin: 0 0 16px; font-size: 13px; line-height: 1.55; color: var(--ink-2); }
.modal-input {
  width: 100%; box-sizing: border-box;
  height: 38px; padding: 0 13px; font: inherit; font-size:14px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  color: var(--ink); background: var(--card);
  transition: border-color .18s, box-shadow .18s;
}
.modal-input:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px rgba(201, 165, 76, .18); }
.modal-err {
  margin-top: 10px; padding: 8px 11px; border-radius: var(--r-sm);
  background: var(--up-bg); color: var(--up-ink);   /* 二轮：#b3261e → --up-ink */
  font-size: 12.5px; line-height: 1.5;
}
.modal-err.hidden { display: none; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }
.mbtn {
  height: 32px; padding: 0 18px; font: inherit; font-size: 13px; font-weight: 600;
  border-radius: var(--r-pill); cursor: pointer; border: 1px solid transparent;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background-color .16s, filter .16s;
}
.mbtn.ghost { background: var(--g4); color: var(--ink-2); }
.mbtn.ghost:hover { background: var(--g5); color: var(--ink); }
.mbtn.primary { background: var(--gold); color: var(--on-gold); }   /* 二轮：#3d2f08 → --on-gold */
.mbtn.primary:hover { filter: brightness(1.06); }
.mbtn[disabled] { opacity: .6; cursor: default; filter: none; }

/* ---------- 自定义条件预警：规则编辑弹窗（2026-10-17）----------
   复用 .modal-mask / .modal-card，只把宽度放开一档：一行要排 6 个控件，
   340px 会折成三行、序号和控件对不上。max-width 920px 是"1440 视口下不挡满屏"的取值。 */
.modal-card.modal-wide { max-width: 920px; padding: 22px 22px 18px; }
.rule-list { display: flex; flex-direction: column; gap: 8px; max-height: 52vh; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
.rule-row {
  display: flex; align-items: center; gap: 6px;
  padding: 8px 10px; border-radius: var(--r-sm);
  background: var(--g3);
  /* ⚠️ flex-wrap 必须开：窄弹窗下宁可折行，也不要让 input 被压成 20px 宽
     （本项目在 320px 搜索框上吃过"被压成一个字"的亏）。 */
  flex-wrap: wrap;
}
.rule-n {
  flex: 0 0 18px; width: 18px; text-align: center;
  font-size: 11.5px; font-weight: 700; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.rule-sel, .rule-num {
  height: 28px; box-sizing: border-box;
  font: inherit; font-size: 12.5px;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--card); color: var(--ink);
  /* 显式 inline-flex + 统一 height —— 与操作钮同列对齐的老坑（按钮与 select 差 2px） */
  display: inline-flex; align-items: center;
}
/* ⚠️ 这里是全页唯一"白底 + 描边"的控件族，是有意的语境分裂，不是漏改：
   规则行本身是 --g3 灰底条（macOS 表单的分组底），字段按 sheet 约定用白底 + 发丝边 ——
   灰字段落在灰行上会直接不可见。页面主界面的控件（.btn-sort / .sel-inline /
   换组下拉）走 iOS 的灰底填充，两者不混用：模态里没有灰底行，页面里也没有白字段。 */
.rule-sel { padding: 0 6px; max-width: 180px; }
.rule-sel.rule-op { max-width: 96px; }
.rule-sel.rule-lv { max-width: 76px; }
.rule-num { padding: 0 8px; width: 92px; flex: 0 0 auto; appearance: textfield; -moz-appearance: textfield; }
.rule-num::-webkit-outer-spin-button, .rule-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.rule-unit { font-size: 11.5px; color: var(--ink-3); min-width: 26px; }
/* 无单位的指标（价格/涨跌额/量比）不占位：否则数值框和"警告"下拉之间空出 26px，
   整行看着像断成两截。有单位的才留宽度 —— 同一行里各规则的"警告"下拉因此可能
   相差 26px 而不对齐；相比之下"一截断"更伤，这个取舍是有意的。 */
.rule-unit.empty { display: none; }
.rule-del { flex: 0 0 auto; margin-left: auto; padding: 0 10px; height: 28px; }
.rule-add { margin-top: 10px; }
.rule-empty {
  padding: 22px 12px; text-align: center;
  font-size: 12.5px; color: var(--ink-3);
  background: var(--g3); border-radius: var(--r-sm);
}
.rule-empty.hidden { display: none; }
/* 页头那个齿轮按钮：与 .notify-btn 同族，但只有图标（页头已经排满）。 */
.alarm-btn { padding: 0; width: 30px; justify-content: center; flex: 0 0 auto; }
/* 手机端：一行放不下 6 个控件，让作用范围下拉独占一整行（它是"这条规则管谁"，
   最需要一眼看清），其余控件在原行内折行。 */
@media (max-width: 720px) {
  .modal-card.modal-wide { max-width: 100%; padding: 18px 14px 14px; }
  .rule-row { gap: 5px; padding: 8px; }
  .rule-sel { max-width: 46%; }
  .rule-sel.rule-op, .rule-sel.rule-lv { max-width: 32%; }
  .rule-num { width: 78px; }
  .rule-list { max-height: 56vh; }
}

/* 点通知后跳到对应行：短暂高亮，帮眼睛定位 */
@keyframes rowFlash { 0%, 100% { background: transparent; } 12%, 58% { background: rgba(201, 165, 76, .22); } }
tr.row-flash { animation: rowFlash 1.6s ease-out; }

.topbar-gold { height: 2px; background: linear-gradient(90deg, transparent, var(--gold) 30%, var(--gold) 70%, transparent); opacity: .85; }

/* ---------- 异常提示条 ----------
   三条提示条（连接异常 / 文件损坏 / 令牌错误）统一 12px 圆角 + 无重描边，
   只靠"淡色底 + 同色系文字"表达严重度 —— 旧版都有 1px 彩色边框，
   与旁边无边框的卡片并排时显得"贴了三条标签"。
   ⚠️⚠️ 2026-10-17 二轮：注释从一轮重构起就这么写，但三条规则里的 border 一直在
   （#f2e2bb / #f4d3cf）——"文档宣称 ≠ 代码事实"的典型。本轮真的删掉了。
   同时 #fdf6e3+#8a5a00 与 .mkt-status.auction 的 #faf3e0+#8a6d1f 是两套琥珀，
   归一为 --amber-bg / --amber-ink（取 mkt-status 那对：底与页面对比更强、字已有 3 处共用）。 */
.alert-bar {
  max-width: 1440px;
  margin: 14px auto 0;
  padding: 11px 16px;
  background: var(--amber-bg);
  border-radius: var(--r-md);
  color: var(--amber-ink);
  font-size: 13px;
}

/* 自选股文件读取异常提示条。
   与上方 .alert-bar 的区别：那条是「上游暂时连不上，会自动恢复」；
   这条是「本地文件读坏了，当前展示的是默认列表，不修文件不会自愈」，所以用更重的红色调。 */
.wl-warn {
  max-width: 1440px;
  margin: 14px auto 0;
  padding: 11px 16px;
  background: var(--up-bg);
  border-radius: var(--r-md);
  color: var(--up-ink);   /* 二轮：#b3261e → --up-ink（与异动 high chip、弹窗错误同一只红字） */
  font-size: 13px;
  line-height: 1.55;
}
.wl-warn code {
  font-family: ui-monospace, Consolas, "Courier New", monospace;
  font-size: 12px;
  background: rgba(163, 45, 45, .08);   /* 与 --up-ink 同色相 8% 底 */
  padding: 1px 5px;
  border-radius: var(--r-pill);   /* 二轮：4px → 胶囊（inline code 也是 chip，见 .dd-type） */
}
/* 令牌错误：用琥珀色而不是红色 —— 它不是故障，是"你还没带钥匙"，
 * 而且解决方式完全不同（换个地址），不该和自选股损坏那种红色警报混为一类。 */
.auth-err {
  max-width: 1440px;
  margin: 14px auto 0;
  padding: 11px 16px;
  background: var(--amber-bg);
  border-radius: var(--r-md);
  color: var(--amber-ink);
  font-size: 13px;
  line-height: 1.55;
}
.auth-err code {
  font-family: ui-monospace, Consolas, "Courier New", monospace;
  font-size: 12px;
  background: rgba(138, 90, 0, .10);   /* 与 --amber-ink 同色相 10% 底 */
  padding: 1px 5px;
  border-radius: var(--r-pill);
}

/* ---------- 主体 ----------
   2026-10-18 整站统一：纵向节奏收到 8 的倍数（8/16/24）。此前是 22/26/14/22 的
   混合值 —— 单看每处都"差不多"，整页扫下来区块间距却在 14~26 之间随机。
   本文件里所有区块级间距现在只有三档：16（标题→内容）、24（区块→区块）、12（条内）。 */
.container { max-width: 1440px; margin: 0 auto; padding: 24px 24px 8px; }

/* 区段标题（2026-10-17 去金条）
   旧版是 `border-left: 3px solid var(--gold)` 的左侧竖条 —— 这是国内 Web 后台
   的通用写法，Apple 的大标题（Large Title）只靠「字号 + 字重 + 字距」建立层级，
   不挂任何竖线。去掉之后品牌金并没有丢：它在顶栏那根 2px 线、focus 环、
   选中态 tint 上各出现一次，面积更小但更克制。
   ⚠️ letter-spacing 取负值：SF/苹方的中文字面本身带侧边空白，负字距能让
   "大盘指数"四个字更像一个整块而不是四个字。 */
/* ---------- 幻灯片：自选股 ⇄ 板块数据（2026-10-17） ----------
   用户需求：板块数据与自选股**同一位置**，用两个点（dots）以幻灯片形式切换。
   做法：viewport 裁切 + track 横移 `translateX(-100% × i)`，两个 panel 各占 100% 宽。
   ⚠️ viewport 的高度**不写 CSS** —— 由 app.js 的 syncSlideHeight() 按当前面板的
      offsetHeight 写入（两个面板高度差一个数量级，写死会在矮面板下留一片空白）。
   ⚠️ track 必须 `align-items: flex-start`：否则 flex 默认 stretch 会把 panel 拉到
      viewport 的固定高度，offsetHeight 量到的是容器高度而非内容高度，高度就永远不更新。 */
.slide-viewport {
  overflow: hidden;
  transition: height .32s cubic-bezier(.4, 0, .2, 1);
}
.slide-track {
  display: flex;
  align-items: flex-start;
  transition: transform .32s cubic-bezier(.4, 0, .2, 1);
}
.slide-panel { flex: 0 0 100%; min-width: 0; }

/* ---------- 自选股 ⇄ 板块 切换：文字分段控件（2026-10-17 三版） ----------
   为什么不是圆点：首版照搬"两个点"做成 7px 小圆点 + 激活拉长胶囊的 Carousel 语义，
   用户反馈"放这有点难看"。圆点暗示"后面还有很多页"，而这里只有两个功能面板；
   财经 APP（同花顺/东财）的这类切换一律用**文字标签** —— "另一个是什么"不言自明，
   命中区也从 22px 变成整块文字。
   设计归队（改前先对一遍全站收口原则）：
   ① 形状 = 胶囊（三种形状之一）；② 控件族 = 灰底填充（--g4 控件底 / 白卡激活态）；
   ③ 阴影 = 卡片档的第一层（0 1px 2px）—— 激活块是"浮在灰槽里的小卡"，不是新浮层；
   ④ 字号 = Apple 阶梯 12；⑤ 焦点环 = 品牌金 3px（与 .btn-sort / .sel-inline 同一支）。
   位置：内容上方居中（width:max-content + margin auto；用户 2026-10-17 要求居中）。
   ⚠️ 不能放内容下方：自选股面板高 2700px，控件会跑到页面最底部看不见。 */
.slide-tabs {
  display: flex;
  align-items: center;
  gap: 2px;
  width: max-content;
  margin: 0 auto 12px;
  padding: 3px;
  border-radius: var(--r-pill);
  background: var(--g4);
}
.slide-tab {
  appearance: none;
  border: none;
  background: none;
  cursor: pointer;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  color: var(--ink-3);
  padding: 7px 18px;
  border-radius: var(--r-pill);
  white-space: nowrap;
  transition: color .18s, background .18s, box-shadow .18s;
}
.slide-tab:hover { color: var(--ink-2); }
.slide-tab.active {
  color: var(--ink);
  font-weight: 600;
  background: var(--card);
  box-shadow: var(--sh-tab);   /* 二轮：字面量 → 令牌（"浮在灰槽里的小卡"，见 :root 注释） */
}
/* 焦点环放最后：同时命中 active 时盖住卡片阴影（键盘用户优先） */
.slide-tab:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(201, 165, 76, .32); }

/* ---------- 板块榜（幻灯片第二页，2026-10-17 二版：涨跌双榜） ----------
   财经 APP 的板块页都是**按当日涨跌幅排序的榜单**，所以这里改成双榜：
   涨幅前 15 + 跌幅前 15，每项两行 —— ① 板块名 + 涨跌幅胶囊；② 领涨股(+涨幅) · 涨跌家数 · 主力净流入。
   配色不照搬参考截图的深色（本站浅底深字），胶囊沿用 .idx-pill / .pct-badge 那套淡底+深字。
   ⚠️ 三列下每项 457px（1600 视口），第二行三个信息刚好放下不换行；窄屏见文件末尾媒体查询：
   ≤720px 回 2 列、≤540px 单列。 */
.sector-block + .sector-block { margin-top: 24px; }
/* 2026-10-18 整站统一：13px/700 → 12.5px/600 + 字距 .01em。
   全站的"组标题"只有两档：区段标题 20/600（h2）与组标签 12.5/600（.grp-name）。
   这里是第三种（13/700）—— 700 在白底上压得过重，13px 又不在任何刻度上；
   归到 .grp-name 那一档后，第一页的「半导体 12」与第二页的「涨幅榜」终于是同一种字。 */
.sector-block-head {
  display: flex; align-items: center; gap: 7px;
  margin: 0 0 10px 2px;
  font-size: 12.5px; font-weight: 600; color: var(--ink-2);
  letter-spacing: .01em;
}
.sbh-dot { width: 6px; height: 6px; border-radius: 50%; flex: 0 0 auto; }
.sbh-dot.up { background: var(--up); }
.sbh-dot.down { background: var(--down); }

.sector-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  /* 二轮：gap 10px → 12px，与 .index-grid 同规格（此前两个卡片网格两套缝宽） */
  gap: 12px;
}
.sector-item {
  display: flex; flex-direction: column; gap: 7px;
  min-width: 0;
  /* 二轮：11/14/10 → 14/16/12，与 .idx-card 完全同规格 */
  padding: 14px 16px 12px;
  background: var(--card);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  /* 2026-10-18 整站统一：与 .idx-card 同一套悬停反馈（位移 + 抬一档阴影，同为 .15s）。
     此前只有位移、没有阴影变化、时长还是 .12s —— 两种白卡并排，悬停手感不一样。 */
  transition: transform .15s, box-shadow .15s;
}
.sector-item:hover { transform: translateY(-1px); box-shadow: var(--sh-card-hover); }
.sec-row1 { display: flex; align-items: center; gap: 8px; min-width: 0; }
.sec-name {
  flex: 1 1 auto; min-width: 0;
  font-size: 13.5px; font-weight: 600; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 涨跌幅胶囊（2026-10-17 二轮统一规格）：idx-pill / pct-badge / sec-pct 是同一语义角色
   （淡底 + 加深字的彩色数值徽章），此前却是三种规格 —— 12px/2px9px、13px/3px10px、
   12.5px/700。统一取 12.5px / 3px 10px / 600：字号与 .chip / .btn-sort 的 chip 档对齐，
   3px 10px 是多数派，字重 600（700 在白底上压得过重）。
   ⚠️ .pct-badge 的 min-width:74px 不动（表格列对齐用，与规格统一无关）。 */
.sec-pct {
  flex: 0 0 auto;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  font-size: 12.5px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* 同一条判据：淡底 + 加深字（2026-10-18 整站统一，原为 --up/--down/--flat 本体）。 */
.sector-item.up .sec-pct { background: var(--up-bg); color: var(--up-ink); }
.sector-item.down .sec-pct { background: var(--down-bg); color: var(--down-ink); }
.sector-item.flat .sec-pct { background: var(--flat-bg); color: var(--ink-2); }
/* 第二行：领涨股可省略（它最长），家数与资金固定宽度靠右 */
.sec-row2 {
  display: flex; align-items: center; gap: 10px;
  font-size: 11.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden;
}
.sec-leader { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.sec-leader b { font-weight: 600; color: var(--ink-2); }
.sec-leader i { font-style: normal; font-weight: 600; }
.sec-leader.dim { color: var(--ink-3); }
.sec-cnt { flex: 0 0 auto; }
.sec-cnt i { font-style: normal; font-weight: 600; }
.sec-cnt .c-up { color: var(--up); }
.sec-cnt .c-down { color: var(--down); }
.sec-flow { flex: 0 0 auto; font-weight: 600; }
/* 沿用上一轮板块行情时整块降一档（与 .breadth-bar.stale 同一语义） */
.sector-grid.stale { opacity: .55; }

/* ---------- 主力行为（幻灯片第三页，2026-10-18） ----------
   页面语义：把"主力在不在吸货"从盘感变成可比较的数值。列很多但不该横向爆炸，
   所以：名称列固定 170px、其余列按内容自适应、整表 min-width 970px（10 列）交给 .table-scroll。
   配色沿用语义色板（阶段=红/琥珀/信息蓝/灰），不引入新色。 */
.mf-status {
  background: var(--card);
  border-radius: var(--r-md);
  box-shadow: var(--shadow);
  padding: 12px 16px;
  margin: 0 0 12px;
}
.mf-status-line {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.mf-status-text {
  font-size: 12.5px; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.mf-retry {
  appearance: none; border: none; cursor: pointer;
  font-size: 12px; font-weight: 600;
  color: var(--gold-ink); background: var(--gold-tint);
  padding: 5px 12px; border-radius: var(--r-pill);
  transition: background .18s;
}
.mf-retry:hover { background: rgba(201, 165, 76, .26); }
.mf-retry:disabled { opacity: .5; cursor: default; }
.mf-bar {
  height: 4px; border-radius: var(--r-pill);
  background: var(--g5); margin-top: 9px; overflow: hidden;
}
.mf-bar > i {
  display: block; height: 100%; width: 0;
  background: var(--gold); border-radius: var(--r-pill);
  transition: width .35s cubic-bezier(.4, 0, .2, 1);
}
/* 汇总胶囊 + 分组筛选同排（2026-10-19 用户："分组筛选按钮移至截图中一行，右对齐"）。
   胶囊吃掉剩余宽度（自己会折行），按钮用 margin-left:auto 钉在右端。
   align-items:center 而不是 flex-start：胶囊高 20.5px、按钮高 28px，顶对齐会让按钮
   看起来"往下掉了半格"（截图里一眼能看出不在一条中线上）。
   窄屏另作处理（见 ≤720px）：按钮独占下一行靠右 —— 否则它会挤掉最后一颗胶囊，
   让「形态观察 11」孤零零掉到第二行（375px 下实测 4+1 折行，很难看）。 */
.mf-summary-row { display: flex; align-items: center; gap: 12px; margin: 0 0 12px; }
.mf-summary { flex: 1 1 auto; min-width: 0; display: flex; flex-wrap: wrap; gap: 8px; }
/* 列口径说明 2026-10-18 改成悬停提示（用户要求：那五行灰字不再占正文）。
   同日二改：虚线底去掉了（用户嫌碍眼）。视觉暗示缩到零 —— 只剩 cursor:help，
   鼠标移到标题上才变问号。要恢复发现性得换一种引导（问号图标 / 点击展开等），
   别指望用户去悬停一个看起来纯文字的标题。 */
#mfTitle { cursor: help; }
/* 2026-10-18 整站统一：与第一页标题行的 .chip 完全同规格（12.5/500、4×10、line-height 1）
   —— 两者都是"淡底 + 数值"的胶囊，只是落在不同面板上。 */
.mf-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border-radius: var(--r-pill);
  font-size: 12.5px; font-weight: 500; line-height: 1;
  background: var(--g4); color: var(--ink-2);
}
.mf-chip b { font-weight: 600; font-variant-numeric: tabular-nums; }
/* 2026-10-18 整站统一：淡底上的文字一律用**成对的加深字档**（--up-ink / --down-ink）。
   此前这四行写的是 --up / --flat 本体，印在自家淡底上只有 3.2~4.2:1 —— 12px 小字发虚；
   而同一个文件里 .chip / .alert-chip 用的是加深档，于是"同一种胶囊两种绿"。
   判据（以后加新胶囊先问这一句）：*底色是谁的淡底，字就必须是谁的 -ink。* */
.mf-chip.mf-b-up { background: var(--up-bg); color: var(--up-ink); }
.mf-chip.mf-b-amber { background: var(--amber-bg); color: var(--amber-ink); }
.mf-chip.mf-b-info { background: var(--info-bg); color: var(--info-ink); }
.mf-chip.mf-b-flat { background: var(--flat-bg); color: var(--ink-2); }
.mf-chip.mf-chip-sig { background: var(--gold-tint); color: var(--gold-ink); }

/* 分组筛选（2026-10-19，多选）。按钮属于**控件族**：灰底胶囊 28px，与 .sel-inline 同高同圆角；
   弹层属于**浮层**：白卡 + --r-md + --sh-pop（全站浮层唯一规格，别新造阴影）。
   ⚠️ 弹层是 absolute，锚在 .mf-filter 上（它必须 position:relative）—— 否则会以页面为参照飞到左上角。 */
.mf-filter { position: relative; flex: 0 0 auto; margin-left: auto; }
.mf-filter-btn {
  display: inline-flex; align-items: center; gap: 6px;
  height: 28px; padding: 0 12px;
  border: none; border-radius: var(--r-pill);
  background: var(--g4); color: var(--ink-2);
  font: inherit; font-size: 12.5px; line-height: 1;
  cursor: pointer; white-space: nowrap;
  transition: background-color .15s, color .15s;
}
.mf-filter-btn:hover { background: var(--g5); color: var(--ink); }
.mf-filter-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(201, 165, 76, .32); }
/* 展开态 = 悬停档（与 .sel-inline:focus 同一套"控件被按住"的表达） */
.mf-filter-btn[aria-expanded="true"] { background: var(--g5); color: var(--ink); }
/* 内联 SVG 必须显式给尺寸：不写的话默认 inline 基线会把它顶偏，并把胶囊撑高（本项目的常见坑） */
.mf-filter-btn svg { flex: 0 0 14px; }
/* 「13/14」是数值，等宽数字 + 比正文弱一档；用 --ink-2 而不是 --ink-3：
   12.5px 的 --ink-3 印在 --g4 上只有 ~2.5:1，实测发灰到"看不清还剩几组"。 */
.mf-filter-btn b { font-weight: 600; color: var(--ink-2); font-variant-numeric: tabular-nums; }

.mf-filter-pop {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 40;
  width: 236px; padding: 6px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--sh-pop);
}
/* 下方空间不够时翻到按钮上方（由 positionGroupPop() 加类）：
   面板只有 230px 高（全部分组被勾掉只剩空态）时，向下弹会被 .slide-viewport 裁掉 300+ 像素。 */
.mf-filter-pop.pop-up { top: auto; bottom: calc(100% + 6px); }
.mf-filter-head {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px 8px; border-bottom: 1px solid var(--line-soft);
}
.mf-filter-title { font-size: 12px; font-weight: 600; color: var(--ink-2); }
/* 「全选 / 全不选」是**弱动作**（不改数据，只改视图），所以走文字按钮，不给它控件族的灰底 */
.mf-filter-acts { margin-left: auto; display: flex; gap: 2px; }
.mf-filter-acts button {
  border: none; background: none; padding: 2px 6px; border-radius: var(--r-sm);
  font: inherit; font-size: 11.5px; color: var(--ink-3); cursor: pointer;
}
.mf-filter-acts button:hover { background: var(--g4); color: var(--ink); }
/* 列表高度：14 个组 × 26px + 表头 ≈ 398px，给到 420 就一屏看全（此前 288 只露出 8 个，
   用户会以为"下面还有一组被截掉了"）。同时兜一层视口高度，别在小窗口里顶出屏幕。 */
.mf-filter-list { max-height: min(420px, calc(100vh - 220px)); overflow-y: auto; padding-top: 4px; }
.mf-filter-item {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 8px; border-radius: var(--r-sm);
  font-size: 13px; color: var(--ink); cursor: pointer;
}
.mf-filter-item:hover { background: var(--g1); }
/* 未勾选的组置灰一档 —— 「哪些组没被算进下面这张表」要一眼看出来，不能只靠那个小方块 */
.mf-filter-item:has(input:not(:checked)) .mf-filter-name { color: var(--ink-3); }
.mf-filter-item input {
  width: 14px; height: 14px; margin: 0; flex: 0 0 14px;
  accent-color: var(--gold); cursor: pointer;
}
.mf-filter-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mf-filter-n { margin-left: auto; font-size: 11.5px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.mf-filter-empty { padding: 10px 8px; font-size: 12.5px; color: var(--ink-3); }

/* ⚠️ 2026-10-18 整站统一：这张表原来与第二页的 .quote-table **是两套排版**
   （表头 11.5 vs 12.5、行 12.5 vs 13.5、内边距 9/10 vs 10~11/12、表头字色 ink-3 vs ink-2）。
   两张表在同一个幻灯片里、同一套白卡里、同一种数据，规格必须同源 ——
   现在四个值全部对齐 .quote-table：表头 12.5/600 + ink-2 + 11×12，行 13.5 + 10×12。
   min-width 2026-10-20 加到 970（10 列 nowrap 的实测下限；再加列要跟着量）。 */
.mf-table {
  width: 100%; border-collapse: collapse;
  font-size: 13.5px; min-width: 970px;   /* 10 列（2026-10-20 加「动作」）的实测下限 */
}
.mf-table th {
  text-align: left; font-weight: 600; font-size: 12.5px; color: var(--ink-2);
  padding: 11px 12px; background: var(--g1);
  border-bottom: 1px solid var(--line); white-space: nowrap;
}
.mf-table td {
  padding: 10px 12px; border-bottom: 1px solid var(--line-soft);
  vertical-align: middle; white-space: nowrap;
}
/* 2026-10-18 整站统一：**数值列右对齐**，与自选股表的 .quote-table（th/td 默认 right）同源。
   原来这张表所有列都是 left，于是 5 日净流入 / 距箱顶 这种宽度不等的百分比左对齐、
   末位参差；而"数字右对齐、文字左对齐"是表格最基本的对齐契约（Apple Numbers 同）。
   ⚠️ 只对数值列加 .mf-num：阶段/信号/量价是标签，仍左对齐。 */
.mf-table th.mf-num,
.mf-td-temp, .mf-td-persist, .mf-td-big, .mf-td-box, .mf-price { text-align: right; }
.mf-table tbody tr:hover { background: var(--g1); }
.mf-th-name { width: 170px; }
/* 名称格与第一页 .td-name 完全同构：名在上、代码在下（2026-10-19）。
   原来这里是 flex 行内排（名字 ← 6px → 代码），于是一只票在第三页是"名称 代码"横排、
   在第一页是"名称／代码"竖排 —— 同一个信息在两页有两种读法。改成块级堆叠后
   两页可以拿同一段 CSS 描述：名 14/600，代码 11/ink-3、上边距 1px。 */
.mf-name .mf-nm { display: block; }
.mf-name .mf-nm .cd { display: block; }
/* 与第一页的 .td-name .nm 同一档（14/600）：两个页面里"股票名"是同一种东西，
   此前这张表继承表格的 12.5 号，同名的票在第三页比第一页小一号。 */
.mf-name .nm { font-size: 14px; font-weight: 600; color: var(--ink); }
.mf-name .cd { font-size: 11px; color: var(--ink-3); margin-top: 1px; font-variant-numeric: tabular-nums; }
/* 行内组名小字已删除（2026-10-19）：第三页改成按自选股分组渲染，组名在组头行上，
   逐行重复是噪音。原来那条 .mf-grp 不再有人消费 —— 不留死规则。 */

/* ============ 第四页 · 估值（2026-10-21）============
 * 视觉规格**全部复用主力行为**，一条不新造：表体 .mf-table（表头 12.5/600 + --ink-2 + 11×12、
 * 行 13.5 + 10×12、行悬停 --g1）、名称格 .mf-name > .nm/.cd、组头 tr.grp-row + .grp-bar +
 * .grp-name/.grp-count、状态条 .mf-status/.mf-status-line/.mf-bar、重算按钮 .mf-retry、
 * 汇总胶囊 .mf-chip、空态 .empty-tip。
 * 这里只新增**四类彩色小标签**（类型 / 分位 / 结论 / 可信度）和数值列右对齐 ——
 * 「UI 参考主力行为页面」落到代码上就是"不新写一套长得像的"。
 *
 * ⚠️ 配色纪律（写在这里是因为它最容易被"顺手改回红绿"）：
 *   这一页表达的是"贵 / 便宜"，不是"涨 / 跌"。红绿在 A 股是涨跌语义，同一屏混用会让人
 *   把"偏高（琥珀）"读成"要跌"、把"低估（蓝）"读成"会涨" —— 两个概念完全不是一回事。
 *   所以用**冷/暖**：冷 = --info-*（蓝）= 位置低；暖 = --amber-*（琥珀）= 位置高；
 *   中性 = 灰。结论标签同一条：底色只表达**位置**（低/合理/高），
 *   **质量趋势靠文字标签**（"低估·质量降"）—— 一个维度一个编码，两者不打架。
 * ⚠️ 淡底上的字一律用同族 -ink 档（--info-ink / --amber-ink），不用本体色：
 *   12.5px 小字印在自家淡底上对比度只有 3.2~4.2:1，会发虚。2026-10-18 全站判据。
 */
/* 10 列。区间格是三个价格（"535 / 762 / 1079"），比主力行为多两个数字 ——
   实测下限 1010px（主力行为 970px）；再窄由 .table-scroll 出横向滚动条。 */
.val-table { min-width: 1010px; }
.val-table th.val-num,
.val-table td.val-num { text-align: right; }
/* 区间列的解释（倍数怎么来的、距中枢多少）**只有悬停才看得到**，所以必须给 help 光标，
   否则没人会去悬停一个看起来普通的数字。与 td.mf-td-stage.has-tip 同一条暗示：
   只加光标、不加下划线（用户明确说过下划线碍眼）。 */
.val-table td.val-td-range[title],
.val-row[title] { cursor: help; }

/* 「类型」标签：形状与 .mf-badge / .mf-chip 同族（胶囊 / 11.5 / 600）。
   颜色按"这把尺子为什么被选中"分：周期 = 琥珀（利润被周期扭曲，PE 不可信）、
   分红 = 蓝（稳定）、成长 = 品牌金（与全站"可执行"暗示同一对令牌）、普通 = 灰。 */
.val-type {
  display: inline-block; padding: 2px 8px; border-radius: var(--r-pill);
  font-size: 11.5px; font-weight: 600; line-height: 1.45; white-space: nowrap;
  background: var(--g4); color: var(--ink-2);
}
.val-type.val-t-cyc { background: var(--amber-bg); color: var(--amber-ink); }
.val-type.val-t-div { background: var(--info-bg); color: var(--info-ink); }
.val-type.val-t-gro { background: var(--gold-tint); color: var(--gold-ink); }
/* 「不适用」不再是灰胶囊里的黑字，而是灰底 + --ink-3：它是一句"这里没有结论"，
   不该和"普通"（有结论、只是不特殊）长得一样。 */
.val-type.val-t-na { background: var(--g4); color: var(--ink-3); font-weight: 500; }

/* 主指标格：「PE 25.6 · 58.1」= 自身倍数 · 同行中位。
   标签 PE/PB 是**单位**不是值，所以压到 11px/--ink-3；同行中位是参照物，同样弱一档； */
.val-met { font-size: 11px; font-weight: 600; color: var(--ink-3); letter-spacing: .02em; }
.val-mid { color: var(--ink-3); }
/* 现价是全表唯一的"此刻事实"，给足字重；它是用户核对区间用的锚点，不能弱化成灰。 */
.val-now { font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
/* 历史分位是**辅助**（受中枢漂移影响），整格弱一档 —— 与结论的权重差必须看得出来 */
.val-dim { color: var(--ink-2); }

/* 「行业分位」：只上色不加底。底一旦给了，这一列会比结论列更抢眼，
   而分位只是结论的**输入**之一（还要看质量趋势）。 */
.val-pct { font-variant-numeric: tabular-nums; color: var(--ink-2); }
.val-pct-low { color: var(--info-ink); font-weight: 600; }
.val-pct-high { color: var(--amber-ink); font-weight: 600; }
.val-pct-mid { color: var(--ink); }

/* 「结论」标签：底色 = 位置（低 / 合理 / 高），文字 = 质量趋势。
   合理与中性都走灰 —— "合理"不是褒义，它就是"没偏离"。 */
.val-sig {
  display: inline-block; padding: 2px 8px; border-radius: var(--r-pill);
  font-size: 11.5px; font-weight: 600; line-height: 1.45; white-space: nowrap;
  background: var(--g4); color: var(--ink-2);
}
.val-sig.val-s-lowgood { background: var(--info-bg); color: var(--info-ink); }
.val-sig.val-s-high,
.val-sig.val-s-highgood { background: var(--amber-bg); color: var(--amber-ink); }
.val-sig.val-s-na { background: var(--g4); color: var(--ink-3); font-weight: 500; }

/* 「可信度」是纯文字、不给底：它是元信息（"这个结论能不能看"），
   再上一块彩色就变成第三套并列语义，表格会花。三档靠字重/字色拉开。 */
.val-conf { font-size: 12.5px; color: var(--ink-3); }
.val-conf.val-c-high { color: var(--ink); font-weight: 600; }
.val-conf.val-c-mid { color: var(--ink-2); }

/* 取数失败：整行只有一格说明。用 --amber-ink 不用红 ——
   红色在这一页已经被"跌"征用了，错误提示再借一次会让两种完全不同的状态同色。 */
.val-err { color: var(--amber-ink); font-size: 12.5px; }

/* 汇总胶囊（低估 / 合理 / 偏高 / 中性 / 不适用）—— 与 .mf-chip 同一形状，
   只在颜色上按上面的冷/暖规则分档。 */
.mf-chip.val-chip-low { background: var(--info-bg); color: var(--info-ink); }
.mf-chip.val-chip-fair { background: var(--g4); color: var(--ink-2); }
.mf-chip.val-chip-high { background: var(--amber-bg); color: var(--amber-ink); }
.mf-chip.val-chip-na { background: var(--g4); color: var(--ink-3); }

/* 第三页标题行右侧：只剩口径小字（分组筛选 2026-10-19 已挪到汇总行右端）。
   .mf-head-right 保留是为了让 section-head 的 space-between 把标题和小字分开，
   而不是让两个元素各占一半。 */
.mf-head-right { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-left: auto; }

.mf-badge {
  display: inline-block; padding: 2px 8px; border-radius: var(--r-pill);
  font-size: 11.5px; font-weight: 600;
  background: var(--g4); color: var(--ink-2);
}
/* 阶段 / 信号两列带悬浮说明时给 help 光标（2026-10-19）：与「主力行为」面板标题同一套暗示，
   只加光标不加下划线 —— 下划线用户明确说过碍眼，这里也不能破例。
   title 挂在 td 上，所以光标要给整个格子，而不是里面 11.5px 的徽标。 */
td.mf-td-stage.has-tip,
td.mf-td-sig.has-tip,
td.mf-td-act.has-tip { cursor: help; }
/* 同一条判据（淡底配加深字）：mf-badge 是"阶段 / 量价"的状态标签，
   与 .mf-chip 是同一个家族的两种尺寸，颜色口径必须一致。 */
.mf-badge.mf-b-up { background: var(--up-bg); color: var(--up-ink); }
.mf-badge.mf-b-amber { background: var(--amber-bg); color: var(--amber-ink); }
.mf-badge.mf-b-info { background: var(--info-bg); color: var(--info-ink); }
.mf-badge.mf-b-flat { background: var(--flat-bg); color: var(--ink-2); }
/* 「取数失败」徽标：它的 title（失败原因）挂在**徽标自己**身上，不像阶段 / 信号列那样
   挂 td（那两列 title 在格子上、光标也给格子，见上面 897 行）。所以这里光标只给徽标
   —— 格子空白处悬停什么也没有，把 help 铺满整格是骗人的（2026-10-19 用户要求）。 */
.mf-err-badge { cursor: help; }
.mf-badge.mf-v-good { background: var(--up-bg); color: var(--up-ink); }
/* 「动作」列（2026-10-20）：三档语义，**借用的是既有令牌**，不新增色值 ——
   买入类（可追 / 低吸 / 埋伏）= 金色 tint（与选中态同一对令牌，全站"可执行"的暗示）；
   等待类（观察 / 等回踩 / 待确认）= 中性灰（与 .mf-b-flat 同）；
   回避 = 与「派发背离」同一对绿令牌（A 股语义里的负面侧）。
   ⚠️ 不与「量价」列的红/绿混用：那一列讲的是资金与涨幅的方向，这一列讲的是**该不该动手**。 */
.mf-badge.mf-b-buy { background: var(--gold-tint); color: var(--gold-ink); }
.mf-badge.mf-b-avoid { background: var(--down-bg); color: var(--down-ink); }
.mf-badge.mf-v-bad { background: var(--down-bg); color: var(--down-ink); }
.mf-badge.mf-v-flat { background: var(--flat-bg); color: var(--ink-2); }
.mf-sig {
  display: inline-block; min-width: 22px; text-align: center;
  padding: 2px 8px; border-radius: var(--r-pill);
  font-size: 11.5px; font-weight: 600; color: var(--ink-3);
}
.mf-sig.mf-s-strong { background: var(--up); color: #fff; }
.mf-sig.mf-s-weak { background: var(--amber-bg); color: var(--amber-ink); }

.mf-temp { display: inline-flex; align-items: center; gap: 6px; }
.mf-temp b { font-weight: 600; font-variant-numeric: tabular-nums; min-width: 22px; }
.mf-mini {
  display: inline-block; width: 46px; height: 4px;
  /* 槽色 --g4 在白卡上只差 6 阶，4px 高的细条几乎看不出"槽"，金色填充就像一条
     悬空的横线（用户看到的是"93 ———"）。改用 --g5（控件悬停档）当槽，
     与填充的 5 倍亮度差才让"已填多少"看得出来。 */
  border-radius: var(--r-pill); background: var(--g5); overflow: hidden;
}
.mf-mini > i { display: block; height: 100%; background: var(--gold); }
.mf-persist { font-weight: 600; font-variant-numeric: tabular-nums; margin-right: 6px; }
.mf-dim { color: var(--ink-3); }
.mf-price b { font-weight: 600; font-variant-numeric: tabular-nums; }
.mf-price i {
  font-style: normal; font-size: 11.5px; margin-left: 5px;
  font-variant-numeric: tabular-nums;
}
/* 组头行（2026-10-19）：第三页不再按「强/弱/形态/回避」分段，改成与第一页同一套
   自选股分组。样式**直接复用**桌面端 tr.grp-row 那组规则（灰底 --g2 + .grp-bar /
   .grp-name / .grp-count），这里不重复定义 —— "格式参考自选股"的落地方式就是让
   两个页面的组头是同一条 CSS，而不是"长得像"的两套。
   原来 .mf-sep（分段标题）的规则已删除；留着它会让人照着调一个永不出现的元素。 */

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 16px;   /* 2026-10-18：14 → 16（8 的倍数；标题到内容这一档全站统一 16） */
}
.section-head h2 {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -.2px;
  line-height: 1.2;
}
.section-note { font-size: 12px; color: var(--ink-3); }
.section-note b { color: var(--ink-2); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ---------- 指数卡片 ----------
   2026-10-17 去掉左侧 3px 彩色竖条（`.up` / `.down` 只改 border-left-color 的那套）。
   理由同区段标题的金条：Apple 不用"边上贴一条色带"表达状态，状态由**数字本身的颜色 +
   涨跌幅胶囊**承载 —— 这一卡里 25px 的红字比 3px 的细条响得多，竖条纯属重复表达，
   还让 6 张卡横排时变成一列"彩条栅栏"。
   去掉后 padding 左移了 3px，所以左 padding 由 14 补到 16，视觉基线不动。 */
.index-grid {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 12px;
  margin-bottom: 24px;   /* 2026-10-18：26 → 24（区块间距统一 24） */
}
.idx-card {
  background: var(--card);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-card);
  padding: 14px 16px 12px;
  transition: transform .15s, box-shadow .15s;
  min-width: 0;
}
.idx-card:hover { transform: translateY(-1px); box-shadow: var(--sh-card-hover); }   /* 二轮：字面量 → 令牌 */
.idx-head { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; }
.idx-name { font-size: 13px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.idx-code { font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.idx-price-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-top: 6px; }
/* tabular-nums 是硬需求：指数价每秒刷新，非等宽数字会让整行宽度随数字跳动而抖 */
.idx-price { font-size: 24px; font-weight: 600; letter-spacing: -.3px; line-height: 1.15; font-variant-numeric: tabular-nums; }
.idx-pill {
  font-size: 12.5px; font-weight: 600;
  padding: 3px 10px;
  border-radius: var(--r-pill);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.idx-canvas { display: block; width: 100%; height: 52px; margin: 4px 0 2px; }
.idx-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; border-top: 1px solid var(--line-soft); padding-top: 8px; }
.stat { min-width: 0; }
.stat-label { display: block; font-size: 11px; color: var(--ink-3); }
.stat-val { display: block; font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 红涨绿跌（A股口径） */
.t-up { color: var(--up); }
.t-down { color: var(--down); }
.t-flat { color: var(--flat); }
.idx-pill.t-up, .pct-badge.t-up { background: var(--up-bg); }
.idx-pill.t-down, .pct-badge.t-down { background: var(--down-bg); }
.idx-pill.t-flat, .pct-badge.t-flat { background: var(--flat-bg); }
/* 2026-10-18 整站统一：**胶囊里的字**改用成对加深档。
   `.t-up` 本体是 --up(#d93025)，它同时负责"白卡上的大字"（.idx-price / .td-price，
   白底 4.6:1 合格）。但同一个类一旦落进淡底胶囊，3.2:1 就发虚 —— 所以在这里按
   "胶囊"这一层覆盖，不动 .t-up 本身（否则指数价那 24px 大字会一起被压暗）。 */
.idx-pill.t-up, .pct-badge.t-up { color: var(--up-ink); }
.idx-pill.t-down, .pct-badge.t-down { color: var(--down-ink); }
.idx-pill.t-flat, .pct-badge.t-flat { color: var(--ink-2); }

/* 骨架屏。sk-line 的 4px 是占位形的微圆角（一条 13px 高的"文字替身"），
   不是控件、不进圆角三档；--r-sm(8px) 在 13px 高的条上会圆成胶囊。 */
.skeleton { pointer-events: none; }
.sk-line { height: 13px; border-radius: 4px; background: linear-gradient(90deg, var(--g3) 25%, var(--g1) 50%, var(--g3) 75%); background-size: 200% 100%; animation: shimmer 1.3s infinite; margin-bottom: 10px; }
.sk-line.w50 { width: 50%; }
.sk-line.w70 { width: 70%; height: 22px; }
.sk-block { height: 52px; border-radius: var(--r-sm); background: linear-gradient(90deg, var(--g3) 25%, var(--g1) 50%, var(--g3) 75%); background-size: 200% 100%; animation: shimmer 1.3s infinite; }
@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ---------- 自选股 ---------- */
/* 工具组整体钉右侧：margin-left:auto 吸收剩余空间；空间不足换行时，
   工具组单独占一行并仍贴右端（auto 边距在换行后的行上依然有效）。
   窄屏约束（uitest [17]）：本容器不得横向溢出、内容不得被裁。 */
.watch-tools { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }

/* ---------- 市场宽度条（大盘温度，2026-10-17 三版：居中温度条 + 数据时点） ----------
   演进：白卡药丸塞标题行（和"最近更新"抢一行，用户反馈"放在这比较难看"）
      → 指数卡下方通栏、6 家数等分贴右、竖线隔开成交额（二版）
      → 内容整体居中、去掉竖线、标出数据时点（三版）
      → 分散对齐、截至移到容器上方右对齐、高度紧凑（四版）
      → 截至改到容器下方右对齐、字体格式对齐"最近更新"（五版）
      → 截至改到容器内右端垂直居中（六版，据"数据在右边"误改时间戳，后澄清）
      → **每项从上下两行改为左右一行：数字放到各自标签右边**（七版，用户 2026-10-17：
        "是上涨、涨停等这些数据放右边。上下结构改成左右"；截至回到五版容器下方）。
      → **项内标签与数字改垂直居中**（八版，用户 2026-10-17：
        "此容器里的文字上下水平居中"：基线对齐时标签贴在数字底部，改 center）。
      → **去掉「截至 HH:MM:SS」整行**（十版，2026-10-18 用户："截至 22:08:06
        这个截至删除，不显示"）：`.bd-asof` 的 DOM/CSS 一起删干净，时点降级进
        容器 tooltip（悬停整条仍能看到"截至 …"）。此前九版把它的右缘对齐
        `.section-note`，现在没有元素，那套定位规则一并作废。
   视觉语言与 `.idx-card` / `.table-card` 同族：白卡 + 卡片档阴影 + r-lg 圆角。
   布局：8 项（6 家数 + 两市成交 + **较上日**）**沿通栏分散对齐**（space-between：首项贴左、
   末项贴右，中间项均分剩余空间 —— 同花顺/东财市场温度条的标准排法），每项一行（七版）——
   左 11px 灰标签、右 20px 粗体彩色数字（涨红跌绿平灰），二者**垂直居中**（八版）。
   竖线已去掉：成交额靠"更大的字 + 更深的色 + 单位小字号"区分量纲，不再靠分隔物。
   ⚠️ 数据时点（十版）只在 `el.title` 里：宽度条自己的节奏是盘中 60s / 休市 5min
      （server.js 的 BREADTH_TTL_*），和旁边"每秒"的行情表不是一回事。它不再
      出现在正文，所以别再按"屏幕上应该有个时间"写断言。
   ⚠️ `.bd-v` 故意**不设 color**：颜色全部由 .t-up / .t-down / .t-flat 提供。
   ⚠️ 伪装态不用单独写规则：本节点在 `.indices-section` 内，而
      `html.disguise .indices-section{display:none}` 已经整块藏掉（那条在文件末尾）。 */
.breadth-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;         /* 分散对齐（四版，用户明确要求） */
  background: var(--card);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-card);
  /* 紧凑（四版）：上下 13px → 8px。右侧 padding 回到 22px（七版）——
     六版曾加到 122px 给容器内右端的「截至」让位；七版起「截至」回到容器下方，
     不再占容器内横向空间，让位量随之取消。十版删掉时点后仍是 22px 对称。 */
  padding: 8px 22px;
  margin: 0 0 24px;               /* 上方间距由 .index-grid 的 margin-bottom:24px 提供（2026-10-18 归 8 的倍数） */
  font-variant-numeric: tabular-nums;
}
/* 家数列：不拉伸（flex:0 0 auto），靠 space-between 形成分散节奏。
   七版（2026-10-17 用户："上下结构改成左右"）：每项从上下两行改为**一行左右** ——
   11px 灰标签在左、20px 粗体数字在右。
   八版（2026-10-17 用户："此容器里的文字上下水平居中"）：align-items 由 baseline
   改 **center** —— 基线对齐时小标签贴在数字底部（实测标签 rect 中心低于数字
   3.7px，视觉上"上涨"挂在"3111"下方），居中后两者互为中线。
   DOM 契约 `.bd>.bd-k+.bd-v` 不变。 */
.bd {
  flex: 0 0 auto;
  min-width: 0;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 7px;
  white-space: nowrap;
}
.bd-k { font-size: 11px; color: var(--ink-3); line-height: 1; }   /* 紧凑（四版）：行高 1.4 → 1 */
.bd-v { font-size: 20px; font-weight: 600; line-height: 1.1; }
/* 两市成交：三版去掉竖线与专属边距，和家数一样只是分散排布里的一项。
   量纲区分靠字号（22 vs 20）+ 字色（--ink vs 红绿灰）+ 单位小字号。 */
.bd-amt .bd-v { font-size: 22px; color: var(--ink); }
/* 单位（万亿/亿）小一号：数字是主体，单位是修饰 */
.bd-unit { font-size: 12px; font-weight: 500; color: var(--ink-2); margin-left: 2px; }
/* 较上日（2026-10-20 下午新增用户需求：「两市成交后面增加一个数据，较上一日…是 +
   还是 −，对应红色和绿」）。
   它是成交额的**派生量**，所以字号比成交额（22px）再小一档到 16px —— 否则一行里
   出现两个大号数字，主次不分。颜色仍然只由 .t-up / .t-down 给（正红负绿，与这一行
   涨/跌两格同向，不引入第二套配色直觉）；单位沿用 .bd-unit 但再小 1px。 */
.bd-prev .bd-v { font-size: 16px; }
.bd-prev .bd-unit { font-size: 11px; }
/* 数据时点（.bd-asof）的样式**十版整块删除**（2026-10-18 用户："截至 22:08:06
   这个截至删除，不显示"）。它曾经换过五种定位：容器上方右对齐 → 下方右对齐 →
   容器内右端 → 回到下方 → 右缘与 .section-note 同线。现在元素不再渲染，时点只
   留在容器 tooltip 里，所以这里什么都不留 —— 别为了"以后可能恢复"保留死规则：
   留着就会有人照着它改定位，改的却是一个永远不会出现的元素。 */
/* 沿用上一次成功结果时整条降一档：数字还在，但要能一眼看出"不是这一分钟的" */
.breadth-bar.stale { opacity: .55; }
/* 窄屏（≤720px）：一行放不下 8 项 → 家数换行成 3 列网格，成交额独占一行、
   较上日再独占一行右对齐。
   七版起每项是一行左右结构（标签+数字），3 列网格里依然放得下。
   （十版删掉「截至」后，窄屏少了一行靠右的时间，块高随之矮一行。） */
@media (max-width: 720px) {
  .breadth-bar { flex-wrap: wrap; padding: 12px 14px; row-gap: 12px; gap: 14px 16px; }
  .bd { flex: 1 1 30%; }
  .bd-v { font-size: 18px; }
  .bd.bd-amt {
    flex: 1 1 100%;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
  }
  .bd-amt .bd-v { font-size: 20px; }
  /* 「较上日」独占一行并**右对齐**，读作上一行成交额的注脚（左对齐会像第 8 个
     并列指标，反而让人以为「较上日 +1840 亿」是某个独立家数）。 */
  .bd.bd-prev {
    flex: 1 1 100%;
    justify-content: flex-end;
    gap: 8px;
  }
  .bd-prev .bd-v { font-size: 17px; }
}

/* 涨跌统计行。三段演进（读之前先看这段，别按某一段的字面回退）：
   ① 2026-10-16 之前：5 个彩色 pill（3 种配色体系 + 2 种描边变体），是"凌乱"感主源；
   ② 2026-10-16：quiet 化 —— 去底色/描边/圆角，只留带色数字 + `·` 分隔；
   ③ 2026-10-18：改成**五个独立胶囊**，颜色对齐自选股异动条（用户："改为分别五个
      胶囊容器，颜色参考自选股异动显示"）。
   ③ 之所以不回到 ①：① 的病根是"配色体系不统一"，而 ③ 用的就是异动 chip 那一套
   （淡底 + 加深字 + 胶囊），全站彩色标签从此只有一种语言。
   ⚠️ `.chips` 这个类名是伪装态的隐藏开关（style.css 末尾 html.disguise），
   改类名必须同步改那里；整块隐藏 → 胶囊颜色不需要另外做伪装态处理。 */
/* 实现要点：
   配色语义与异动条一致：红=涨（--up-bg/--up-ink）、绿=跌（--down-bg/--down-ink）、
   灰=平盘。⚠️ 一律用**成对令牌**，别拿 --up/--down 直接印在淡底上（3.2:1，小字发虚）。
   ⚠️ 分隔符 `·` 的 ::before 随整行胶囊一起删除 —— 独立胶囊自带 6px 间距，再插点号是噪音。 */
.chips {
  display: flex; gap: 6px; flex-wrap: wrap; align-items: center;
  /* 桌面**整块不许被压缩**：右侧工具组的宽度随分组数变化（"全部组别（已隐藏 N 组）"
     最长），flex 默认 `shrink:1` 会把本行挤窄 → 内部 wrap 把 5 颗拆成 3+2，
     比掉到下一行难看得多。禁 shrink 后要么一行放得下、要么整块掉行（.section-head
     自己是 wrap）。窄屏必须放开，见文件末尾 ≤720px 那条。 */
  flex: 0 0 auto;
}
.chip {
  /* 用 inline-block 而不是 inline-flex：app.js 拼的 HTML 里「上涨」与数字之间本来就有一个
     空格（`上涨 <b>`），flex 容器会把这段空白变成一个**匿名 flex item**，再叠 gap
     就成了双倍间距。inline-block 让空格保持原样，也省掉一个需要维护的 gap 值。 */
  display: inline-block;
  font-size: 12.5px; font-weight: 500; line-height: 1;
  padding: 4px 10px;
  border: 0;
  border-radius: var(--r-pill);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.chip-up, .chip-best { background: var(--up-bg); color: var(--up-ink); }
.chip-down, .chip-worst { background: var(--down-bg); color: var(--down-ink); }
/* 平盘没有"方向"，用中性灰底；字色取 --ink-2（--flat 印在 --flat-bg 上只有 4.2:1）。 */
.chip-flat { background: var(--flat-bg); color: var(--ink-2); }
/* 数字与股票名同为 600：整颗胶囊已经同色（不再有"标签灰、数字彩"的分层），
   靠字重而不是颜色把数值拎出来。12.5px/600 与 .alert-chip 的 .alert-name 同档。 */
.chip-nm { font-weight: 600; }
.chip-num { font-weight: 600; font-variant-numeric: tabular-nums; }

/* ---------- 异动提示 ----------
   2026-10-16 Apple 风格重构：旧样式是整条暖黄带（#fffaf0 + 金描边），
   与下方白色表格卡并列时形成"两条色带夹一张表"的割裂感。现在改成
   白底软卡（与 .table-card 同一族视觉语言），铃铛 SVG 图标 + 粗体小字标题，
   chips 去描边、底色更淡、字重降到 500。
   ⚠️ `.alert-list` 这个类名同样是伪装态隐藏开关（html.disguise），不可改。
   2026-10-16 二次调整（用户："宽度调整到最大，异动股比较多宽度不够时滚动提示，
   不要显示 +4 类似这样的"）：异动**全量展示不截断**，chips 放进 `.alert-scroll`
   横向滚动；label 固定在左不跟着滚。容器本身 nowrap（换行改由内部滚动条承担）。 */
.alert-list {
  display: flex; align-items: center; flex-wrap: nowrap; gap: 7px;
  padding: 9px 14px; margin-bottom: 12px;
  background: var(--card);
  /* 去掉 1px 描边：它与下方 .table-card（无边框、纯阴影）并排，
     一个有边一个没边，是"两条带夹一张表"割裂感的最后一点残留。 */
  /* 圆角取 --r-md 而不是卡片的 --r-lg：这条只有 33px 高，16px 圆角在矮条上会圆成胶囊。
     规则 = 高卡（表格/指数/板块，16px）用 r-lg，矮条（提示条/浮层/toast，12px）用 r-md，
     与 Apple 的连续圆角随元素尺寸缩放同一思路。 */
  border-radius: var(--r-md);
  box-shadow: var(--sh-card);
}
.alert-list.hidden { display: none; }
/* chips 滚动条：吃掉全部剩余宽度（min-width:0 才能在 flex 里收缩）。
   2026-10-17 用户："异动自选股过多时，自动滚动不需要手动拉动" —— 滚动交给
   app.js 的 autoScrollAlerts()（逐帧改 scrollLeft，悬停即暂停），这里只负责：
   ① 把滚动条**藏掉**（留一条 6px 的灰条会让人以为"还得自己拖"，而它也会随自动
      滚动一起动、看起来像在抖）；② `pointer-events` 保留（悬停暂停要靠 :hover 命中）；
   ③ `overflow-x: auto` 保留 —— 它是自动滚动的物理前提，只是用户看不到条。
   ⚠️ 别改成 `overflow: hidden`：那样 scrollLeft 仍可写，但**滚不到末尾**（部分浏览器下
   scrollWidth 计算与 auto 不同），段末停顿的判断会失准。 */
.alert-scroll {
  display: flex; align-items: center; gap: 7px;
  flex: 1 1 auto; min-width: 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* 旧 Edge */
}
.alert-scroll::-webkit-scrollbar { height: 0; display: none; }   /* Chrome / 新 Edge */
.alert-scroll .alert-chip { flex: 0 0 auto; }   /* chip 不参与压缩，否则文字会被挤变形 */
/* 铃铛用 CSS ::before 的 data-uri SVG —— 不动 app.js 的 innerHTML 模板，
   textContent 与 [21] 段的 firstChild 稳定性断言都不受影响。
   flex:0 0 auto：label 固定不滚也不被压缩，异动再多"异动"两个字始终在眼前。
   字重 700→600、色 #633806→#8a5a00：与三条琥珀色提示条同一色系；
   700 的黑棕色在白卡上"压得住"，但与旁边 500 字重的 chips 差三档，过于跳。 */
.alert-label {
  display: inline-flex; align-items: center; gap: 6px;
  flex: 0 0 auto;
  font-size: 12.5px; font-weight: 600; color: var(--amber-ink); letter-spacing: .02em;
}
/* 铃铛 data-uri 里的 stroke 写死 %238a5a00：background-image 引用不了 CSS 变量，
   改 --amber-ink 时要同步改这一处（二轮已对账：两处同值）。 */
.alert-label::before {
  content: "";
  width: 13px; height: 13px; flex: 0 0 13px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%238a5a00' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9a6 6 0 0 1 12 0c0 5 2 6 2 6H4c0 0 2-1 2-6'/%3E%3Cpath d='M10 20a2 2 0 0 0 4 0'/%3E%3C/svg%3E") no-repeat center / contain;
}
/* 2026-10-18 整站统一：12px → 12.5px，与标题行那五颗 .chip 完全同档。
   两者是同一颗东西（淡底 + 名称 600 + 说明 500），此前差半个字号、且都写在
   两个相距 600 行的规则里，谁也看不出是"故意不同的两档"。 */
.alert-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; font-weight: 500; line-height: 1;
  padding: 4px 10px; border-radius: var(--r-pill); white-space: nowrap;
}
.alert-chip .alert-name { font-weight: 600; }
/* 三个等级各自一对"淡底 + 加深字"令牌（二轮从字面量提取：high 的 #a32d2d、
   warn 的 #faf3e0/#8a5a00、info 的 #eef4fb/#185fa5 原本都是散落的硬编码）。 */
.alert-chip.lv-high { background: var(--up-bg); color: var(--up-ink); }
.alert-chip.lv-warn { background: var(--amber-bg); color: var(--amber-ink); }
.alert-chip.lv-info { background: var(--info-bg); color: var(--info-ink); }
/* 方向优先于级别（2026-10-18，用户：跌停应该用绿色）：
   「跌停」原本是 high 级 → 红底红字，和「涨停」**一模一样**，用户第一眼会把
   跌停读成涨 —— 级别色表达的是"多重要"，这里要表达的是"往哪走"，后者更首要。
   三条 lv-* 之后写，同特异性（0,2,0）靠顺序覆盖，不需要 !important。
   只染**下跌**方向（跌停 / 跌超5% / 自定义下穿规则）：
   · 上涨侧沿用级别色 ——「涨停」本来就是红，而「涨超5%」刻意是 info 蓝，
     不让它跟涨停抢同一个红；
   · 振幅 / 放量 / 换手没有方向，保持琥珀与蓝；
   · 自定义规则的 `≥` 也不染，它的 label 已写明条件，颜色留给"提醒强度"。 */
.alert-chip.tone-down { background: var(--down-bg); color: var(--down-ink); }
/* 2026-10-16：`.alert-more`（"+N 更多"）已删除 —— 异动改全量展示 + 横向滚动，
   见 .alert-scroll 一节。类名曾出现在 renderAlerts 的截断分支里，一并移除。 */
/* 标题行计数胶囊（用户 2026-10-16："53 加上背景胶囊，参考半导体 12只"）。
   ⚠️ 旧底色 #edf0f5 与页面背景 --bg(#eef1f6) 只差 1/255，胶囊等于不存在
   （用户截图里"53"白底一颗）。现在与 .grp-count / .chips / 所有控件
   共用全站唯一控件底色 --g4 —— 四处计数胶囊终于是同一颗。
   ⚠️ 标题 h2 已是 flex 容器，vertical-align 对它无效；改用 align-self 保持
   与 20px 标题的视觉基线。 */
.count-badge {
  font-size: 11.5px;
  color: var(--ink-2);
  background: var(--g4);
  border-radius: var(--r-pill);
  padding: 2px 8px;
  align-self: center;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
/* Apple 风格统一控件（2026-10-16 建立，2026-10-17 全站推广）：
   新建分组按钮 + 两个下拉 + 组别筛选共用同一套"灰胶囊"语言 —— 无描边、--g4 底、
   hover 加深一档。**现在这套语言已是全站唯一**：顶栏的搜索框 / 市场状态 /
   通知 / 锁，表格内的换组下拉，弹窗的次级按钮，全部同一族。
   ⚠️ 高度严格相等（uitest [5]④ 实测三控件齐高：新建分组 = 添加至 = 全部组别）
   —— 三者都是 28px，谁改一处必须三处一起改。 */
.btn-sort {
  border: 1px solid transparent;
  background: var(--g4);
  color: var(--ink-2);
  font-size: 12.5px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  padding: 0 14px;
  border-radius: var(--r-pill);
  cursor: pointer;
  transition: background-color .15s, color .15s;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.btn-sort:hover { background: var(--g5); color: var(--ink); }
.btn-sort:active { background: var(--g6); }   /* 二轮：#cfd8e6 → 新令牌 --g6（按压档） */
.btn-sort:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(201, 165, 76, .32); }

/* 「添加至」标签降为 11.5px 弱化小字（它只是两个下拉的说明，不该和控件抢重量） */
.add-group-wrap { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--ink-3); letter-spacing: .02em; }
/* Apple popup-button 风格：appearance:none 去掉系统箭头，自绘 chevron（data-uri SVG），
   右侧留 28px 给箭头。与 .btn-sort 同一灰底语言，height 同样 28px（齐高断言见上）。 */
.sel-inline {
  appearance: none;
  -webkit-appearance: none;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: var(--g4) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6' fill='none' stroke='%235b6478' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E") no-repeat right 11px center;
  color: var(--ink-2);
  font-size: 12.5px;
  height: 28px;
  padding: 0 28px 0 13px;
  cursor: pointer;
  max-width: 140px;
  transition: background-color .15s, color .15s;
}
.sel-inline:hover { background-color: var(--g5); color: var(--ink); }
.sel-inline:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(201, 165, 76, .32); }
/* 组别筛选文案最长（「全部组别（已隐藏 N 组）」）—— 旧 max-width:130 会把它截成
   「全部组别（已隐…」，既是视觉瑕疵也让用户看不出已隐了几组。
   放宽到 230px：375px 窄屏下仍完整在视口内（uitest [17] 断言 btnRight ≤ vw）。 */
#groupFilterSel { max-width: 230px; }

/* ---------- 分组（组头行） ---------- */
tr.grp-row td {
  background: var(--g2);
  padding: 0 12px;
  border-bottom: 1px solid var(--line);
}
tr.grp-row:hover td { background: var(--g3); }
/* 分组「隐藏 / 显示」按钮：眼睛图标（无文字，用户 2026-10-15 要求），
   尺寸与 ↑↓✎× 一致（22px 圆形）。SVG 在 app.js 里已写死 width/height，这里再兜一层。
   「置顶」按钮（2026-10-18）同为"图标按钮、无文字"，共用这套居中方框与 SVG 尺寸 ——
   否则 SVG 默认 inline 基线会把它顶偏 2~3px，与其他按键不齐。 */
.btn-grp-vis,
.btn-grp-top { display: inline-flex; align-items: center; justify-content: center; padding: 0; }
.btn-grp-vis svg,
.btn-grp-top svg { width: 14px; height: 14px; display: block; }
.grp-bar { display: flex; align-items: center; gap: 8px; padding: 7px 0; }
/* 组头名从 700 降到 600：它下面每行的股票名是 600，组头若 700 会比"数据"更响，
   而组头只是分隔标签。600 + 12.5px 与 .chip-nm 同一档，层级才顺。 */
.grp-name { font-weight: 600; font-size: 12.5px; color: var(--ink-2); letter-spacing: .01em; }
/* 2026-10-18 整站统一：11px/400/1×8 + --ink-3 → 11.5px/500/2×8 + --ink-2，
   与标题行的 .count-badge 完全同规格（同一种东西 —— 一个带灰壳的数字）。
   顺带修一档对比度：--ink-3 印在 --g4 上只有 2.3:1，那个"12"在组头行里几乎是虚的。 */
.grp-count {
  font-size: 11.5px; font-weight: 500; color: var(--ink-2);
  background: var(--g4); border-radius: var(--r-pill); padding: 2px 8px;
  font-variant-numeric: tabular-nums;
}
/* 组操作默认隐藏、鼠标进入所在行时才显现 —— 与自选股**行内**操作（↑↓ / 换组 / ×）
   完全同一模式（见下方 .btn-mv / .sel-grp / .btn-del）：表格平时只有数据，指针移到哪一行，
   哪一行的控件才出来。
   `:focus-within` 是给键盘留的口子：Tab 走到按钮时若不显示，键盘用户等于对着隐形控件按回车。
   ⚠️⚠️ 2026-10-17 回归修复：这里原本有**两条** `.grp-ops` 规则（一条管
   margin-left:auto / display:flex / gap / opacity:0，一条管 sticky / max-width:0 零占位）。
   上一轮把它们"合并成一条"时**漏掉了第一条的 4 个属性**，后果是：
   ① 工具栏 no longer 靠右（贴在组名屁股后面，因为丢了 margin-left:auto）；
   ② opacity 恒为 1，uitest 里 9 条「组工具栏默认隐藏 / 收回」断言全红；
   ③ 窄屏横向滚动后按钮跑到视口外（丢了 margin-left:auto + sticky 组合）。
   教训：**合并同一选择器的两处规则前，先把两处的属性并集列出来逐项对照**，
   不能只保留后写的那条的属性。现恢复为完整并集（见下）。 */
/* 窄屏补丁：表格是横向滚动容器，`margin-left:auto` 会把组操作推到**表格**最右端 ——
   页面本身不溢出，但按钮落在视口之外，必须横向滚动才看得见（实测 375 / 768 下三行全部如此，
   等于"入口可见"在窄屏上并不成立）。sticky 把它钉在**可视区**右侧：
   宽屏时与原来一样贴在行尾，一旦横向滚动就始终停在右手边。
   背景取**白色**（与 .table-card 同色）：上方 .btn-grp 已改成灰底无描边按钮，
   灰钮在白条上对比清晰，也与自选股行内「白底行 + 灰按钮」完全一致；
   不取组头行灰（#f2f5fa）是为了避免「灰钮落在灰条上几乎看不见」。
   默认隐藏 + 悬停显现之后这条更要紧：显现的位置必须是**可视区内**，否则"悬停了却看不见按钮"。
   改变 `.table-scroll` 的 scrollLeft 时按钮右缘只应漂移几像素（跟随内容会平移整个 scrollLeft）。
   ── 零占位（用户 2026-10-15：隐藏的编辑工具栏不该占宽度、显得右边一块空白）──
   隐藏态 max-width:0 + overflow:hidden：真·零占位（border-box 下水平 padding 也要归零，
   否则 8px padding 仍占宽），按钮被裁出命中区，不拦任何点击；悬停/:focus-within 时展开到
   176px（≥6×22+5×gap+8padding = 160，留 16px 余量）并恢复 pointer-events。因为 .grp-ops 由 margin-left:auto
   钉在行尾，展开是向左生长，组名不动、无重排。
   ⚠️ 2026-10-18 加「置顶」按钮时踩到的坑：这里原为 150px（按 5 个按钮算），
   第 6 个按钮会被 max-width 裁掉一截（按钮还在、右缘被切）。**加/删组工具栏按钮
   必须同步改这个数**，窄屏那条（@media ≤720px，同为 max-width）也一样。 */
.grp-ops {
  /* 属性并集（短规则 + sticky 规则，缺一不可）：
     - margin-left:auto → 推进到行尾（组名后 → 行右端）
     - display:flex / gap:4px → 6 个按钮横排且留缝
     - opacity:0 / transition → "隐藏"的语义信号（uitest 直接断言等于 0）
     - max-width:0 / overflow:hidden → 真·零占位（不占宽度）
     - sticky / right:8px → 窄屏横向滚动时钉在可视区右侧
     - background:#fff → 与灰底按钮对比清晰（见 .btn-grp 注释） */
  margin-left: auto;
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity .15s;
  position: sticky;
  right: 8px;
  padding: 2px 0;
  border-radius: var(--r-sm);   /* 二轮：7px → --r-sm（8px；7 不在圆角三档里） */
  background: var(--card);
  max-width: 0;
  overflow: hidden;
  pointer-events: none;
}
tr.grp-row:hover .grp-ops,
tr.grp-row:focus-within .grp-ops {
  opacity: 1;
  max-width: 176px;
  padding: 2px 4px;
  pointer-events: auto;
}
/* 组头行工具按钮：与自选股行内的 .btn-mv / .btn-del 同一族 —— 灰底填充、无描边、小圆角。
   旧版是「白底 + 1px 描边」，与全站「灰底填充」控件语言（原则②）冲突；改灰底后
   所在的 .grp-ops 工具条背景同步改成白（见该规则），白底灰钮在浅色组头行上对比清晰，
   也与自选股行的「白底行 + 灰按钮」完全同款。hover 用「灰加深 / 红 tint」而非描边变色。
   ⚠️⚠️ 2026-10-17 二轮：填充 #eef1f6 = 页面底色 --bg，与首轮 .chips/.count-badge
   踩的是同一个坑（"胶囊等于没做"）—— 且首轮明说 --g4 是"全站唯一控件底色"，
   这里却是 #eef1f6：223 个行内控件用页底色、只有 20 个用 --g4。本轮归入 --g4 族，
   悬停 #e2e8f1 → --g5，圆角 6px → --r-sm。 */
.btn-grp {
  width: 22px; height:22px;
  /* 2026-10-18 整站统一：8px 圆角矩形 → 圆形。
     文件头的形状规则写着「圆形 = 纯图标按钮」，而组工具栏这 6 个按钮**只有图标**，
     却用了"圆角矩形"（那是卡片/面板的形）。同一页里行内 ↑↓× 是圆的、组头 ⤒👁✎× 是方的，
     两个 22px 灰按钮并排却是两种形 —— 现在统一成圆形。 */
  border-radius: 50%;
  border: none;
  background: var(--g4);
  color: var(--ink-2);
  font-size: 12px; line-height: 1;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.btn-grp:hover { background: var(--g5); color: var(--ink); }
.btn-grp-del:hover { background: var(--up-bg); color: var(--up-ink); }

/* ---------- 行内操作（换组下拉 + ↑↓ + 移除）----------
   零占位（用户 2026-10-15：与组工具栏同一诉求——隐藏时不占宽度，把空间让给分时列）：
   列宽归零。注意 th/td 的水平 padding 也必须归零——border-box 下 padding 一样占宽。
   控件收进 .op-inner，用**绝对定位浮层**挂在行尾（right:0 向左展开）：
   不能靠流式展开——表格列是所有行共享的，某一行 hover 展开会把整张表的列宽顶宽，
   每一行的分时图都被压缩（还会引起画布缩放失真）。浮层只影响当前行、永远不改列宽。
   隐藏态 pointer-events:none：浮层压在分时图上方，不禁指的话"点分时图"会变成删股票。 */
.quote-table th.th-op { width: 0; padding-left: 0; padding-right: 0; overflow: hidden; }
/* 选择器必须带上 .quote-table td：`.quote-table td{padding:10px 12px}` 特异性 0-1-1，
   单类选择器压不住它，水平 padding 会残留 24px（实测踩到）。 */
.quote-table td.td-op { width: 0; padding-left: 0; padding-right: 0; position: relative; }
.op-inner {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 4px;
  pointer-events: none;
}
tr:hover .op-inner,
tr:focus-within .op-inner { pointer-events: auto; }
.btn-mv {
  width: 22px; height: 22px;
  border-radius: 50%;
  border: none;
  background: var(--g4);   /* 二轮：#eef1f6 → --g4（与 .btn-sort/.sel-inline 同族同色） */
  color: var(--ink-3);
  font-size: 12px; line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: all .15s;
}
tr:hover .btn-mv { opacity: 1; }
/* 2026-10-18 整站统一：悬停从「深藏青实底 + 白字」改成灰底加深一档（--g5 + --ink）。
   深蓝是深色导航栏时代的残留，也是全站唯一一个"图标按钮悬停变深色块"的控件 ——
   旁边的 .btn-grp / .btn-sort / .sel-inline 悬停都只是灰加深一档。 */
.btn-mv:hover { background: var(--g5); color: var(--ink); }
/* 行内「置顶」是图标按钮（与 ↑↓ 的文字符号不同源）：圆形按钮里放 SVG 必须显式居中 + 定尺寸，
   否则 inline 基线会把图标顶偏、且 14px 图标在 22px 圆里不居中。与 .btn-grp-top 同一条规则。 */
.btn-mv-top { display: inline-flex; align-items: center; justify-content: center; padding: 0; }
.btn-mv-top svg { width: 14px; height: 14px; display: block; }
/* 自选股行内「换组」下拉：与旁边 .btn-mv / .btn-del 同一族 —— 灰底填充、无描边、小圆角。
   旧版是「白底 + 1px 描边」，与同 op-inner 里的灰圆钮并在一行时三种控件语言打架。
   原生 select 去边框后靠 OS 箭头；灰底在白行 / 悬停浅灰行上都清晰，且整行控件终于是同一颗。
   二轮：底色 #eef1f6（= 页面底）→ --g4、悬停 #e2e8f1 → --g5、圆角 6px → --r-sm。 */
.sel-grp,
.sel-addgrp {
  border: none;
  /* 下拉 = 文本控件 → 胶囊（形状规则①）。原来是 8px 圆角矩形，与旁边 22px 的
     圆形 ↑↓× 拼在一行时是"圆 + 方 + 圆"；改胶囊后与 .sel-inline / .btn-sort 也是同一形。 */
  border-radius: var(--r-pill);
  background: var(--g4);
  color: var(--ink-2);
  font-size: 11.5px;
  padding: 2px 4px;
  max-width: 92px;
  cursor: pointer;
  opacity: 0;
  transition: opacity .15s, background .15s;
}
tr:hover .sel-grp,
tr:hover .sel-addgrp { opacity: 1; }
.sel-grp:hover,
.sel-addgrp:hover { background: var(--g5); color: var(--ink); }

.table-card {
  background: var(--card);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
}
.table-scroll { overflow-x: auto; }
.quote-table { width: 100%; border-collapse: collapse; min-width: 1020px; }
.quote-table th {
  background: var(--g1);   /* 二轮：#f7f9fc 字面量 → 令牌（值与 --g1 相同） */
  color: var(--ink-2);
  font-size: 12.5px;
  font-weight: 600;
  text-align: right;
  padding: 11px 12px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
  user-select: none;
}
.quote-table th.th-name { text-align: left; }
/* 分时列吃下行内操作列让出的宽度（用户 2026-10-15：让分时图长一些）。
   固定 300px 而非 width:100%：auto 表格布局下百分比会引发「列宽↔canvas 宽」循环、
   max-width 也会被忽略（实测列被顶到 580px），固定值才可预期。canvas 284 = 300-16(padding)。
   重绘由 renderTable 末尾的 drawAllTrends + resize 防抖负责。
   （2026-10-17 曾按用户要求缩到 210px 并把省出的 90px 用 padding 平摊给其余 10 列，
     同日用户要求回滚，已恢复 300px。若以后再次考虑：缩窄会把分时图从 284px 压到 194px。） */
.quote-table th.th-trend { width: 300px; }
.quote-table th.sortable { cursor: pointer; }
.quote-table th.sortable:hover { color: var(--ink); background: var(--g2); }   /* 二轮：#f0f4f9 → --g2 */
.quote-table th.sortable::after { content: ' ⇅'; color: var(--ink-3); font-size: 11px; }
/* 当前排序列显示方向（用户 2026-10-15 删掉「默认顺序」文字按钮后，排序状态的归属地）。
   类由 updateSortIndicator() 维护；纯箭头无文字，伪装态黑名单扫描不受影响。 */
.quote-table th.sortable.asc::after { content: ' ↑'; color: var(--ink); }
.quote-table th.sortable.desc::after { content: ' ↓'; color: var(--ink); }
.quote-table td {
  padding: 10px 12px;
  text-align: right;
  border-bottom: 1px solid var(--line-soft);   /* 二轮：#f0f3f8 → --line-soft */
  font-size: 13.5px;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.quote-table tbody tr { transition: background .12s; }
.quote-table tbody tr:hover { background: var(--g1); }   /* 二轮：#f5f8fc → --g1（令牌注释本就写着"行悬停"归 g1） */
.quote-table tbody tr:last-child td { border-bottom: none; }
.td-name { text-align: left !important; }
.td-name .nm { font-weight: 600; font-size: 14px; }
.td-name .cd { font-size: 11px; color: var(--ink-3); margin-top: 1px; }
.td-price { font-weight: 700; font-size: 15px; }
/* 涨跌幅徽章改全圆角 pill（2026-10-16 Apple 风格延伸）：
   与 idx-pill / alert-chip / chip 统一"彩色数值徽章 = 胶囊"语言，
   旧的 7px 圆角矩形是全页最后一个异类。 */
.pct-badge {
  display: inline-block;
  min-width: 74px;
  text-align: center;
  font-weight: 600;
  font-size: 12.5px;
  padding: 3px 10px;
  border-radius: var(--r-pill);
}
.td-turnover, .td-volratio { color: var(--ink-2); }
.td-amount { color: var(--ink-2); }
.td-trend { padding: 4px 8px !important; }
.td-trend canvas { display: block; width: 100%; height: 30px; }
.btn-del {
  width: 22px; height: 22px;
  border-radius: 50%;
  border: none;
  background: var(--g4);   /* 二轮：#eef1f6 → --g4 */
  color: var(--ink-3);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  opacity: 0;
  transition: all .15s;
}
tr:hover .btn-del { opacity: 1; }
/* 2026-10-18 整站统一：删除键的悬停从「红实底 + 白字」改成「淡红底 + 深红字」——
   与组头的 .btn-grp-del:hover 完全同款（同一个动作在两个位置不该有两种反馈），
   也符合全站"淡底 + 加深字"的语义色用法：实底红是页面里最响的一档，留给「强信号」。 */
.btn-del:hover { background: var(--up-bg); color: var(--up-ink); }
.empty-tip { padding: 44px 20px; text-align: center; color: var(--ink-3); font-size: 13.5px; }

/* 价格闪烁 */
@keyframes tickUp { 0% { background-color: var(--tick-up); } 100% { background-color: transparent; } }
@keyframes tickDown { 0% { background-color: var(--tick-down); } 100% { background-color: transparent; } }
.tick-up { animation: tickUp .9s ease-out; }
.tick-down { animation: tickDown .9s ease-out; }

/* ---------- 页脚 ---------- */
.footer { max-width: 1440px; margin: 0 auto; padding: 20px 24px 30px; }
.footer p { font-size: 12px; color: var(--ink-3); text-align: center; }
/* 页脚分隔符（2026-10-17 用户要求：用元素代替原来的间隔号「·」）
   颜色走 currentColor —— 自动跟随 .footer p 的 --ink-3，将来改字色不用同步改这里；
   opacity .45 让它比文字淡一档（只做分隔，不抢正文注意力）。
   ⚠️ 必须是 inline-block：块级会在 <p> 里被浏览器拆行（<p> 不能含块级元素）。 */
.footer-divider {
  display: inline-block;
  width: 1px;
  height: 10px;
  background: currentColor;
  opacity: .45;
  vertical-align: middle;
  margin: 0 10px;
}

/* ---------- Toast ---------- */
.toast-wrap { position: fixed; right: 22px; bottom: 22px; z-index: 100; display: flex; flex-direction: column; gap: 8px; }
.toast {
  background: var(--toast-bg);
  color: #fff;
  font-size: 13px;
  padding: 10px 18px;
  border-radius: var(--r-md);
  /* 二轮：0 8px 28px rgba(6,15,33,.3) → --sh-pop（(6,15,33) 是首轮点名消除的黑之一） */
  box-shadow: var(--sh-pop);
  animation: toastIn .25s ease-out;
}
.toast-error { background: rgba(176, 34, 34, .94); }
.toast.out { opacity: 0; transform: translateY(6px); transition: all .3s; }
@keyframes toastIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

/* ---------- 响应式 ---------- */
@media (max-width: 1280px) {
  .index-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 860px) {
  .index-grid { grid-template-columns: repeat(2, 1fr); }
  .searchbox input { width: 210px; }
  .clock, .conn { display: none; }
}
/* ============ 手机端适配（≤720px：表格转卡片 + 顶栏堆叠）============
   目标：手机上不再靠横向滚动看 12 列；每只股票变成一张卡片，关键数字
   （最新价/涨跌幅）突出，分时图占满卡宽，操作钮常驻可见（触屏无 hover）。
   断点取 720px：覆盖全部手机（含横屏 740 以内），平板(≥768)仍用可横向滚动
   的表格，避免小笔记本(≤760)被误判成手机。
   列名靠 app.js 写入的 data-label + 下方 ::before 生成，不进 textContent，
   伪装态黑名单扫描不受影响（见文件末尾 html.disguise 块仍按类隐藏）。 */
@media (max-width: 720px) {
  /* 顶栏：品牌一行，右侧控件换行到下一行并占满宽度 */
  .topbar-inner { padding: 10px 14px; gap: 10px; }
  .brand-text h1 { font-size: 17px; }
  .brand-sub { display: none; }            /* 副标题在窄屏让位给搜索框 */
  .topbar-right { width: 100%; gap: 10px; }
  .searchbox { flex: 1 1 100%; }
  .searchbox input { width: 100%; }
  .mkt-status { margin-left: auto; }       /* 市场状态靠右，与通知/锁同排 */

  /* 区段标题与工具组换行：工具组不再死贴右端（margin-left:auto 在窄屏会顶到溢出） */
  .section-head { gap: 8px 12px; margin-bottom: 12px; }
  .watch-tools { margin-left: 0; width: 100%; }
  #groupFilterSel { max-width: 100%; }
  /* 第三页标题行的口径小字：窄屏跟着标题换行后独占一行 */
  .mf-head-right { margin-left: 0; width: 100%; }
  /* 第三页汇总行：胶囊吃满一行，分组按钮折到下一行靠右。
     实测 375~390px 下"按钮与胶囊抢一行"会把「形态观察 11」挤成孤零零的第二行；
     让按钮自己占一行后，5 颗胶囊反而能在一行里排完（总宽 ~316 < 362）。 */
  .mf-summary-row { flex-wrap: wrap; align-items: flex-start; }
  .mf-summary { flex: 1 1 100%; }
  /* 窄屏必须放开统计行的"禁压缩"（桌面那条 `flex: 0 0 auto`）：5 颗胶囊在 375px 下
     一行放不下，禁 shrink 会直接横向溢出，而这里允许折行只是多占一行高度。 */
  .chips { flex: 1 1 auto; }

  /* 指数卡：手机上 2 列（≤540 再由下方规则降到 1 列） */
  .index-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }

  /* 板块网格：3 列在这个宽度下每列只有 ~210px，名称会被压成省略号 → 回 2 列
     （≤540 再由下方规则降到单列）。2026-10-17 从 2 列改 3 列时同步加的这一条。 */
  .sector-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* 表格 → 卡片：取消横向滚动容器，整表变块级 */
  .table-scroll { overflow: visible; }
  .quote-table { min-width: 0; width: 100%; display: block; }
  .quote-table thead { display: none; }     /* 列头在卡片里无意义 */
  .quote-table tbody { display: block; }
  .quote-table tr { display: block; }

  /* 股票数据行 = 一张紧凑卡片（flex-wrap 布局）：
     第 1 行 = 名称(左，自动占满) + 最新价 + 涨跌幅徽章(右)；
     次要指标 = 小字 inline（label 灰 + 数值彩），自动换行成 ~2 行；
     分时图 / 操作钮各占整行。相比「9 行 label:value」每卡高度减半，
     53 只股票时页面不会拉成一万八千 px。 */
  .quote-table tbody tr:not(.grp-row) {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    column-gap: 10px;
    row-gap: 2px;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: var(--sh-card);
    padding: 10px 12px;
    margin-bottom: 10px;
    position: relative;
  }
  .quote-table tbody tr:not(.grp-row):hover { background: var(--card); }  /* 触屏无 hover 底色 */

  .quote-table td {
    display: block;
    width: auto !important;
    padding: 0 !important;
    border: none !important;
    text-align: left !important;
  }

  /* 第 1 行：名称 / 最新价 / 涨跌幅 */
  .quote-table td.td-name { order: 1; flex: 1 1 auto; min-width: 0; }
  .td-name .nm { font-size: 15.5px; }
  .td-name .cd { font-size: 11px; }
  .quote-table td.td-price { order: 2; flex: 0 0 auto; font-size: 16px; font-weight: 700; }
  .quote-table td.td-pct { order: 3; flex: 0 0 auto; }
  /* 第 1 行三格不再重复列名（价格/涨幅本身直观） */
  .quote-table td.td-name::before,
  .quote-table td.td-price::before,
  .quote-table td.td-pct::before { content: none; }

  /* 次要指标：小字 inline，label(灰) + 数值(彩)，自动换行 */
  .quote-table td.td-change,
  .quote-table td.td-open,
  .quote-table td.td-high,
  .quote-table td.td-low,
  .quote-table td.td-amount,
  .quote-table td.td-turnover,
  .quote-table td.td-volratio {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: baseline;
    gap: 3px;
    font-size: 12px;
  }
  .quote-table td.td-change   { order: 4; }
  .quote-table td.td-open     { order: 5; }
  .quote-table td.td-high     { order: 6; }
  .quote-table td.td-low      { order: 7; }
  .quote-table td.td-amount   { order: 8; }
  .quote-table td.td-turnover { order: 9; }
  .quote-table td.td-volratio { order: 10; }
  /* 列名由 app.js 写入的 data-label 经 ::before 生成（不进 textContent） */
  .quote-table td.td-change::before,
  .quote-table td.td-open::before,
  .quote-table td.td-high::before,
  .quote-table td.td-low::before,
  .quote-table td.td-amount::before,
  .quote-table td.td-turnover::before,
  .quote-table td.td-volratio::before {
    content: attr(data-label);
    color: var(--ink-3);
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
  }

  /* 分时图：整行（drawTrend 按 clientWidth 重绘，清晰不拉伸） */
  .quote-table td.td-trend { order: 11; flex: 1 1 100%; padding: 6px 0 2px !important; }
  .td-trend canvas { width: 100% !important; height: 30px; }

  /* 操作钮：整行、触屏常驻可见（无 hover → 直接显示） */
  .quote-table td.td-op {
    order: 12;
    flex: 1 1 100%;
    padding-top: 7px !important;
    margin-top: 5px;
    border-top: 1px solid var(--line-soft) !important;
  }
  .op-inner {
    position: static !important;
    transform: none !important;
    opacity: 1 !important;
    pointer-events: auto !important;
    flex-wrap: wrap;
    gap: 6px;
    justify-content: flex-end;
  }
  .btn-mv, .sel-grp, .sel-addgrp, .btn-del { opacity: 1 !important; pointer-events: auto !important; }
  .sel-grp, .sel-addgrp { max-width: 130px; }

  /* 组头行：独立分组标题条 */
  .quote-table tr.grp-row td {
    display: block;
    background: var(--g2);
    border-radius: var(--r-sm);
    padding: 8px 12px !important;
    margin-bottom: 8px;
  }
  /* 组工具栏在触屏常驻可见（无 hover/focus 触发）。
     宽度口径与桌面一致：6 个按钮 = 160px，留余量 176（加按钮要同步改）。 */
  .grp-ops {
    opacity: 1 !important;
    max-width: 176px !important;
    padding: 2px 4px !important;
    pointer-events: auto !important;
    position: static !important;
    margin-left: 0 !important;
    background: transparent !important;
  }
  .grp-bar { flex-wrap: wrap; padding: 4px 0; }
}

/* ---------- ≤720px：主力行为表 → 卡片（与自选股同一套手机语言） ----------
   为什么必须做：这张表 9 列、min-width 880px，手机视口只有 390px。不做自适应就是
   "整页被裁或要横着拖"，与 [16] 定下的「手机端不横向滚动」直接冲突
   （2026-10-18 实测：面板 362px / 表 880px）。
   布局照抄自选股卡片的思路：第 1 行 = 名称 + 阶段 + 现价，
   其余六个指标排成**两列三行**的键值对（2026-10-19 收敛，首版是自动换行 → 位置漂移），
   列名由 app.js 写的 data-label 经 ::before 生成（不进 textContent，[19] 文案扫描不受影响）。 */
@media (max-width: 720px) {
  .mf-table { min-width: 0; width: 100%; display: block; }
  .mf-table thead { display: none; }
  .mf-table tbody { display: block; }
  .mf-table tr { display: block; }
  .mf-table tbody tr[data-code] {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    column-gap: 12px;
    row-gap: 7px;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    box-shadow: var(--sh-card);
    padding: 10px 12px;
    margin-bottom: 10px;
  }
  .mf-table tbody tr[data-code]:hover { background: var(--card); }
  /* ⚠️ 第一行之后强制换行（2026-10-19）。`::after` 是一个零高、占满整行的
     flex item —— 没有它就会出现"信号 —"被塞进第一行右缘的病：
     flex-wrap 只在**放不下**时才换行，而名称那格是 flex:1、可以无限压小，
     于是第一行永远"放得下"下一个指标。order 必须排在 阶段/现价 之后、
     指标（5 起）之前，同一个 order 值不行（DOM 里 ::after 在最后）。 */
  .mf-table tbody tr[data-code]::after {
    content: '';
    order: 4;
    flex: 0 0 100%;
    height: 0;
  }
  .mf-table td {
    display: block;
    width: auto !important;
    padding: 0 !important;
    border: none !important;
    text-align: left !important;
    white-space: normal;
    min-width: 0;
  }
  .mf-table td.mf-name { order: 1; flex: 1 1 auto; }
  .mf-table td.mf-td-stage { order: 2; flex: 0 0 auto; }
  .mf-table td.mf-price { order: 3; flex: 0 0 auto; align-self: center; }
  /* 次要指标 = **两列固定网格**（flex-basis 50%），六个指标正好 3 行 × 2 列：
     信号 | 资金温度 ／ 大单持续 | 5日净流入 ／ 量价 | 距箱顶。
     首版是"能塞几个塞几个"的 inline-flex，标签与数值间距 3px、相邻两组间距 10px
     只差 7px，"5日净流入 +8.40% 量价 吸货背离 距箱顶 +4.86%"会被连读成四个并列项 ——
     **位置不固定就是"数据错乱"**。固定两列后每行两项、列起点是两条竖线。
     ⚠️ 值**不做**右对齐（不用 space-between）：左列的值会被推到列右缘，与右列
     label 只隔 12px，"信号 —  资金温度" 会被连读成一组。标签紧邻值 + 列起点固定，
     配对关系靠"组内 6px / 组间 ≥12px 的空白"区分，比两端对齐更不会误读。 */
  .mf-table td.mf-td-sig,
  .mf-table td.mf-td-temp,
  .mf-table td.mf-td-persist,
  .mf-table td.mf-td-big,
  .mf-table td.mf-td-vs,
  .mf-table td.mf-td-box {
    flex: 0 0 calc(50% - 6px);
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    font-size: 12px;
  }
  .mf-table td.mf-td-sig { order: 6; }
  .mf-table td.mf-td-temp { order: 7; }
  .mf-table td.mf-td-persist { order: 8; }
  .mf-table td.mf-td-big { order: 9; }
  .mf-table td.mf-td-vs { order: 10; }
  .mf-table td.mf-td-box { order: 11; }
  /* 「动作」列在手机上**独占一行**（2026-10-20）：它是每张卡片的结论，
     塞进两列网格会变成第 7 个指标、落单在第四行左格，读起来像"又一个数据"。
     独占整行 + 紧跟第一行（order 5，在 ::after 换行之后、指标之前），
     视觉上就是"这只票的结论"。标签走 ::before，与其它指标同源。 */
  .mf-table td.mf-td-act {
    order: 5;
    flex: 0 0 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    margin: 1px 0 2px;
  }
  .mf-table td.mf-td-act::before {
    content: attr(data-label);
    flex: 0 0 auto;
    color: var(--ink-3);
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
  }
  /* 值容器（目前只有大单持续用到）：数字与进度条作为一个整体，不被 flex 拆开 */
  .mf-table .mf-val { display: inline-flex; align-items: center; gap: 6px; }
  /* 桌面端 .mf-persist 靠自己的 margin-right 留 6px；这里已有 gap，别叠成 12px */
  .mf-table .mf-val .mf-persist { margin-right: 0; }
  /* 窄屏两列各约 150px，46px 的进度条会把「大单持续 7/10 ▬」顶出格子 */
  .mf-table .mf-mini { width: 38px; }
  .mf-table td.mf-td-sig::before,
  .mf-table td.mf-td-temp::before,
  .mf-table td.mf-td-persist::before,
  .mf-table td.mf-td-big::before,
  .mf-table td.mf-td-vs::before,
  .mf-table td.mf-td-box::before {
    content: attr(data-label);
    flex: 0 0 auto;              /* 标签永不压缩：挤的时候先挤值 */
    color: var(--ink-3);
    font-size: 11px;
    font-weight: 500;
    white-space: nowrap;
  }
  /* 组头行（2026-10-19 第三页按自选股分组）：与第一页手机的组头条同款。
     ⚠️ 必须在这里重写一遍：上面的 `.mf-table td { padding:0 !important;
     border:none !important }` 是 !important，会把桌面端 tr.grp-row 的灰底和
     内边距一起抹掉（特异性再高也压不过 !important）。 */
  .mf-table tr.grp-row { margin-bottom: 8px; }
  .mf-table tr.grp-row td {
    display: block;
    background: var(--g2);
    border: none !important;
    border-radius: var(--r-sm);
    padding: 8px 12px !important;
    white-space: normal;
  }
  .mf-table tr.grp-row .grp-bar { flex-wrap: wrap; padding: 4px 0; }
  /* 口径说明已挪到标题的悬停提示（2026-10-18），窄屏不再吃 5 行高度 */
  .mf-summary-row { gap: 8px; }
  .mf-summary { gap: 6px; }
  .mf-chip { font-size: 11.5px; }
}

@media (max-width: 540px) {
  .index-grid { grid-template-columns: 1fr; }
  .topbar-inner { padding: 10px 14px; }
  .container { padding: 16px 14px 8px; }
  /* ⚠️ 这里原来写的是 `.searchbox { flex: 1 }` —— 但 720 段已经把 .searchbox 设成
     `flex: 1 1 100%`（独占一行），540 段的 `flex:1` 会把它压回「与状态/锁/通知同一行」，
     320px 下搜索框只剩 ~40px，占位字被裁成「搜」。改成不覆盖宽度，让它继续独占整行。 */
  .searchbox { flex: 1 1 100%; }
  .searchbox input { width: 100%; }
  /* 板块网格：430px 下两列每列仅 ~190px，「AI算力 + ▼-5.46%」会被压到省略号，
     改单列（2026-10-17）。 */
  .sector-grid { grid-template-columns: 1fr; }
  .sector-item { padding: 12px 14px; }
}

/* ============ 深色模式（2026-10-21）============
 * 用户要求「整站适配黑暗模式，按钮放在顶部通知右边」。
 * 做法：**只覆盖 :root 的令牌**，不逐条重写规则 —— 全站配色在 2026-10-17 那两轮重构里
 * 已经收敛到这三十来个令牌，覆盖它们等于整站换肤；逐条改规则将来必与重构打架。
 * 没走令牌的硬编码只剩 12 处，在第二小节按选择器列清（不需要改的也一并列出，避免重复劳动）。
 *
 * 四条必须同时成立的约束（少一条就是"局部发白 / 字看不见"的经典症状）：
 *   ① --bg 与 --card 的**亮度方向不能反**：浅色是"灰底 + 白卡"（卡比底亮 17 阶），
 *      深色仍要保持"卡比底亮"，只是整体压暗（底 #0e1218 / 卡 #171d26，差 9 阶）。
 *      把 --card 做成比 --bg 更暗是很多人会写错的版本 —— 卡片边界消失、整页糊成一团灰。
 *   ② --up/--down 必须提亮：原 #d93025 / #0a9d5a 是照白底算的，印在 #0e1218 上
 *      对比度只有 3.3:1 / 3.1:1，12px 小字发虚 → 深色档用 #ff5f5f / #2ecc8f（约 6.4:1 / 7.1:1）。
 *      **涨红跌绿的语义一个字不动** —— 那是中国股市约定，与明暗无关。
 *   ③ 所有"淡底 + 深字"的语义对（--up-bg/--up-ink、--amber-bg/--amber-ink、
 *      --gold-tint/--gold-ink、--info-bg/--info-ink）**必须成对反相**：
 *      浅色是"浅底 + 加深字"，深色要变成"深底 + 提亮字"。只翻底不翻字 = 字直接消失
 *      （深金字 #7d6219 印在 #33280f 上只有 1.6:1）。同理 --g1~--g6 也是方向反相、顺序不变。
 *   ④ 阴影必须换纯黑并加重：rgba(15,22,36,.04~.24) 在深底上等于没有，卡片与浮层的层次全丢。
 *
 * ⚠️ 本段必须写在文件末尾 `html.disguise` 段**之前**。两者特异性都是 (0,1,1)
 *    （html + 类 / html + 属性），同级比的是先后顺序：暗色段若排在后面，
 *    同时开"伪装态 + 深色"时 --up/--down 会被这里的红绿盖回去，伪装当场失效。
 *    伪装态在深色下的正确性**不靠另写一份**，靠"它引用的 --ink-2 / --flat-bg 已被本段改过"。
 * ⚠️ **故意不跟 prefers-color-scheme**：默认跟随系统会让"默认深色"的设定随对方系统漂移。
 *    默认值由我们自己定：**默认深色**，用户在按钮上点过之后记住他的选择
 *    （2026-10-21 五版；四版短暂试过"默认浅色 + 不记忆"，已按用户更正改回并恢复记忆）。
 *    约定：localStorage 里**没有** 'ashare.theme' 键 = 默认深色；值为 'light' = 用户选了浅色。
 *    这条约定 index.html 的 <head> 脚本与 app.js 的 setTheme **两处必须一致**（那边判的是 !== 'light'）。
 *    ⚠️ 那段脚本必须放在样式表**之前**：默认是深色，写晚了浏览器会先按浅色画一帧再变黑，就是白闪。
 * ⚠️ `color-scheme: dark` 不能省：它让原生控件（滚动条 / select 下拉 / 输入框自动填充）
 *    一起变深，漏了它会在深色页面上挂一条纯白滚动条。 */
html[data-theme="dark"] {
  color-scheme: dark;

  /* 底与卡：卡仍比底亮（约束①） */
  --bg: #0e1218;
  --card: #171d26;
  --ink: #e8ecf3;
  --ink-2: #a7b0c0;
  --ink-3: #74808f;
  --line: #262e3a;
  --line-soft: #1e242e;

  /* 灰阶五档（约束③：方向反相、语义不变） */
  --g1: #1c222c;   /* 表头底 / 行悬停 */
  --g2: #202733;   /* 组头行 */
  --g3: #0e1218;   /* 页面底（= --bg） */
  --g4: #232a35;   /* 控件填充 */
  --g5: #2c3441;   /* 控件悬停 */
  --g6: #37404e;   /* 控件按压 */

  /* 涨跌（约束②）：色相不动，只提亮度 */
  --up: #ff5f5f;
  --up-bg: #3a1d1e;
  --up-ink: #ffa3a3;
  --down: #2ecc8f;
  --down-bg: #12332a;
  --down-ink: #6de9b8;
  --flat: #8b94a5;
  --flat-bg: #262e3a;

  /* 品牌金：金在深底上本身够醒目，只微提亮。
     --on-gold 保持不变 —— .mbtn.primary 的底仍是实心金，深字才是对的。 */
  --gold: #d4b463;
  --gold-tint: rgba(201, 165, 76, .20);
  --gold-ink: #e3c887;
  --on-gold: #2b2109;

  /* 三条提示条的语义对（约束③） */
  --amber-bg: #33280f;
  --amber-ink: #f0c96b;
  --info-bg: #17263d;
  --info-ink: #82bcf3;

  /* 前景半透明层：遮罩更重；toast 必须与深底拉开亮度差
     —— 原来的深蓝 toast（rgba(13,31,60,.92)）放在 #0e1218 上会直接融进背景。 */
  --topbar-bg: rgba(14, 18, 24, .86);
  --mask: rgba(0, 0, 0, .62);
  --toast-bg: rgba(42, 50, 62, .96);
  /* 跳动闪现：22% 在深底上几乎看不见，提到 32% */
  --tick-up: rgba(255, 95, 95, .32);
  --tick-down: rgba(46, 204, 143, .32);
  /* 分时图昨收虚线：原 rgba(120,130,150,.5) 在 #0e1218 上几乎与底色同亮度 */
  --trend-ref: rgba(160, 172, 192, .55);

  /* 阴影（约束④） */
  --sh-card: 0 1px 2px rgba(0, 0, 0, .32), 0 4px 16px rgba(0, 0, 0, .28);
  --sh-card-hover: 0 2px 4px rgba(0, 0, 0, .38), 0 10px 28px rgba(0, 0, 0, .40);
  --sh-tab: 0 1px 2px rgba(0, 0, 0, .40);
  --sh-pop: 0 8px 32px rgba(0, 0, 0, .55);
  --sh-modal: 0 24px 64px rgba(0, 0, 0, .66);
}

/* ---- 深色下需要单独改的 3 处硬编码 ----
 * 其余 9 处硬编码**逐条核对过，不需要**深色版本，列在这里省得以后重复排查：
 *   · #34d399 / #f87171（.mkt-status.open / .conn 的状态点）：本身是亮色，深底上更清楚；
 *   · rgba(201,165,76,.18~.32) 一组金色 focus 环 + .mf-retry:hover：金在深底上更醒目；
 *   · @keyframes rowFlash 的 rgba(201,165,76,.22)：同上（注意 keyframes 里不能按主题覆盖）；
 *   · .toast 的 color:#fff：深色 --toast-bg 是 #2a323e，白字对比度 11:1；
 *   · 6 处 #fff 底色（modal-input / rule-sel / grp-ops / 搜索框与下拉 / modal-card）
 *     已直接改成 var(--card)，浅色取值不变（--card 就是白），不再有裸值可漏。
 * 剩下这 3 处都是"半透明淡底印在淡底上"或"实心彩底印白字"，令牌化收益太小，就地覆盖。 */
html[data-theme="dark"] .wl-warn code { background: rgba(255, 120, 120, .16); }
html[data-theme="dark"] .auth-err code { background: rgba(240, 201, 107, .16); }
/* .mf-sig.mf-s-strong 是"实心 --up 底 + 白字"：浅色下 #d93025 配白字 4.6:1 合格；
   深色把 --up 提到 #ff5f5f 后白字掉到 3.1:1，而它还是 11px 小字 → 改深字（8.6:1）。 */
html[data-theme="dark"] .mf-sig.mf-s-strong { color: #2a1010; }

/* ============ 伪装模式（老板键：F2 或双击页头 logo 切换）============
 * 用途：办公场合一键把页面变成"普通数据表格"，再按一次还原。
 * 做法不是逐个元素打补丁，而是覆盖 :root 里的两个涨跌色变量 —— 所有引用处
 * （涨跌文字、百分比徽章底色、卡片左边框、异动 chip）一次性失去"涨红跌绿"语义。
 * 规则放在文件末尾 + 用 html.disguise 提高特异性，确保压过 :root 的定义。 */
html.disguise {
  --up: var(--ink-2);        /* 与 --ink-2 同色系：数字还在，但没有涨跌信号。
                                二轮：#5b6472 字面量 → var(--ink-2)（#5b6478，此前是第二只"灰字"） */
  --down: var(--ink-2);
  --up-bg: var(--flat-bg);   /* 二轮：#eef1f5 → var(--flat-bg)（#eef1f6，差 1/255 的第二只） */
  --down-bg: var(--flat-bg);
}
html.disguise .indices-section { display: none; }    /* 指数卡片（上证指数 3692.65）最扎眼 */
html.disguise .chips { display: none; }              /* 「上涨 0 下跌 6 领跌 数码科技 -7.03%」 */
/* 幻灯片切换控件与板块页（2026-10-17）：板块页整页都是行业词（军工/半导体/创新药/低空经济），
   伪装态必须整块藏掉；app.js 的 applyDisguise 还会把当前页钉回自选股页，
   否则 transform 停在 -100% 会让"只剩一个 panel"的轨道显示成空白。 */
html.disguise .slide-tabs { display: none; }
html.disguise #panelSector { display: none; }
/* 主力行为页（2026-10-18）：整页都是「主力/吸货/派发/箱体」这类行情词，比板块页更露。
   与 #panelSector 同一条规则族；app.js 的 applyDisguise 还会把当前页钉回自选股页。 */
html.disguise #panelMainforce { display: none; }
html.disguise .alert-list { display: none; }         /* 逐条异动：「数码科技 跌超5%」 */
html.disguise .footer { display: none; }             /* 数据来源 / 非投资建议 */
html.disguise .th-trend, html.disguise .td-trend { display: none; }  /* 分时走势图 */
html.disguise .td-name .nm { display: none; }        /* 名称藏起，只留代码（看起来像编号）*/
html.disguise .section-note { visibility: hidden; }  /* 「行情每秒自动刷新」 */
/* 页头 logo：金牛 ↔ 中性列表图。与 swapFavicon()（标签页图标）同一个理由 ——
   老板键切过去而屏幕正中央挂一头金牛最扎眼；favicon 管标签栏，这里管页面内。
   两个 svg 都在静态 HTML 里（index.html .brand-mark），纯 CSS 切换、不依赖 JS。 */
html.disguise .brand-mark .mark-bull { display: none; }
html.disguise .brand-mark .mark-list { display: block; }
/* 估值页（2026-10-21）：整页都是「高估 / 低估 / 合理 / PE / PB」这类词，
   比主力行为的「吸货 / 派发」更直接 —— 与 #panelSector / #panelMainforce 同一条规则族。
   app.js 的 applyDisguise 同样把当前页钉回自选股页。 */
html.disguise #panelValuation { display: none; }
/* 持仓页（2026-10-21）：**比估值页更该藏**。估值暴露的是"我在研究什么"，
   持仓暴露的是"我有多少钱、赚了多少"—— 这是全站最敏感的一页。
   ⚠️ 整条 .slide-tabs 在伪装态已被隐藏（上面那条），所以 tab 按钮不会露字；
      剩下唯一的破绽是"用户上一次停在第五页、刷新后直接显示"——
      app.js 的 applyDisguise 里那句 `if (slideIndex !== 0) slideTo(0, true)`
      就是为它准备的（对所有页生效，不需要为持仓单独写）。 */
html.disguise #panelHoldings { display: none; }

/* ============ 第四页 · 估值：窄屏卡片（2026-10-21）============
 * 主力行为的窄屏卡片（上面 @media 720 那段）挂在 `tbody tr[data-code]` 上，
 * 且每格靠 .mf-td-stage / .mf-td-sig 这类专属类拿 order —— 估值页的格子类名不同，
 * 套不上。所以这里写一段自己的，**结构照抄**：第一行 = 名称 + 类型 + 现价，
 * 第二行独占 = 结论，其余六个指标排两列三行。
 * ⚠️ 放在文件末尾是有意的：上面 `.mf-table td { padding:0 !important; border:none !important }`
 *    是 !important，桌面端的 .val-table 规则压不过；这里只用更高特异性的选择器覆盖行为，
 *    不去和 !important 对抗（对抗就要再加 !important，下一轮就没人收得住）。
 * ⚠️ 列名走 ::before + data-label，与主力行为同一手法：不进 textContent，
 *    uitest 的文案扫描面不受影响。 */
@media (max-width: 720px) {
  .val-table { min-width: 0; width: 100%; display: block; }
  .val-table thead { display: none; }
  .val-table tbody { display: block; }
  .val-table tr { display: block; }
  .val-table tbody tr.val-row {
    display: flex; flex-wrap: wrap;
    align-items: flex-start; column-gap: 12px; row-gap: 7px;
    background: var(--card); border: 1px solid var(--line);
    border-radius: var(--r-md); box-shadow: var(--sh-card);
    padding: 10px 12px; margin-bottom: 10px;
  }
  .val-table td {
    display: block; width: auto !important; padding: 0 !important;
    border: none !important; text-align: left !important;
    white-space: normal; min-width: 0;
  }
  .val-table td.mf-td-name { order: 1; flex: 1 1 auto; }
  .val-table td.val-td-type { order: 2; flex: 0 0 auto; }
  .val-table td.val-td-price { order: 3; flex: 0 0 auto; align-self: center; }
  /* 零高、占满整行的 flex item —— 强制第一行只放 名称/类型/现价 三样。
     没有它，名称格是 flex:1 可无限压小，第一行永远"放得下"下一个指标。 */
  .val-table tbody tr.val-row::after { content: ''; order: 4; flex: 0 0 100%; height: 0; }
  /* 结论 + 区间**各占一整行**，紧接第一行 —— 这两条是这张卡片"是什么 + 值多少"，
     是结果不是指标。区间尤其不能进两列：三个价格（"46.3 / 62.7 / 71.7"）在半栏
     160px 里会被折成两行，数字断在斜杠中间。 */
  .val-table td.val-td-sig {
    order: 5; flex: 0 0 100%;
    display: flex; align-items: center; gap: 8px; font-size: 12px;
  }
  .val-table td.val-td-range {
    order: 6; flex: 0 0 100%;
    display: flex; align-items: center; gap: 8px; font-size: 12px;
  }
  .val-table td.val-td-met,
  .val-table td.val-td-peer,
  .val-table td.val-td-hist,
  .val-table td.val-td-qual,
  .val-table td.val-td-conf {
    flex: 0 0 calc(50% - 6px);
    display: flex; align-items: center; justify-content: flex-start;
    gap: 8px; font-size: 12px;
  }
  .val-table td.val-td-met { order: 7; }
  .val-table td.val-td-peer { order: 8; }
  .val-table td.val-td-hist { order: 9; }
  .val-table td.val-td-qual { order: 10; }
  .val-table td.val-td-conf { order: 11; }
  .val-table td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 auto;                 /* 标签永不压缩：挤的时候先挤值 */
    color: var(--ink-3); font-size: 11px; font-weight: 500; white-space: nowrap;
  }
  /* 组头行：上面 `.mf-table td` 的 !important 会把桌面端 tr.grp-row 的灰底与内边距抹掉，
     必须在同一层重写（与主力行为那段同一条理由、同一段写法）。 */
  .val-table tr.grp-row { margin-bottom: 8px; }
  .val-table tr.grp-row td {
    display: block; padding: 7px 10px !important;
    background: var(--g2); border-radius: var(--r-sm); border: none !important;
  }
}


/* ============ 第五页 · 持仓（2026-10-21）============
 * 视觉规格全部复用主力行为/估值：表体 .mf-table、名称格 .mf-name > .nm/.cd、
 * 汇总胶囊 .mf-chip、空态 .empty-tip。这里只新增四样：
 *   ① 数值列表头右对齐（.hold-num）  ② 汇总条间距（.hold-summary）
 *   ③ 未取到价的提示条（.hold-warn） ④ 行内「改 / 删」小按钮（.hold-op）
 *
 * ⚠️ 配色纪律（与估值页相反的一条）：这里的红绿是**真的涨跌**，不是"位置高低"。
 *    盈亏为正用 --up、为负用 --down，与自选股表同源 —— 全站只有一种红绿语义。
 *    淡底上当字用时一律换 -ink 档（--up-ink / --down-ink），理由见 .mf-chip 那段注释。
 */
/* 10 列。名称 170px + 8 个数值列 + 操作列，实测下限 940px；
   比主力行为（970）窄一点，因为这里没有徽标（阶段/信号/量价都是标签列）。 */
.hold-table { min-width: 940px; }
.hold-table th.hold-num,
.hold-table td.hold-num { text-align: right; }
/* 数值列宽让给内容：股数最长（百万股），成本价次之。
   ⚠️ 只给 th 设宽度（表格布局下 th 定宽即列定宽），td 不写 —— 两边都写会打架。 */
.hold-table th.hold-num:nth-child(4) { width: 76px; }   /* 股数 */
.hold-table th.hold-th-op { width: 62px; }
.hold-summary { margin: 0 0 12px; }

/* 金额类数字统一 tabular-nums：等宽数字在右对齐时竖列才对得齐，
   否则 1,234 与 888 的个位会差半个字符宽（这是"看起来乱"的真实原因）。 */
.hold-num { font-variant-numeric: tabular-nums; }

/* 未取到价 / 停牌的提示条。琥珀而不是红 —— 它不是故障，是"这几只暂时没有效报价"，
   红色会让用户以为亏了。与令牌错误条同一条色阶选择（见 .wl-warn 上方的注释）。 */
.hold-warn {
  margin: 0 0 12px;
  padding: 9px 13px;
  background: var(--amber-bg);
  color: var(--amber-ink);
  border-radius: var(--r-md);
  font-size: 12.5px;
  line-height: 1.55;
}
.hold-warn.hidden { display: none; }

/* 行内操作：改 / 删。做成**悬停才出现**（桌面），手机端常驻 ——
   常驻会把 10 列挤成 11 列，而这两个动作的使用频率远低于"看一眼盈亏"。
   ⚠️ 不用 display:none 藏：那会让键盘用户 Tab 不进去。用 opacity + pointer-events。 */
.hold-op {
  display: inline-flex; align-items: center; gap: 4px;
  opacity: 0; transition: opacity .15s;
}
.hold-row:hover .hold-op,
.hold-op:focus-within { opacity: 1; }
.hold-op-btn {
  border: none; background: transparent; cursor: pointer;
  padding: 3px 5px; border-radius: var(--r-sm);
  font: inherit; font-size: 12px; color: var(--ink-3);
}
.hold-op-btn:hover { background: var(--g3); color: var(--ink); }
.hold-op-btn.hold-op-del:hover { background: var(--up-bg); color: var(--up-ink); }
/* 停牌行：价格与当日盈亏都是"没有变化"，整行压暗以示"这一行不是实时数据"。
   ⚠️ 压暗的是**权重**不是可见度：opacity 低于 .55 会让成本/盈亏看不清，
      而这两个数恰恰是用户要看的。 */
.hold-row.is-suspended td { color: var(--ink-3); }
.hold-row.is-suspended .hold-tag {
  display: inline-block; margin-left: 5px;
  padding: 1px 5px; border-radius: var(--r-pill);
  background: var(--flat-bg); color: var(--ink-3);
  font-size: 10.5px; font-weight: 600;
}

/* 新增/编辑表单：两列网格（代码 + 股数 / 成交价 + 费用），备注独占整行。
   ⚠️ 用 grid 不用 flex-wrap：flex 在"标签文字长度不同"时两列起点会对不齐
      （「股数」两字 vs 「买入费用」四字），而表单对齐是"能不能一眼扫完"的关键。 */
.hold-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin-top: 4px;
}
.hold-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.hold-field > span { font-size: 12px; color: var(--ink-3); font-weight: 500; }
.hold-field-full { grid-column: 1 / -1; }
/* 手机/窄弹窗：单列。440px 是弹窗自身的宽度上限，两列各剩 ~180px 时
   「买入费用」这个标签会被压断成两行。 */
@media (max-width: 520px) {
  .hold-form { grid-template-columns: 1fr; }
}

/* ============ 第五页 · 持仓：窄屏卡片（2026-10-21）============
 * 结构照抄主力行为/估值：第一行 = 名称 + 涨跌幅 + 现价，
 * 第二行独占 = 持仓盈亏（这张卡的结论），其余六个指标两列三行。
 * ⚠️ 依赖 .mf-table 在 @media 720 里的 `tr[data-code]` 卡片化规则（同一段），
 *    所以下面的 selectors 必须是 .hold-table 前缀 + 更高特异性，不去改那段公共规则。
 * ⚠️ 「当日盈亏」与「持仓盈亏」是两个不同的数，卡片上**绝不能合并**：
 *    一个是今天的、一个是建仓以来的，混成一个数字就再也分不开了。 */
@media (max-width: 720px) {
  .hold-table { min-width: 0; width: 100%; display: block; }
  .hold-table thead { display: none; }
  .hold-table tbody { display: block; }
  .hold-table tr { display: block; }
  .hold-table tbody tr.hold-row {
    display: flex; flex-wrap: wrap;
    align-items: flex-start; column-gap: 12px; row-gap: 7px;
    background: var(--card); border: 1px solid var(--line);
    border-radius: var(--r-md); box-shadow: var(--sh-card);
    padding: 10px 12px; margin-bottom: 10px;
  }
  .hold-table tbody tr.hold-row:hover { background: var(--card); }
  .hold-table td {
    display: block; width: auto !important; padding: 0 !important;
    border: none !important; text-align: left !important;
    white-space: normal; min-width: 0;
  }
  .hold-table td.mf-name { order: 1; flex: 1 1 auto; }
  .hold-table td.hold-td-chg { order: 2; flex: 0 0 auto; align-self: center; font-size: 12px; }
  .hold-table td.hold-td-price { order: 3; flex: 0 0 auto; align-self: center; }
  /* 零高、占满整行的 flex item —— 强制第一行只放 名称/涨跌幅/现价。 */
  .hold-table tbody tr.hold-row::after { content: ''; order: 4; flex: 0 0 100%; height: 0; }
  /* 持仓盈亏 + 盈亏率**同占一行**（order 5）：它们是同一个结论的两种表述（钱 / 百分比），
     拆到两行会让人以为其中一个是别的指标。 */
  .hold-table td.hold-td-pnl { order: 5; flex: 0 0 100%; display: flex; align-items: center; gap: 10px; font-size: 13px; }
  /* 其余五个指标两列网格。当日盈亏**单独一格**，不跟持仓盈亏并排。 */
  .hold-table td.hold-td-shares,
  .hold-table td.hold-td-cost,
  .hold-table td.hold-td-mv,
  .hold-table td.hold-td-day {
    flex: 0 0 calc(50% - 6px);
    display: flex; align-items: center; justify-content: flex-start;
    gap: 8px; font-size: 12px;
  }
  .hold-table td.hold-td-shares { order: 6; }
  .hold-table td.hold-td-cost { order: 7; }
  .hold-table td.hold-td-mv { order: 8; }
  .hold-table td.hold-td-day { order: 9; }
  .hold-table td.hold-td-op { order: 10; flex: 0 0 100%; display: flex; justify-content: flex-end; }
  .hold-table td[data-label]::before {
    content: attr(data-label);
    flex: 0 0 auto;
    color: var(--ink-3); font-size: 11px; font-weight: 500; white-space: nowrap;
  }
  /* 手机上操作按钮**常驻**：没有 hover 这回事（触摸设备），藏起来等于删掉了功能。 */
  .hold-op { opacity: 1; }
}
