/*
 * 三栏工作台的样式。颜色一律引用 design-tokens.css，本文件不写颜色字面量。
 *
 * 只用三个有色令牌：--accent 表示「当前选中」与链接，--up / --down 表示涨跌与
 * 通过/排除。其余全部灰阶。控制台那版铺了八个强调色家族，结果是到处都在喊、
 * 于是没有地方在喊——设计稿点名要把它收回到「1 个强调色 + 2 个语义色」。
 *
 * 断点沿用令牌文件里的约定值 1200 / 900 / 600（媒体查询用不了变量）。
 */

* { box-sizing: border-box; }

html, body {
    margin: 0;
    height: 100%;
    background: var(--bg);
    color: var(--ink);
    font-family: var(--font-ui);
    font-size: var(--fs-body);
    line-height: 1.55;
}

.desk {
    display: grid;
    grid-template-columns: 208px minmax(0, 1fr) 360px;
    /* 100% 而不是 100vh：外壳把这一页放进一个 `inset: 2.6rem 0 0` 的 iframe，
       用视口高度会正好多出一个顶栏的高度、把底部推出可视区。独立打开时
       html/body 已经是 height:100%，两种场合都成立。 */
    height: 100%;
    overflow: hidden;
}

.col {
    min-width: 0;
    min-height: 0;
    overflow-y: auto;
}

.col-nav {
    background: var(--surface);
    border-right: 1px solid var(--line);
    display: flex;
    flex-direction: column;
    gap: var(--sp-4, 16px);
    padding: 14px 12px;
}

/* —— 左栏 —— */

.brand { display: flex; flex-direction: column; gap: 2px; padding: 0 6px; }
.brand-name { font-size: var(--fs-h1, 15px); font-weight: 600; letter-spacing: .01em; }
.brand-sub { font-size: 11px; color: var(--muted); font-family: var(--font-mono); }

.nav-group { display: flex; flex-direction: column; gap: 2px; }
.nav-title {
    font-size: 10.5px;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--muted);
    padding: 0 6px 4px;
}

.nav-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 8px;
    border: 0;
    border-radius: 5px;
    background: transparent;
    color: var(--ink-2);
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.nav-item:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
.nav-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.nav-item.is-active { background: var(--accent-bg); color: var(--ink); }
/* 会离开终端的条目：`<a>` 自带下划线，不去掉就与旁边的 button 对不齐。 */
.nav-item.nav-away { text-decoration: none; }
.nav-item.nav-away .nav-count { font-family: inherit; font-variant-numeric: normal; }

/* 未接入的条目保持可读但明显不可用——做成看起来能点的样子，等于骗一次点击。 */
.nav-item.is-off { color: var(--muted); cursor: not-allowed; }

.nav-count {
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}
.nav-item.is-active .nav-count { color: var(--ink-2); }

.nav-foot {
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 10px 6px 0;
    border-top: 1px solid var(--line);
}
.freshness { font-size: 12px; color: var(--muted); }
.freshness.is-stale { color: var(--caution); }
.freshness.is-never { color: var(--down); }
/* 产物写坏了（产出者中途崩了，留下半截 JSON）。这一档原来没有样式，于是
   最该喊的那个状态跟「一切正常」画成同一个灰。 */
.freshness.is-corrupt { color: var(--down); font-weight: 600; }

/* 排程那行。**故意跟新鲜度同一档灰**：它不是告警，是背景事实，按计划空转
   本来就不该喊。开着窗口的时候才抬一档，因为那时它在回答「现在正好在跑」。 */
.freshness-schedule { font-size: 12px; color: var(--muted); }
.freshness-schedule.is-open { color: var(--ink); }

.link-button {
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    font-size: 11px;
    color: var(--accent);
    text-align: left;
    text-decoration: none;
    cursor: pointer;
}
.link-button:hover { text-decoration: underline; }

/* —— 中栏 —— */

.col-table { display: flex; flex-direction: column; overflow: hidden; }

.table-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
    padding: 14px 18px 10px;
    border-bottom: 1px solid var(--line);
}
.table-title { margin: 0; font-size: var(--fs-h1, 15px); font-weight: 600; }
.table-sub { margin: 3px 0 0; font-size: 12.5px; color: var(--muted); max-width: 62ch; }
/* 放在说明下面而不是右边那列：右边每行不换行，一句长话会把标题挤成一个字宽
   （2026-10-19 实测）；这里跟说明一样按 62ch 折行。 */
.table-verdict { margin: 6px 0 0; font-size: 12.5px; color: var(--muted); max-width: 62ch; }
.table-verdict .verdict-head { color: var(--ink); }
.table-meta {
    font-family: var(--font-mono);
    font-size: 12px;
    color: var(--muted);
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.table-scroll { flex: 1; overflow: auto; }

.picks {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
    /* 12px 是这一页最费眼的地方——满屏数字，而它比令牌里的正文字阶
       还小一号。抬到 13.5 之后一屏少两三行，值。 */
    font-size: var(--fs-body);
}
.picks th, .picks td {
    /* 字号从 12 抬到 13.5，行距要跟着走——不加的话字变大反而更挤，
       「费眼睛」是行距不是字号的问题居多。 */
    padding: 9px 12px;
    text-align: right;
    white-space: nowrap;
    border-bottom: 1px solid var(--line);
}
.picks th:first-child, .picks td:first-child { text-align: left; }

.picks thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--surface);
    font-size: 11.5px;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--muted);
    font-weight: 600;
    cursor: pointer;
    user-select: none;
}
.picks thead th:hover { color: var(--ink-2); }
.picks thead th[aria-sort]:not([aria-sort="none"]) { color: var(--ink); }
.picks thead th .arrow { font-size: 9px; margin-left: 3px; }

.picks tbody tr { cursor: pointer; }
.picks tbody tr:hover { background: var(--surface-2); }
/* 只靠背景色标选中不够：--accent-bg 与 --surface-2 在深色下差别极小，
   点了一行看不出点中哪行。加一条左边线，形状比色差可靠。 */
.picks tbody tr.is-selected { background: var(--accent-bg); }
.picks tbody tr.is-selected td:first-child {
    box-shadow: inset 3px 0 0 var(--accent);
}
.picks tbody tr.is-selected .symbol { color: var(--ink-max); }
.picks tbody tr:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

.symbol { font-family: var(--font-mono); font-weight: 600; }
.num { font-family: var(--font-mono); }
.up { color: var(--up); }
.down { color: var(--down); }
.dim { color: var(--muted); }
/* 盘中价叠上来之后，这一轮没取到价、仍是收盘价的那几格。 */
.is-close-price { color: var(--muted); }

/* 回填标记：这一行的资产负债表来自更早的期，读的人有权知道。 */
.flag {
    display: inline-block;
    margin-left: 5px;
    padding: 0 4px;
    border: 1px solid var(--line-hi);
    border-radius: 3px;
    font-size: 10.5px;
    color: var(--muted);
    vertical-align: 1px;
}
/* 股本两个方向的记号。都是坏消息，所以都走警示色——但它们是**两个词**，
   不是同一个红。只上色的话「增发」和「并股」在一列里长得一模一样，而
   并股这条价格序列根本看不见（价格到手时已经复权）。 */
.share-flag {
    border-color: var(--down);
    color: var(--down);
}
/* 双重信号：两条独立的线同时响。整行给一层很淡的底色，两张表上都给
   ——从哪一边看都是同一批票。**底色不能是唯一的信号**：色盲模式下它和
   普通行分不开，所以代码后面还挂一个「双重」的记号。 */
.picks tbody tr.is-dual > td { background: var(--caution-bg); }
/* 左侧一道竖条。底色在悬停时会被覆盖，而这道条不会——「这一行特别」
   这件事不能在鼠标经过时消失。 */
.picks tbody tr.is-dual > td:first-child { box-shadow: inset 3px 0 0 var(--caution); }
/* 选中态压过底色：选中的那一行必须一眼看得出是被选中的那一行。 */
.picks tbody tr.is-dual.is-selected > td { background: var(--accent-bg); }
.dual-flag {
    border-color: var(--caution);
    color: var(--caution);
}

/* K 线入口：外壳删掉之后，工作台唯一的进入方式就是从这一行点过去，
   所以它必须看起来可点（其余 flag 是纯标注，不可点）。 */
