
/* ============================================================
   设计令牌 —— 沿用家族深蓝 #172a63 与红 #c8102e，
   但按数据密集型后台系统重置：低圆角、细分隔线、等宽数字。
   ============================================================ */
:root{
  --navy:#172a63; --navy-deep:#0e1c44; --navy-soft:#33457f; --navy-mist:#e8edf7;
  --red:#c8102e; --red-soft:#fbeef1; --red-line:#f0c9d1;
  --up:#c8102e; --down:#178a4c;
  --amber:#a8730a; --amber-soft:#fbf3e2; --amber-line:#ecdcb6;
  --teal:#1f6b73; --teal-soft:#e8f1f2; --teal-line:#c3dcdf;
  --gray:#6b7280; --gray-soft:#f0f1f4;
  --ink:#1c2331; --muted:#5d6675; --faint:#8b94a4;
  --line:#dee4ee; --line-soft:#edf0f6;
  --paper:#ffffff; --bg:#eaeef5; --tint:#f6f8fc;
  --font:"Microsoft YaHei","PingFang SC","Hiragino Sans GB","Segoe UI",sans-serif;
  --mono:"Cascadia Mono","Consolas","SF Mono",ui-monospace,"Courier New",monospace;
  /* 拖拽只改 --rail-w（写成 html 的行内样式），--rail 由它派生。若让拖拽直接写 --rail，
     行内值会压过下面 html.rail-collapsed 里的 52px，收起功能当场失效。 */
  --rail-w:214px; --rail:var(--rail-w);
}
*{margin:0;padding:0;box-sizing:border-box;}
html,body{height:100%;}
body{
  font-family:var(--font); font-size:13px; color:var(--ink); background:var(--bg);
  -webkit-font-smoothing:antialiased; display:flex; overflow:hidden;
}
.num{font-family:var(--mono); font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1;}
.up{color:var(--up);} .dn{color:var(--down);} .nv{color:var(--navy);}
button,input,select{font-family:inherit; font-size:inherit; color:inherit;}
button{cursor:pointer; background:none; border:none;}
:focus-visible{outline:2px solid var(--navy-soft); outline-offset:1px;}
::-webkit-scrollbar{width:9px;height:9px;}
::-webkit-scrollbar-thumb{background:#c3ccdd;border-radius:5px;border:2px solid var(--bg);}
::-webkit-scrollbar-track{background:transparent;}
@media (prefers-reduced-motion:reduce){*{transition:none !important;animation:none !important;}}

/* ============ 左侧导航（品牌深蓝竖轨） ============ */
.rail{
  width:var(--rail); flex:none; height:100vh; background:linear-gradient(178deg,var(--navy-deep),#16265a 60%,var(--navy));
  color:#c4cee6; display:flex; flex-direction:column; position:relative; transition:width .16s;
}
.rail::after{content:"";position:absolute;right:0;top:0;bottom:0;width:3px;
  background:linear-gradient(180deg,var(--red) 0 88px,rgba(255,255,255,.10) 88px 100%);}
.brand{padding:16px 16px 14px; border-bottom:1px solid rgba(255,255,255,.09);}
/* 两行标题：字号与字距按 214px 的左轨反推，单行放不下十一个字 */
.brand .bt{font-size:15px;font-weight:700;color:#fff;letter-spacing:1.2px;line-height:1.45;}
.brand .bs{margin-top:4px;font-size:10.5px;color:#8fa0c8;letter-spacing:1.6px;font-family:var(--mono);}
.brand .bm{display:none;font-family:var(--mono);font-size:14px;font-weight:700;color:#fff;letter-spacing:2px;}
.navgrp{padding:14px 0 2px;}
.navgrp .gt{padding:0 16px 7px;font-size:10px;color:#7286b3;letter-spacing:2.4px;}
.nav{display:flex;align-items:center;gap:9px;padding:8px 16px;width:100%;text-align:left;
  color:#c4cee6;font-size:12.5px;border-left:3px solid transparent;transition:background .12s;}
.nav:hover{background:rgba(255,255,255,.06);color:#fff;}
/* 债券ETF 那条是 <a> 不是 <button>：它跳的是 /etf 那个独立页面。锚点自带下划线，
   也不继承按钮那套盒模型，补齐这两条，视觉上与其余菜单项一致。 */
a.nav{text-decoration:none;box-sizing:border-box;}
.nav.on{background:rgba(255,255,255,.10);color:#fff;border-left-color:var(--red);font-weight:700;}
.nav svg{width:14px;height:14px;flex:none;stroke:currentColor;fill:none;stroke-width:1.5;opacity:.85;}
.nav .n{margin-left:auto;font-family:var(--mono);font-size:10.5px;color:#8fa0c8;}
.nav.on .n{color:#e2b7bd;}
/* 二级菜单：策略详情与策略对比挂在策略市场下面，常驻而不是选中才出现。
   缩进 + 更小的字号把层级说清楚，展开箭头让它可收起，省得三条常年占着左轨。 */
.nav.sub{padding-left:38px;font-size:12px;color:#a9b6d6;}
.nav.sub::before{content:"";position:absolute;left:26px;width:5px;height:1px;background:#5c6f9e;}
.nav.sub{position:relative;}
.nav.sub.on{color:#fff;}
/* 箭头不再只归导航用，方案那块共用同一个视觉。transform 对非替换的行内元素不生效，
   靠的是父级 display:flex 把它变成 flex item——给 .cx 换宿主时父级也得是 flex。 */
.cx{font-size:9px;color:#7286b3;transition:transform .12s;padding-left:6px;}
.cx.open{transform:rotate(90deg);}
.cx:hover{color:#fff;}
.nav .cx{margin-left:auto;}
/* 左轨中段。min-height:0 不能省：flex 子项的默认 min-height 是 auto，不压成 0 它就会被
   内容撑开，overflow 永远轮不到触发，滚动条根本不出现——而页面看上去只是「底下那块没了」。 */
.railbody{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;}
.railbody>nav,.railbody>.shelfkey{flex:none;}
/* 全局那条滚动条样式的边框用的是浅色 --bg，压在深色左轨上是一道白边，这里单独给一套 */
.railbody::-webkit-scrollbar{width:6px;}
.railbody::-webkit-scrollbar-thumb{background:rgba(255,255,255,.16);border:2px solid transparent;
  background-clip:padding-box;border-radius:5px;}

/* 货架分层图例 —— 界面各处色带的对照表 */
.shelfkey{margin-top:auto;padding:14px 16px 12px;border-top:1px solid rgba(255,255,255,.09);}
.shelfkey .gt{display:flex;align-items:center;width:100%;text-align:left;
  font-size:10px;color:#7286b3;letter-spacing:2.4px;margin-bottom:8px;}
.shelfkey .gt:hover{color:#c4cee6;}
.shelfkey .gt .n{margin-left:auto;font-family:var(--mono);font-size:10px;letter-spacing:0;color:#8fa0c8;}
/* 收起后连标题下边距一起收掉，否则底下空一条 */
.shelfkey.fold .mytpl{display:none;}
.shelfkey.fold .gt{margin-bottom:0;}
.shelfkey div.k{display:flex;align-items:center;gap:8px;font-size:11.5px;color:#a9b6d6;padding:2.5px 0;}
.shelfkey i{width:11px;height:3px;flex:none;display:block;}
/* 收起开关。压在左轨最底下，视觉上与 .nav 拉开距离——它不是一个可以点进去的页面。
   左边那 3px 透明边与 .nav 的 border-left 对齐，箭头才和上面一列图标同一条竖线上。 */
.railtog{flex:none;display:flex;align-items:center;gap:8px;width:100%;text-align:left;
  padding:9px 16px;color:#7286b3;font-size:11.5px;border-top:1px solid rgba(255,255,255,.09);
  border-left:3px solid transparent;transition:background .12s,color .12s;}
.railtog::before{content:"\00ab";font-size:14px;line-height:1;}
.railtog:hover{background:rgba(255,255,255,.06);color:#fff;}
/* 右缘拖拽条。盖在 .rail::after 那条红饰条上，自身透明，hover 或聚焦才现出一条亮线。
   宽 7px 且向外探 2px：照着 3px 的饰条去拖，十次有八次落空。 */
/* 大半个身子探到主区那侧：中段的滚动条也贴着这条边，拖拽条压上去会把滚动条的把手
   整个挡住。往外让 4px，滚动条还剩一半可抓，滚轮任何时候都不受影响。 */
.railgrip{position:absolute;top:0;bottom:0;right:-4px;width:7px;z-index:5;
  cursor:col-resize;touch-action:none;}
/* 高亮落在红饰条外侧那 2px 上，不盖住它——盖住的效果是「一碰左轨品牌红就没了」 */
.railgrip::after{content:"";position:absolute;top:0;bottom:0;left:3px;width:2px;
  background:var(--navy-soft);opacity:0;transition:opacity .12s;}
.railgrip:hover::after,.railgrip:focus-visible::after{opacity:.9;}

/* ---------- 收起态：左轨缩成图标轨 ----------
   `--rail` 是继承变量，且全项目只被上面 `.rail` 那一处消费，所以在 html 上重定义就够了，
   主区 `flex:1` 自动补位，不必给 `.main` 再写第二份宽度——两份宽度迟早会对不上。
   标记为什么打在 html 上而不是 body，见 index.html 头部那段还原脚本的注释。
   过渡不用为 prefers-reduced-motion 另写降级，文件开头那条 !important 通配规则已经管了。 */
html.rail-collapsed{--rail:52px;}
html.rail-collapsed .brand{height:52px;padding:0;display:flex;align-items:center;justify-content:center;}
html.rail-collapsed .brand .bt,html.rail-collapsed .brand .bs{display:none;}
html.rail-collapsed .brand .bm{display:block;}
/* 品牌块矮了，右缘那条红饰条的断点得跟着挪，否则红线在品牌分隔线上下错开一截 */
html.rail-collapsed .rail::after{
  background:linear-gradient(180deg,var(--red) 0 52px,rgba(255,255,255,.10) 52px 100%);}
html.rail-collapsed .navgrp{padding:8px 0 2px;}
html.rail-collapsed .navgrp .gt{display:none;}
/* 右边补的 3px 抵掉 border-left 那 3px，不然图标偏出竖轨中线一点五个像素 */
html.rail-collapsed .nav{position:relative;justify-content:center;padding:9px 3px 9px 0;}
/* 一条规则盖掉名称、数量角标 .n 与展开箭头 .cx——收起态只留图标 */
html.rail-collapsed .nav>span{display:none;}
/* 二级项没有图标（buildNav 只给一级项渲 svg），留着就是几条空白横条 */
html.rail-collapsed .nav.sub{display:none;}
html.rail-collapsed .shelfkey{display:none;}
/* 52px 宽下再留 8px 给滚动条，图标列会被挤得偏左。收起态本来也只剩一列图标，藏掉。 */
html.rail-collapsed .railbody{scrollbar-width:none;}
html.rail-collapsed .railbody::-webkit-scrollbar{display:none;}
/* 收起态是固定 52px 的图标轨，没有可拖的余地 */
html.rail-collapsed .railgrip{display:none;}

/* 拖动进行中。关掉宽度过渡，否则左轨会追着光标一路橡皮筋；顺手禁掉文本选中，
   不然光标扫过主区会把满屏文字刷成蓝的。 */
html.rail-sizing .rail{transition:none;}
html.rail-sizing{cursor:col-resize;user-select:none;-webkit-user-select:none;}
/* .shelfkey 的 margin-top:auto 是把底部那几块顶下去的那一脚，收起态它整块不显示，
   auto 得转交给开关，否则开关会紧贴着图标列悬在半空。 */
html.rail-collapsed .railtog{margin-top:auto;justify-content:center;padding:11px 3px 11px 0;}
html.rail-collapsed .railtog::before{content:"\00bb";}
html.rail-collapsed .railtog>span{display:none;}
/* 悬停气泡。图标轨上名称是唯一的辨识途径，原生 title 那一秒延迟等浮出来时人已经点过了。 */
html.rail-collapsed .nav::after{content:attr(data-t);position:absolute;left:calc(100% + 9px);top:50%;
  transform:translateY(-50%);background:var(--navy-deep);border:1px solid rgba(255,255,255,.16);
  color:#fff;font-size:11.5px;line-height:1;padding:5px 9px;white-space:nowrap;
  opacity:0;pointer-events:none;z-index:60;transition:opacity .1s;}
html.rail-collapsed .nav:hover::after{opacity:1;}

/* ============ 主区 ============ */
.main{flex:1;min-width:0;height:100vh;display:flex;flex-direction:column;}
.topbar{flex:none;height:50px;background:var(--paper);border-bottom:1px solid var(--line);
  display:flex;align-items:center;gap:14px;padding:0 18px;}
.topbar h1{font-size:15px;font-weight:700;color:var(--navy);letter-spacing:.5px;}
.topbar .crumb{font-size:11.5px;color:var(--faint);}
.topbar .sp{flex:1;}
.topbar .meta{font-size:11.5px;color:var(--muted);display:flex;align-items:center;gap:14px;}
.topbar .meta b{color:var(--navy);font-weight:700;}
.hairline{flex:none;height:2px;display:flex;}
.hairline i:nth-child(1){width:20%;background:var(--navy);}
.hairline i:nth-child(2){width:6%;background:var(--red);}
.hairline i:nth-child(3){flex:1;background:var(--line);}
.scroll{flex:1;overflow-y:auto;overflow-x:hidden;padding:14px 18px 30px;}
.view{display:none;} .view.on{display:block;}

/* ============ 通用面板 ============ */
.panel{background:var(--paper);border:1px solid var(--line);margin-bottom:12px;}
.ph{height:32px;display:flex;align-items:center;gap:8px;padding:0 12px;background:var(--tint);border-bottom:1px solid var(--line);}
.ph h2{font-size:12.5px;font-weight:700;color:var(--navy);display:flex;align-items:center;gap:7px;}
.ph h2::before{content:"";width:3px;height:11px;background:var(--red);flex:none;}
.ph .sub{font-size:11px;color:var(--faint);}
.ph .sp{flex:1;}
.pb{padding:12px;}
.pb.tight{padding:0;}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:12px;}
.grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;}

/* ============ 概览数字条 ============ */
.kpibar{display:flex;background:var(--paper);border:1px solid var(--line);margin-bottom:12px;}
.kpi{flex:1;padding:11px 16px;border-right:1px solid var(--line-soft);position:relative;}
.kpi:last-child{border-right:none;}
.kpi .k{font-size:10.5px;color:var(--faint);letter-spacing:1.6px;}
.kpi .v{font-family:var(--mono);font-size:27px;font-weight:700;color:var(--navy);line-height:1.15;margin-top:3px;}
.kpi .v small{font-size:12px;font-weight:400;color:var(--muted);margin-left:3px;letter-spacing:0;}
.kpi .d{font-size:11px;color:var(--muted);margin-top:2px;}
.kpi.alert .v{color:var(--red);}
.kpi::before{content:"";position:absolute;left:0;top:11px;bottom:11px;width:2px;background:var(--navy);}
.kpi.alert::before{background:var(--red);}

/* ============ 筛选器 ============ */
.market{display:grid;grid-template-columns:212px 1fr;gap:12px;align-items:start;}
.filters{position:sticky;top:0;}
.fgrp{padding:10px 12px;border-bottom:1px solid var(--line-soft);}
.fgrp:last-child{border-bottom:none;}
.fgrp .ft{font-size:10.5px;color:var(--faint);letter-spacing:1.4px;margin-bottom:7px;}
.chips{display:flex;flex-wrap:wrap;gap:5px;}
.chip{font-size:11.5px;padding:3px 8px;border:1px solid var(--line);background:#fff;color:var(--muted);
  line-height:1.5;transition:all .12s;}
.chip:hover{border-color:var(--navy-soft);color:var(--navy);}
.chip.on{background:var(--navy);border-color:var(--navy);color:#fff;font-weight:700;}
.chip .c{font-family:var(--mono);font-size:10px;opacity:.65;margin-left:3px;}
.chip.zero{opacity:.42;}
.chip:disabled{cursor:not-allowed;}
.chip:disabled:hover{border-color:var(--line);color:var(--muted);}
.srch{width:100%;padding:6px 8px;border:1px solid var(--line);background:#fff;font-size:12px;}
.srch::placeholder{color:var(--faint);}
.lnk{font-size:11px;color:var(--navy-soft);text-decoration:underline;text-underline-offset:2px;}
.lnk:hover{color:var(--red);}

/* ============ 策略卡片 ============ */
.toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 12px;background:var(--paper);
  border:1px solid var(--line);margin-bottom:12px;font-size:11.5px;color:var(--muted);}
.toolbar select{border:1px solid var(--line);padding:4px 6px;background:#fff;font-size:11.5px;}
.toolbar .sp{flex:1;}
.seg{display:flex;border:1px solid var(--line);}
.seg button{padding:4px 10px;font-size:11.5px;color:var(--muted);border-right:1px solid var(--line);}
.seg button:last-child{border-right:none;}
.seg button.on{background:var(--navy);color:#fff;font-weight:700;}

.cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(262px,1fr));gap:10px;}
/* 资产类别分组：6.4 规定默认按资产类别分组展示，不做跨资产类的单一排行榜 */
.grp{margin-bottom:14px;}
.grp:last-child{margin-bottom:0;}
.grphd{display:flex;align-items:baseline;gap:9px;padding:0 0 5px;margin-bottom:9px;border-bottom:1px solid var(--line);}
.grphd b{font-size:12.5px;color:var(--navy);letter-spacing:.5px;}
.grphd b::before{content:"";display:inline-block;width:3px;height:10px;background:var(--navy);margin-right:7px;vertical-align:-1px;}
.grphd .gc{font-family:var(--mono);font-size:11px;color:var(--faint);}
.grphd .gs{font-size:11px;color:var(--faint);margin-left:auto;}
.crosswarn{background:var(--amber-soft);border:1px solid var(--amber-line);border-left:3px solid var(--amber);
  padding:8px 11px;font-size:11.5px;line-height:1.55;color:#6d4a08;margin-bottom:12px;}
.crosswarn b{color:#8a5c06;}
.card{background:var(--paper);border:1px solid var(--line);border-left:3px solid var(--navy);
  padding:10px 11px 11px;position:relative;cursor:pointer;transition:box-shadow .12s,border-color .12s;}
.card:hover{box-shadow:0 3px 14px rgba(23,42,99,.10);border-color:var(--navy-soft);}
.card.sel{box-shadow:0 0 0 1px var(--navy) inset;}
.card.plan{border-left-style:dashed;background:repeating-linear-gradient(135deg,#fafbfd,#fafbfd 9px,#f3f5fa 9px,#f3f5fa 18px);cursor:default;}
.card.plan:hover{box-shadow:none;border-color:var(--line);}
.card .r1{display:flex;align-items:center;gap:6px;font-family:var(--mono);font-size:10.5px;color:var(--faint);}
.card .r1 .as{font-family:var(--font);color:var(--muted);}
.card .r1 .sp{flex:1;}
.card h3{font-size:13px;font-weight:700;color:var(--navy);line-height:1.35;margin:4px 0 3px;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:35px;}
.card .cmeta{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.card .mrow{display:flex;gap:2px;margin:8px 0 6px;border-top:1px solid var(--line-soft);padding-top:7px;}
.card .m{flex:1;min-width:0;}
.card .m .mk{font-size:10px;color:var(--faint);}
.card .m .mv{font-family:var(--mono);font-size:14px;font-weight:700;margin-top:1px;}
.card .kv{display:flex;justify-content:space-between;font-size:11px;color:var(--muted);margin-top:3px;gap:6px;}
.card .kv b{font-family:var(--mono);font-weight:700;color:var(--ink);}
.spark{width:100%;height:26px;display:block;margin:2px 0 5px;}
.bar{height:4px;background:var(--line-soft);position:relative;margin-top:3px;}
.bar i{position:absolute;left:0;top:0;bottom:0;background:var(--navy-soft);}
.bar i.hot{background:var(--red);}
.bar i.ok{background:var(--teal);}
.pick{position:absolute;top:8px;right:9px;width:13px;height:13px;border:1px solid var(--line);background:#fff;}
.pick.on{background:var(--navy);border-color:var(--navy);}
.pick.on::after{content:"";position:absolute;left:3px;top:5px;width:5px;height:2px;background:#fff;}
.pick.on::before{content:"";position:absolute;left:5px;top:3px;width:2px;height:7px;background:#fff;transform:rotate(38deg);}

/* 状态与层级标签 */
.tag{font-size:10px;padding:1.5px 5px;border:1px solid;line-height:1.5;white-space:nowrap;}
.t-live{color:#fff;background:var(--navy);border-color:var(--navy);}
/* 已回测待进模拟盘：预审已过但平台无日更调度，与模拟跟踪中（青色）必须一眼可分 */
.t-backtested{color:var(--navy-soft);background:var(--navy-mist);border-color:#c2cde6;border-style:dashed;}
.t-paper{color:var(--teal);background:var(--teal-soft);border-color:var(--teal-line);}
.t-review{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line);}
.t-priv{color:var(--muted);background:var(--tint);border-color:var(--line);}
/* 只读字段：长得像输入框，但明确不能改。用在择时策略的合成基准那一栏 */
.rofld{border:1px dashed var(--line);background:var(--tint);color:var(--muted);
       padding:5px 8px;font-size:12px;line-height:1.5;}
/* 表格里就地改的小下拉，比按钮省地方 */
.minisel{border:1px solid var(--line);background:#fff;font-size:11px;padding:2px 4px;
         font-family:inherit;color:var(--ink);}
/* 页面上的说明块。基础规则原先漏了，只有 `.warn` 那一条改 border-color——
   而没有 border-width 与 border-style，颜色改了也不会有框，两种告示看着一样。 */
.notice{border:1px solid var(--line);background:var(--tint);color:var(--muted);
        padding:7px 10px;font-size:11.5px;line-height:1.65;}
.notice b{color:var(--ink);}
.notice.warn{background:var(--amber-soft);border-color:var(--amber-line);color:var(--amber);}
.notice.warn b{color:var(--amber);}
.t-study{color:var(--gray);background:var(--gray-soft);border-color:#d9dce3;}
.t-pause{color:#fff;background:var(--gray);border-color:var(--gray);}
.t-refuted{color:var(--gray);background:#fff;border-color:var(--gray);border-style:dashed;}
.t-plan{color:#9aa4b5;background:#fff;border-color:#c6ccd8;border-style:dashed;}
.shelf-可申购{border-left-color:var(--navy) !important;}
.shelf-工具{border-left-color:var(--teal) !important;}
.shelf-监控信号{border-left-color:var(--amber) !important;}
.shelf-否证档案{border-left-color:var(--gray) !important;}
.shelf-规划中{border-left-color:#9aa4b5 !important;}

/* ============ 表格 ============ */
table{width:100%;border-collapse:collapse;font-size:12px;}
th{background:var(--tint);color:var(--muted);font-weight:700;font-size:11px;letter-spacing:.4px;
  text-align:left;padding:7px 9px;border-bottom:1px solid var(--line);white-space:nowrap;}
th.r,td.r{text-align:right;}
th.c,td.c{text-align:center;}
th.s{cursor:pointer;user-select:none;}
th.s:hover{color:var(--navy);}
th.s .ar{width:7px;height:5px;color:var(--navy);margin-left:3px;display:inline-block;}
td{padding:6px 9px;border-bottom:1px solid var(--line-soft);vertical-align:middle;}
tbody tr:nth-child(even){background:#fbfcfe;}
tbody tr.hov:hover{background:var(--navy-mist);cursor:pointer;}
td.n{font-family:var(--mono);font-variant-numeric:tabular-nums;}
tbody tr.tot{background:var(--navy-mist) !important;font-weight:700;}
tbody tr.tot td{border-top:1px solid var(--line);}
.nm{font-weight:700;color:var(--navy);}
.dim{color:var(--faint);}

/* ============ 详情页 ============ */
.dhead{background:var(--paper);border:1px solid var(--line);border-left:3px solid var(--navy);
  padding:12px 14px;margin-bottom:12px;display:flex;align-items:flex-start;gap:16px;}
.dhead .l{min-width:0;flex:1;}
.dhead .id{font-family:var(--mono);font-size:11px;color:var(--faint);letter-spacing:.6px;}
.dhead h2{font-size:19px;font-weight:700;color:var(--navy);margin:2px 0 6px;letter-spacing:.3px;}
.dhead .facts{display:flex;flex-wrap:wrap;gap:0 18px;font-size:11.5px;color:var(--muted);}
.dhead .facts span b{color:var(--ink);font-weight:700;}
.dhead .acts{display:flex;gap:6px;flex:none;}
.btn{border:1px solid var(--navy);color:var(--navy);background:#fff;padding:5px 11px;font-size:11.5px;font-weight:700;transition:all .12s;}
.btn:hover{background:var(--navy);color:#fff;}
.btn.pri{background:var(--navy);color:#fff;}
.btn.pri:hover{background:var(--navy-deep);}
.btn.gh{border-color:var(--line);color:var(--muted);font-weight:400;}
.btn.gh:hover{background:var(--tint);color:var(--navy);border-color:var(--navy-soft);}
.btn.sm{padding:3px 8px;font-size:11px;}
.lockband{background:var(--red-soft);border:1px solid var(--red-line);border-left:3px solid var(--red);
  padding:7px 11px;font-size:11.5px;color:#7a1424;margin-bottom:12px;display:flex;gap:8px;align-items:baseline;}
.lockband b{font-family:var(--mono);}
.dcols{display:grid;grid-template-columns:1fr 306px;gap:12px;align-items:start;}
.chart{width:100%;}
.mini{font-size:11.5px;line-height:1.6;color:var(--muted);}
.mini b{color:var(--ink);}
.deflist{font-size:11.5px;}
.deflist div{display:flex;justify-content:space-between;gap:8px;padding:4px 0;border-bottom:1px solid var(--line-soft);}
.deflist div:last-child{border-bottom:none;}
.deflist span{color:var(--muted);}
.deflist b{font-family:var(--mono);font-weight:700;color:var(--ink);text-align:right;}
.tl{position:relative;padding-left:15px;}
.tl::before{content:"";position:absolute;left:3px;top:5px;bottom:5px;width:1px;background:var(--line);}
.tl .it{position:relative;padding:0 0 11px;}
.tl .it::before{content:"";position:absolute;left:-15px;top:4px;width:7px;height:7px;background:#fff;border:1.5px solid var(--navy-soft);border-radius:50%;}
.tl .it.cur::before{background:var(--red);border-color:var(--red);}
.tl .it .vv{font-family:var(--mono);font-size:11.5px;font-weight:700;color:var(--navy);}
.tl .it .dd{font-family:var(--mono);font-size:10.5px;color:var(--faint);margin-left:6px;}
.tl .it p{font-size:11.5px;color:var(--muted);line-height:1.5;margin-top:2px;}

/* ============ 组合工作台 ============ */
.wb{display:grid;grid-template-columns:288px 1fr 292px;gap:12px;align-items:start;}
.sleeve{padding:9px 11px;border-bottom:1px solid var(--line-soft);}
.sleeve:last-child{border-bottom:none;}
.sleeve .s1{display:flex;align-items:baseline;gap:6px;}
.sleeve .s1 .nm2{font-size:12px;font-weight:700;color:var(--navy);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.sleeve .s1 .w{font-family:var(--mono);font-size:12.5px;font-weight:700;color:var(--ink);}
.sleeve .s2{font-size:10.5px;color:var(--faint);font-family:var(--mono);margin-top:1px;display:flex;gap:8px;}
.sleeve .s2 .sp{flex:1;}
.rng{position:relative;height:20px;margin-top:5px;}
.rng .track{position:absolute;left:0;right:0;top:8px;height:4px;background:var(--line);}
.rng .fill{position:absolute;top:8px;height:4px;background:var(--navy-soft);}
.rng input{position:absolute;left:0;top:0;width:100%;height:20px;margin:0;background:transparent;
  -webkit-appearance:none;appearance:none;pointer-events:none;}
.rng input::-webkit-slider-runnable-track{height:4px;background:transparent;}
.rng input::-webkit-slider-thumb{-webkit-appearance:none;pointer-events:auto;width:11px;height:11px;
  border-radius:50%;background:#fff;border:2px solid var(--navy);cursor:grab;margin-top:-3.5px;}
.rng input::-moz-range-track{height:4px;background:transparent;}
.rng input::-moz-range-thumb{pointer-events:auto;width:9px;height:9px;border-radius:50%;
  background:#fff;border:2px solid var(--navy);cursor:grab;}
.cons{padding:8px 11px;border-bottom:1px solid var(--line-soft);}
.cons:last-child{border-bottom:none;}
.cons .c1{display:flex;align-items:center;gap:7px;}
.cons .c1 .lb{font-size:11.5px;color:var(--ink);flex:1;}
.cons .c1 .vl{font-family:var(--mono);font-size:12px;font-weight:700;}
.cons .c2{font-size:10.5px;color:var(--faint);margin-top:2px;line-height:1.45;}
.dot{width:7px;height:7px;flex:none;border-radius:50%;}
.d-ok{background:var(--teal);} .d-warn{background:var(--amber);} .d-bad{background:var(--red);}
.gauge{height:3px;background:var(--line-soft);margin-top:4px;position:relative;}
.gauge i{position:absolute;left:0;top:0;bottom:0;background:var(--navy-soft);}
.gauge i.warn{background:var(--amber);} .gauge i.bad{background:var(--red);}
.gauge .lim{position:absolute;top:-2px;bottom:-2px;width:1px;background:var(--red);}
.note{background:var(--navy-mist);border-left:3px solid var(--navy-soft);padding:8px 10px;
  font-size:11.5px;line-height:1.55;color:#2c3a5e;}
.note b{color:var(--navy);}

/* ============ 治理 ============ */
.steps{display:flex;align-items:center;gap:0;flex:1;min-width:280px;}
.step{flex:1;position:relative;text-align:center;padding-top:12px;}
.step::before{content:"";position:absolute;top:3px;left:50%;width:7px;height:7px;margin-left:-3.5px;
  border-radius:50%;background:#fff;border:1.5px solid var(--line);z-index:1;}
.step::after{content:"";position:absolute;top:6px;left:50%;width:100%;height:1px;background:var(--line);}
.step:last-child::after{display:none;}
.step.done::before{background:var(--navy);border-color:var(--navy);}
.step.done::after{background:var(--navy);}
.step.cur::before{background:var(--red);border-color:var(--red);width:9px;height:9px;margin-left:-4.5px;top:2px;}
.step .sl{font-size:10px;color:var(--faint);}
.step.cur .sl{color:var(--red);font-weight:700;}
.step.done .sl{color:var(--navy);}
.revrow{padding:9px 12px;border-bottom:1px solid var(--line-soft);display:flex;gap:16px;align-items:flex-start;}
.revrow:last-child{border-bottom:none;}
.revrow .rl{width:214px;flex:none;}
.revrow .rl .nm3{font-size:12px;font-weight:700;color:var(--navy);}
.revrow .rl .mt{font-size:10.5px;color:var(--faint);font-family:var(--mono);margin-top:1px;}
.revrow .rr{width:150px;flex:none;text-align:right;font-size:11px;color:var(--muted);}
.revrow p{font-size:11px;color:var(--muted);line-height:1.5;margin-top:6px;}
.sla{font-size:10px;padding:1px 5px;border:1px solid;}
.sla.normal{color:var(--navy);border-color:var(--navy-mist);background:var(--navy-mist);}
.sla.late{color:var(--red);border-color:var(--red-line);background:var(--red-soft);}
.sla.hold{color:var(--gray);border-color:#d9dce3;background:var(--gray-soft);}
/* 治理页只有审批工作台与相似度两块。热力图panel不锁死高度，
   由右侧策略对列表把这一行撑开，图跟着填满，避免左侧留出大片空白 */
.simmap{display:grid;grid-template-columns:1fr 396px;gap:12px;}
.simmap .simchart{display:flex;flex-direction:column;}
.simmap .simchart .pb{flex:1;display:flex;}
.simmap .simchart .chart{flex:1;min-height:392px;}
.pairs{font-size:11.5px;}
.pairs .pr{display:flex;align-items:center;gap:8px;padding:6px 0;border-bottom:1px solid var(--line-soft);}
.pairs .pr:last-child{border-bottom:none;}
.pairs .pr .cc{font-family:var(--mono);font-weight:700;width:42px;text-align:right;}
.pairs .pr .tx{flex:1;color:var(--muted);}
.pairs .pr .tx b{color:var(--ink);font-weight:400;}

/* ============ 告警 ============ */
.lv{font-size:10px;padding:1.5px 6px;border:1px solid;font-weight:700;white-space:nowrap;}
.nw{white-space:nowrap;}
.lv-红灯{color:#fff;background:var(--red);border-color:var(--red);}
.lv-黄灯{color:var(--amber);background:var(--amber-soft);border-color:var(--amber-line);}
.lv-观察{color:var(--muted);background:var(--gray-soft);border-color:#d9dce3;}
.st{font-size:10.5px;color:var(--muted);}
.st.open{color:var(--red);font-weight:700;}

/* ============ 提示条 ============ */
.toast{position:fixed;right:18px;bottom:18px;background:var(--navy-deep);color:#fff;
  padding:10px 14px;font-size:12px;border-left:3px solid var(--red);max-width:340px;line-height:1.5;
  box-shadow:0 8px 26px rgba(14,28,68,.34);opacity:0;transform:translateY(8px);
  transition:opacity .18s,transform .18s;pointer-events:none;z-index:99;}
.toast.on{opacity:1;transform:translateY(0);}
.empty{padding:34px 12px;text-align:center;color:var(--faint);font-size:12px;}
.empty b{display:block;color:var(--muted);font-size:13px;margin-bottom:4px;}

@media (max-width:1360px){
  .dcols{grid-template-columns:1fr 272px;}
  .simmap{grid-template-columns:1fr 336px;}
  .wb{grid-template-columns:250px 1fr 258px;}
  .market{grid-template-columns:190px 1fr;}
  .cards{grid-template-columns:repeat(auto-fill,minmax(232px,1fr));}
  /* 分区间绩效加了信息比一列，窄屏收紧单元格内边距，避免横向溢出 */
  #dMetrics th,#dMetrics td{padding-left:5px;padding-right:5px;}
}

/* ==================== 以下为策略平台新增 ==================== */

/* ---------- 时间区间选择器 ---------- */
.rangebar{display:flex;flex-wrap:wrap;gap:6px;align-items:center;padding:7px 11px;
  background:var(--tint);border-bottom:1px solid var(--line);}
.rangebar .lb{font-size:11.5px;color:var(--muted);}
.rangebar button.pz{padding:3px 9px;border:1px solid var(--line);background:#fff;
  font-size:11.5px;color:var(--muted);cursor:pointer;font-family:inherit;}
.rangebar button.pz:hover{border-color:var(--navy-soft);color:var(--navy);}
.rangebar button.pz.on{border-color:var(--navy);color:var(--navy);font-weight:700;
  background:var(--navy-mist);}
.rangebar input[type=date]{font-family:var(--mono);font-size:11px;padding:3px 5px;
  border:1px solid var(--line);color:var(--ink);background:#fff;width:122px;}
.rangebar .sp{flex:1;}
.rangebar .rinfo{font-family:var(--mono);font-size:11px;color:var(--muted);}
.rangebar .warn{color:var(--amber);font-weight:700;}
.short-note{font-size:11px;color:var(--amber);padding:4px 11px;background:#fdf8ee;
  border-bottom:1px solid var(--line);}
.dimmed{opacity:.42;}

/* ---------- 投研工坊 ---------- */
.wsgrid{display:grid;grid-template-columns:minmax(340px,1fr) minmax(420px,1.35fr);gap:12px;
  align-items:start;}
@media(max-width:1180px){.wsgrid{grid-template-columns:1fr;}}
.leg{border:1px solid var(--line);background:var(--paper);margin-bottom:10px;}
.leg>.lh{display:flex;align-items:center;gap:8px;padding:7px 11px;
  border-bottom:1px solid var(--line);background:var(--tint);}
.leg>.lh .nm{font-weight:700;font-size:12.5px;color:var(--navy);}
.leg>.lh .sp{flex:1;}
.leg>.lh .cap{font-family:var(--mono);font-size:11px;color:var(--muted);}
.leg.eq{border-left:3px solid #c8102e;}
.leg.cb{border-left:3px solid var(--navy);}
.leg.ma{border-left:3px solid var(--amber);}
.leg.bd{border-left:3px solid var(--teal);}
.leg .lb2{padding:8px 11px;border-bottom:1px solid var(--line-soft);}
.leg .lb2:last-child{border-bottom:none;}
.leg .sub2{font-size:10.5px;color:var(--faint);margin-bottom:5px;}
.numin{font-family:var(--mono);font-size:11.5px;width:56px;padding:2px 5px;
  border:1px solid var(--line);text-align:right;}
.selmode{display:flex;gap:10px;font-size:11px;color:var(--muted);margin-bottom:5px;}
.selmode label{display:flex;align-items:center;gap:3px;cursor:pointer;}
.legsel{width:100%;font-size:11.5px;padding:3px 5px;border:1px solid var(--line);
  background:#fff;color:var(--ink);}
.picked{display:flex;flex-wrap:wrap;gap:4px;margin-top:5px;}
.picked .pk{display:flex;align-items:center;gap:4px;font-size:11px;padding:2px 6px;
  border:1px solid var(--navy-soft);background:var(--navy-mist);color:var(--navy);}
.picked .pk b{font-family:var(--mono);font-weight:700;}
.picked .pk button{color:var(--red);font-size:12px;line-height:1;padding:0 1px;}
.zerocap{background:repeating-linear-gradient(135deg,#fafbfd,#fafbfd 9px,#f3f5fa 9px,#f3f5fa 18px);}
.legnote{font-size:10.5px;color:var(--faint);padding:5px 11px;background:var(--tint);
  border-top:1px solid var(--line-soft);}
.schemebar{display:flex;gap:6px;align-items:center;flex-wrap:wrap;}
.schemebar input.nm{font-size:11.5px;padding:3px 6px;border:1px solid var(--line);width:150px;}
.mytpl{padding:6px 9px;}
.mytpl .t{display:flex;align-items:center;gap:5px;padding:4px 6px;cursor:pointer;
  font-size:11.5px;color:#c3cbdd;border-left:2px solid transparent;}
.mytpl .t:hover{background:rgba(255,255,255,.06);color:#fff;}
.mytpl .t .sp{flex:1;}
.mytpl .t .x{color:#8792ab;font-size:12px;}
.mytpl .t .x:hover{color:#ff8a9c;}
.mytpl .empty{font-size:11px;color:#7c869c;padding:3px 6px;}

/* ---------- 上传 / 维护 ---------- */
.drop{border:1px dashed var(--line);padding:14px;text-align:center;font-size:11.5px;
  color:var(--muted);background:var(--tint);cursor:pointer;}
.drop:hover{border-color:var(--navy-soft);color:var(--navy);}
.drop.hot{border-color:var(--navy);background:var(--navy-mist);}
.errbox{border:1px solid var(--red);background:var(--red-soft);padding:8px 10px;
  font-size:11.5px;color:#8d1024;margin-top:8px;}
.errbox ul{margin:4px 0 0 16px;}
.okbox{border:1px solid var(--teal);background:#eef7f7;padding:8px 10px;
  font-size:11.5px;color:#12545a;margin-top:8px;}
.fld{margin-bottom:8px;}
.fld label{display:block;font-size:11px;color:var(--muted);margin-bottom:3px;}
.fld input,.fld select,.fld textarea{width:100%;font-family:inherit;font-size:12px;
  padding:4px 6px;border:1px solid var(--line);color:var(--ink);background:#fff;}
.fld textarea{min-height:56px;resize:vertical;}
/* 下拉筛选框。贴着下面的 select，视觉上是一组，宽度与它对齐 */
.selq{width:100%;font-family:inherit;font-size:11px;padding:3px 6px;margin-bottom:2px;
  border:1px solid var(--line);border-bottom:none;color:var(--ink);background:var(--tint);}
.selq::placeholder{color:var(--faint);}
.selq:focus{background:#fff;border-color:var(--navy-soft);}
/* 工坊的添加行是横向 flex，每对「筛选框 + 下拉」要自成一列，
   否则四个元素排成一行、下拉被挤得只剩一个箭头 */
.addcol{flex:1;min-width:0;display:flex;flex-direction:column;}
.addcol .selq{margin-bottom:0;}
.addcol .legsel{width:100%;}
.f2{display:grid;grid-template-columns:1fr 1fr;gap:9px;}
.f3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:9px;}

/* ---------- 登录页 ---------- */
/* body 是 flex 容器（左轨 + 主区），登录页只有这一个孩子，要自己占满 */
.loginwrap{flex:1;width:100%;min-height:100vh;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:18px;
  background:linear-gradient(160deg,#0e1c44,#22336d 60%,#33457f);}
.beian{font-size:11px;color:rgba(255,255,255,.5);letter-spacing:.3px;text-align:center;}
.beian a{color:inherit;text-decoration:none;}
.beian a:hover{color:rgba(255,255,255,.8);}
.beian .sep{margin:0 6px;}
.loginbox{width:352px;background:#fff;padding:26px 28px 22px;border-top:3px solid var(--red);}
.loginbox h1{font-size:19px;color:var(--navy);letter-spacing:.5px;}
.loginbox .s{font-family:var(--mono);font-size:10.5px;color:var(--faint);
  letter-spacing:1.6px;margin:2px 0 18px;}
.loginbox .tabs{display:flex;margin-bottom:14px;border-bottom:1px solid var(--line);}
.loginbox .tabs button{flex:1;padding:6px 0;font-size:12.5px;color:var(--muted);
  border-bottom:2px solid transparent;}
.loginbox .tabs button.on{color:var(--navy);font-weight:700;border-bottom-color:var(--navy);}
.loginbox .btn{width:100%;justify-content:center;margin-top:6px;}
.loginbox .msg{font-size:11.5px;margin-top:9px;min-height:16px;}
.loginbox .msg.err{color:var(--red);}
.loginbox .hint{font-size:11px;color:var(--faint);margin-top:12px;line-height:1.6;
  border-top:1px solid var(--line);padding-top:9px;}
.userbox{display:flex;align-items:center;gap:7px;font-size:11.5px;color:var(--muted);}
.userbox b{color:var(--navy);}
.userbox .role{font-family:var(--mono);font-size:10px;padding:1px 5px;
  background:var(--navy-mist);color:var(--navy);}

/* 详情页页签 */
.tabs2{display:flex;gap:2px;border-bottom:1px solid var(--line);}
.tabs2 .tb{padding:6px 15px;font-size:12.5px;color:var(--muted);
  border-bottom:2px solid transparent;margin-bottom:-1px;cursor:pointer;}
.tabs2 .tb:hover{color:var(--navy);}
.tabs2 .tb.on{color:var(--navy);font-weight:700;border-bottom-color:var(--navy);}
.dhead{display:flex;align-items:flex-start;gap:14px;}
.dhead .acts{display:flex;gap:6px;flex-wrap:wrap;}

/* ---------- 投研工坊：仓位区间提示与择券组件 ---------- */
.rangetip{font-size:10.5px;color:var(--muted);padding:5px 11px;background:var(--navy-mist);
  border-bottom:1px solid var(--line-soft);line-height:1.7;}
.rangetip b{font-family:var(--mono);color:var(--navy);}
.rangetip.warn{background:#fdf8ee;color:#7a5a12;}
.rangetip.warn b{color:var(--amber);}
.addrow{display:flex;gap:5px;align-items:flex-start;}
.addrow .legsel{flex:1;min-width:0;}
.complist{margin-top:6px;display:flex;flex-direction:column;gap:4px;}
.comp{display:flex;align-items:center;gap:6px;padding:3px 6px;border:1px solid var(--line);
  background:var(--tint);}
.comp .cn{flex:1;min-width:0;font-size:11.5px;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.comp .pctv{font-family:var(--mono);font-size:11px;font-weight:700;color:var(--navy);
  width:38px;text-align:right;}
.comp button{color:var(--red);font-size:13px;line-height:1;padding:0 2px;}
.tagk{font-size:9.5px;padding:1px 4px;font-weight:700;}
.tagk.ts{background:var(--navy);color:#fff;}
.tagk.ti{background:var(--teal);color:#fff;}
/* 就绪度小标：只在「不是已上架」时出现，所以一律用提醒色 */
.tagk.tw{background:var(--amber-soft);color:var(--amber);border:1px solid var(--amber-line);
         margin-left:5px;}
.leg .lh .numin{width:48px;}

/* ---------- 弹窗 ---------- */
.modalwrap{position:fixed;inset:0;background:rgba(14,28,68,.42);z-index:900;
  display:flex;align-items:center;justify-content:center;padding:20px;}
.modalbox{background:var(--paper);width:428px;max-width:100%;max-height:88vh;
  display:flex;flex-direction:column;border-top:3px solid var(--navy);
  box-shadow:0 18px 48px rgba(14,28,68,.28);}
.modalbox.danger{border-top-color:var(--red);}
.modalbox .mh{font-size:14px;font-weight:700;color:var(--navy);padding:13px 17px 10px;
  border-bottom:1px solid var(--line);}
.modalbox.danger .mh{color:var(--red);}
.modalbox .mb{padding:14px 17px;overflow:auto;font-size:12px;color:var(--ink);line-height:1.75;}
.modalbox .mf{display:flex;justify-content:flex-end;gap:7px;padding:11px 17px;
  border-top:1px solid var(--line);background:var(--tint);}
.modalbox .mb .fld{margin-bottom:11px;}
.modalbox .mb .fld:last-child{margin-bottom:0;}
.modalbox .warnline{background:var(--red-soft);border:1px solid #f0c5ce;padding:7px 9px;
  font-size:11.5px;color:#8d1024;margin-top:9px;}
.modalbox .hintline{background:var(--tint);border:1px solid var(--line);padding:7px 9px;
  font-size:11px;color:var(--muted);margin-top:9px;line-height:1.7;}
.btn.danger{background:var(--red);border-color:var(--red);color:#fff;font-weight:700;}
.btn.danger:hover{background:#a80d26;border-color:#a80d26;}
.vis{display:flex;flex-direction:column;gap:6px;}
.vis label{display:flex;align-items:flex-start;gap:7px;cursor:pointer;padding:7px 9px;
  border:1px solid var(--line);background:#fff;}
.vis label:hover{border-color:var(--navy-soft);}
.vis label.on{border-color:var(--navy);background:var(--navy-mist);}
.vis label input{margin-top:3px;}
.vis .vt{font-size:12px;font-weight:700;color:var(--ink);}
.vis .vd{font-size:10.5px;color:var(--muted);line-height:1.6;}
.mytpl .t .sh{font-size:9.5px;padding:0 4px;background:var(--teal);color:#fff;}

/* ---------- 回测设置与过期提示 ---------- */
.panel.bt{border-left:3px solid var(--navy);}
.panel.bt.stale{border-left-color:var(--amber);}
.panel.bt.stale .ph h2{color:var(--amber);}
.rangerow{display:flex;align-items:center;gap:6px;}
.rangerow input[type=date]{font-family:var(--mono);font-size:11px;padding:3px 5px;
  border:1px solid var(--line);color:var(--ink);background:#fff;flex:1;min-width:0;}
.stalebar{display:none;background:#fdf8ee;border:1px solid #ecd9ab;color:#7a5a12;
  font-size:11.5px;padding:7px 11px;margin-bottom:10px;}

/* 最新信号表里当前生效的那一行。择时策略的详情页要一眼看出「现在是什么仓位」，
   下面几行是历史，只作对照。 */
tbody tr.hi td { background: var(--hl, rgba(127,127,127,.10)); font-weight: 600; }

/* 因子目录的代号筛选框。刻意不复用 `.selq`——那个类在 api.js 里绑着「筛选紧邻的
   下拉」的行为，而这里紧邻的正好是排序下拉。 */
.fxq{width:130px;font-family:var(--mono);font-size:11px;padding:3px 6px;
  border:1px solid var(--line);background:var(--tint);color:var(--ink);}
.fxq::placeholder{color:var(--faint);font-family:inherit;}
.fxq:focus{background:#fff;border-color:var(--navy-soft);outline:none;}
