/* ===== 售电侧电力交易平台 - 全局样式 ===== */
*{margin:0;padding:0;box-sizing:border-box}
:root{
  --bg:#f0f2f5;--sidebar-bg:#001529;--sidebar-width:240px;
  --sidebar-hover:#002140;--sidebar-active:#1677ff;
  --header-bg:#fff;--card-bg:#fff;
  --primary:#1677ff;--primary-light:#e6f4ff;--primary-dark:#0958d9;
  --success:#52c41a;--success-bg:#f6ffed;
  --warning:#faad14;--warning-bg:#fffbe6;
  --danger:#ff4d4f;--danger-bg:#fff2f0;
  --purple:#722ed1;--purple-bg:#f9f0ff;
  --cyan:#13c2c2;--cyan-bg:#e6fffb;
  --orange:#fa8c16;--orange-bg:#fff7e6;
  --text:#1f1f1f;--text-secondary:#666;--text-disabled:#bfbfbf;
  /* ⚠️ 2026-10-10 版式审计：次要文字原来用 #999（白底对比度约 2.85:1，低于 WCAG AA 的 4.5:1，
     全站大量小字都在用它）→ 稍微压深到 #6b7280（约 4.8:1），字号/排布都不动。 */
  --text-muted:#6b7280;
  --bg-light:#fafafa;--border:#f0f0f0;--border-dark:#d9d9d9;
  --shadow-sm:0 1px 2px rgba(0,0,0,0.03);--shadow:0 2px 8px rgba(0,0,0,0.08);
  --shadow-lg:0 4px 16px rgba(0,0,0,0.12);
  --radius-sm:4px;--radius:8px;--radius-lg:12px;
  --transition:all 0.2s cubic-bezier(0.645,0.045,0.355,1);
}
body{
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;
  background:var(--bg);color:var(--text);display:flex;height:100vh;overflow:hidden;
  -webkit-font-smoothing:antialiased;
}