a.chart-link {
    color: var(--accent);
    border-color: var(--accent);
    text-decoration: none;
}
a.chart-link:hover,
a.chart-link:focus-visible { background: var(--surface-2); }

.empty { padding: 28px 18px; color: var(--muted); }

.table-foot {
    border-top: 1px solid var(--line);
    padding: 10px 18px;
    font-size: 12px;
    color: var(--muted);
    max-height: 30%;
    overflow-y: auto;
}
.table-foot p { margin: 0 0 4px; }
.table-foot p:last-child { margin-bottom: 0; }

/* —— 右栏 —— */

.col-detail {
    background: var(--surface);
    border-left: 1px solid var(--line);
    padding: 14px 16px 20px;
}

.detail-empty, .detail-error { color: var(--muted); padding: 24px 4px; font-size: 12px; }
.detail-error { color: var(--down); }

.detail-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.detail-symbol { margin: 0; font-family: var(--font-mono); font-size: 18px; font-weight: 600; }
.detail-name { margin: 1px 0 0; font-size: 11.5px; color: var(--ink-2); }
.detail-filed { margin: 6px 0 12px; font-size: 11px; color: var(--muted); }

.icon-button {
    background: none;
    border: 0;
    color: var(--muted);
    font-size: 18px;
    line-height: 1;
    padding: 2px 6px;
    cursor: pointer;
}
.icon-button:hover { color: var(--ink); }
.icon-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.block { border-top: 1px solid var(--line); padding-top: 10px; margin-top: 12px; }
.block-title {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 8px;
    margin: 0 0 6px;
    font-size: 12px;
    font-weight: 600;
}
.block-score { font-family: var(--font-mono); font-size: 11px; color: var(--ink-2); }

.rows { display: flex; flex-direction: column; gap: 4px; }
.row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 10px;
    font-size: 11.5px;
}
.row-label { color: var(--ink-2); min-width: 0; }
.row-value { font-family: var(--font-mono); color: var(--ink); white-space: nowrap; }

.check { display: flex; gap: 7px; align-items: baseline; font-size: 11.5px; }
.check-mark { width: 1.1em; flex: none; text-align: center; }
.check-body { min-width: 0; }
.check-name { color: var(--ink-2); }
.check-detail { color: var(--muted); font-size: 10.5px; }

.note { margin: 8px 0 0; font-size: 10.5px; color: var(--muted); }

/* 两套判据给出不同答案时，这句话是要看的东西，不是脚注。 */
.conflict {
    margin: 14px 0 0;
    padding: 9px 11px;
    border-left: 2px solid var(--caution);
    background: var(--caution-bg);
    font-size: 11.5px;
    color: var(--ink-2);
}

.disclaimer { margin: 12px 0 0; font-size: 10.5px; color: var(--muted); }

/* —— 登录 —— */

.login {
    border: 1px solid var(--line-hi);
    border-radius: 8px;
    background: var(--surface);
    color: var(--ink);
    padding: 18px 20px;
    min-width: 300px;
}
.login::backdrop { background: rgba(0, 0, 0, .55); }
.login h2 { margin: 0 0 4px; font-size: 14px; }
.login-hint { margin: 0 0 12px; font-size: 11px; color: var(--muted); }
.login input {
    width: 100%;
    padding: 7px 9px;
    border: 1px solid var(--line-hi);
    border-radius: 5px;
    background: var(--bg);
    color: var(--ink);
    font: inherit;
}
.login input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.login-status { min-height: 1.2em; margin: 7px 0 0; font-size: 11px; color: var(--down); }
.login-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; }
.login-actions button {
    padding: 6px 14px;
    border: 1px solid var(--line-hi);
    border-radius: 5px;
    background: var(--accent);
    color: var(--ink-max);
    font: inherit;
    cursor: pointer;
}
.login-actions button.ghost { background: transparent; color: var(--ink-2); }
.login-actions button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* —— 窄屏退化 —— */

/*
 * 设计稿写明的代价：宽屏才舒服，窄屏要退化成上下两段、右栏变抽屉。
 * 三栏挤在 1200px 以下会让中栏那张表横向滚动，而「一眼扫完排序」正是它
 * 存在的理由——所以窄屏让右栏浮起来盖住，而不是把三栏都压扁。
 */
@media (max-width: 1200px) {
    .desk { grid-template-columns: 184px minmax(0, 1fr); }
    .col-detail {
        position: fixed;
        inset: 0 0 0 auto;
        width: min(400px, 92vw);
        z-index: 20;
        box-shadow: -18px 0 40px rgba(0, 0, 0, .45);
        transform: translateX(100%);
        transition: transform .18s ease;
    }
    .col-detail.is-open { transform: translateX(0); }
    @media (prefers-reduced-motion: reduce) {
        .col-detail { transition: none; }
    }
}

@media (max-width: 900px) {
    .desk { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
    .col-nav {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: center;
        gap: 10px;
        border-right: 0;
        border-bottom: 1px solid var(--line);
        overflow: visible;
    }
    .nav-group { flex-direction: row; align-items: center; gap: 4px; }
    .nav-title { display: none; }
    .nav-foot { margin-top: 0; border-top: 0; flex-direction: row; gap: 12px; padding: 0 6px; }
    .table-head { flex-direction: column; gap: 6px; }
    .table-meta { text-align: left; }
}

/* —— 浅色 —— */

/*
 * 令牌文件负责浅色下的取值，这里只处理本页自己写死的那一处半透明遮罩。
 * 颜色只在令牌层定义一次，是这套系统能同时活在两种主题下的前提。
 */
@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) .login::backdrop { background: rgba(15, 23, 38, .35); }
}
:root[data-theme="light"] .login::backdrop { background: rgba(15, 23, 38, .35); }

/* 立即扫描。它是左栏底部唯一一个「会改变世界」的控件，所以给它按钮的样子，
   而旁边的旧版控制台仍是链接——形态要对得上后果。 */
.scan-button {
    width: 100%;
    padding: 6px 8px;
    border: 1px solid var(--line-hi);
    border-radius: 4px;
    background: var(--surface-2);
    color: var(--ink-2);
    font: inherit;
    font-size: 11px;
    cursor: pointer;
}
.scan-button:hover:not(:disabled),
.scan-button:focus-visible:not(:disabled) {
    border-color: var(--accent);
    color: var(--ink);
}
.scan-button:disabled { color: var(--muted); cursor: progress; }
.scan-status { font-size: 11px; color: var(--muted); }
.scan-status.is-running { color: var(--accent); }
.scan-status.is-failed { color: var(--down); }

/* 公司名与行业：左对齐、可截断。数字列继续右对齐。 */
.picks td .company, .picks td .industry { display: inline-block; max-width: 100%; }
.picks th:nth-child(2), .picks td:nth-child(2),
.picks th:nth-child(3), .picks td:nth-child(3) { text-align: left; }
.company { color: var(--ink-2); }
.industry { color: var(--muted); font-size: 11.5px; }

/* 档位：极端与观察必须一眼分得开。用底色而不是只用文字，
   因为这一列会被排序，成组出现时形状比字更快。 */
.tier-extreme, .tier-watch {
    display: inline-block;
    padding: 0 6px;
    border-radius: 3px;
    font-size: 10.5px;
}
.tier-extreme { background: var(--caution-bg); color: var(--caution); }
.tier-watch { background: var(--surface-2); color: var(--muted); }

/* —— 点一下复制 —— */

/* 名单里代码出现几百次，做成按钮的样子就是几百个按钮。静止时只多一条
   虚线，悬停才补背景。 */
.copyable {
    cursor: pointer;
    border-radius: 3px;
    border-bottom: 1px dashed var(--line);
    padding: 0 2px;
    margin: 0 -2px;
    /* `role="button"` 让屏幕阅读器知道这能点，代价是浏览器按原生控件处理、
       抑制拖选——于是「加了点击复制」会顺手废掉「划着复制」，而这正是
       用户一开始抱怨的那件事。两个都要，所以把文本选择显式放回来。 */
    user-select: text;
    -webkit-user-select: text;
}
.copyable:hover { background: var(--surface-2); border-bottom-color: var(--muted); }
.copyable:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* 回执写在原地：另起 toast 会画在表外，而这一行可能在滚动区下半截。
   `<dialog>` 的 top layer 也压不过——这个项目已经栽过一次。 */
