/* ========== 集团数字化学习平台 v3.0 样式 ========== */
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
  --primary: #0F4BB8;
  --primary-light: #E8EEF9;
  --primary-dark: #0A3A8F;
  --accent: #FF6B1A;
  --accent-light: #FFF0E6;
  --brand-blue: #0F4BB8;
  --brand-orange: #FF6B1A;
  --success: #52c41a;
  --warning: #faad14;
  --danger: #ff4d4f;
  --purple: #722ed1;
  --cyan: #13c2c2;
  --text: #1f1f1f;
  --text-secondary: #595959;
  --text-light: #6b7280;   /* U-17：原 #8c8c8c 白底对比度约 3.5:1，低于 WCAG AA 4.5:1 */
  --border: #f0f0f0;
  --bg: #f5f7fa;
  --bg-white: #ffffff;
  --shadow: 0 2px 8px rgba(0,0,0,0.06);
  --shadow-lg: 0 4px 16px rgba(0,0,0,0.1);
  --radius: 8px;
  --radius-lg: 12px;
}
html, body { font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", sans-serif; color: var(--text); background: var(--bg); font-size: 14px; line-height: 1.6; -webkit-font-smoothing: antialiased; }
a { color: var(--primary); text-decoration: none; }
button { cursor: pointer; border: none; background: none; font-family: inherit; font-size: inherit; }
input, select, textarea { font-family: inherit; font-size: inherit; outline: none; }
img { max-width: 100%; display: block; }
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-thumb { background: #d9d9d9; border-radius: 3px; }
::-webkit-scrollbar-track { background: transparent; }

/* ========== 按钮 ========== */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 16px; border-radius: var(--radius); font-weight: 500; transition: all 0.2s; cursor: pointer; white-space: nowrap; }
.btn-primary { background: var(--primary); color: #fff; }
.btn-primary:hover { background: var(--primary-dark); }
.btn-success { background: var(--success); color: #fff; }
.btn-warning { background: var(--warning); color: #fff; }
.btn-danger { background: var(--danger); color: #fff; }
.btn-default { background: #fff; color: var(--text); border: 1px solid var(--border); }
.btn-default:hover { border-color: var(--primary); color: var(--primary); }
.btn-text { color: var(--primary); padding: 4px 8px; }
.btn-sm { padding: 4px 12px; font-size: 12px; }
.btn-lg { padding: 12px 24px; font-size: 16px; }
.btn-block { width: 100%; }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* ========== 卡片 ========== */
.card { background: var(--bg-white); border-radius: var(--radius-lg); box-shadow: var(--shadow); padding: 20px; margin-bottom: 16px; }
.card-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
.card-title { font-size: 16px; font-weight: 600; }
.card-extra { font-size: 13px; color: var(--primary); }

/* ========== 徽章/标签 ========== */
# ★ 2026-10-11：加 white-space:nowrap。.tag 是 inline-block，落在窄列（如「课程状态」
#   只给 80px、扣掉 td 左右各 16px 内边距只剩 48px，而「已发布」实宽 52px）里会被
#   压成两行「已发 / 布」。标签本来就是不可断的短词，一律不许折行。
.tag { display: inline-block; white-space: nowrap; padding: 2px 8px; border-radius: 4px; font-size: 12px; font-weight: 500; }
.tag-video { background: #fff1f0; color: #cf1322; }
.tag-audio { background: #f6ffed; color: #389e0d; }
.tag-h5 { background: #e6f7ff; color: #096dd9; }
.tag-scorm { background: #f9f0ff; color: #722ed1; }
.tag-link { background: #fff7e6; color: #d46b08; }
.tag-required { background: var(--danger); color: #fff; }
.tag-done { background: #f6ffed; color: var(--success); }
.tag-urgent { background: #fff1f0; color: var(--danger); animation: pulse 2s infinite; }
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.6; } }

/* ========== 布局 ========== */
.app-container { min-height: 100vh; padding-bottom: 80px; }
.top-nav { position: sticky; top: 0; z-index: 100; background: var(--bg-white); box-shadow: var(--shadow); }
.top-nav-inner { max-width: 1400px; margin: 0 auto; display: flex; align-items: center; justify-content: space-between; padding: 0 24px; height: 60px; }
.logo { font-size: 20px; font-weight: 700; color: var(--primary); display: flex; align-items: center; gap: 8px; }
.logo img { height:32px; }
.nav-links { display: flex; gap: 4px; }
.nav-link { padding: 8px 16px; border-radius: var(--radius); color: var(--text-secondary); font-weight: 500; transition: all 0.2s; cursor: pointer; }
.nav-link:hover, .nav-link.active { background: var(--primary-light); color: var(--primary); }
.nav-right { display: flex; align-items: center; gap: 16px; }
.user-menu { display: flex; align-items: center; gap: 8px; cursor: pointer; padding: 4px 12px; border-radius: 20px; transition: background 0.2s; }
.user-menu:hover { background: var(--bg); }
.avatar { width: 36px; height: 36px; border-radius: 50%; background: linear-gradient(135deg, #667eea, #764ba2); color: #fff; display: flex; align-items: center; justify-content: center; font-weight: 600; font-size: 14px; flex-shrink: 0; position: relative; overflow: hidden; }
/* 2026-09-19 头像：.avatar 里放了 <img>（用户上传的头像）时铺满圆形。
   img 绝对定位压在姓名首字之上；图片加载失败时前端会移除 img，
   自动露出下面的首字 —— 不会留下空白方块。 */
.avatar img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
/* 2026-09-19c：头像自己就是入口（不再有按钮），这里只负责可点击手感，
   并在触摸端抑制长按系统菜单（iOS 会弹「存储图像」，不挡会盖住我们的清除确认框）。 */
.avatar-clickable { cursor: pointer; transition: transform 0.15s, box-shadow 0.15s;
  -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none; touch-action: manipulation; }
.avatar-clickable img { -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; }
.avatar-clickable:active { transform: scale(0.94); }
.avatar-clickable:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }
.avatar-clickable.has-custom { box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.35); }
/* 2026-09-19：登录页"被退出来"的原因提示条（app.js showAuthNotice() 填充）。
   原来 401 是直接 location.reload()，学员只看到又回到登录页、不知道发生了什么。 */
.auth-notice { background: #fffbe6; border: 1px solid #ffe58f; color: #874d00; border-radius: 8px;
  padding: 10px 12px; font-size: 13px; line-height: 1.6; margin-bottom: 14px; }
.badge { position: absolute; top: -4px; right: -4px; min-width: 18px; height: 18px; background: var(--danger); color: #fff; border-radius: 9px; font-size: 11px; display: flex; align-items: center; justify-content: center; padding: 0 5px; }

.main-content { max-width: 1400px; margin: 0 auto; padding: 24px; }

/* ========== 底部Tab（手机端） ========== */
.bottom-tab { display: none; position: fixed; bottom: 0; left: 0; right: 0; background: var(--bg-white); box-shadow: 0 -2px 8px rgba(0,0,0,0.06); z-index: 100; border-top: 1px solid var(--border); }
.bottom-tab-inner { display: flex; justify-content: space-around; padding: 8px 0 env(safe-area-inset-bottom); }
.tab-item { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 6px 0; color: var(--text-light); font-size: 11px; cursor: pointer; position: relative; }
.tab-item.active { color: var(--primary); }
.tab-icon { font-size: 22px; }

/* ========== 页面切换 ========== */
.page { display: none; }
.page.active { display: block; }

/* ========== 首页 ========== */
/* 首页头部卡片：配色全部走变量，[data-style] 一挂即换肤（学员点卡片右上角 🎨 自选）
   文字色也必须跟着变量走 —— "纯净白卡"是浅底，写死 #fff 就看不见字了。 */
.welcome-bar { --wc-text: #fff; --wc-sub: rgba(255,255,255,.85); --wc-chip: rgba(255,255,255,.18);
  background: linear-gradient(135deg, #0F4BB8 0%, #1976D2 60%, #FF6B1A 140%);
  border-radius: var(--radius-lg); padding: 28px; color: var(--wc-text); margin-bottom: 20px;
  position: relative; overflow: hidden; }
.welcome-bar[data-style="aurora"] { background: linear-gradient(135deg, #4C1D95 0%, #7C3AED 45%, #06B6D4 100%); }
.welcome-bar[data-style="sunrise"] { background: linear-gradient(135deg, #FF7A18 0%, #FF4D6D 58%, #C2185B 100%); }
.welcome-bar[data-style="forest"] { background: linear-gradient(135deg, #0B3D2E 0%, #12735A 58%, #7BC96F 135%); }
.welcome-bar[data-style="midnight"] { background: linear-gradient(135deg, #0B1020 0%, #1B2440 58%, #8C6B2F 145%); }
.welcome-bar[data-style="minimal"] { --wc-text: #1F2329; --wc-sub: #5A6472; --wc-chip: rgba(15,75,184,.08);
  background: linear-gradient(135deg, #FFFFFF 0%, #F4F8FF 100%); border: 1px solid #E4EAF5;
  box-shadow: 0 2px 12px rgba(15,75,184,.07); }
.welcome-bar[data-style="minimal"]::after { background: rgba(15,75,184,.05); }
.welcome-bar::after { content: ''; position: absolute; top: -50%; right: -10%; width: 300px; height: 300px; background: rgba(255,255,255,0.08); border-radius: 50%; }
.welcome-title { font-size: 22px; font-weight: 700; margin-bottom: 6px; position: relative; z-index: 1;
  padding-right: 44px; }   /* 避开右上角换风格按钮 */
/* 日期 + 星期：学员一眼看到"今天周几" */
.welcome-date { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
  line-height: 1.6; padding: 3px 11px; border-radius: 20px; background: var(--wc-chip);
  color: var(--wc-text); margin-bottom: 10px; position: relative; z-index: 1; }
.welcome-date .wd-week { font-weight: 600; }
.welcome-sub { font-size: 13px; color: var(--wc-sub); margin-bottom: 18px; position: relative; z-index: 1; }

/* 首页卡片右上角「换风格」：就地换肤入口（不用进设置页）
   颜色全走 --wc-*，所以 6 套配色下都可见（纯白卡也不会白底白字） */
.welcome-style-btn { position: absolute; top: 12px; right: 12px; z-index: 3;
  width: 34px; height: 34px; padding: 0; border: 0; border-radius: 50%; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: var(--wc-chip); color: var(--wc-text); font-size: 16px; line-height: 1;
  transition: transform .2s, background .2s; }
.welcome-style-btn:hover { transform: scale(1.08); background: rgba(255,255,255,.3); }
.welcome-style-btn:active { transform: scale(.94); }
.welcome-bar[data-style="minimal"] .welcome-style-btn:hover { background: rgba(15,75,184,.16); }

.welcome-style-panel { position: absolute; top: 52px; right: 12px; z-index: 4;
  display: none; flex-wrap: wrap; justify-content: flex-end; gap: 7px; padding: 9px;
  max-width: calc(100% - 24px); border-radius: 14px;
  background: rgba(17,24,39,.66); backdrop-filter: blur(8px);
  box-shadow: 0 8px 24px rgba(0,0,0,.22); }
.welcome-style-panel.show { display: flex; }
.wsp-item { width: 36px; height: 30px; padding: 2px; border-radius: 9px; cursor: pointer;
  background: rgba(255,255,255,.16); transition: transform .15s, background .15s; }
.wsp-item:hover { transform: translateY(-2px); }
.wsp-item.active { background: #fff; }
.wsp-item .wsp-prev { width: 100%; height: 100%; border-radius: 7px; }

/* 待办卡片 */
.todo-card { background: #fff; border-radius: var(--radius); padding: 16px; margin-bottom: 20px; display: flex; gap: 16px; align-items: center; flex-wrap: wrap; box-shadow: var(--shadow); }
.todo-item { flex: 1; min-width: 100px; text-align: center; padding: 12px; border-radius: var(--radius); cursor: pointer; transition: all 0.2s; position: relative; }
.todo-item:hover { background: var(--bg); transform: translateY(-2px); }
.todo-item .num { font-size: 28px; font-weight: 700; color: var(--primary); line-height: 1.2; }
.todo-item.urgent .num { color: var(--danger); }
.todo-item .label { font-size: 12px; color: var(--text-secondary); margin-top: 4px; }
.todo-divider { width: 1px; height: 40px; background: var(--border); }

/* KPI统计 */
.stats-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 20px; }
.stat-card { background: var(--bg-white); border-radius: var(--radius-lg); padding: 20px; box-shadow: var(--shadow); transition: transform 0.2s; }
.stat-card:hover { transform: translateY(-2px); }
.stat-card .stat-value { font-size: 28px; font-weight: 700; color: var(--text); }
.stat-card .stat-label { font-size: 13px; color: var(--text-light); margin-top: 4px; }
.stat-card .stat-icon { font-size: 28px; float: right; opacity: 0.8; }

/* 可点击的统计卡（我的学习页 4 张卡同时是 tab 入口，2026-09-17）：
   原来它们只有 hover 上浮、没有光标也没有高亮，用户点了没反应会以为是坏了。
   这里给"能点"的卡一个明确的手势 + 当前态描边，让它看起来就像入口。 */
.stat-card.link { cursor: pointer; position: relative; }
.stat-card.link:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg, 0 6px 16px rgba(0,0,0,.1)); }
.stat-card.link:active { transform: translateY(0); }
.stat-card.link.active { border: 1px solid var(--primary); box-shadow: 0 0 0 2px rgba(22,119,255,.12); }
.stat-card.link.active .stat-label { color: var(--primary); font-weight: 600; }
.stat-card.link .stat-icon { transition: transform 0.2s; }
.stat-card.link:hover .stat-icon { transform: scale(1.08); }

/* 快捷入口 */
.quick-entries { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin-bottom: 20px; }
.quick-entry { background: var(--bg-white); border-radius: var(--radius); padding: 16px 8px; text-align: center; cursor: pointer; transition: all 0.2s; box-shadow: var(--shadow); }
.quick-entry:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.quick-entry .qe-icon { font-size: 32px; margin-bottom: 8px; }
.quick-entry .qe-text { font-size: 12px; color: var(--text-secondary); font-weight: 500; }

/* 轮播Banner */
.banner { height: 180px; border-radius: var(--radius-lg); overflow: hidden; margin-bottom: 20px; position: relative; background: linear-gradient(135deg, #667eea, #764ba2); display: flex; align-items: center; padding: 32px; color: #fff; }
.banner-title { font-size: 24px; font-weight: 700; margin-bottom: 8px; }
.banner-desc { font-size: 14px; opacity: 0.9; }

/* 区块标题 */
.section-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
.section-title { font-size: 18px; font-weight: 600; display: flex; align-items: center; gap: 8px; }

/* 课程卡片 */
.course-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.course-card { background: var(--bg-white); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow); cursor: pointer; transition: all 0.2s; display: flex; flex-direction: column; }
.course-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.course-cover { position: relative; width: 100%; padding-top: 56.25%; background: linear-gradient(135deg, #667eea, #764ba2); overflow: hidden; }
.course-cover img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; }
/* 2026-09-28：分类与时长上浮到封面（学员端 H5 卡片重构，方案 B）。
   ★ 原实现把分类放在 .course-meta 里，与「类型/讲师」和「人数/评分/时长」三组信息
   抢同一条行宽：手机双列时正文只剩约 156px，而 .tag-cat 缺 flex 保护（对比
   .course-instructor .tag 与 .course-stats 都是 flex:0 0 auto），被压到 19px 宽
   → 中文只能逐字换行，看起来就是一根竖排横幅，长分类名还会被截断。
   max-width 留出右上角「必修」标签的位置，超长分类名走省略号。 */
.course-cover .card-cat-badge { position: absolute; left: 8px; top: 8px; z-index: 2; max-width: calc(100% - 60px); padding: 2px 8px; border-radius: 6px; background: rgba(255,255,255,0.94); color: var(--primary); font-size: 11px; font-weight: 500; line-height: 1.5; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.course-cover .card-dur-badge { position: absolute; right: 8px; bottom: 8px; z-index: 2; padding: 2px 7px; border-radius: 6px; background: rgba(0,0,0,0.45); color: #fff; font-size: 11px; line-height: 1.5; }
.course-cover .progress-mini { position: absolute; bottom: 0; left: 0; right: 0; height: 4px; background: rgba(0,0,0,0.2); }
.course-cover .progress-mini-bar { height: 100%; background: var(--primary); border-radius: 0 2px 2px 0; }
.course-body { padding: 12px; flex: 1; display: flex; flex-direction: column; }
.course-title { font-size: 14px; font-weight: 600; line-height: 1.4; height: 40px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; margin-bottom: 8px; }
.course-meta { display: flex; justify-content: space-between; align-items: center; gap: 6px; font-size: 12px; color: var(--text-light); margin-top: auto; }
.course-instructor { display: flex; align-items: center; gap: 4px; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.course-instructor .tag { flex: 0 0 auto; }
.course-stats { display: flex; gap: 8px; flex: 0 0 auto; }

/* 2026-09-29：.course-meta 的**直接子元素**统一兜底。
   「我的收藏 / 我的学习」走的是各自的内联模板，里面有没有 class 的裸 <span>：
   默认 flex-shrink:1 + min-width:auto，窄列（178px）下「3/9章」被压到 19px
   逐字竖排、卡片从 195px 撑到 253px；收藏页则是「视频+讲师」被压到 7px 后
   被 overflow:hidden 吃掉。规矩：首个可缩（带省略号），其余不缩也不换行。 */
.course-meta > span { flex: 0 0 auto; white-space: nowrap; }
.course-meta > span:first-child { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* 卡片副信息行（2026-09-29）：「上次学习 / 收藏于 / 完成于」这类长文本从 .course-meta
   里挪到标题下方单独一行。.course-meta 是 space-between 的两端布局，硬塞第三组
   信息必然互相挤压 —— 9-28 修了课程中心，9-29 才发现收藏页与我的学习页是另外三套模板。 */
.course-subline { font-size: 12px; color: var(--primary); line-height: 1.5; margin-bottom: 4px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 横向滚动列表 */
.scroll-row { display: flex; gap: 12px; overflow-x: auto; padding-bottom: 8px; margin: 0 -4px -8px; }
.scroll-row::-webkit-scrollbar { display: none; }
.scroll-card { flex: 0 0 260px; background: var(--bg-white); border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; cursor: pointer; transition: all 0.2s; display: flex; flex-direction: column; }
.scroll-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
.scroll-card .course-cover { padding-top: 50%; }
.scroll-card .course-body { padding: 10px; }
.scroll-card .course-title { font-size: 13px; height: 36px; margin-bottom: 6px; }

/* ========== 播放器页 ========== */
.player-page { max-width: 1200px; margin: 0 auto; padding: 16px; }
.player-layout { display: grid; grid-template-columns: 1fr 320px; gap: 16px; }
.player-main { background: #000; border-radius: var(--radius-lg); overflow: hidden; position: relative; }
.player-video-wrap { position: relative; width: 100%; background: #000; aspect-ratio: 16/9; }
.player-video-wrap video, .player-video-wrap audio { width: 100%; height: 100%; }
.player-video-wrap audio { margin: auto; position: absolute; top: 50%; transform: translateY(-50%); }
.player-watermark { position: absolute; top: 0; left: 0; right: 0; bottom: 0; pointer-events: none; z-index: 10; overflow: hidden; }
.watermark-text { position: absolute; color: rgba(255,255,255,0.3); font-size: 14px; transform: rotate(-30deg); white-space: nowrap; }
.iframe-player { width: 100%; height: 100%; border: none; position: absolute; top:0; left:0; background:#fff; }
/* H5/SCORM 课件容器：iframe 为绝对定位不占文档流，必须由容器撑起高度，
   否则课件在 0 高度容器内初始化 → 只有声音没画面 */
#h5Player, #scormPlayer { position: relative; width: 100%; aspect-ratio: 16 / 9; background: #fff; }
/* 组织架构（后台） */
.org-tenant-card { border:1px solid var(--border); border-radius:10px; padding:14px 18px; min-width:220px; background:var(--bg-white); cursor:pointer; transition:.2s; }
.org-tenant-card:hover { border-color:var(--primary); box-shadow:0 2px 8px rgba(22,119,255,.12); }
.org-tenant-card.dim { opacity:.45; }
.org-dept-row { display:flex; align-items:center; gap:8px; padding:7px 12px; border-radius:8px; cursor:pointer; font-size:13px; }
.org-dept-row:hover { background:#f5f8ff; }
.org-dept-row.active { background:#e8f1ff; }
.org-dept-row .org-dept-twirl { color:#bbb; width:10px; display:inline-block; }
.player-link-wrap { padding: 60px 32px; text-align: center; color: #fff; }
.player-controls { position: absolute; bottom: 0; left: 0; right: 0; background: linear-gradient(transparent, rgba(0,0,0,0.7)); padding: 30px 16px 12px; z-index: 20; }
.player-info-bar { background: var(--bg-white); padding: 16px; border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
.player-title { font-size: 18px; font-weight: 600; margin-bottom: 8px; }
/* 播放页参数行（讲师/时长/学分 + 收藏/报名）
   2026-09-18：原来是 display:flex 无 flex-wrap、span 无 white-space —— 一行放不下时
   flex 会把每项压窄，于是文字在**项内部**折断，"60分钟"变成"60分"+"钟"、"
   已报名"变成"已报"+"名"，五项挤成一团。
   两个条件缺一不可：① 允许整项换行 ② 禁止项内断行（少任何一个都还会挤）。 */
.player-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px;
  font-size: 12.5px; color: var(--text-light); line-height: 1.5; }
.player-meta > span { white-space: nowrap; }
/* 收藏 / 报名：直接作为 .player-meta 的 flex 子项，与「时长·学分」同排、一起换行。
   2026-09-18b 去掉了原先的操作组包装层 —— 它靠 margin-left:auto 顶到最右、窄屏整组
   width:100%，结果「收藏」被单独挤成一行，与参数脱节。
   现在放不下时跟着前面的项一起整项折到下一行，不会再出现"孤行按钮"。
   内边距刻意压到与文字行等高（只留 hover 底色），视觉上与参数同属一行。 */
.player-meta .pm-fav { border: none; background: none; cursor: pointer; font-size: 12.5px;
  color: var(--text-secondary); padding: 2px 8px; border-radius: 12px; white-space: nowrap;
  line-height: 1.5; transition: background .2s, color .2s; }
.player-meta .pm-fav:hover { background: var(--bg); color: var(--primary); }
.player-meta .pm-enroll { border: none; cursor: pointer; font-size: 12.5px; color: #fff;
  background: var(--primary); padding: 3px 12px; border-radius: 12px; white-space: nowrap;
  line-height: 1.5; transition: opacity .2s; }
.player-meta .pm-enroll:hover { opacity: .9; }
.player-meta .pm-enrolled { font-size: 12px; color: #52c41a; white-space: nowrap; }
/* 报名审核中（功能包 G）：与「已报名」同位置互斥显示 */
.player-meta .pm-pending { font-size: 12px; color: #d98a00; white-space: nowrap; }

/* 通知页候选框（功能包 G） */
.nt-pick { max-height: 220px; overflow: auto; border: 1px solid #e8e8e8; border-radius: 8px;
           padding: 8px 10px; display: flex; flex-wrap: wrap; gap: 8px 18px; }
.nt-pick .nt-ck { white-space: nowrap; font-size: 13px; }
/* 详情页分类（2026-09-29）：原来播放器头部只有讲师/时长/学分，学员看不出这门课属于哪一类。 */
.player-meta .pm-cat { display: inline-flex; align-items: center; padding: 1px 8px;
  border-radius: 999px; background: #f0f5ff; color: #2f54eb; border: 0.5px solid #adc6ff; }
.player-meta .pm-cat:empty { display: none; }
@media (max-width: 480px) {
  .player-meta { gap: 6px 10px; font-size: 12px; }
}
.player-sidebar { display: flex; flex-direction: column; gap: 12px; }
.sidebar-tabs { display: flex; background: var(--bg-white); border-radius: var(--radius); overflow: hidden; }
.sidebar-tab { flex: 1; padding: 10px; text-align: center; cursor: pointer; font-size: 13px; font-weight: 500; color: var(--text-secondary); border-bottom: 2px solid transparent; }
.sidebar-tab.active { color: var(--primary); border-bottom-color: var(--primary); background: var(--primary-light); }
.sidebar-content { background: var(--bg-white); border-radius: var(--radius); padding: 12px; max-height: calc(100vh - 200px); overflow-y: auto; }
.chapter-list { list-style: none; }
.chapter-item { padding: 10px 12px; border-radius: var(--radius); cursor: pointer; margin-bottom: 4px; display: flex; align-items: center; gap: 10px; font-size: 13px; transition: all 0.2s; }
.chapter-item:hover { background: var(--bg); }
.chapter-item.active { background: var(--primary-light); color: var(--primary); font-weight: 500; }
.chapter-item.completed .ch-status { color: var(--success); }
.chapter-item .ch-status { width: 20px; height: 20px; border-radius: 50%; background: var(--bg); display: flex; align-items: center; justify-content: center; font-size: 11px; flex-shrink: 0; }
.chapter-item.completed .ch-status { background: var(--success); color: #fff; }
.chapter-item .ch-title { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chapter-item .ch-duration { font-size: 11px; color: var(--text-light); }

.note-input { width: 100%; border: 1px solid var(--border); border-radius: var(--radius); padding: 8px 12px; resize: none; font-size: 13px; margin-bottom: 8px; }
.note-input:focus { border-color: var(--primary); }
.note-item { padding: 10px 0; border-bottom: 1px solid var(--border); font-size: 13px; }
.note-item:last-child { border-bottom: none; }
.note-content { margin-bottom: 4px; }
.note-meta { font-size: 11px; color: var(--text-light); display: flex; justify-content: space-between; }
.note-time { color: var(--primary); cursor: pointer; }

.discussion-item { padding: 12px 0; border-bottom: 1px solid var(--border); }
.discussion-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.discussion-name { font-weight: 500; font-size: 13px; }
.discussion-time { font-size: 11px; color: var(--text-light); }
.discussion-content { font-size: 13px; color: var(--text-secondary); line-height: 1.6; }

.player-complete-overlay { position: absolute; top:0; left:0; right:0; bottom:0; background: rgba(0,0,0,0.85); z-index: 30; display: none; flex-direction: column; align-items: center; justify-content: center; color: #fff; }
.player-complete-overlay.show { display: flex; }
.complete-icon { font-size: 64px; margin-bottom: 16px; }
.complete-title { font-size: 24px; font-weight: 700; margin-bottom: 8px; }
.complete-sub { font-size: 14px; opacity: 0.8; margin-bottom: 24px; text-align: center; }
.complete-actions { display: flex; gap: 12px; }

/* ========== 考试页 ========== */
.exam-page { max-width: 900px; margin: 0 auto; padding: 20px; }
.exam-header { background: var(--bg-white); border-radius: var(--radius-lg); padding: 20px; margin-bottom: 16px; box-shadow: var(--shadow); display: flex; justify-content: space-between; align-items: center; }
.exam-title { font-size: 20px; font-weight: 600; }
.exam-timer { font-size: 24px; font-weight: 700; color: var(--primary); font-variant-numeric: tabular-nums; }
.exam-timer.warning { color: var(--danger); animation: pulse 1s infinite; }
.exam-body { background: var(--bg-white); border-radius: var(--radius-lg); padding: 24px; box-shadow: var(--shadow); }
.question-item { padding: 20px 0; border-bottom: 1px solid var(--border); }
.question-item:last-child { border-bottom: none; }
.q-number { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; background: var(--primary); color: #fff; border-radius: 50%; font-size: 13px; font-weight: 600; margin-right: 10px; flex-shrink: 0; }
.q-type-tag { font-size: 12px; color: var(--text-light); margin-left: 8px; }
.q-mark { font-size: 12px; color: var(--warning); margin-left: 8px; cursor: pointer; }
.q-mark.marked { color: var(--danger); font-weight: 600; }
.q-content { font-size: 15px; font-weight: 500; margin-bottom: 16px; line-height: 1.6; }
.q-options { list-style: none; }
.q-option { padding: 12px 16px; border: 1px solid var(--border); border-radius: var(--radius); margin-bottom: 8px; cursor: pointer; transition: all 0.2s; display: flex; align-items: center; gap: 12px; font-size: 14px; }
.q-option:hover { border-color: var(--primary); background: var(--primary-light); }
.q-option.selected { border-color: var(--primary); background: var(--primary-light); color: var(--primary); font-weight: 500; }
.q-option .opt-letter { width: 24px; height: 24px; border-radius: 50%; border: 1.5px solid #d9d9d9; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; flex-shrink: 0; }
.q-option.selected .opt-letter { background: var(--primary); border-color: var(--primary); color: #fff; }
.q-fill-input { width: 100%; padding: 10px 14px; border: 1px solid var(--border); border-radius: var(--radius); font-size: 14px; }
.q-fill-input:focus { border-color: var(--primary); }
.exam-footer { position: sticky; bottom: 0; background: var(--bg-white); padding: 16px; border-radius: var(--radius-lg); margin-top: 16px; box-shadow: var(--shadow-lg); display: flex; justify-content: space-between; align-items: center; z-index: 50; }
.exam-progress { font-size: 13px; color: var(--text-secondary); }

/* 浮动答题卡（手机端） */
.float-answer-card { position: fixed; bottom: 80px; right: 16px; width: 56px; height: 56px; background: var(--primary); color: #fff; border-radius: 50%; display: none; align-items: center; justify-content: center; font-size: 20px; box-shadow: var(--shadow-lg); cursor: pointer; z-index: 60; }
.answer-card-panel { position: fixed; bottom: 0; left: 0; right: 0; background: var(--bg-white); border-radius: var(--radius-lg) var(--radius-lg) 0 0; padding: 20px; box-shadow: 0 -4px 20px rgba(0,0,0,0.15); z-index: 200; display: none; transform: translateY(100%); transition: transform 0.3s; }
.answer-card-panel.show { display: block; transform: translateY(0); }
.answer-card-mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.4); z-index: 199; display: none; }
.answer-card-mask.show { display: block; }
.answer-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px; margin: 16px 0; }
.answer-grid .ag-item { aspect-ratio: 1; border-radius: var(--radius); border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; font-size: 13px; cursor: pointer; font-weight: 500; }
.ag-item.answered { background: var(--primary); color: #fff; border-color: var(--primary); }
.ag-item.current { border-color: var(--primary); box-shadow: 0 0 0 2px var(--primary-light); }
.ag-item.marked { background: var(--warning); color: #fff; border-color: var(--warning); }
.ag-item.wrong { background: var(--danger); color: #fff; border-color: var(--danger); }
.ag-item.correct { background: var(--success); color: #fff; border-color: var(--success); }

/* 考试结果 */
.result-score { text-align: center; padding: 40px 20px; }
.result-num { font-size: 72px; font-weight: 700; color: var(--primary); line-height: 1; }
.result-num.fail { color: var(--danger); }
.result-label { font-size: 16px; color: var(--text-secondary); margin-top: 8px; }
.result-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 24px 0; }
.result-stat { text-align: center; padding: 16px; background: var(--bg); border-radius: var(--radius); }
.result-stat .rs-num { font-size: 24px; font-weight: 700; }
.result-stat .rs-label { font-size: 12px; color: var(--text-light); margin-top: 4px; }
.wrong-answer-item { padding: 16px; background: #fff1f0; border-radius: var(--radius); margin-bottom: 12px; border-left: 3px solid var(--danger); }
.wrong-answer-item .my-answer { color: var(--danger); font-weight: 500; }
.wrong-answer-item .correct-answer { color: var(--success); font-weight: 500; }

/* ========== 认证页（登录） ========== */
/* ========== 品牌Logo ========== */
.brand-logo { display:flex; align-items:center; gap:10px; }
.brand-logo img { height:36px; }
.brand-logo span { font-size:18px; font-weight:700; color:var(--primary); letter-spacing:1px; }
.brand-logo.light img { height:38px; }
.brand-logo.white span { color:#fff; }

/* ========== 登录页（PC+移动端统一华企智训品牌风格） ========== */
.auth-page {
  min-height:100vh;
  display:flex;
  padding:0;
  background:linear-gradient(135deg,#082E72 0%,#0F4BB8 45%,#1976D2 100%);
  position:relative;
  overflow:hidden;
}
.auth-page::before {
  content:'';
  position:absolute;
  width:600px; height:600px;
  background:radial-gradient(circle, rgba(255,107,26,0.25) 0%, transparent 70%);
  top:-200px; right:-150px;
  border-radius:50%;
  animation:float 8s ease-in-out infinite;
}
.auth-page::after {
  content:'';
  position:absolute;
  width:400px; height:400px;
  background:radial-gradient(circle, rgba(255,255,255,0.08) 0%, transparent 70%);
  bottom:-100px; left:-100px;
  border-radius:50%;
}
@keyframes float {
  0%,100%{transform:translate(0,0);}
  50%{transform:translate(-30px,30px);}
}

/* PC端左侧品牌区 */
.auth-brand {
  flex:1.2;
  display:flex;
  flex-direction:column;
  justify-content:center;
  padding:60px 80px;
  color:#fff;
  position:relative;
  z-index:2;
}
.auth-brand-logo {
  background:rgba(255,255,255,0.95);
  display:inline-flex;
  align-items:center;
  padding:14px 28px;
  border-radius:12px;
  margin-bottom:40px;
  box-shadow:0 8px 32px rgba(0,0,0,0.2);
}
.auth-brand-logo img { height:56px; }
.auth-brand-title {
  font-size:42px;
  font-weight:800;
  line-height:1.2;
  margin-bottom:16px;
  letter-spacing:2px;
}
.auth-brand-sub {
  font-size:18px;
  opacity:0.85;
  margin-bottom:48px;
  line-height:1.8;
}
.auth-features {
  display:grid;
  grid-template-columns:1fr 1fr;
  gap:24px;
  max-width:560px;
}
.auth-feature {
  display:flex;
  gap:14px;
  align-items:flex-start;
}
.auth-feature-icon {
  width:48px; height:48px;
  background:rgba(255,107,26,0.9);
  border-radius:12px;
  display:flex;
  align-items:center;
  justify-content:center;
  font-size:24px;
  flex-shrink:0;
  box-shadow:0 4px 12px rgba(255,107,26,0.4);
}
.auth-feature-text .t { font-size:16px; font-weight:600; margin-bottom:4px; }
.auth-feature-text .d { font-size:13px; opacity:0.8; line-height:1.6; }
.auth-brand-footer {
  position:absolute;
  bottom:40px; left:80px;
  font-size:12px;
  opacity:0.6;
}

/* 登录卡片区 */
.auth-panel {
  width:480px;
  flex-shrink:0;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:40px;
  position:relative;
  z-index:2;
}
.auth-card {
  background:#fff;
  border-radius:20px;
  padding:44px 40px;
  width:100%;
  box-shadow:0 20px 60px rgba(0,0,0,0.25);
}
.auth-card-head { text-align:center; margin-bottom:24px; }
/* 登录卡专用：label 与输入框同排（设置页等处的表单仍用旧上下布局） */
.form-group-inline { display:flex; align-items:center; gap:12px; }
.form-label-inline { margin-bottom:0; flex:none; width:30px; }
.form-field { position:relative; flex:1; min-width:0; }
.form-field .form-icon, .form-field .form-eye { top:50%; transform:translateY(-50%); }
.auth-card-logo {
  display:flex; justify-content:center; margin-bottom:16px;
}
.auth-card-logo img { height:52px; }
.auth-title { font-size:24px; font-weight:700; color:var(--text); margin-bottom:8px; }
.auth-subtitle { font-size:14px; color:var(--text-secondary); }

.form-group { margin-bottom:20px; position:relative; }
.form-label { display:block; font-size:13px; font-weight:500; color:var(--text-secondary); margin-bottom:8px; }
.form-input { width:100%; padding:12px 14px; border:1px solid var(--border); border-radius:10px; font-size:14px; transition:all 0.2s; background:#fafbfc; }
.form-input:focus { border-color:var(--primary); background:#fff; box-shadow:0 0 0 3px var(--primary-light); outline:none; }
.form-input.with-icon { padding-left:42px; }
.form-icon { position:absolute; left:14px; top:38px; color:var(--text-light); font-size:16px; }
.form-eye { position:absolute; right:14px; top:38px; color:var(--text-light); cursor:pointer; font-size:16px; }
.form-row-flex { display:flex; justify-content:space-between; align-items:center; margin-bottom:24px; font-size:13px; color:var(--text-secondary); }
.form-row-flex label { display:flex; align-items:center; gap:6px; cursor:pointer; }
.form-row-flex a { color:var(--primary); }
.btn-primary { background:linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%); color:#fff; border:none; box-shadow:0 4px 12px rgba(15,75,184,0.3); }
.btn-primary:hover { background:linear-gradient(135deg, var(--primary-dark) 0%, #073070 100%); transform:translateY(-1px); box-shadow:0 6px 16px rgba(15,75,184,0.4); }
.btn-orange { background:linear-gradient(135deg, var(--accent) 0%, #E55A10 100%); color:#fff; box-shadow:0 4px 12px rgba(255,107,26,0.3); }
.auth-divider { display:flex; align-items:center; gap:12px; margin:24px 0; color:var(--text-light); font-size:12px; }
.auth-divider::before,.auth-divider::after { content:''; flex:1; height:1px; background:var(--border); }
.auth-other { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; }
.auth-other-btn { padding:10px; border:1px solid var(--border); border-radius:8px; text-align:center; font-size:12px; color:var(--text-secondary); cursor:pointer; transition:all 0.2s; background:#fff; }
.auth-other-btn:hover { border-color:var(--primary); color:var(--primary); background:var(--primary-light); }
.auth-other-btn:active { transform: scale(0.98); }
.auth-other-btn.linked { border-color:var(--success); color:var(--success); background:#f0fdf4; }
.auth-other-tip { margin-top:10px; font-size:12px; color:var(--text-light); text-align:center; line-height:1.6; }
.auth-hint { text-align:center; font-size:12px; color:var(--text-light); margin-top:20px; padding:12px; background:var(--bg); border-radius:var(--radius); line-height:1.8; }
.auth-hint a { color:var(--primary); font-weight:500; }
.auth-footer { text-align:center; font-size:12px; color:var(--text-light); margin-top:24px; }
.auth-footer a { color:var(--text-secondary); margin:0 6px; }
/* 登录被锁定 / 来源被限流时的常驻提示（2026-09-27b）。
   与 .btn:disabled 配合：锁定期间按钮置灰，到点自动恢复。 */
.login-lock {
  margin-top:12px; padding:10px 14px; border-radius:var(--radius);
  background:#fff2f0; border:1px solid #ffccc7; color:var(--danger);
  font-size:13px; line-height:1.6; text-align:center;
}
/* 还没锁、只是提醒「还剩几次」时用黄色底（学员端 / 管理端共用一套） */
.login-lock.warn {
  background:#fffbe6; border-color:#ffe58f; color:#874d00;
}
.btn:disabled, .btn[disabled] { opacity:.55; cursor:not-allowed; }

/* 管理员登录页专属（橙色强调） */
.auth-page.admin-login .auth-brand-title span:not(.auth-badge) { color:#FF8A3D; }
.auth-page.admin-login .auth-feature-icon { background:linear-gradient(135deg,#FF6B1A,#FF8A3D); }
.auth-page.admin-login .btn-primary { background:linear-gradient(135deg,#FF6B1A 0%,#E55A10 100%); box-shadow:0 4px 12px rgba(255,107,26,0.3); }
.auth-page.admin-login .btn-primary:hover { background:linear-gradient(135deg,#E55A10 0%,#C84A00 100%); }
.auth-badge { display:inline-block; background:linear-gradient(135deg,#FF6B1A,#FF8A3D); color:#fff; font-size:12px; padding:4px 12px; border-radius:20px; margin-left:8px; font-weight:500; letter-spacing:1px; }

/* 移动端响应式登录 */
@media (max-width: 900px) {
  .auth-brand { display:none; }
  .auth-panel { width:100%; padding:20px; }
  .auth-card { padding:36px 24px; border-radius:16px; }
  .auth-page::before { width:300px; height:300px; top:-100px; right:-100px; }
}
@media (max-width: 480px) {
  .auth-card-title { font-size:20px; }
  .auth-card-logo img { height:44px; }
  .auth-features-m { display:block !important; margin-top:20px; }
}

/* ========== 管理后台 ========== */
.admin-layout { display: flex; min-height: 100vh; }
.admin-sidebar { width: 220px; background: linear-gradient(180deg,#082E72 0%,#0A3A8F 100%); color: #fff; flex-shrink: 0; position: fixed; height: 100vh; transition: width 0.25s;
  /* 纵向 flex：logo 固定顶部 / 菜单区自身滚动 / 收起按钮固定底部。
     原先整条侧边栏 overflow-y:auto，菜单一长就把底部按钮挤出可视区，
     所以必须把滚动下沉到 .admin-menu 这一层。 */
  display: flex; flex-direction: column; overflow: hidden; }
.admin-logo { padding: 20px 8px; font-size: 17px; font-weight: 800; letter-spacing: 1px; text-align: center; border-bottom: 1px solid rgba(255,255,255,0.1); white-space: nowrap; }
.admin-logo img { height:24px; background:#fff; padding:2px 5px; border-radius:6px; flex-shrink:0; }
/* 收起/展开：固定在侧边栏底部的图标条（不再有文字）*/
.sidebar-toggle { flex: 0 0 auto; width: 100%; background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.7); border: none; border-top: 1px solid rgba(255,255,255,0.1); padding: 10px 0; cursor: pointer; transition: background 0.2s, color 0.2s;
  display: flex; align-items: center; justify-content: center; line-height: 0; }
.sidebar-toggle .sb-ico { width: 18px; height: 18px; display: block; transition: transform 0.25s; }
/* 收起态：图标整体翻转，箭头指向内容区（=点击可展开）*/
.admin-layout.sb-collapsed .sidebar-toggle .sb-ico { transform: rotate(180deg); }
.sidebar-toggle:hover { color: #fff; background: rgba(255,255,255,0.14); }
/* ★ 2026-10-07（功能包 R）：侧边栏底部改为「工具条」—— 设置菜单 + 收起/展开 并排。
   原先 .sidebar-toggle 独占整行；加设置入口后若仍叠两层，底部会占掉近百像素把菜单区挤没。
   折叠按钮**仍是** .sidebar-toggle（收起态的图标旋转规则不受影响），
   设置按钮单独用 .sidebar-cfg —— 否则它也会跟着一起转 180°。 */
.sidebar-tools { flex: 0 0 auto; display: flex; align-items: stretch; border-top: 1px solid rgba(255,255,255,0.1); }
.sidebar-tools .sidebar-toggle { flex: 1 1 0; width: auto; border-top: none; }
.sidebar-cfg { flex: 0 0 auto; background: rgba(255,255,255,0.06); color: rgba(255,255,255,0.7);
  border: none; border-right: 1px solid rgba(255,255,255,0.1); padding: 10px 14px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; line-height: 0; transition: background 0.2s, color 0.2s; }
.sidebar-cfg:hover { color: #fff; background: rgba(255,255,255,0.14); }
.sidebar-cfg .sb-ico { width: 18px; height: 18px; display: block; }
/* 「设置菜单显示隐藏」弹窗里的每一行 */
.mcfg-row { display: flex; align-items: center; gap: 10px; padding: 10px 4px; border-bottom: 1px solid #f0f0f0; }
.mcfg-row:last-child { border-bottom: none; }
.mcfg-ico { width: 22px; text-align: center; font-size: 16px; flex: 0 0 auto; }
.mcfg-name { flex: 1 1 auto; font-size: 14px; color: #262626; }
.mcfg-fixed { font-size: 12px; color: #bfbfbf; flex: 0 0 auto; }
/* 开关：纯 CSS 实现，不引第三方组件（本项目前端零构建、零依赖） */
.sw { position: relative; display: inline-block; width: 40px; height: 22px; flex: 0 0 auto; }
.sw input { opacity: 0; width: 0; height: 0; }
.sw .sw-track { position: absolute; inset: 0; background: #d9d9d9; border-radius: 11px; transition: background 0.2s; cursor: pointer; }
.sw .sw-track:before { content: ''; position: absolute; width: 18px; height: 18px; left: 2px; top: 2px;
  background: #fff; border-radius: 50%; transition: transform 0.2s; box-shadow: 0 1px 3px rgba(0,0,0,.2); }
.sw input:checked + .sw-track { background: #52c41a; }
.sw input:checked + .sw-track:before { transform: translateX(18px); }
.sw input:disabled + .sw-track { background: #f0f0f0; cursor: not-allowed; }
/* 收起态：60px 图标栏 */
.admin-layout.sb-collapsed .admin-sidebar { width: 60px; }
.admin-layout.sb-collapsed .admin-main { margin-left: 60px; }
.admin-layout.sb-collapsed .admin-logo { font-size: 14px; padding: 18px 0; writing-mode: vertical-rl; text-orientation: upright; letter-spacing: 4px; margin: 0 auto; }

.admin-layout.sb-collapsed .admin-menu-item { padding: 14px 0; justify-content: center; font-size: 17px; }
.admin-layout.sb-collapsed .admin-menu-item .mt { display: none; }
.admin-menu .mt { flex: 1; }
.admin-menu { list-style: none; padding: 12px 0; flex: 1 1 auto; overflow-y: auto;
  min-height: 0; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.22) transparent; }
/* 深色侧边栏里默认的浅色滚动条很扎眼，换成细的白色半透明条 */
.admin-menu::-webkit-scrollbar { width: 6px; }
.admin-menu::-webkit-scrollbar-track { background: transparent; }
.admin-menu::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.18); border-radius: 3px; }
.admin-menu::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,0.32); }
.admin-menu-item { padding: 12px 20px; color: rgba(255,255,255,0.75); cursor: pointer; display: flex; align-items: center; gap: 10px; transition: all 0.2s; font-size: 14px; border-left:3px solid transparent; }
.admin-menu-item:hover { color: #fff; background: rgba(255,255,255,0.08); }
.admin-menu-item.active { color: #fff; background: linear-gradient(90deg,rgba(255,107,26,0.25) 0%,rgba(255,107,26,0.05) 100%); border-left-color:var(--accent); }
.admin-main { flex: 1; margin-left: 220px; }
.admin-topbar { height: 60px; background: var(--bg-white); box-shadow: var(--shadow); display: flex; justify-content: space-between; align-items: center; padding: 0 24px; position: sticky; top: 0; z-index: 50; }
.admin-content { padding: 24px; background: var(--bg); min-height: calc(100vh - 60px); }

.admin-page { display: none; }
.admin-page.active { display: block; }

/* 管理KPI卡片 */
.admin-kpi-row { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 16px; margin-bottom: 24px; }
/* 2026-09-18h：KPI 由 4 张变 6 张（活跃率 / 从未学习）。<1500px 时 6 列会窄到读不出数字，
   退成 3 列两行；<=1024px 由文末响应式段退成 2 列。 */
@media (max-width: 1500px) { .admin-kpi-row { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.admin-kpi { background: var(--bg-white); border-radius: var(--radius-lg); padding: 20px; box-shadow: var(--shadow); }
.admin-kpi .kpi-value { font-size: 32px; font-weight: 700; color: var(--text); }
.admin-kpi .kpi-label { font-size: 13px; color: var(--text-light); margin-top: 4px; }
.admin-kpi .kpi-trend { font-size: 12px; margin-top: 8px; }
.kpi-trend.up { color: var(--success); }
.kpi-trend.down { color: var(--danger); }

.chart-row { display: grid; grid-template-columns: 2fr 1fr; gap: 16px; margin-bottom: 20px; }
/* 驾驶舱栅格（2026-09-18h）：原布局用同一套 2fr/1fr 去装 2 个、3 个、2 个 chart-box，
   结果是 trend 占满整行后 type 独占一行、level/asmt/hot 三个挤两列、dept 占满后 warn 独占 ——
   三处都留下空格子。改成按内容定列：单图整行 / 三图三等分 / 两图二等分。 */
.chart-row-1 { grid-template-columns: 1fr; }
.chart-row-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.chart-row-2eq { grid-template-columns: repeat(2, minmax(0, 1fr)); }
/* 三图并排在 <1400px 会把「人才测评」的纵轴标签压没 → 退两列（<=1024px 由响应式段归一列） */
@media (max-width: 1400px) { .chart-row-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.chart-box { background: var(--bg-white); border-radius: var(--radius-lg); padding: 20px; box-shadow: var(--shadow); }
.chart-title { font-size: 15px; font-weight: 600; margin-bottom: 16px; }

/* 管理表格 */
.table-toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; flex-wrap: wrap; gap: 12px; }
.table-filters { display: flex; gap: 8px; flex-wrap: wrap; }
.table-search { padding: 8px 12px; border: 1px solid var(--border); border-radius: var(--radius); width: 240px; font-size: 13px; }
/* 课程中心筛选条：搜索 / 类型 / 分类 / 排序 —— 宽屏四件同一行，窄屏（≤480px）改两行。
   用 grid 分配宽度：宽屏搜索框 minmax(0,1fr) 可收缩到 0、下拉吃内容宽度；
   ≤480px 时搜索框跨整行、3 个下拉平分等分轨道（见下面的 @media 块）。
   旧版是 flex + 搜索框 min-width:200px + flex-wrap:wrap，窄屏必然把下拉挤到第二行。 */
.course-filter-bar { display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: 8px; align-items: center; margin-bottom: 16px; }
.course-filter-bar .course-filter-search { width: 100%; min-width: 0; }
.course-filter-bar .course-filter-select { width: auto; min-width: 0; max-width: 40vw; text-overflow: ellipsis; }
@media (max-width: 768px) {
  .course-filter-bar { gap: 6px; margin-bottom: 12px; }
  .course-filter-bar .form-input { padding: 9px 10px; font-size: 13px; }
  /* 窄屏给下拉定宽：<select> 的固有宽度取决于**最长选项**（"🎮 H5互动"），
     但收起态只显示当前项（"最新"），用最长选项撑宽纯属浪费 —— 定宽 + 省略号更省地方。
     6.8em 在 border-box（本项目全局 box-sizing:border-box）下含内边距，
     足够放下 4 个中文字（"全部类型" / "评分最高"）。 */
  .course-filter-bar .course-filter-select { padding-left: 8px; padding-right: 20px; font-size: 12.5px; width: 6.8em; max-width: 34vw; }
}
@media (max-width: 480px) {
  /* 2026-09-28：分类下拉已改为 chips 行（见 .cat-tabs），本行控件回到 3 个
     （搜索框 + 类型 + 排序），故轨道数由 3 降为 2。下面 9-27f 的记录保留作考古。 */
  /* 2026-09-27f：加了分类下拉后有 4 个控件，一行放不下 → 搜索框独占一行，
     3 个下拉平分第二行。
     单行下限（容器 = 视口 − 12×2 − 20×2 = 视口 − 64）：
       3×85(下拉 6.8em@12.5px) + 3×6(间隙) + 93.45(搜索框底线) = 366.45px
       → 视口需 ≥ 430px。实测 414px 屏单行只剩 77px 给搜索框
         （内容区 57px，placeholder「搜索课程...」要 73.45px）→ 必然截断。
       故断点取 480px（标准移动端断点，留余量）。
     两行后每列 (容器 − 2×6) / 3：480px→134.7px；320px→81.3px，
     内容区 81.3−6−18−2 = 55.3px ≥ 48px（「评分最高」4 个中文 @12px）。 */
  .course-filter-bar { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .course-filter-bar .course-filter-search { grid-column: 1 / -1; width: 100%; max-width: none; }
  /* 两行后每列都是等分轨道，下拉吃满本列（.form-input 的 width:100% 在此重新生效） */
  .course-filter-bar .course-filter-select { width: 100%; max-width: none; }
}
@media (max-width: 400px) {
  /* 320~400px 极窄屏：两行布局下每列更窄，内边距/字号再收一档，
     保证「评分最高」4 个中文仍放得下。
     宽度由上面 480 断点的 100% 决定，此处不再写定宽 em（写了也是被覆盖的死声明）。 */
  .course-filter-bar .course-filter-select { padding-left: 6px; padding-right: 18px; font-size: 12px; }
}

/* ===== AI 大模型配置状态条（2026-09-27g）=====
   管理端「AI 配置」页与「AI 出题」页共用。要在出题**之前**就让管理员看清
   这次走的是真大模型还是降级模板 —— 改造前只有生成后一句 tip，还误报成
   「未配置 LLM_API_KEY」，照着修也修不好。 */
.llm-banner { padding:12px 14px; border-radius:8px; font-size:13px; line-height:1.95; margin-bottom:14px; }
.llm-banner.ok { background:#f6ffed; border:1px solid #b7eb8f; color:#237804; }
.llm-banner.warn { background:#fffbe6; border:1px solid #ffe58f; color:#874d00; }
.llm-banner.err { background:#fff2f0; border:1px solid #ffccc7; color:#a8071a; }
.llm-banner .llm-b-title { font-weight:700; margin-bottom:4px; }
.llm-kv { font-size:12px; color:#595959; }
.llm-kv b { color:#262626; font-weight:600; }
.llm-hint { font-size:12px; margin-top:6px; }
.llm-hint code { background:rgba(0,0,0,.05); padding:1px 5px; border-radius:3px; }

/* 课程分类标签（管理端列表 / 学员端卡片共用）：蓝底细边，与课程类型标签区分开 */
.tag-cat { background:#f0f5ff; color:#2f54eb; border:1px solid #adc6ff; flex:0 0 auto; }
.filter-tabs { display: flex; gap: 4px; background: var(--bg); padding: 4px; border-radius: var(--radius); overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.filter-tabs::-webkit-scrollbar { display: none; }
/* 2026-09-29：滚动条被隐藏时，右侧渐隐是唯一的「还能往右滑」暗示。
   实测首页 chips 内容宽 736px / 容器 366px，后 4 个分类全在屏幕外却毫无提示。 */
.filter-tabs.has-overflow { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent);
  mask-image: linear-gradient(to right, #000 calc(100% - 26px), transparent); }
.filter-tab { flex: 0 0 auto; white-space: nowrap; padding: 6px 14px; border-radius: 6px; font-size: 13px; cursor: pointer; color: var(--text-secondary); }
.filter-tab.active { background: var(--bg-white); color: var(--primary); font-weight: 500; box-shadow: var(--shadow); }
.filter-tab .tab-count { display: inline-block; margin-left: 5px; padding: 0 6px; min-width: 14px; text-align: center; background: #e9edf3; border-radius: 9px; font-size: 11px; color: var(--text-light); line-height: 17px; vertical-align: 1px; }
.filter-tab.active .tab-count { background: var(--primary); color: #fff; }

/* 分类 chips（2026-09-28）：首页「为你推荐」与课程中心共用一套。
   与类型 tabs 复用同一个 .filter-tabs 骨架（横向滚动 + 隐藏滚动条 + 计数徽章），
   只用胶囊形与主色边框区分主次 —— 避免长出第二套筛选组件后两边逻辑漂移。 */
.cat-tabs { margin-bottom: 8px; }
.cat-tabs .filter-tab { border-radius: 999px; border: 0.5px solid transparent;
  padding: 8px 14px; position: relative; }
/* 触摸目标补偿（2026-09-29）：实测芯片原可视高只有 35px，低于移动端 44px 推荐值，
   横向密集排列容易点空。视觉高只加到 39px（筛选区占高基本持平），
   再用 ::after 把**可点热区**撑到 44px —— 手指不容易点偏，又不抬高页面。 */
.cat-tabs .filter-tab::after { content: ''; position: absolute; left: 0; right: 0;
  top: 50%; height: 44px; transform: translateY(-50%); }
.cat-tabs .filter-tab.active { border-color: var(--primary); }

.data-table { width: 100%; background: var(--bg-white); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow); }
.data-table table { width: 100%; border-collapse: collapse; }
.data-table th { background: #fafafa; padding: 12px 16px; text-align: left; font-size: 13px; font-weight: 600; color: var(--text-secondary); border-bottom: 1px solid var(--border); }
.data-table td { padding: 12px 16px; font-size: 13px; border-bottom: 1px solid var(--border); }
.data-table tr:hover td { background: #fafafa; }
.data-table tr:last-child td { border-bottom: none; }
.table-actions { display: flex; gap: 4px; }
.rating-stars { color: var(--warning); font-size: 12px; }

.progress-bar { width: 80px; height: 6px; background: var(--bg); border-radius: 3px; overflow: hidden; display: inline-block; vertical-align: middle; margin-right: 8px; }
.progress-bar-inner { height: 100%; background: var(--primary); border-radius: 3px; }
.progress-bar-inner.low { background: var(--danger); }
.progress-bar-inner.mid { background: var(--warning); }
.progress-bar-inner.high { background: var(--success); }

/* 弹窗/Modal */
.modal-mask { position: fixed; top:0; left:0; right:0; bottom:0; background: rgba(0,0,0,0.45); z-index: 1000; display: none; align-items: center; justify-content: center; padding: 20px; }
.modal-mask.show { display: flex; }
.modal { background: var(--bg-white); border-radius: var(--radius-lg); width: 100%; max-width: 600px; max-height: 90vh; overflow-y: auto; box-shadow: 0 10px 40px rgba(0,0,0,0.2); }
.modal-lg { max-width: 900px; }
.modal-header { padding: 16px 20px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; }
.modal-title { font-size: 16px; font-weight: 600; }
.modal-close { font-size: 20px; color: var(--text-light); cursor: pointer; }
.modal-body { padding: 20px; }
.modal-footer { padding: 12px 20px; border-top: 1px solid var(--border); display: flex; justify-content: flex-end; gap: 8px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px; }
.form-row.full { grid-template-columns: 1fr; }
/* 三列变体（学分 / 难度 / 课程分类）。
   ⚠ 不要写成 .form-row.form-row-3 —— 那是 (0,2,0)，会压过下面 @media 里的
   .form-row { grid-template-columns: 1fr; } (0,1,0)，窄屏就永远降不到单列。 */
.form-row-3 { grid-template-columns: 1fr 1fr 1fr; }

/* 空状态 */
.empty-state { text-align: center; padding: 60px 20px; color: var(--text-light); }
.empty-icon { font-size: 64px; margin-bottom: 16px; opacity: 0.3; }
.empty-text { font-size: 14px; }

/* Toast */
.toast-container { position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 9999; pointer-events: none; }
.toast { background: rgba(0,0,0,0.8); color: #fff; padding: 10px 20px; border-radius: var(--radius); margin-bottom: 8px; font-size: 14px; animation: fadeInDown 0.3s; }
.toast.success { background: var(--success); }
.toast.error { background: var(--danger); }
.toast.warning { background: var(--warning); }
.toast.info { background: var(--primary, #3b82f6); }
@keyframes fadeInDown { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } }

/* 加载 */
.loading { text-align: center; padding: 40px; color: var(--text-light); }
.spinner { display: inline-block; width: 32px; height: 32px; border: 3px solid var(--border); border-top-color: var(--primary); border-radius: 50%; animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* ========== 响应式 ========== */
@media (max-width: 1024px) {
  .course-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .player-layout { grid-template-columns: 1fr; }
  /* 视频窗保持最上（DOM 顺序：player-main → player-sidebar），目录跟在下方 */
  .chart-row, .chart-row-3, .chart-row-2eq { grid-template-columns: 1fr; }
  .admin-kpi-row { grid-template-columns: repeat(2, 1fr); }
}

/* ===== 设置页开关 ===== */
.switch { position:relative; display:inline-block; width:44px; height:24px; flex:0 0 44px; }
.switch input { opacity:0; width:0; height:0; }
.switch .slider { position:absolute; cursor:pointer; inset:0; background:#d0d5dd; border-radius:24px; transition:.25s; }
.switch .slider:before { content:""; position:absolute; height:18px; width:18px; left:3px; bottom:3px; background:#fff; border-radius:50%; transition:.25s; box-shadow:0 1px 3px rgba(0,0,0,.18); }
.switch input:checked + .slider { background:var(--primary); }
.switch input:checked + .slider:before { transform:translateX(20px); }

@media (max-width: 768px) {
  .top-nav-inner { padding: 0 16px; height: 52px; }
  .nav-links { display: none; }
  .main-content { padding: 12px; }
  .bottom-tab { display: block; }
  .app-container { padding-bottom: 70px; }
  .welcome-bar { padding: 20px; border-radius: var(--radius); }
  .welcome-title { font-size: 18px; }
  .stats-row { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .stat-card { padding: 14px; }
  .stat-card .stat-value { font-size: 22px; }
  .quick-entries { grid-template-columns: repeat(5, 1fr); gap: 6px; }
  .quick-entry { padding: 12px 4px; }
  .quick-entry .qe-icon { font-size: 24px; }
  .quick-entry .qe-text { font-size: 10px; }
  .course-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .todo-card { padding: 12px; gap: 8px; }
  .todo-item { padding: 8px 4px; min-width: 70px; }
  .todo-item .num { font-size: 22px; }
  .todo-divider { height: 30px; }
  .section-title { font-size: 16px; }
  .player-page { padding: 8px; }
  .player-info-bar { padding: 12px; }
  .player-title { font-size: 15px; }
  .exam-page { padding: 12px; }
  .exam-header { padding: 14px; flex-direction: column; gap: 8px; text-align: center; }
  .exam-timer { font-size: 20px; }
  .exam-body { padding: 16px; }
  .question-item { padding: 14px 0; }
  .q-content { font-size: 14px; }
  .result-num { font-size: 56px; }
  .float-answer-card { display: flex; }
  .answer-grid { grid-template-columns: repeat(6, 1fr); }
  /* 管理后台手机端 */
  .admin-sidebar { display: none; }
  .admin-main { margin-left: 0; }
  .admin-content { padding: 12px; }
  .admin-kpi-row { grid-template-columns: repeat(2, 1fr); gap: 10px; }
  .admin-kpi { padding: 14px; }
  .admin-kpi .kpi-value { font-size: 24px; }
  .data-table { overflow-x: auto; }
  .form-row { grid-template-columns: 1fr; gap: 12px; }
  .table-filters { overflow-x: auto; }
  .modal { max-width: 95vw; }
  .exam-footer { flex-wrap: wrap; gap: 8px; }
  .result-stats { grid-template-columns: repeat(3, 1fr); gap: 8px; }
  .result-stat { padding: 10px; }
  .result-stat .rs-num { font-size: 18px; }
}


/* ========== U-5：课程中心分页条 ========== */
.pager { display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 6px; margin: 20px 0 4px; grid-column: 1 / -1; }
.pager-btn { min-width: 34px; height: 32px; padding: 0 10px; border: 1px solid var(--border);
  background: var(--bg-white); color: var(--text-secondary); border-radius: 6px; font-size: 13px; }
.pager-btn:hover:not(:disabled) { border-color: var(--primary); color: var(--primary); }
.pager-btn.active { background: var(--primary); border-color: var(--primary); color: #fff; font-weight: 600; }
.pager-btn:disabled { opacity: .45; cursor: not-allowed; }
.pager-gap { color: var(--text-light); padding: 0 2px; }
.pager-info { margin-left: 8px; font-size: 12px; color: var(--text-light); }

/* ========== U-11：加载失败占位（含重试按钮） ========== */
.error-box { color: var(--text-secondary); }
.error-box .btn { margin-top: 2px; }

/* ========== 课程章节数据分析弹窗（2026-09-27h） ========== */
/* 仅管理端使用（#chapterStatsBody 只存在于 admin.html）；app.css 两端共用，故用 id 收窄 */
#chapterStatsBody table { width: 100%; border-collapse: collapse; font-size: 13px; }
#chapterStatsBody thead th { background: #fafafa; color: #8c8c8c; font-weight: 500;
  border-bottom: 1px solid var(--border); }
#chapterStatsBody tbody td { padding: 8px; border-top: 1px solid #f0f0f0;
  color: var(--text-secondary); }
#chapterStatsBody tbody tr:hover td { background: #fafafa; }
#chapterStatsSummary b { color: var(--primary); }


/* 消息中心：公众号推送渠道标签（功能包 H · notifications.send_channel） */
.msg-ch-wx{display:inline-block;padding:1px 6px;border-radius:8px;font-size:10px;line-height:1.5;
  background:rgba(7,193,96,.12);color:#07954a;border:1px solid rgba(7,193,96,.35);margin-left:4px;}


/* ===== 图文课 / 讲义正文（学员端内联渲染，样式对齐课程详情排版）===== */
.aico-doc { font-size: 15px; line-height: 1.9; color: #262626; word-break: break-word; }
.aico-doc h2 { font-size: 20px; line-height: 1.5; margin: 22px 0 10px; color: #1677ff; font-weight: 600; }
.aico-doc h3 { font-size: 17px; line-height: 1.5; margin: 18px 0 8px; color: #262626; font-weight: 600; }
.aico-doc h4 { font-size: 15px; margin: 14px 0 6px; font-weight: 600; }
.aico-doc p { margin: 10px 0; }
.aico-doc ul, .aico-doc ol { margin: 10px 0 10px 24px; }
.aico-doc li { margin: 4px 0; }
.aico-doc strong { font-weight: 600; color: #0b4fa8; }
.aico-doc blockquote { margin: 14px 0; padding: 9px 14px; border-left: 3px solid #1677ff;
  background: #f5f9ff; color: #595959; border-radius: 0 6px 6px 0; }
.aico-doc code { background: #f5f5f5; padding: 1px 5px; border-radius: 4px; font-size: 13px; }
.aico-doc figure.aico-fig { margin: 0 0 16px; }
.aico-doc figure.aico-fig img { width: 100%; max-width: 680px; border-radius: 10px;
  display: block; margin: 0 auto; box-shadow: 0 2px 10px rgba(0,0,0,0.06); }
.aico-doc table.aico-table { width: 100%; border-collapse: collapse; margin: 12px 0; font-size: 14px; }
.aico-doc table.aico-table th, .aico-doc table.aico-table td {
  border: 1px solid #e8e8e8; padding: 7px 10px; text-align: left; }
.aico-doc table.aico-table th { background: #f0f5ff; font-weight: 600; }
@media (max-width: 640px) {
  .aico-doc { font-size: 14px; }
  .aico-doc h2 { font-size: 18px; }
}