/* ===== 侧边栏 ===== */
.sidebar{
  width:var(--sidebar-width);min-width:var(--sidebar-width);
  background:var(--sidebar-bg);color:#fff;
  display:flex;flex-direction:column;transition:width 0.25s;overflow:hidden;
  position:relative;z-index:100;
}
.sidebar.collapsed{width:64px;min-width:64px}
.sidebar-logo{
  height:56px;display:flex;align-items:center;gap:10px;padding:0 16px;
  border-bottom:1px solid rgba(255,255,255,0.08);white-space:nowrap;
}
.sidebar-logo .logo-icon{
  width:34px;height:34px;border-radius:8px;
  background:linear-gradient(135deg,#1677ff,#36cfc9);
  display:flex;align-items:center;justify-content:center;
  font-size:18px;flex-shrink:0;
}
.sidebar-logo .logo-text{font-size:15px;font-weight:600;letter-spacing:0.5px}
.sidebar.collapsed .logo-text{display:none}
.sidebar-nav{flex:1;overflow-y:auto;overflow-x:hidden;padding:8px 0}
.sidebar-nav::-webkit-scrollbar{width:3px}
.sidebar-nav::-webkit-scrollbar-thumb{background:rgba(255,255,255,0.15);border-radius:3px}
.nav-section{padding:8px 0 4px}
.nav-section-title{
  padding:6px 16px 2px;font-size:11px;font-weight:500;
  color:rgba(255,255,255,0.3);letter-spacing:1px;white-space:nowrap;
  text-transform:uppercase;
}
.sidebar.collapsed .nav-section-title{display:none}
.nav-item,.nav-parent{
  display:flex;align-items:center;padding:9px 16px;
  cursor:pointer;transition:var(--transition);color:rgba(255,255,255,0.7);
  gap:10px;white-space:nowrap;font-size:13px;position:relative;
  border-left:3px solid transparent;
}
.nav-item:hover,.nav-parent:hover{background:var(--sidebar-hover);color:#fff}
.nav-item.active{background:rgba(22,119,255,0.25);color:#fff;border-left-color:var(--primary)}
.nav-parent.active{color:#fff}
.nav-icon{width:16px;text-align:center;flex-shrink:0;font-size:14px;line-height:1}
.nav-text{flex:1;overflow:hidden;text-overflow:ellipsis}
.nav-arrow{font-size:10px;transition:transform 0.2s;opacity:0.5}
.nav-parent.expanded .nav-arrow{transform:rotate(90deg)}
.sidebar.collapsed .nav-text,.sidebar.collapsed .nav-arrow,.sidebar.collapsed .nav-badge{display:none}
.nav-badge{
  font-size:11px;background:var(--danger);color:#fff;border-radius:10px;
  padding:1px 6px;min-width:18px;text-align:center;line-height:16px;
}
.sub-nav{max-height:0;overflow:hidden;transition:max-height 0.3s ease}
.sub-nav.open{max-height:800px}
.sub-item{
  padding:8px 16px 8px 52px;
  cursor:pointer;color:rgba(255,255,255,0.55);font-size:12px;
  white-space:nowrap;transition:var(--transition);position:relative;
  border-left:3px solid transparent;
}
.sub-item:hover{color:#fff;background:rgba(22,119,255,0.12)}
.sub-item.active{color:#fff;background:rgba(22,119,255,0.18);border-left-color:var(--primary)}
.sidebar.collapsed .sub-nav{display:none}

/* ===== 主区域 ===== */
.main{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0}
.header{
  height:56px;background:var(--header-bg);display:flex;align-items:center;
  justify-content:space-between;padding:0 20px;
  border-bottom:1px solid var(--border);box-shadow:var(--shadow-sm);
  z-index:50;
}
.header-left{display:flex;align-items:center;gap:14px}
.collapse-btn{
  cursor:pointer;font-size:17px;color:var(--text-secondary);
  padding:4px 6px;border-radius:var(--radius-sm);transition:var(--transition);
  line-height:1;
}
.collapse-btn:hover{background:var(--bg);color:var(--primary)}
.breadcrumb{font-size:13px;color:var(--text-muted);display:flex;align-items:center;gap:6px}
.breadcrumb .current{color:var(--text);font-weight:500}
.page-tag{font-size:11px;padding:2px 8px;border-radius:10px;font-weight:500}
.page-tag.trade{background:var(--primary-light);color:var(--primary)}
.page-tag.market{background:var(--purple-bg);color:var(--purple)}
.header-right{display:flex;align-items:center;gap:18px}
.header-date{font-size:12px;color:var(--text-muted)}
.notification-btn{
  position:relative;cursor:pointer;font-size:17px;color:var(--text-secondary);
  padding:4px;border-radius:var(--radius-sm);transition:var(--transition);
}
.notification-btn:hover{color:var(--primary);background:var(--bg)}
.notification-btn .dot{
  position:absolute;top:2px;right:2px;width:7px;height:7px;
  background:var(--danger);border-radius:50%;border:2px solid #fff;
}
.user-info{display:flex;align-items:center;gap:8px;cursor:pointer;padding:4px 8px;border-radius:var(--radius)}
.user-info:hover{background:var(--bg)}
.user-avatar{
  width:30px;height:30px;border-radius:50%;
  background:linear-gradient(135deg,var(--primary),var(--purple));
  color:#fff;display:flex;align-items:center;justify-content:center;
  font-size:13px;font-weight:500;
}
.user-name{font-size:13px;color:var(--text)}

/* ===== 内容区 ===== */
.content{flex:1;overflow-y:auto;overflow-x:hidden;padding:20px 24px}
.content::-webkit-scrollbar{width:5px}
.content::-webkit-scrollbar-thumb{background:#d9d9d9;border-radius:3px}
.content::-webkit-scrollbar-thumb:hover{background:#bfbfbf}
.page{display:none;animation:fadeIn 0.25s ease}
.page.active{display:block}
@keyframes fadeIn{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
.page-title{font-size:20px;font-weight:600;margin-bottom:4px;color:var(--text)}
.page-desc{font-size:13px;color:var(--text-muted);margin-bottom:20px}

/* ===== 统计卡片 ===== */
/* 卡片行：grid + **`auto-fit`**
   ⚠️ 原来是 `auto-fill` —— 它**会保留空轨道**：实测气象页 4 张卡在 1312px 行宽下
      建了 5 条 251px 轨道、只占 4 条，**右边空 265px**。`auto-fit` 会把空轨道收掉，
      4 张卡就能铺满整行。
   ⚠️ **不要改用 flex**（`.panel-row` 那种）—— 小卡片被 flex-grow 拉伸会变成巨卡：
      实测工作台 6 张卡在 1600px 下第 6 张被拉成 **1312px 宽**，比留白难看得多。
      **面板/图表适合拉伸（宽图不难看），小卡片不适合。** */
.stat-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;margin-bottom:20px}
.stat-card{
  background:var(--card-bg);border-radius:var(--radius);padding:18px 20px;
  box-shadow:var(--shadow);transition:var(--transition);cursor:default;
}
.stat-card:hover{box-shadow:var(--shadow-lg);transform:translateY(-1px)}
.stat-card .card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}
.stat-card .card-label{font-size:13px;color:var(--text-secondary)}
.stat-card .card-icon{width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:18px}
.stat-card .card-icon.blue{background:var(--primary-light);color:var(--primary)}
.stat-card .card-icon.green{background:var(--success-bg);color:var(--success)}
.stat-card .card-icon.orange{background:var(--orange-bg);color:var(--orange)}
.stat-card .card-icon.red{background:var(--danger-bg);color:var(--danger)}
.stat-card .card-icon.purple{background:var(--purple-bg);color:var(--purple)}
.stat-card .card-icon.cyan{background:var(--cyan-bg);color:var(--cyan)}
.stat-card .card-value{font-size:28px;font-weight:700;color:var(--text);line-height:1.2}
.stat-card .card-value.up{color:var(--danger)}
.stat-card .card-value.down{color:var(--success)}
.stat-card .card-value .unit{font-size:14px;font-weight:400;color:var(--text-secondary);margin-left:2px}
.stat-card .card-sub{font-size:12px;color:var(--text-muted);margin-top:6px}
.stat-card .card-sub .trend{display:inline-flex;align-items:center;gap:2px;padding:1px 6px;border-radius:4px;font-size:11px;margin-right:4px}
.trend-up{background:var(--danger-bg);color:var(--danger)}
.trend-down{background:var(--success-bg);color:var(--success)}
.trend-flat{background:#f5f5f5;color:var(--text-muted)}

/* ===== 面板 ===== */
/* 面板行：用 flex 自动换行，而不是**固定列数的 grid**。
   ⚠️ 原来写的是 `grid-template-columns:1fr 1fr` + `.three{1fr 1fr 1fr}`，
      并在 `@media(max-width:1400px)` 把 three 降成两列 —— 于是一行三张图
      在 1366 笔记本屏上变成「两张 + 单独一张」，**最后一张旁边空掉半屏**（实测空 531px）。
      而且 grid 的末行项不会自动拉伸，留白永远存在。
   flex + flex-grow 的末行项会**自动拉满**，任何宽度都不留白；顺带各面板等高。 */
.panel-row{display:flex;flex-wrap:wrap;gap:16px;margin-bottom:16px}
.panel-row > *{flex:1 1 340px;min-width:0}
.panel-row.three > *{flex-basis:300px}
.panel-row.four > *{flex-basis:240px}
.panel-row.full > *{flex-basis:100%}
.panel{
  background:var(--card-bg);border-radius:var(--radius);
  box-shadow:var(--shadow);overflow:hidden;
}
.panel-header{
  padding:14px 20px;border-bottom:1px solid var(--border);
  display:flex;align-items:center;justify-content:space-between;
}
.panel-header h3{font-size:14px;font-weight:600;color:var(--text)}
.panel-header .panel-actions{display:flex;gap:8px;align-items:center}
/* 「数据时间」章 —— 每个面板右上角，说明这份数据是哪一段的、能参考到什么时候。
   ⚠️ 用户明确要求"所有板块都要说明数据时间以及可参考时间"。
      由 `App._stampPanels(page)` 自动盖（见 app.js 的 DATA_PROV 登记表）。 */
/* 挂在 **h3 内部、紧跟标题**（不是在标题栏最右侧）——
   用户反馈"看不到时间说明"，因为放右上角与标题脱节。
   现在读起来是：「分时段电价对比（重庆时段口径） 🕒 数据 2026-08-08~09-06」 */
.panel-header .panel-stamp,
.panel-header h3 .panel-stamp{
  margin-left:8px;font-size:11px;font-weight:400;color:var(--text-muted);
  background:var(--bg-light,#fafafa);border:1px solid var(--border);
  border-radius:10px;padding:1px 8px;
  /* ⚠️ 2026-10-10 版式审计修：原来是 `white-space:nowrap` —— 长章（负荷相似日 1143px、
     气象 484px、市场总览 535px、披露 433px）比面板还宽，被 `.panel{overflow:hidden}`
     **从右端裁掉**，句子停在中途（实测：相似日页章宽 1143 vs 面板 713，裁掉近 600px）。
     现在允许章自己换行；`min-width:0` 是为了让它作为 flex 子项能缩（否则最小宽度仍是整句宽）。 */
  white-space:normal;overflow-wrap:anywhere;max-width:100%;min-width:0;
  display:inline-block;vertical-align:middle;
}
.panel-header .panel-stamp.demo{
  color:#d46b08;background:#fff7e6;border-color:#ffd591;
}
/* h3 允许换行（标题 + 时间章可能很长） */
.panel-header h3{flex-wrap:wrap;line-height:1.9}
.panel-header .panel-action{
  font-size:12px;color:var(--primary);cursor:pointer;padding:2px 8px;
  border-radius:var(--radius-sm);transition:var(--transition);
}
.panel-header .panel-action:hover{background:var(--primary-light)}
.panel-body{padding:16px 20px}
.panel-body.no-padding{padding:0}
.chart-wrap{position:relative;height:280px}
.chart-wrap.tall{height:360px}
.chart-wrap.short{height:220px}
.panel-full{grid-column:1/-1}

/* ===== 表格 ===== */
/* ⚠️ 2026-10-10 版式审计补：**数字等宽**（本方对账要求 —— 竖着比一列数字时，
   默认字体的数字宽度不齐会读错）。`tabular-nums` 让数字等宽，正文仍然是普通字体。 */
.data-table{width:100%;border-collapse:collapse;font-size:13px;
  font-variant-numeric:tabular-nums}
.data-table thead th{
  background:#fafafa;padding:10px 14px;text-align:left;font-weight:500;
  color:var(--text-secondary);border-bottom:1px solid var(--border);
  white-space:nowrap;font-size:12px;
}
.data-table tbody td{padding:10px 14px;border-bottom:1px solid var(--border);color:var(--text)}
.data-table tbody tr:hover td{background:var(--primary-light)}
.data-table .text-right{text-align:right}
.data-table .text-center{text-align:center}

/* ===== 标签 ===== */
.tag{display:inline-block;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:500}
.tag-blue{background:var(--primary-light);color:var(--primary)}
.tag-green{background:var(--success-bg);color:var(--success)}
.tag-orange{background:var(--orange-bg);color:var(--orange)}
.tag-red{background:var(--danger-bg);color:var(--danger)}
.tag-purple{background:var(--purple-bg);color:var(--purple)}
.tag-cyan{background:var(--cyan-bg);color:var(--cyan)}
.tag-default{background:#f5f5f5;color:var(--text-secondary)}

/* ===== 通用圆点（表格构成项等）===== */
.dot{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:6px;vertical-align:middle}

/* ===== 警报/通知 ===== */
.alert-list{display:flex;flex-direction:column;gap:8px}
.alert-item{
  display:flex;align-items:flex-start;gap:10px;
  padding:10px 12px;border-radius:var(--radius-sm);font-size:13px;
  transition:var(--transition);cursor:pointer;
}
.alert-item:hover{filter:brightness(0.97)}
.alert-item.warn{background:var(--warning-bg);border-left:3px solid var(--warning)}
.alert-item.info{background:var(--primary-light);border-left:3px solid var(--primary)}
.alert-item.danger{background:var(--danger-bg);border-left:3px solid var(--danger)}
.alert-item.success{background:var(--success-bg);border-left:3px solid var(--success)}
.alert-item .alert-dot{width:7px;height:7px;border-radius:50%;margin-top:5px;flex-shrink:0}
.alert-item.warn .alert-dot{background:var(--warning)}
.alert-item.info .alert-dot{background:var(--primary)}
.alert-item.danger .alert-dot{background:var(--danger)}
.alert-item .alert-content{flex:1;line-height:1.5}
.alert-item .alert-title{font-weight:600;margin-bottom:2px}
.alert-item .alert-desc{color:var(--text-secondary);font-size:12px}
.alert-item .alert-time{font-size:11px;color:var(--text-muted);white-space:nowrap}

/* ===== 按钮 ===== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:4px;
  padding:7px 16px;border-radius:var(--radius-sm);border:none;cursor:pointer;
  font-size:13px;font-weight:500;transition:var(--transition);white-space:nowrap;
}
.btn-primary{background:var(--primary);color:#fff}
.btn-primary:hover{background:var(--primary-dark)}
.btn-default{background:#fff;border:1px solid var(--border-dark);color:var(--text)}
.btn-default:hover{border-color:var(--primary);color:var(--primary)}
.btn-text{background:0;border:none;color:var(--primary);padding:4px 8px}
.btn-text:hover{background:var(--primary-light)}
.btn-danger{background:var(--danger);color:#fff}
.btn-sm{padding:4px 10px;font-size:12px}
.btn-lg{padding:10px 24px;font-size:15px}
.btn-block{width:100%}
.btn-group{display:flex;gap:8px}

/* ===== 选项卡 ===== */
.tabs{display:flex;gap:0;border-bottom:2px solid var(--border);margin-bottom:16px}
.tab{
  padding:10px 18px;cursor:pointer;font-size:13px;
  color:var(--text-secondary);border-bottom:2px solid transparent;
  margin-bottom:-2px;transition:var(--transition);
}
.tab:hover{color:var(--primary)}
.tab.active{color:var(--primary);border-bottom-color:var(--primary);font-weight:500}

/* ===== 表单 ===== */
.form-row{display:flex;gap:12px;margin-bottom:12px;flex-wrap:wrap}
.form-group{display:flex;flex-direction:column;gap:4px;min-width:150px}
.form-group label{font-size:12px;color:var(--text-secondary);font-weight:500}
.form-group input,.form-group select{
  padding:7px 12px;border:1px solid var(--border-dark);border-radius:var(--radius-sm);
  font-size:13px;outline:none;transition:var(--transition);background:#fff;
}
.form-group input:focus,.form-group select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(22,119,255,0.1)}
.form-group input::placeholder{color:var(--text-disabled)}

/* ===== AI对话 ===== */
.ai-chat{
  background:var(--card-bg);border-radius:var(--radius);box-shadow:var(--shadow);
  display:flex;flex-direction:column;height:480px;
}
.ai-chat-header{
  padding:14px 20px;border-bottom:1px solid var(--border);
  display:flex;align-items:center;gap:10px;
}
.ai-avatar{
  width:38px;height:38px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  color:#fff;font-size:16px;flex-shrink:0;
}
.ai-avatar.blue{background:linear-gradient(135deg,#1677ff,#36cfc9)}
.ai-avatar.purple{background:linear-gradient(135deg,#722ed1,#eb2f96)}
.ai-chat-body{flex:1;overflow-y:auto;padding:16px 20px;display:flex;flex-direction:column;gap:12px}
.ai-chat-body .msg{max-width:82%;padding:10px 14px;border-radius:12px;font-size:13px;line-height:1.6}
.ai-chat-body .msg.ai{background:var(--primary-light);align-self:flex-start;border-bottom-left-radius:4px}
.ai-chat-body .msg.user{background:var(--primary);color:#fff;align-self:flex-end;border-bottom-right-radius:4px}
.ai-chat-body .msg .msg-time{font-size:10px;opacity:0.6;margin-top:4px}
.ai-chat-input{
  padding:12px 16px;border-top:1px solid var(--border);
  display:flex;gap:8px;align-items:center;
}
.ai-chat-input input{
  flex:1;padding:9px 14px;border:1px solid var(--border-dark);
  border-radius:20px;outline:none;font-size:13px;transition:var(--transition);
}
.ai-chat-input input:focus{border-color:var(--primary)}
.ai-chat-input .send-btn{
  width:38px;height:38px;border-radius:50%;background:var(--primary);
  color:#fff;border:none;cursor:pointer;font-size:16px;
  display:flex;align-items:center;justify-content:center;transition:var(--transition);
  flex-shrink:0;
}
.ai-chat-input .send-btn:hover{background:var(--primary-dark)}

/* ===== 日历 ===== */
.calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}
.calendar-nav{display:flex;align-items:center;gap:12px}
.calendar-nav .month-label{font-size:16px;font-weight:600;min-width:120px;text-align:center}
.calendar-nav button{
  background:var(--card-bg);border:1px solid var(--border-dark);border-radius:50%;
  width:30px;height:30px;display:flex;align-items:center;justify-content:center;
  cursor:pointer;font-size:14px;color:var(--text-secondary);transition:var(--transition);
}
.calendar-nav button:hover{border-color:var(--primary);color:var(--primary)}
.calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:1px;background:var(--border)}
.calendar-grid .day-header{
  padding:8px;text-align:center;font-size:11px;font-weight:500;
  color:var(--text-muted);background:#fafafa;
}
.calendar-grid .day{
  padding:6px;text-align:left;font-size:13px;background:var(--card-bg);
  cursor:pointer;min-height:70px;transition:var(--transition);
}
.calendar-grid .day:hover{background:var(--primary-light)}
.calendar-grid .day.today{background:var(--primary);color:#fff}
.calendar-grid .day.other{color:var(--text-disabled);background:#fafafa}
.calendar-grid .day .day-num{padding:2px 6px;display:inline-block;border-radius:50%;width:24px;height:24px;text-align:center;line-height:20px}
.calendar-grid .day.today .day-num{font-weight:700}
.calendar-grid .day .day-event{font-size:11px;padding:1px 4px;border-radius:2px;margin-top:2px;line-height:1.4}
.day-event.trade{background:var(--danger-bg);color:var(--danger)}
.day-event.deadline{background:var(--warning-bg);color:var(--warning)}
.day-event.holiday{background:var(--success-bg);color:var(--success)}
.day-event.info{background:var(--primary-light);color:var(--primary)}
/* 交易日历：法定节假日 / 调休补班（2026-09-28 接真数据时新增，语义比复用 trade/holiday 清楚） */
.day-event.legal{background:var(--danger-bg);color:var(--danger)}
.day-event.makeup{background:var(--warning-bg);color:var(--warning)}
.day-event.weekend{background:var(--success-bg);color:var(--success)}

/* ===== 策略卡片 ===== */
/* ⚠️ 同 `.stat-cards`：用小卡片要用 grid+auto-fit（等宽），不要用 flex ——
   3 张策略卡被 flex-grow 拉伸时，实测 1200px 下第 3 张会变成 912px 宽。
   auto-fit 下 3 张等宽铺满，任何宽度都不掉列。 */
.strategy-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:16px}
.strategy-card{
  background:var(--card-bg);border-radius:var(--radius-lg);padding:22px;
  box-shadow:var(--shadow);border-top:3px solid var(--primary);
  transition:var(--transition);
}
.strategy-card:hover{box-shadow:var(--shadow-lg);transform:translateY(-2px)}
.strategy-card.aggressive{border-top-color:var(--danger)}
.strategy-card.balanced{border-top-color:var(--primary)}
.strategy-card.conservative{border-top-color:var(--success)}
.strategy-card .strat-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.strategy-card .strat-name{font-size:16px;font-weight:600}
.strategy-card .strat-badge{font-size:11px;padding:3px 10px;border-radius:12px}
.strategy-card .strat-item{display:flex;justify-content:space-between;padding:7px 0;font-size:13px;border-bottom:1px dashed var(--border)}
.strategy-card .strat-item:last-child{border-bottom:none}
.strategy-card .strat-val{font-weight:600}

/* ===== 进度条 ===== */
.progress-bar{height:6px;background:var(--border);border-radius:3px;overflow:hidden}
.progress-bar .fill{height:100%;border-radius:3px;transition:width 0.3s}
.progress-bar .fill.blue{background:var(--primary)}
.progress-bar .fill.green{background:var(--success)}
.progress-bar .fill.orange{background:var(--orange)}

/* ===== 搜索/筛选 ===== */
.search-bar{display:flex;align-items:center;gap:8px;margin-bottom:16px}
.search-input{
  flex:1;max-width:320px;padding:7px 12px;border:1px solid var(--border-dark);
  border-radius:var(--radius-sm);font-size:13px;outline:none;transition:var(--transition);
}
.search-input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(22,119,255,0.1)}

/* ===== 数据卡片网格 ===== */
.data-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px}
.data-card{
  background:var(--card-bg);border-radius:var(--radius);padding:18px 20px;
  box-shadow:var(--shadow);transition:var(--transition);
}
.data-card:hover{box-shadow:var(--shadow-lg)}
.data-card .dc-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
.data-card .dc-title{font-size:14px;font-weight:600}
.data-card .dc-count{font-size:24px;font-weight:700;margin-bottom:4px}
.data-card .dc-desc{font-size:12px;color:var(--text-muted);margin-bottom:10px}
.data-card .dc-actions{display:flex;gap:6px}

/* ===== 网格行（整行面板） ===== */
.panel-full{grid-column:1/-1}

/* ===== 响应式 ===== */
@media(max-width:1400px){
  /* 这些 grid 覆盖规则**已全部失效**，故清空：
     · `.panel-row` 改成了 flex —— 列数由 flex-basis + 自动换行决定；
     · `.stat-cards` / `.strategy-cards` 改成了 auto-fit 的 grid —— 列数自适应。
     两者都不再需要「按宽度降列」的断点。留着只会误导后来的人，以为还能靠改列数调版式。 */
}
@media(max-width:1100px){
  /* 同上：不再需要按宽度降列，窄屏会自动换行。 */
}

/* ===== 数字人页面 ===== */
.digital-human-container{
  display:flex;align-items:center;justify-content:center;min-height:450px;
  background:linear-gradient(135deg,#f0f5ff 0%,#f9f0ff 50%,#fff7e6 100%);
  border-radius:var(--radius-lg);padding:40px;text-align:center;
}
.dh-avatar{
  width:120px;height:120px;border-radius:50%;
  background:linear-gradient(135deg,#1677ff,#722ed1);
  margin:0 auto 20px;display:flex;align-items:center;justify-content:center;
  font-size:52px;color:#fff;box-shadow:0 8px 32px rgba(22,119,255,0.3);
}
.dh-name{font-size:20px;font-weight:600;margin-bottom:6px}
.dh-desc{font-size:14px;color:var(--text-secondary);margin-bottom:20px}

/* ===== 登录页 ===== */
.login-overlay{
  position:fixed;top:0;left:0;right:0;bottom:0;
  background:linear-gradient(135deg,#001529 0%,#002140 50%,#001529 100%);
  display:flex;align-items:center;justify-content:center;z-index:9999;
}
/* ⚠️ 2026-10-19：只用于消除"已登录的人刷新时先闪一下登录页"。
   标记写在 <head> 的内联脚本里（首次绘制之前），**不是权限**；
   会话失效时 auth.js 会摘掉这个类，遮罩照常显示。 */
html.auth-resume #loginOverlay{display:none}
.login-card{
  background:#fff;border-radius:var(--radius-lg);padding:40px;
  width:400px;box-shadow:0 20px 60px rgba(0,0,0,0.3);
}
.login-card .login-logo{
  text-align:center;margin-bottom:24px;
  font-size:24px;font-weight:700;color:var(--text);
}
.login-card .input-group{margin-bottom:16px}
.login-card .input-group label{display:block;font-size:13px;color:var(--text-secondary);margin-bottom:6px;font-weight:500}
.login-card .input-group input{
  width:100%;padding:10px 14px;border:1px solid var(--border-dark);
  border-radius:var(--radius-sm);font-size:14px;outline:none;transition:var(--transition);
}
.login-card .input-group input:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(22,119,255,0.1)}
.login-card .login-btn{
  width:100%;padding:11px;background:var(--primary);color:#fff;
  border:none;border-radius:var(--radius-sm);font-size:15px;font-weight:500;
  cursor:pointer;transition:var(--transition);margin-top:8px;
}
.login-card .login-btn:hover{background:var(--primary-dark)}
.login-card .login-extra{
  text-align:center;margin-top:16px;font-size:12px;color:var(--text-muted);
}
/* ⚠️ 2026-10-16：`.role-switch` / `.role-btn`（角色切换按钮）已删除 —— 角色是账号自带的，不由前端选。 */
.login-card .login-err{
  margin-top:12px;font-size:12.5px;color:#ff4d4f;text-align:center;min-height:16px;
}
/* 密码框的「显示/隐藏」开关（2026-10-16；用户要求：**不要独立按钮框**，
   做成输入框**内部的右侧小眼睛** —— 所以是绝对定位的裸图标，不是按钮） */
.pw-wrap{position:relative;display:flex;align-items:center;width:100%}
.pw-wrap input{flex:1 1 auto;min-width:0;padding-right:32px}   /* 右边给眼睛留位置，文字别钻到图标底下 */
/* ⚠️ 登录卡片里那条 `.login-card .input-group input{padding:10px 14px}` 更具体（0,2,1），
   会把我上面那条盖掉 → 这里用更高的选择器补一次，否则登录页的密码会跑到眼睛下面去 */
.login-card .input-group .pw-wrap input{padding-right:32px}
.pw-wrap > .eye-btn{
  position:absolute;right:9px;top:50%;transform:translateY(-50%);
  cursor:pointer;font-size:14px;line-height:1;color:#8c8c8c;
  background:none;border:none;padding:2px;user-select:none;
}
.pw-wrap > .eye-btn:hover{color:var(--primary)}
/* 表格里"显示某个账号的密码"那个小眼睛：同样是**裸图标**，不要边框框 */
.eye-btn{cursor:pointer;font-size:13px;line-height:1;color:#8c8c8c;background:none;border:none;padding:0 2px;user-select:none}
.eye-btn:hover{color:var(--primary)}

/* 顶栏账号（点一下展开「个人信息 / 修改口令 / 退出登录」） */
.user-info{position:relative;cursor:pointer;display:flex;align-items:center;gap:8px}
.user-info .user-role{
  font-size:11px;padding:1px 6px;border-radius:8px;
  background:var(--primary-light);color:var(--primary);
}
.user-menu{
  display:none;position:absolute;right:0;top:130%;min-width:120px;
  background:#fff;border:1px solid var(--border);border-radius:var(--radius-sm);
  box-shadow:0 6px 20px rgba(0,0,0,0.12);padding:4px 0;z-index:1000;
}
.user-menu-item{padding:8px 14px;font-size:13px;color:var(--text);white-space:nowrap}
.user-menu-item:hover{background:var(--primary-light);color:var(--primary)}

/* ===== 省份看板（全国地图选择）===== */
.page-tag.prov{
  background:var(--purple-bg);color:var(--purple);
  border:1px solid rgba(114,46,209,0.18);font-weight:600;
}
/* ⚠️ 原来写 `align-items:start` —— 左栏（30日走势图，360px）比右栏（概况卡组，667px）矮，
   **左图下面空掉 307px**（实测）。改成拉伸，并让图随面板高度长高。 */
.province-layout{display:grid;grid-template-columns:1.6fr 1fr;gap:16px;align-items:stretch}
.province-layout > .panel{display:flex;flex-direction:column}
.province-layout > .panel > .panel-body{flex:1;display:flex;flex-direction:column}
.province-layout > .panel .chart-wrap{flex:1;height:auto;min-height:280px}
@media(max-width:1100px){.province-layout{grid-template-columns:1fr}}
.province-map-panel .map-body{padding:12px}
.map-body svg{width:100%;height:auto;display:block;background:linear-gradient(180deg,#eef6ff 0%,#f7fbff 100%);border-radius:8px}
.map-body svg path[data-name]{
  fill:#cfe5ff;stroke:#ffffff;stroke-width:0.8;cursor:pointer;
  transition:fill 0.2s ease, opacity 0.2s ease;
}
.map-body svg path[data-name]:hover{fill:#69b1ff;opacity:0.92}
.map-body svg path.prov-active{fill:#1677ff;stroke:#0c5cd7;stroke-width:1.4}
.map-body svg path.jd-line{fill:none;stroke:#8c8c8c;stroke-width:1.2;stroke-dasharray:4 3;pointer-events:none}
.map-note{margin-top:6px;font-size:11px;color:var(--text-muted);text-align:right}
.province-info-panel .panel-header{display:flex;align-items:center;justify-content:space-between;gap:8px}
.province-info-panel .panel-header.sub{margin-top:14px;padding-top:12px;border-top:1px dashed var(--border)}
.province-metrics{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:12px}
.pm-item{
  background:var(--bg-light);border:1px solid var(--border);border-radius:8px;
  padding:10px 12px;display:flex;flex-direction:column;gap:4px;
}
.pm-label{font-size:11px;color:var(--text-muted)}
.pm-value{font-size:20px;font-weight:700;color:var(--text)}
.pm-value small{font-size:11px;font-weight:400;color:var(--text-muted);margin-left:3px}
.province-mix{margin-top:10px}
.mix-bar{display:flex;height:14px;border-radius:7px;overflow:hidden;background:#f0f0f0}
.mix-seg{height:100%;transition:width 0.4s ease}
.seg-hydro{background:#1677ff}
.seg-wind{background:#52c41a}
.seg-solar{background:#faad14}
.seg-thermal{background:#8c8c8c}
.mix-legend{display:flex;flex-wrap:wrap;gap:12px;margin-top:8px;font-size:12px;color:var(--text)}
.mix-legend .dot{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:4px;vertical-align:-1px}
.province-actions{margin-top:14px}
.province-actions .btn:disabled{background:var(--success);opacity:0.75;cursor:not-allowed}
.province-tip{animation:fadeIn 0.3s ease}
@keyframes fadeIn{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}

/* ===== 四川大中型水库水情看板 ===== */
.reservoir-note{
  font-size:12px;color:var(--text-secondary);background:var(--bg-light);
  border:1px solid var(--border);border-radius:8px;padding:8px 12px;margin-bottom:10px;line-height:1.6;
}
.reservoir-frame{
  border:1px solid var(--border);border-radius:10px;overflow:hidden;background:#fff;
}
.reservoir-frame iframe{
  width:100%;height:520px;border:none;display:block;background:#fff;
}
.table-scroll{overflow-x:auto}
.table-scroll .data-table{min-width:860px}
@media(max-width:1100px){.reservoir-frame iframe{height:420px}}

/* ===== 工作台省份联动切换条 ===== */
.dash-prov-bar{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  background:linear-gradient(90deg,#e6f4ff 0%,#f0f7ff 55%,#f6ffed 100%);
  border:1px solid #b7e3ff;border-radius:10px;padding:10px 14px;margin-bottom:14px;
}
.dash-prov-label{font-size:13px;font-weight:600;color:var(--primary)}
.dash-prov-select{
  min-width:180px;padding:6px 10px;border:1px solid var(--border-dark);border-radius:6px;
  font-size:13px;background:#fff;color:var(--text);cursor:pointer;outline:none;
}
.dash-prov-select:focus{border-color:var(--primary);box-shadow:0 0 0 2px rgba(22,119,255,0.12)}
.dash-prov-hint{font-size:11px;color:var(--text-muted);margin-left:auto}
@media(max-width:1100px){.dash-prov-hint{display:none}}
.btn-sm{
  padding:5px 12px;font-size:12px;border:1px solid var(--primary);color:var(--primary);
  background:#fff;border-radius:6px;cursor:pointer;transition:all 0.2s ease;
}
.btn-sm:hover{background:var(--primary);color:#fff}

/* ===== 省份看板升级：全国概览 + 地图工具栏 + 热力/云图 ===== */
/* ⚠️ 原来靠覆盖 `.stat-cards` 的 grid 列数（4 列 → 2 列 → 1 列）并加断点降列。
   只要指标个数不是列数的整数倍就留白。现在统一用 auto-fit，这里**只需调最小卡宽**。
   ⚠️ 注意要用 `grid-template-columns`（它继承的是 `.stat-cards` 的 **grid**）——
     写 `flex-basis` 是无效的死规则（踩过）。 */
.prov-stats{grid-template-columns:repeat(auto-fit,minmax(200px,1fr));margin-bottom:16px}

/* 地图工具栏 */
.map-toolbar{
  display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  margin:12px 14px 0;padding:10px 14px;
  background:var(--bg-light);border:1px solid var(--border);border-radius:10px;
}
.mt-group{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.mt-label{font-size:12px;color:var(--text-secondary);margin-right:2px;white-space:nowrap}
.mt-btn{
  padding:5px 13px;font-size:12px;border:1px solid var(--border-dark);
  background:#fff;color:var(--text-secondary);border-radius:6px;cursor:pointer;
  transition:var(--transition);white-space:nowrap;font-family:inherit;
}
.mt-btn:hover{border-color:var(--primary);color:var(--primary)}
.mt-btn.active{background:var(--primary);border-color:var(--primary);color:#fff;font-weight:500}

/* 地图容器与悬浮提示 */
.map-wrap{position:relative}
.map-tooltip{
  position:absolute;z-index:20;pointer-events:none;
  background:rgba(0,21,41,0.94);color:#fff;border-radius:8px;
  padding:10px 13px;font-size:12px;line-height:1.55;
  box-shadow:0 6px 20px rgba(0,21,41,0.35);max-width:300px;white-space:nowrap;
}
.map-tooltip .tip-title{font-weight:600;margin-bottom:4px}
.map-tooltip .tip-row{font-size:11px;color:rgba(255,255,255,0.85)}
.map-tooltip .tip-row b{color:#ffd666}

/* 图例 */
.map-legend{display:flex;align-items:center;gap:10px;margin-top:10px;font-size:12px;color:var(--text-secondary);flex-wrap:wrap}
.lg-label{font-weight:500;color:var(--text)}
.lg-min,.lg-max{font-size:11px;color:var(--text-muted)}
.lg-bar{flex:1;min-width:140px;max-width:260px;height:10px;border-radius:5px;border:1px solid rgba(0,0,0,0.06)}
.lg-chips{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:11px;color:var(--text-secondary)}
.lg-chips i{display:inline-block;width:12px;height:12px;border-radius:3px;margin-right:4px;vertical-align:-2px}

/* 云图叠加层（SVG 椭圆云团 + 飘动动画） */
.cloud-layer{pointer-events:none;animation-name:cloudDrift;animation-timing-function:ease-in-out;animation-iteration-count:infinite;animation-direction:alternate;animation-duration:90s}
@keyframes cloudDrift{from{transform:translate(-28px,-6px)}to{transform:translate(36px,10px)}}
.cloud-banner{
  margin-top:10px;display:flex;align-items:center;gap:6px;flex-wrap:wrap;
  background:linear-gradient(90deg,#001529,#0b2f55);color:#bae0ff;
  border:1px solid rgba(22,119,255,0.4);border-radius:8px;
  padding:8px 14px;font-size:12px;
}
.cloud-banner b{color:#fff}

/* 省份概览面板（右侧） */
.province-info-panel{padding:18px 20px}
.prov-head{
  background:linear-gradient(135deg,#e6f4ff 0%,#f0f9ff 60%,#f6ffed 100%);
  border:1px solid #b7e3ff;border-radius:12px;padding:16px 18px;margin-bottom:14px;
}
.prov-head-top{display:flex;align-items:center;justify-content:space-between;gap:8px}
.prov-title{font-size:20px;font-weight:700;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.prov-weather{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:10px;flex-wrap:wrap}
.pw-main{display:flex;align-items:baseline;gap:10px}
.pw-temp{font-size:34px;font-weight:700;line-height:1;color:var(--primary)}
.pw-cond{font-size:14px;color:var(--text-secondary)}
.pw-items{display:flex;gap:8px;flex-wrap:wrap}
.pw-items span{
  font-size:12px;background:#fff;border:1px solid var(--border);
  border-radius:14px;padding:3px 10px;color:var(--text-secondary);box-shadow:var(--shadow-sm);
}

/* 交易智能提示 */
.prov-tips{
  margin-top:14px;background:var(--warning-bg);border:1px solid #ffe58f;
  border-radius:10px;padding:12px 14px;
}
.prov-tips-title{font-size:13px;font-weight:600;color:#ad6800;margin-bottom:8px}
.prov-tip-item{font-size:12px;color:#874d00;line-height:1.65;padding:3px 0 3px 18px;position:relative}
.prov-tip-item::before{content:'▸';position:absolute;left:2px;color:#faad14;font-weight:700}

/* ===== 市场情报中心 ===== */
.intel-list{display:flex;flex-direction:column;gap:10px}
.intel-item{
  display:flex;align-items:flex-start;gap:12px;padding:12px 14px;
  background:var(--bg-light);border:1px solid var(--border);border-radius:10px;
  transition:var(--transition);
}
.intel-item:hover{box-shadow:var(--shadow);border-color:var(--border-dark);transform:translateY(-1px)}
.intel-main{flex:1;min-width:0}
.intel-title{font-size:13.5px;font-weight:600;margin-bottom:3px}
.intel-desc{font-size:12.5px;color:var(--text-secondary);line-height:1.6}
.intel-meta{font-size:11px;color:var(--text-muted);margin-top:5px}

/* ===== 数据采集中心：采集链路 ===== */
.pipeline{display:flex;align-items:stretch;gap:6px;flex-wrap:wrap}
.pipe-step{
  flex:1;min-width:150px;text-align:center;
  background:linear-gradient(180deg,#f0f7ff,#fff);
  border:1px solid var(--border);border-top:3px solid var(--primary);
  border-radius:10px;padding:14px 12px;transition:var(--transition);
}
.pipe-step:hover{box-shadow:var(--shadow);transform:translateY(-2px)}
.pipe-icon{font-size:26px;margin-bottom:6px}
.pipe-title{font-size:13px;font-weight:600;margin-bottom:4px}
.pipe-desc{font-size:11.5px;color:var(--text-muted);line-height:1.55}
.pipe-arrow{display:flex;align-items:center;font-size:18px;color:var(--primary);font-weight:700;flex-shrink:0}
@media(max-width:1100px){
  .pipeline{flex-direction:column}
  .pipe-arrow{transform:rotate(90deg);justify-content:center;padding:2px 0}
}

/* ===== 市场行情看板：枢纽导航卡片 ===== */
.hub-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px}
.hub-card{
  display:flex;align-items:center;gap:12px;padding:16px;
  background:#fff;border:1px solid var(--border);border-radius:10px;
  transition:var(--transition)
}
.hub-card:hover{box-shadow:var(--shadow);border-color:var(--primary);transform:translateY(-2px)}
.hub-icon{
  width:42px;height:42px;border-radius:10px;display:flex;align-items:center;justify-content:center;
  font-size:20px;flex-shrink:0
}
.hub-icon.c-blue{background:rgba(22,119,255,0.1);color:#1677ff}
.hub-icon.c-green{background:rgba(82,196,26,0.1);color:#52c41a}
.hub-icon.c-orange{background:rgba(250,140,22,0.1);color:#fa8c16}
.hub-icon.c-purple{background:rgba(114,46,209,0.1);color:#722ed1}
.hub-icon.c-teal{background:rgba(19,194,194,0.1);color:#13c2c2}
.hub-info{flex:1;min-width:0}
.hub-title{font-size:14px;font-weight:600;margin-bottom:3px}
.hub-desc{font-size:12px;color:var(--text-secondary);line-height:1.5}
.hub-arrow{font-size:18px;color:var(--text-muted);flex-shrink:0}

/* ===== 基础信息档案：客户摘要卡 ===== */
.archive-summary{display:flex;gap:24px;align-items:center;flex-wrap:wrap}
.arch-stat{text-align:center}
.arch-num{display:block;font-size:28px;font-weight:700;color:var(--primary)}
.arch-label{font-size:12px;color:var(--text-secondary);margin-top:2px}
.arch-hint{flex:1;min-width:200px;font-size:12.5px;color:var(--text-muted);line-height:1.6;padding-left:16px;border-left:2px solid var(--border)}

/* ===== 交叉引用提示 ===== */
.cross-ref{display:flex;align-items:center;flex-wrap:wrap;font-size:13px;color:var(--text-secondary);line-height:1.6}