.copyable[data-copy-tone="ok"] { color: var(--up); border-bottom-color: var(--up); }
.copyable[data-copy-tone="warn"] { color: var(--caution); border-bottom-color: var(--caution); }

/* —— 200 日均线雷达 —— */

/* 右栏没选中行时放板块结构。它同时是筛选器，所以每一行都得看起来能点，
   而没有标的的那些必须留在表上写零——「今天一只都没跌破」和「这个板块
   不在名单里」是两个答案，缺行只能表达后者。 */
.detail-overview { padding: 14px 16px; overflow-y: auto; }
.ma200-head { display: flex; flex-direction: column; gap: 3px; margin-bottom: 10px; }
.ma200-sub { font-size: 11px; color: var(--muted); }

.ma200-clear {
    display: block;
    width: 100%;
    margin-bottom: 8px;
    padding: 6px 8px;
    border: 1px solid var(--accent);
    border-radius: 5px;
    background: var(--accent-bg);
    color: var(--ink);
    font: inherit;
    font-size: 11.5px;
    text-align: left;
    cursor: pointer;
}
.ma200-clear:hover { background: var(--surface-2); }

/* 行与行之间靠**一条细线**分开，不靠间距。二十一行两排的表里，只留 1px
   间距时上一行的第二排和下一行的第一排贴在一起，整张表糊成一片；
   而拉大间距会把本来就要滚的面板拉得更长。 */
.ma200-sectors { display: flex; flex-direction: column; }
.ma200-srow + .ma200-srow { border-top: 1px solid var(--line); }
.ma200-srow {
    display: grid;
    /* 两排四格：
         第一排  板块名（撑满剩余宽度） | 今日涨跌
         第二排  跌破占比条形           | 即将 · 已破
       五列平铺时板块名只分到不足 90px，二十一个里十三个被省略号切掉，
       而板块名是这张表唯一不能靠上下文猜出来的那一格。 */
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 3px 10px;
    width: 100%;
    padding: 7px 6px 8px;
    border: 0;
    border-radius: 4px;
    background: transparent;
    color: var(--ink-2);
    font: inherit;
    font-size: 11.5px;
    text-align: left;
    cursor: pointer;
}
.ma200-srow.is-head {
    color: var(--muted);
    font-size: 10px;
    letter-spacing: .06em;
    text-transform: uppercase;
    cursor: default;
    border-bottom: 1px solid var(--line);
    padding-bottom: 5px;
}
/* 表头的第二排是说明这一排画的是什么，不该跟数据行一样重。 */
.ma200-srow.is-head .ma200-share,
.ma200-srow.is-head .ma200-tally { font-size: 9.5px; opacity: .85; }
.ma200-srow:hover:not(:disabled):not(.is-head) { background: var(--surface-2); color: var(--ink); }
.ma200-srow:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.ma200-srow.is-on { background: var(--accent-bg); color: var(--ink); }
/* 零行留着但不可点：点进去是一张空表，做成能点等于骗一次点击。 */
.ma200-srow:disabled { color: var(--muted); cursor: default; }
.ma200-sname {
    grid-column: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: flex;
    align-items: baseline;
    gap: 5px;
    min-width: 0;
    font-size: 12px;
}
.ma200-sname b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; }
/* 成分股数是背景信息，不该跟板块名抢。它也不能被省略号吃掉，
   所以给它一个不收缩的位置。 */
.ma200-scount { font-style: normal; font-size: 10.5px; color: var(--muted); flex: 0 0 auto; }
/* 跌破占比：条形是给板块之间比长度的，数字之间要心算。
   它在第二排第一格——条形要够长才比得出来，挤在 76px 里所有板块看起来
   都差不多。 */
.ma200-share {
    grid-column: 1;
    grid-row: 2;
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
}
/* 3px 不是 4px：二十一行每行一条满宽的饱和红，整栏都在喊，于是没有一行
   在喊。条形要能比长度，不需要抢注意力——颜色留给「今日」那一列。 */
.ma200-bar {
    flex: 1 1 auto;
    height: 3px;
    min-width: 0;
    border-radius: 2px;
    background: var(--surface-3, var(--surface-2));
    overflow: hidden;
}
.ma200-bar i { display: block; height: 100%; background: var(--down); opacity: .8; }
.ma200-srow:disabled .ma200-bar i { opacity: .35; }
.ma200-sharenum {
    flex: 0 0 auto;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 10.5px;
    color: var(--muted);
}
.ma200-srow.is-head .ma200-share,
.ma200-srow.is-head span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ma200-srow .num {
    grid-column: 2;
    grid-row: 1;
    text-align: right;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* 即将 · 已破 并成一格：分成两列时列标题比数字还宽。颜色分工跟表里
   一致——琥珀是「还没破」，红是「破了」，位置不用再标签。 */
.ma200-tally {
    grid-column: 2;
    grid-row: 2;
    display: flex;
    align-items: baseline;
    justify-content: flex-end;
    gap: 4px;
    white-space: nowrap;
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 11px;
}
.ma200-tally b { font-weight: 600; }
.ma200-tally .caution { color: var(--caution); }
.ma200-tally .down { color: var(--down); }
.ma200-tallysep { color: var(--muted); }
/* 一只都没有的板块整行压暗：它留在表里是为了回答「这个板块今天没事」，
   不该跟正在走弱的那些抢注意力。 */
.ma200-srow:disabled .ma200-tally b { color: var(--muted); }
.ma200-foot { margin-top: 10px; font-size: 10.5px; line-height: 1.6; color: var(--muted); }

/* —— 判断卡 —— */

.ma200-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 12px; }
.ma200-fact { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ma200-flabel { font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.ma200-fact .num { font-family: var(--font-mono); font-size: 12.5px; color: var(--ink); white-space: nowrap; }
.ma200-fact .num.up { color: var(--up); }
.ma200-fact .num.down { color: var(--down); }
.ma200-tier { font-size: 12px; }
.ma200-tier.is-broken, .ma200-tier.is-far_below { color: var(--down); }
.ma200-tier.is-approaching { color: var(--caution); }
.ma200-badges { display: flex; gap: 3px; flex-wrap: wrap; }

/* 一年来首次穿越单独一行：一年内破过多次的不给标记，所以这一行出现
   就意味着「这是这一年里的第一次」。 */
.ma200-special {
    margin: 10px 0 0;
    padding: 6px 8px;
    border-radius: 5px;
    font-size: 12px;
    background: var(--accent-bg);
}
.ma200-special[data-dir="down"] { color: var(--down); }
.ma200-special[data-dir="up"] { color: var(--up); }

.ma200-chart { margin-top: 12px; }
.ma200-chart svg { width: 100%; height: auto; display: block; }
.ma200-axis { fill: var(--muted); font-family: var(--font-mono); font-size: 9.5px; }
.ma200-legend { display: flex; gap: 10px; align-items: center; margin-top: 4px; font-size: 10.5px; color: var(--muted); }
.ma200-key::before { content: ''; display: inline-block; width: 10px; height: 2px; margin-right: 4px; vertical-align: middle; }
.ma200-key.is-price::before { background: var(--ink-2); }
.ma200-key.is-ma::before { background: var(--caution); }
.ma200-key.is-rsi::before { background: var(--accent); }
/* 两块图叠着画时给一道缝。同一个 <svg> 里塞两套坐标系会让两边的刻度
   互相牵制——分开两个 svg，各自的轴各管各的。 */
.ma200-chart svg + svg { margin-top: 6px; }
.ma200-span { margin-left: auto; font-family: var(--font-mono); }

/* 指数筛选。全市场那条链路没有成分股概念，那一排不出现。 */
.ma200-seg { display: flex; gap: 4px; margin-bottom: 10px; flex-wrap: wrap; }
.ma200-segbtn {
    padding: 4px 9px;
    border: 1px solid var(--line);
    border-radius: 5px;
    background: transparent;
    color: var(--ink-2);
    font: inherit;
    font-size: 11px;
    cursor: pointer;
}
.ma200-segbtn:hover { background: var(--surface-2); color: var(--ink); }
.ma200-segbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.ma200-segbtn.is-on { background: var(--accent-bg); border-color: var(--accent); color: var(--ink); }

/* —— 板块涨跌的口径开关（等权 ↔ 市值）——
   两处各画一个，读同一个 state。中栏那个住在「当日」的 <th> 里，压在
   列名下面一行：横着放会把这一列撑宽，而它下面每一行只有「-0.49%」。 */
.move-toggle {
    display: flex;
    gap: 2px;
    margin-top: 3px;
    justify-content: flex-end;
}
.picks th .move-toggle { font-weight: 400; }
.move-opt {
    padding: 1px 5px;
    border: 1px solid var(--line);
    border-radius: 4px;
    background: none;
    color: var(--muted);
    font: inherit;
    font-size: 9.5px;
    line-height: 1.5;
    cursor: pointer;
}
.move-opt:hover:not(:disabled) { color: var(--ink); border-color: var(--ink-2); }
.move-opt:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.move-opt.is-on {
    background: var(--accent-bg);
    border-color: var(--accent);
    color: var(--ink);
}
/* 禁用的那一档留在原地、变淡、带说明。隐藏它会读作「没有这个功能」，
   而事实是「这份产物还没算过」。 */
.move-opt:disabled { opacity: .4; cursor: not-allowed; }
/* 右栏那一格：口径名在上，开关在下，整格右对齐跟数字列对齐。 */
.ma200-move { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.move-name { white-space: nowrap; }

/* —— 中栏的板块分组头 ——
   组头跟数据行一样一列一个 <td>，每个数落在它自己那一列下面。第一版是
   一整行 <td colSpan>、四个数挤在最左边——每个数单独看都对，可是要知道
   +0.10% 说的是哪一列，得自己抬头往右数。
   行本身可点，第一格里还留着一个按钮：没有 href 的元素键盘到不了。 */
.group-row { cursor: pointer; }
.group-row > td {
    padding: 6px 10px;
    background: var(--surface-2);
    vertical-align: baseline;
}
/* 第一格装的是按钮，内边距由按钮自己出，否则点击热区会缩在格子中间。 */
.group-row > td:first-child { padding: 0; }
.group-row:hover > td { background: var(--surface-3, var(--surface-2)); }
.group-toggle {
    display: flex;
    align-items: baseline;
    gap: 8px;
    width: 100%;
    padding: 6px 10px;
    border: 0;
    background: none;
    color: var(--ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.group-toggle:hover { background: var(--surface-3, var(--surface-2)); }
.group-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.group-chev {
    display: inline-block;
    flex: 0 0 auto;
    width: 10px;
    color: var(--muted);
    transform: rotate(90deg);
    transition: transform .12s ease;
}
.group-row.is-closed .group-chev { transform: rotate(0deg); }
.group-name { font-weight: 600; }
/* 每个数各自住在一个 <td> 里，所以不再需要 flex 定位——列自己会对齐。
   数字类的跟数据行同一套字体和 tabular-nums，否则同一列上下两行的小数点
   对不上，而「对得上」正是把它们摆进列里的理由。 */
.group-count { font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.group-change {
    font-family: var(--font-mono);
    font-variant-numeric: tabular-nums;
    font-size: 12.5px;
    white-space: nowrap;
}
.group-tally { font-size: 11.5px; color: var(--muted); white-space: nowrap; }
/* 组的排序键。写出来才看得出中间跳过了谁——排第一的板块可能一只都没上榜。 */
.group-share {
    font-size: 10.5px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
@media (prefers-reduced-motion: reduce) {
    .group-chev { transition: none; }
}

/* —— 行内走势图 ——
   图摊在它那一行的正下方，不是跳到另一个页面、也不是画在右栏。跳走一次
   只看得到一只票；右栏一次也只装得下一只。摊开在名单里才能几只并排比。 */

.chart-toggle {
    padding: 1px 6px;
    border: 1px solid var(--line-hi);
    border-radius: 3px;
    background: transparent;
    color: var(--ink-2);
    font: inherit;
    font-size: 10.5px;
    line-height: 1.5;
    white-space: nowrap;
    cursor: pointer;
}
.chart-toggle:hover { background: var(--surface-2); color: var(--ink); }
.chart-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.chart-toggle.is-on {
    background: var(--accent-bg);
    border-color: var(--accent);
    color: var(--ink);
}
.chart-row > td { padding: 0; background: var(--surface-2); }

/* —— 自选 ——
   ☆ 挂在每一行的代码后面。它是按钮（有动作），外形跟走势键同一族，但只占一个
   字宽：代码那一列在窄屏上是钉住的，多宽一点就多挤一点判断列。 */
.watch-star {
    padding: 0 3px;
    margin-left: 4px;
    border: 1px solid transparent;
    border-radius: 3px;
    background: transparent;
    color: var(--muted);
    font: inherit;
    font-size: 11px;
    line-height: 1.4;
    cursor: pointer;
}
.watch-star:hover { border-color: var(--line-hi); color: var(--ink); }
.watch-star:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.watch-star.is-on { color: var(--caution); }
/* 自选那张表表头上的输入框。表头右栏是等宽、右对齐、不换行的读数区，
   输入框贴在读数上面，同一个对齐。 */
.watch-add {
    display: flex;
    justify-content: flex-end;
    gap: 6px;
    margin-bottom: 6px;
}
.watch-add input {
    width: 22ch;
    padding: 3px 6px;
    border: 1px solid var(--line-hi);
    border-radius: 3px;
    background: var(--surface-2);
    color: var(--ink);
    font: inherit;
    text-transform: uppercase;
}
.watch-add input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.watch-add button {
    padding: 3px 10px;
    border: 1px solid var(--accent);
    border-radius: 3px;
    background: var(--accent-bg);
    color: var(--ink);
    font: inherit;
    cursor: pointer;
}
.watch-status { min-height: 1.2em; white-space: normal; }
.watch-status.is-failed { color: var(--down); }
/* 图跟着表一起横向滚会滚出视野——这张表比视口宽。所以它贴住左边，
   不随右边那几列走。**宽度由 JS 按可见区量出来后写在行内**：写死
   `min(560px,100%)` 时它在 1032px 的表里只占 54%，屏幕空着一半。
   两侧 padding 之和 24px 是 desk-ma200.js 里 CHART_GUTTER 的那个数。 */
.chart-row .ma200-chart {
    position: sticky;
    left: 0;
    padding: 10px 12px 12px;
}

/* —— 板块结构入口（只在窄屏出现） —— */

.table-side { display: flex; align-items: flex-start; gap: 10px; }
.overview-button {
    display: none;
    flex: 0 0 auto;
    padding: 5px 10px;
    border: 1px solid var(--line-hi);
    border-radius: 4px;
    background: var(--surface-2);
    color: var(--ink-2);
    font: inherit;
    font-size: 11.5px;
    white-space: nowrap;
    cursor: pointer;
}
.overview-button:hover { background: var(--surface); color: var(--ink); }
.overview-button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* 宽屏不出现：板块结构一直在右栏里摆着，再给一个入口只是多一次点击。
   窄屏右栏是抽屉，而抽屉此前只有点某一行才打开——那时看到的是个股详情。 */
@media (max-width: 1200px) {
    .overview-button:not([hidden]) { display: inline-block; }
}

/* 抽屉自己的关闭键。宽屏右栏是常驻一栏，不需要「返回」。 */
.drawer-close {
    display: none;
    width: 100%;
    margin-bottom: 10px;
    padding: 8px 10px;
    border: 1px solid var(--line-hi);
    border-radius: 4px;
    background: var(--surface-2);
    color: var(--ink-2);
    font: inherit;
    font-size: 12px;
    text-align: left;
    cursor: pointer;
}
.drawer-close:hover { background: var(--surface); color: var(--ink); }
.drawer-close:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
@media (max-width: 1200px) {
    .drawer-close { display: block; }
}

/* —— 手机 ——
 *
 * 之前只有 1200 / 900 两档，900 以下就再没管过。实测 390px 下：顶部导航
 * 吃掉半屏（两排换行 + 扫描状态挤成三窄列竖排），中栏 1014px 的表塞在
 * 390px 里、只看得到代码和公司两列，而**离均线和当日恰恰是判断依据**。
 *
 * 处理方式是取舍不是缩放：把长而不决策的列（公司名、ISIN）藏掉，
 * 其余仍可横向滚，并把代码那一列钉住——横滚时没有锚点就不知道在看谁。
 */
@media (max-width: 600px) {
    .col-nav { gap: 6px; padding: 8px 10px; }
    /* 导航挤成一条可横滚的带子。换行会让它一路吃掉半个屏幕。 */
    .nav-group {
        flex-wrap: nowrap;
        overflow-x: auto;
        gap: 2px;
        /* 滚动条在手机上会盖住内容的最后几像素。 */
        scrollbar-width: none;
    }
    .nav-group::-webkit-scrollbar { display: none; }
    .nav-item { padding: 6px 9px; white-space: nowrap; }
    .brand { padding: 0; }
    .brand-name { font-size: 13.5px; }
    .brand-sub { display: none; }

    /* 左下角那一坨在窄屏上会竖排成一个字一行。动作挤一行，两段状态各占
       一整行——并排的话两段都被省略号截断，等于两段都读不了。 */
    .nav-foot { flex-wrap: wrap; align-items: center; gap: 6px 8px; }
    .scan-button { width: auto; flex: 0 0 auto; }
    .nav-foot .link-button { flex: 0 0 auto; white-space: nowrap; }
    /* 动作挤在同一行，两段状态排到它们下面。不排序的话状态文字先占满
       一整行，把外观开关和链接推成第三行。 */
    .scan-button, #appearanceMount, .nav-foot .link-button { order: 1; }
    .scan-status { order: 2; }
    .freshness { order: 3; }
    .freshness-schedule { order: 4; }
    .freshness, .freshness-schedule, .scan-status {
        flex: 1 0 100%;
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        font-size: 10.5px;
    }

    .table-head { padding: 10px 12px 8px; }
    /* 手机上字要更大不是更小：屏幕近、但也拿得远，而这一页满屏是数字。
       原来这里把桌面的字号又压了一级，是「费眼睛」最直接的来源。 */
    .table-title { font-size: 16px; }
    .table-sub { font-size: 12.5px; }
    .table-meta { font-size: 12px; }

    /* 长而不决策的列让位。它们不是不重要，是在 390px 上放不下——
       点开抽屉全都在。ISIN 还留着可复制的入口（详情卡里）。 */
    .picks [data-col="name"],
    .picks [data-col="company_name"],
    /* `display_name` **不在这张单子上**：它是 HL 那张表唯一的身份列。
       美股那几张表的第一列是 `symbol`，让 `name` 走开之后行还认得出来；
       HL 没有 `symbol` 列，`display_name` 一让位，390px 上第一列就是
       标记价——64 行数字，没有一列说这是哪个币。实测过，不是推的。 */
    .picks [data-col="isin"],
    .picks [data-col="industry"],
    /* 现价/均线让位给离均线和当日：离均线**就是**价与线的关系，
       两者并列时前者占 180px 而后者是真正的判断依据。 */
    /* 「指数」那列在手机上让位：它是三个静态标记（标普/纳指/道指），
       而字号抬上来之后表宽多了 34px，把 RSI 挤出了可见区——RSI 是现在
       这张表的判断依据之一，标记不是。判断依据永远排在标记前面。 */
    .picks [data-col="indexes"],
    .picks [data-col="price"],
    /* 「冲高」那一列在 390px 上让位。实测带对照组：带它 scrollWidth 425、
       去掉正好 390——**那 35px 就是它**，而横向滚动在这张表上是缺陷。
       它有自己的一条源（「冲高悬空」），在那张表上档位列就是它，所以在
       这里让位不等于手机上看不到。 */
    .picks [data-col="overheated"],
    /* 板块列在按板块分组的表里每行都在重复它头顶那一行。 */
    .picks [data-col="sector_label"] { display: none; }

    /* 一屏少几行没关系，用户原话：「可以换成 2 行也没关系 但是字要大」。 */
    .picks th, .picks td { padding: 9px 8px; font-size: 13.5px; }
    /* 代码钉在左边：横着滚的时候没有锚点就不知道这一行是谁。 */
    .picks th:first-child, .picks td:first-child {
        position: sticky;
        left: 0;
        z-index: 2;
        background: var(--bg);
    }
    .picks thead th:first-child { z-index: 3; background: var(--surface); }
    .picks tbody tr:hover td:first-child { background: var(--surface-2); }
    .picks tbody tr.is-selected td:first-child { background: var(--accent-bg); }
    /* 组头第一格跨「代码 + 公司」两列，而钉列那条规则钉的是一列宽——
       钉住它会把板块名从中间切开。窄屏上让它跟着表一起滚。 */
    .picks tbody tr.group-row td:first-child { position: static; }
    /* 组头上那两串字在宽屏上不折行，是为了跟自己那一列对齐。390px 上
       「上榜 14（即将 7 · 已破 7）」不折行会把「档位」列撑到 150px，
       把「当日」整列挤出可见区——实测就是这么坏的，而名单在手机上的
       判断依据正是「离均线」和「当日」。这里让它折，列宽交还给数据。 */
    .group-tally, .group-share { white-space: normal; }
    /* 排序键在窄屏上让位：它解释的是板块之间的排法，而手机上一屏只看
       得到一两个板块，排法本来就看不出来。 */
    .group-share { display: none; }

    /* 脚注在手机上比数据还显眼。压到两行左右，仍可滚。 */
    .table-foot { max-height: 4.2em; padding: 8px 12px; font-size: 12px; }

    /* 抽屉占满宽度：360px 屏上留 8% 的缝没有意义。 */
    .col-detail { width: 100vw; padding: 12px 14px 20px; }
}

/* —— 右栏的基本面 ——
   颜色落在**数字本身**，跟名单里「当日」那一列同一套（`.num.up` / `.num.down`）：
   扫一眼就知道这一项是好是坏，不用先读一个记号再回来找数。
   估值那一组不染色——便宜不等于好，涂绿等于替读的人下了一个没人做过的判断。 */
.fund-block { margin-top: 14px; }
.fund-warn {
    margin: 0 0 8px;
    font-size: 11px;
    color: var(--caution);
}
.fund-group { margin-bottom: 10px; }
.fund-gname {
    margin-bottom: 4px;
    font-size: 12px;
    font-weight: 600;
    color: var(--ink-2);
    letter-spacing: .06em;
}
/* 四列定宽，标签不推数字。上一版数值跟着中文标签的宽度走，长短不一的
   标签把整栏推成了波浪。 */
.fund-row {
    display: grid;
    grid-template-columns: 5.6em minmax(0, 1fr) 46px minmax(0, 1.5fr);
    align-items: center;
    gap: 6px;
    padding: 2px 0;
}
.fund-label { font-size: 13px; color: var(--ink-2); }
.fund-value {
    text-align: right;
    font-size: 13.5px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* 分位条。默认中性灰——只有方向明确且离中位够远时才跟着数字一起变色。 */
.fund-bar {
    height: 3px;
    border-radius: 2px;
    background: var(--line);
    overflow: hidden;
}
.fund-bar > i { display: block; height: 100%; background: var(--ink-2); }
.fund-bar.is-up > i { background: var(--up); }
.fund-bar.is-down > i { background: var(--down); }
.fund-note {
    font-size: 11.5px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
@media (max-width: 900px) {
    /* 窄屏收成两列：分位条和说明各占一行，宁可高一点也不要挤成一团。 */
    .fund-row { grid-template-columns: 5.6em minmax(0, 1fr); }
    .fund-bar, .fund-note { grid-column: 1 / -1; }
}
/* 可比样本薄的时候那一行要看得见——常态下它不出现，出现就是有话说。 */
.fund-note.is-thin { color: var(--caution); }

/* —— 按业务反推市值 ——
   低于 = `--up`，高于 = `--down`；两个 token 在色盲外观下自动换成蓝 / 橙。
   颜色从不单独出现，旁边一定有带正负号的数字。 */
.val-block { margin-top: 14px; }
.val-verdict {
    margin: 0 0 8px;
    font-size: 13px;
    font-weight: 600;
}
.val-verdict.is-below { color: var(--up); }
.val-verdict.is-above { color: var(--down); }
.val-verdict.is-neutral { color: var(--ink-2); }
.val-why { font-weight: 400; color: var(--muted); }
/* 锚 / 反推 / 差额一行，「怎么算的」折到**它自己**那一行下面、占满整宽。
   第一版是四列并排，而抽屉在 1600px 屏上也只有 290px 宽：实测说明被截成
   「同板块中位 4.3…」——倍数和家数恰恰是读的人用来推翻这个结论的信息，
   截掉就是不给看。抽屉永远是窄栏，所以这就是默认，不是窄屏特例。 */
.val-row {
    display: grid;
    grid-template-columns: 5.6em minmax(0, 1fr) minmax(0, 0.9fr);
    align-items: center;
    column-gap: 6px;
    row-gap: 0;
    padding: 3px 0 5px;
}
.val-row > .val-note { grid-column: 1 / -1; grid-row: 2; white-space: normal; }
.val-row.is-head > span:last-child { display: none; }
.val-row.is-head > span {
    font-size: 10.5px;
    color: var(--muted);
    letter-spacing: .04em;
}
.val-label { font-size: 13px; color: var(--ink-2); }
.val-gap {
    text-align: right;
    font-size: 13.5px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* 反推那一格是两行：股价大字、市值小字。股价才是能直接跟屏幕上那个价对比
   的数，市值是它的来源。两行都靠右，跟差额那列对齐。 */
.val-implied {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    min-width: 0;
    line-height: 1.2;
}
.val-px {
    font-size: 13.5px;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.val-cap {
    font-size: 10.5px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.val-gap { font-weight: 600; }
.val-gap.is-below { color: var(--up); }
.val-gap.is-above { color: var(--down); }
.val-note {
    font-size: 11.5px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* 底线那一行：抽屉里指出名单上那个价是哪个锚给的。只加一个可读的小标签，
   不靠底色——色盲外观下底色区分不出来，而这一行恰恰是要被指认的。 */
.val-floor-tag {
    margin-left: 5px;
    padding: 0 4px;
    border: 1px solid var(--border);
    border-radius: 3px;
    font-size: 9.5px;
    color: var(--muted);
    vertical-align: 1px;
}
.val-row.is-floor .val-px { font-weight: 700; }
/* 区间那一行：同一组同行便宜四分之一 / 贵四分之一各给的价。**比市值那行还淡**
   ——它不是结论，只是尺度，不该跟主数抢眼睛。 */
.val-band {
    font-size: 10px;
    color: var(--muted);
    opacity: .85;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
/* 名单里那一列。颜色跟抽屉里的差额同一对令牌，旁边永远有数字。 */
.val-floor {
    font-variant-numeric: tabular-nums;
    display: inline-flex;
    flex-direction: column;
    align-items: flex-end;
    line-height: 1.15;
}
.val-floor.is-below { color: var(--up); }
.val-floor.is-above { color: var(--down); }
/* 底线价下面那个区间：跟着格子走，不带货币符号、不着色——着了色会看起来
   像第二个结论。 */
.val-floor-band {
    font-size: 10px;
    font-weight: 400;
    color: var(--muted);
    white-space: nowrap;
}
.val-actual { margin: 6px 0 0; font-size: 12px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* 「跟增速相近的公司比」：只是对照，灯不看它。上面一条细线、标题用弱化色，
   免得跟主结论读成同一件事；结论那行沿用 .val-verdict 的颜色规矩。 */
.val-growth { margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--line); }
.val-growth-head { margin: 0 0 6px; font-size: 10.5px; color: var(--muted); letter-spacing: .02em; }
.val-growth-none { margin: 10px 0 0; font-size: 10.5px; color: var(--muted); }
.val-foot { margin: 6px 0 0; font-size: 10.5px; color: var(--muted); line-height: 1.5; }
.value-flag { border-color: var(--up); }
/* 组头上的「一年来首次穿越」计数，跟那盏灯并排。跌破用跌色、突破用涨色，
   跟行上 🚨 / ⭐ 两个记号对应；描边只是分组，数字和 emoji 本身已经说清了。 */
.group-cross.is-down { border-color: var(--down); }
.group-cross.is-up { border-color: var(--up); }


/* ==========================================================================
   手机端：把「讲话」压下去，把名单让出来

   实测 390×844 上，左栏 209px + 表头 176px = 385px——**一半屏幕在讲话**，
   而这一页存在的理由是那张名单。下面每一条都对着一个量出来的数改。
   ========================================================================== */
@media (max-width: 900px) {
    /* 左栏 209px → 一条可横滑的标签栏。分组标题、扫描按钮、旧版入口
       在手机上都不是「现在要做的事」，收进右边滑得到的地方。 */
    .col-nav {
        flex-direction: row;
        /* **必须显式写 nowrap**：同一个断点里前面那条规则设了 `wrap`，
           不覆盖的话这些标签会换到四五行去，量出来 155px——而收成一条
           可横滑的带子正是这次要做的事。 */
        flex-wrap: nowrap;
        align-items: center;
        gap: 6px;
        padding: 6px 10px;
        overflow-x: auto;
        overflow-y: hidden;
        scrollbar-width: none;
    }
    /* 一行放不下就横滑，不许换行、不许把字挤成两行。 */
    .col-nav .nav-item span,
    .col-nav .nav-foot .freshness,
    .col-nav .nav-foot .freshness-schedule,
    .col-nav .nav-foot .scan-status {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .col-nav::-webkit-scrollbar { display: none; }
    .col-nav .brand,
    .col-nav .nav-title { display: none; }
    .col-nav .nav-group {
        flex-direction: row;
        gap: 6px;
        flex: 0 0 auto;
    }
    .col-nav .nav-item {
        flex: 0 0 auto;
        width: auto;
        gap: 5px;
        padding: 5px 9px;
        border-radius: 999px;
        background: var(--surface-2);
        white-space: nowrap;
    }
    .col-nav .nav-item.is-active { background: var(--accent-bg); }
    /* 底部那块（扫描按钮、新鲜度、外观切换）跟着排到同一条上，
       不再占一整段高度。 */
    .col-nav .nav-foot {
        flex-direction: row;
        align-items: center;
        gap: 8px;
        margin: 0;
        padding: 0 0 0 8px;
        border-top: 0;
        border-left: 1px solid var(--line);
        flex: 0 0 auto;
    }
    .col-nav .nav-foot .freshness,
    .col-nav .nav-foot .freshness-schedule,
    .col-nav .nav-foot .scan-status { max-width: 40vw; }

    /* 表头六行 meta 折成一行，点「详情」展开。原来它们全部铺开占 176px，
       而其中五行是「这条链路怎么算的」——第一次读有用，之后每次都占地方。 */
    .table-head { padding: 8px 12px 6px; gap: 8px; }
    .table-sub { display: none; }
    /* 实盘检验只留结论那一句：说明那段在窄屏折到七行，把表推出第一屏。 */
    .table-verdict div:not(.verdict-head) { display: none; }
    .table-meta { text-align: left; }
    .table-meta.is-folded div:not(:first-child):not(.meta-more) { display: none; }
    .meta-more {
        display: inline-block;
        margin-top: 2px;
        color: var(--accent);
        cursor: pointer;
        font-size: 10px;
    }

    /* 组头在窄屏不折行：折行之后「上榜 1（即将 1 · 已破 0）」竖成三行，
       一个板块占掉四行高度。窄屏上这几个数收进悬停，行内只留名字和涨跌。 */
    .group-tally, .group-share, .group-count { display: none; }
    .picks tbody tr.group-row > td { padding: 5px 10px; }

    /* 基本面：说明行必须贴住**它自己**那个数。原来 bar 和 note 各占一整行，
       note 落在行底、紧挨着下一个标签——读起来像是下一项的基准。 */
    .fund-row {
        grid-template-columns: minmax(0, 1fr) auto;
        row-gap: 0;
        padding: 4px 0 6px;
    }
    .fund-label { font-size: 12px; }
    .fund-value { font-size: 13px; }
    .fund-bar { display: none; }
    .fund-note {
        grid-column: 1 / -1;
        grid-row: 2;
        margin-top: -2px;
        white-space: normal;
    }
}

/* —— 中栏放不下时，按「哪一列最不承重」让位 ——

   实测：字号抬到 13.5 之后表要 1221px，而 1600px 屏上中栏只有 1032px
   （左栏 208 + 右栏 360 是常驻的）。1920 才刚好放得下。横滚不是错，但
   要滚才看得见的判断依据等于没有，所以按承重排队让位：

     板块   分组表头上已经写着板块名了，每行再写一次是重复
     指数   三个静态标记，不是判断依据
     公司   名字长的截短一点（代码还在，鼠标停上去有全名）

   ISIN 和「现价/均线」不让：前者是拿去券商里查的东西，后者是这一行存在
   的理由。 */
/* 先收两侧——那是零信息损失的空间。中栏宽 = 视口 − 左栏 − 右栏，所以
   两侧各让 40px，中栏就多 80px，等于少砍一列。 */
/* **下界必须写**：1200 以下右栏本来会浮起来变抽屉（见上面那段），而这条
   规则写在文件后面，不加下界会用三栏模板把它盖回去——实测 1024px 上中栏
   被压到 532px，三个判断列全被挤出可见区。改坏一个已有行为的最省事方式，
   就是在后面补一条更宽的选择器而不看它压住了谁。 */
@media (min-width: 1201px) and (max-width: 1780px) {
    .desk { grid-template-columns: 172px minmax(0, 1fr) 320px; }
    .col-detail { padding: 12px 13px 18px; }
}
/* 断点写在**视口**上，但决定放不放得下的是**中栏宽**：中栏 = 视口 − 两侧。
   1780 以下两侧收成 172+320=492，所以中栏 ≈ 视口 − 492。整表要 1221px，
   于是 1713 以下就得开始让列。 */
@media (min-width: 1201px) and (max-width: 1713px) {
    /* 按板块分组时，行里那一列跟组头重复。 */
    .picks [data-col="sector_label"] { display: none; }
}
@media (min-width: 1201px) and (max-width: 1620px) {
    .picks [data-col="indexes"] { display: none; }
}
/* 1440 以下 ISIN 让位。它是拿去券商里查的东西，但**判断依据排在它前面**
   ——实测 1280 上不让的话「当日」和「RSI」被挤出可见区，而那两列正是这
   张表回答问题的地方。ISIN 在右栏判断卡里，照样一点即复制。 */
@media (min-width: 1201px) and (max-width: 1440px) {
    .picks [data-col="isin"] { display: none; }
}
@media (min-width: 1201px) and (max-width: 1460px) {
    .picks [data-col="name"] { max-width: 14ch; }
    .picks [data-col="name"] .company {
        display: inline-block;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        vertical-align: bottom;
    }
}

/* 1200 以下右栏浮起来了，但**列也要跟着让** —— 中栏虽然拿回了右栏那 320px，
   十列还是放不下（实测 1024 上溢出 381px，RSI 被挤出去）。这一档跟宽屏
   那道梯子是同一个取舍，只是一次让完。 */
@media (max-width: 1200px) {
    .picks [data-col="sector_label"],
    .picks [data-col="indexes"],
    /* 准入是 HL 那张表的治理标记，不是行情。加了「24h」和「未平仓」两列
       之后**实测 1100 上表 942 / 容器 916，差 26px，准入正好被挤出可见区**
       ——与其让它挂在看不见的地方，不如明确让位；详情头一行有它。 */
    .picks [data-col="approval_status"],
    .picks [data-col="isin"] { display: none; }
}

/* HL 那张表在手机上：让掉准入之后仍差 55px（实测 390 上九列 494px，
   容器 390）。**未平仓再让一档**——它和涨跌都是 HL 原生指标，而两个里
   只能留一个时留涨跌：涨跌是「现在发生了什么」，未平仓是「有多少人还在
   场上」，前者才是扫一眼要的。两个数在详情「行情」块里都有，
   连币数一起。 */
@media (max-width: 900px) {
    .picks [data-col="open_interest_usd"] { display: none; }
}

/* HL 的身份列在最窄处要放得下又不吃掉整行。名字截断没关系——代码那个
   `.flag` 才是认人的东西，中文名是补充。 */
@media (max-width: 600px) {
    /* 日额让位给身份。**它是一道入场筛，不是逐行的判断依据**——这张表里
       每一行都已经过了 100 万成交额那道门槛，所以它在行与行之间不区分
       什么；而不知道这一行是哪个币，整行数字都读不了。
       实测：留着它 scrollWidth 478 / 视口 390，去掉正好装得下。 */
    .picks [data-col="day_notional_volume_usd"] { display: none; }

    /* 身份列和标记价各收一点，正好装进 390px。名字截断没关系——认人的是
       前面那个代码 `.flag`，中文名是补充。 */
    /* 身份列在最窄处**只留代码**，不留中文名。
       两个都留的话，截断会从右边吃掉——而右边正是代码（`.flag`），
       于是省下来的是「布伦特原…」，认得出是油，认不出是哪张合约，
       也没法拿去查。代码是身份，名字是补充，截断要从补充那头开始。
       min-width 也是必须的：只给 max-width 时表格会把这一列压到 55px。 */
    .picks [data-col="display_name"] .symbol { display: none; }
    .picks [data-col="display_name"] {
        min-width: 78px;
        max-width: 96px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .picks [data-col="mark_price"] {
        max-width: 74px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}

/* 三栏那一整段都差最后几十像素：1600 上三大指数差 20px（表 1128 / 容器 1108，
   它比全市场多一列 ISIN），1280 上全市场差 3px（中栏只有 788px）。
   **差这么点不该砍列**——从留白里出：八九列各减 2px 得三十几像素，够了，
   而 2px 的留白肉眼看不出来。行距一律不动，那是「费眼睛」的来源。 */
@media (min-width: 1201px) and (max-width: 1713px) {
    .picks th, .picks td { padding: 9px 6px; }
}
@media (max-width: 600px) {
    /* 手机上再收内边距。字号已经抬到 13.5，横向那点空间只能从留白里出——
       实测差 45px，五列各减 4px 正好。行距不动：那是「费眼睛」的来源。 */
    .picks th, .picks td { padding: 9px 6px; }
}

/* 1280px 上差最后 2px：这一档还有右栏（中栏只有 788px），八列各减 1px
   得 16px。跟上面那条注释里的「1280 上差 3px」是同一件事的第二次——
   **这条链路每加一列都会再来一遍**，所以量法（`scratch/ladder_probe.py`
   逐档印每列宽度）要留着，别只留结论。 */
@media (min-width: 1201px) and (max-width: 1320px) {
    .picks th, .picks td { padding: 9px 5px; }
}

/* 360px 上 RSI 出界 13px。**这条不是这次加列造成的**——对照组
   （注入 `[data-col="floor_price"]{display:none}`，等于这一列不存在）量得
   同样是 +13，而且这一列在 600 以下本来就让位了。它是更早那次给代码格加
   「🔔 灯」带进来的，而那次没有逐档跑过这道闸。

   撑住「代码」那一列的是**组头**，不是行里的记号。

   我在记号上白收了三轮（收 `.flag` 的内外边距、把「走势」缩成一个字、
   截断板块名），因为头两次量错了：按格子宽度排序，而所有格子都被拉伸到列宽，
   排出来的是任意几个。一锤定音的对照是藏掉组头整行再量列宽
   （`scratch/shot_group_header.py`）：**194 → 137，差 57px**。

   为什么截断板块名那次没效果：`.group-toggle` 是 flex，而 **flex 子项默认
   `min-width: auto`，压根压不到内容宽度以下**——只给 `max-width` 和
   `text-overflow` 是不够的，必须同时给 `min-width: 0`。

   收的是组头里的空和板块名，不是判断列，也不动字号（这一档的字号是用户
   明确要过的：「可以换成 2 行也没关系 但是字要大」）。板块名在组头上是重复
   信息——整组的身份靠它在表里的位置就认得出来，悬停/长按里还有全名。 */
@media (max-width: 430px) {
    .picks .group-toggle {
        min-width: 0;
        gap: 4px;
        padding: 6px 6px;
    }
    .picks .group-name {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}

/* 最后这几十像素，按「哪个字最不承重」收。实测缺口：360px 差 59、390 差 29、
   768 差 24、1024 差 37 —— 都不到一列宽，所以收留白和长名字，不再砍列。 */
@media (min-width: 601px) and (max-width: 1200px) {
    /* 公司名收窄。代码还在，全名在悬停和右栏里。 */
    .picks [data-col="name"] { max-width: 12ch; }
    .picks [data-col="name"] .company {
        display: inline-block;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        vertical-align: bottom;
    }
}
@media (max-width: 600px) {
    /* 行内那几个小标签（走势、双重）收一收。它们是入口和记号，不是读数，
       在手机上让出宽度给「离均线 / 当日 / RSI」那三列。 */
    .picks .flag { margin-left: 3px; padding: 0 3px; font-size: 10px; }
}
@media (max-width: 430px) {
    .picks th, .picks td { padding: 9px 4px; }
}

/* 中文名那一列是**后加的**，加完之后先把 390px 上的「当日」挤出可见区，
   逐宽扫描又发现 768 / 1024 / 1280 / 1440 上 **RSI 整列滚出可见区**
   （1280 的全市场连「离均线」一起）——而「这几档放得下」都是加它**之前**
   量的。**后加一列会让先前量的所有宽度作废，要整条梯子重扫。**

   让位的该是名字不是判断列：这张表回答「离均线多远、超没超卖」，名字是
   标识不是判据。所以这条界跟 ISIN 同档（≤1440），不是只在手机上让。
   中文名在右栏基本面卡片顶上还有一份（`fund-zhname`，两处是一对，
   手机那条闸同时量两边）。 */
@media (max-width: 1440px) {
    .picks [data-col="name_zh"] { display: none; }
}

/* **「当日」让位，「离均线」和 RSI 留下**。理由是这张表回答的问题——
   「它离均线多远、超没超卖」是判断，当日涨跌是背景，而背景在右栏判断卡里有。

   这个界原来是 380（当时量的：390 上不让也放得下）。2026-09-16 加「底线价」
   那一列之后逐档重量，抬到 1280，两件事一起改的：

   **一、加列把 RSI 挤出去了。** 768 上 RSI 右边缘从容器内 −3px 变成 +58px，
   1024 从 −4 变成 +57。**列顺序决定了砍谁**：RSI 排在「冲高」左边，
   让「冲高」让位一个像素都救不了它——要省的是它**左边**那些列的宽度。

   **二、RSI 在 390 / 430 / 1280 上本来就出界**（对照组量得 +55 / +15 / +11），
   那是加这一列之前就有的缺陷，只是没人逐档看过。同一条规则一起修掉。

   数是量出来的不是拍的：`scratch/ladder_probe.py` 注入
   `[data-col="floor_price"]{display:none}` 做对照组，同一次加载里开关各量一次，
   并印出每一档**还看得见的每列宽度**——省多少像素可以直接相加。 */
@media (max-width: 1280px) {
    .picks [data-col="change"] { display: none; }
}

/* 600 以下「底线价」也让位。它不是被牺牲掉的判断列——**它的用法是拿现价去
   跟它比，而「现价 / 均线」那一列在 600 以下已经让位了**（见上面那条）。
   一个没有现价可比的触发价，在手机上占一列却答不了任何问题。抽屉里有，
   而且抽屉在手机上是整屏的。 */
@media (max-width: 600px) {
    .picks [data-col="floor_price"] { display: none; }
}

/* 业务与壁垒：公司自己的表述，不是我们的判断——所以来源必须写在它下面。 */
.fund-intro { margin-bottom: 12px; }
.fund-introtext {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.7;
    color: var(--ink-2);
}
.fund-source { margin-top: 3px; font-size: 11px; color: var(--muted); }
/* 中文名：手机上中栏那列让位之后，这里是唯一一份，所以给它标题的分量。 */
.fund-zhname {
    margin: -4px 0 10px;
    font-size: 15px;
    font-weight: 600;
    color: var(--text);
    letter-spacing: 0.02em;
}
/* 市场参考那一行跟上面的 PE 是两个口径，缩进一格表示「它是那一行的注脚」，
   而不是又一个并列指标。 */
.fund-row.is-reference .fund-label { padding-left: 10px; color: var(--muted); }
.fund-row.is-reference .fund-value { font-weight: 400; color: var(--muted); }
.fund-bar.is-blank { background: none; }

/* —— 成员 —— */

/* `min-width` 赢过 `max-width`，也赢过 <dialog> 自带的 `max-width: calc(100% - …)`。
   写死 420px 的话，390px 的手机上整页可以横向滚，而右边的「发钥匙」和「收回」
   被推出视口。窄屏那一段的表格取舍全都处理过，这两个弹窗漏了。 */
.members { min-width: min(420px, 100%); max-width: 560px; }
.members-list {
    display: grid;
    gap: 6px;
    margin: 0 0 14px;
    font-size: 12px;
}
.member-row {
    display: grid;
    grid-template-columns: 1fr auto auto auto;
    align-items: center;
    gap: 10px;
    padding: 6px 8px;
    border: 1px solid var(--line);
    border-radius: 5px;
}
.member-row .member-name { font-weight: 600; }
.member-row .member-role,
.member-row .member-devices { color: var(--muted); font-size: 11px; }
/* 数字要对齐，否则「1/2」和「2/2」在一列里会左右跳。 */
.member-row .member-devices { font-variant-numeric: tabular-nums; }
.member-row button {
    padding: 3px 9px;
    border: 1px solid var(--line-hi);
    border-radius: 4px;
    background: var(--bg);
    color: var(--muted);
    font: inherit;
    font-size: 11px;
    cursor: pointer;
}
.member-row button:hover { color: var(--down); border-color: var(--down); }
.members-empty { color: var(--muted); font-size: 11px; }

.members-new { display: flex; gap: 8px; align-items: center; }
.members-new input { flex: 1 1 auto; }
.members-new select,
.members-new button {
    padding: 7px 10px;
    border: 1px solid var(--line-hi);
    border-radius: 5px;
    background: var(--bg);
    color: var(--ink);
    font: inherit;
}
.members-new button { cursor: pointer; }

.members-secret {
    margin: 0 0 14px;
    padding: 10px;
    border: 1px solid var(--accent);
    border-radius: 5px;
}
.members-secret code {
    display: block;
    /* 43 个字符要能整个选中复制，断行比截断重要。 */
    word-break: break-all;
    margin: 0 0 8px;
    font-size: 11.5px;
    color: var(--ink);
}
.members-secret button {
    padding: 4px 12px;
    border: 1px solid var(--line-hi);
    border-radius: 4px;
    background: var(--bg);
    color: var(--ink);
    font: inherit;
    font-size: 11px;
    cursor: pointer;
}
.members-secret span { margin-left: 8px; font-size: 11px; color: var(--muted); }
/* 不投票的锚（营收）：标一个可读的小字，并把整行压淡一档。**不靠颜色**——
   色盲外观下分不出来，而这一行恰恰是「别拿它下结论」的那一行。 */
.val-ref-tag {
    margin-left: 5px;
    padding: 0 4px;
    border: 1px dashed var(--border);
    border-radius: 3px;
    font-size: 9.5px;
    color: var(--muted);
    vertical-align: 1px;
}
.val-row.is-reference .val-px,
.val-row.is-reference .val-gap { opacity: .72; }

/* —— 研究线（desk-research.js）——
   这张表大半是文字不是数字：默认的右对齐会让结论那一列参差不齐。
   结论那一列允许折行，否则一句话结论会把表撑出横向滚动。 */
.picks th[data-col="verdict"], .picks td[data-col="verdict"],
.picks th[data-col="waiting_on"], .picks td[data-col="waiting_on"] { text-align: left; }
.picks td[data-col="verdict"] { white-space: normal; min-width: 16em; }
.research-text { margin: 6px 0 0; font-size: 12px; line-height: 1.6; color: var(--ink); }
.research-cmd {
    margin-top: 4px;
    font-family: var(--font-mono);
    font-size: 11px;
    color: var(--ink-2);
    overflow-wrap: anywhere;
}
/* 右栏那三个固定区块（融冰 / 去劣 / 格雷厄姆）只有美股和 HL 会填。别的源
   选中一行时它们是空的，却照样画出三条分隔线。空着就不占地方。 */
#detail .block:empty { display: none; }

/* 超过期限没核对的整行变灰。状态那枚章保留自己的颜色：「等你定」过期了
   也还是在等你。 */
.picks tbody tr.is-stale td { color: var(--muted); }

/* 手机：实测 390px 宽时表要横滚 301px。「在等谁」「核对」让位——右栏
   抽屉的头两行就是这两样，过期的那条整行灰、抽屉顶上还会再说一遍。
   研究线名字折行，把宽度让给结论。 */
@media (max-width: 600px) {
    .picks [data-col="waiting_on"],
    .picks [data-col="checked_on"] { display: none; }
    .picks td[data-col="line"] { white-space: normal; min-width: 5em; }
    .picks td[data-col="verdict"] { min-width: 0; }
}
