/* ==========================================================================
   teach.css · 教学平台（学习页 / 任务页 / 教学看板）
   --------------------------------------------------------------------------
   样式口径对照四张参考截图：
     · 底：极浅的粉紫渐变（沿用 lx.css 的 --lx-bg-*，不再另造一套颜色）
     · 卡：纯白 + 1px 极细描边 + 柔和投影，圆角 12—14px
     · 主色：洋红 #e11d48（进度条、按钮、印章），辅助紫 #7c5cff（可切换页签）
     · 学习页：左列表（章 → 条目）+ 右窄栏（能力图谱 / 主讲老师 / 公告），约 1fr : 320px
     · 任务页：左学习窗格（约 380px）+ 右「开始任务」大区，带淡紫渐变背景
     · 「已完成」用斜置红章而不是打勾图标 —— 截图里就是印章，一眼能扫出哪些章过了

   所有类以 tp- 开头，且只在 .tp-page / .tp-task 容器下生效，
   不与既有 app.css / lx.css 的类名冲突。
   ========================================================================== */

:root {
  --tp-side: 320px;
  /* 任务页右「开始任务」栏宽度。第四十四轮起左栏改为流式（吃掉剩余宽度），
     右栏是一根定宽的指令栏：默认 30%，最窄 340px、最宽 470px。
     拖动条改的就是这个值（见 .tp-task-body / .tp-split）。 */
  --tp-rail: clamp(340px, 30%, 470px);
  --tp-radius: 14px;
}

/* ------------------------------------------------------------------ 公共 */
.tp-page, .tp-task {
  color: var(--lx-ink);
  font-size: 13px;
  line-height: 1.7;
}
.tp-page .sp, .tp-task .sp { flex: 1; }
.tp-num { font-family: var(--lx-num); }

/* 顶部课程条：课程身份 + 七个页签（学习 / 资源 / 互动 / 团队 / 评价 / 分析 / 结课考试） */
.tp-coursebar {
  display: flex;
  align-items: center;
  gap: 18px;
  background: #fff;
  border: 1px solid var(--lx-line);
  border-radius: var(--tp-radius);
  padding: 0 16px;
  margin-bottom: 14px;
  box-shadow: var(--lx-sh);
  overflow-x: auto;
  scrollbar-width: none;
}
.tp-coursebar::-webkit-scrollbar { display: none; }
/* F-37：教学看板的场次下拉。跟其他页面的 select 一样用原生控件，
   但尺寸小一档 —— 它嵌在课程条里，太大会把「口径」提示挤出屏幕。 */
.tp-sess {
  flex: none; max-width: 300px; font-size: 12px; color: var(--lx-ink2, #4b4660);
  border: 1px solid var(--lx-line); border-radius: 8px; background: #fff;
  padding: 5px 26px 5px 9px; cursor: pointer; outline: none;
}
.tp-sess:focus { border-color: #7c5cff; box-shadow: 0 0 0 3px rgba(124, 92, 255, .12); }
.tp-cb-id {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 0; flex: none;
}
.tp-cb-id .dot {
  width: 26px; height: 26px; border-radius: 9px; flex: none;
  background: linear-gradient(135deg, #f43f5e, #7c5cff);
  color: #fff; font-size: 12px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}
.tp-cb-id b { font-size: 14px; font-weight: 800; letter-spacing: .2px; }
.tp-cb-id em {
  font-style: normal; font-size: 11.5px; color: var(--lx-ink3);
  padding-left: 8px; border-left: 1px solid var(--lx-line);
}
.tp-nav { display: flex; align-items: center; gap: 2px; flex: none; }
.tp-nav button {
  border: 0; background: none; cursor: pointer;
  padding: 14px 13px 12px; font-size: 13px; color: var(--lx-ink2);
  border-bottom: 2px solid transparent; transition: .15s; white-space: nowrap;
  font-family: inherit;
}
.tp-nav button:hover { color: var(--lx-red); }
.tp-nav button.on {
  color: var(--lx-red); font-weight: 800; border-bottom-color: var(--lx-red);
}

/* ------------------------------------------------------------- 学习页主体 */
.tp-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--tp-side);
  gap: 16px;
  align-items: start;
}
.tp-main { min-width: 0; }
.tp-side { display: flex; flex-direction: column; gap: 14px; }

/* 顶部总进度条 */
.tp-overall {
  background: #fff; border: 1px solid var(--lx-line); border-radius: var(--tp-radius);
  padding: 13px 16px; box-shadow: var(--lx-sh); margin-bottom: 14px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.tp-overall .lbl { font-size: 12px; color: var(--lx-ink3); }
.tp-overall .big { font-size: 20px; font-weight: 800; color: var(--lx-red); }
/* 注意：进度条元素本身的类名是 .tp-bar，这里必须写 .tp-bar。
   早期版本写成 .bar 匹配不到（没有单独的 bar 类），进度条会被 flex 压成 0 宽——肉眼看不见。 */
.tp-overall .tp-bar { flex: 1 1 260px; min-width: 200px; }
.tp-overall .meta { font-size: 11.5px; color: var(--lx-ink3); }
/* F-36：主数字旁边必须写明它是哪个口径 —— 页面上同时存在
   「学习完成度 / 实操完成度 / 任务完成度」三个数，光写一个大百分比等于没说。 */
.tp-overall .big .unit {
  font-size: 11.5px; font-weight: 600; color: var(--lx-ink3);
  margin-left: 6px; letter-spacing: 0;
}
.tp-overall .meta b { color: var(--lx-ink2, #4b4660); font-variant-numeric: tabular-nums; }
.tp-overall .meta .why {
  display: inline-block; margin-left: 6px; padding: 0 5px; border-radius: 4px;
  background: #f3eefc; color: #7c5cff; font-size: 10.5px; cursor: help;
}

/* 进度条（复用于总进度与条目） */
.tp-bar {
  height: 6px; border-radius: 99px; background: #f1ecf4; overflow: hidden;
}
.tp-bar > i {
  display: block; height: 100%; border-radius: 99px;
  background: linear-gradient(90deg, #f43f5e, #7c5cff);
  transition: width .45s cubic-bezier(.2, .8, .3, 1);
}
.tp-bar.vio > i { background: linear-gradient(90deg, #7c5cff, #a78bfa); }

/* 章 */
.tp-chap { margin-bottom: 18px; }
.tp-chap-hd {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 4px 10px; border-bottom: 1px solid var(--lx-line);
  margin-bottom: 2px;
}
.tp-chap-hd .dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--lx-ink3); flex: none;
}
.tp-chap-hd h3 { margin: 0; font-size: 13.5px; font-weight: 800; color: var(--lx-ink); }
.tp-chap-hd .pct { font-size: 11.5px; color: var(--lx-ink3); }
.tp-chap-hd .intro {
  border: 0; background: none; cursor: pointer; color: var(--lx-ink3);
  font-size: 11.5px; display: inline-flex; align-items: center; gap: 4px;
  font-family: inherit; padding: 2px 6px; border-radius: 6px;
}
.tp-chap-hd .intro:hover { color: var(--lx-red); background: var(--lx-red-soft); }

/* 条目（单元）行 —— 截图里一条一行，左侧图标、中间名称与进度、右侧印章或按钮 */
.tp-unit {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr) auto;
  gap: 12px; align-items: center;
  padding: 13px 12px; border-radius: 12px;
  border: 1px solid transparent; cursor: pointer;
  transition: .16s;
}
.tp-unit + .tp-unit { border-top: 1px dashed var(--lx-line2); }
.tp-unit:hover { background: #fffafb; border-color: var(--lx-line); box-shadow: var(--lx-sh); }
.tp-unit.open { background: #fffafb; border-color: var(--lx-line); box-shadow: var(--lx-sh); }
.tp-unit-ic {
  width: 38px; height: 38px; border-radius: 12px; flex: none;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 13px; font-weight: 800;
  background: linear-gradient(135deg, #ff8a4c, #f43f5e);
  box-shadow: 0 4px 10px rgba(244, 63, 94, .22);
}
.tp-unit-ic.v2 { background: linear-gradient(135deg, #f472b6, #a855f7); box-shadow: 0 4px 10px rgba(168, 85, 247, .22); }
.tp-unit-ic.v3 { background: linear-gradient(135deg, #38bdf8, #6366f1); box-shadow: 0 4px 10px rgba(99, 102, 241, .22); }
.tp-unit-ic.v4 { background: linear-gradient(135deg, #34d399, #059669); box-shadow: 0 4px 10px rgba(5, 150, 105, .2); }
.tp-unit-ic.v5 { background: linear-gradient(135deg, #fbbf24, #f59e0b); }
.tp-unit-b { min-width: 0; }
.tp-unit-t {
  font-size: 13.5px; font-weight: 700; color: var(--lx-ink);
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
}
.tp-unit-t .idx { color: var(--lx-ink); font-weight: 800; }
.tp-unit-t .sub { font-size: 11px; font-weight: 500; color: var(--lx-ink3); }
.tp-unit-d { font-size: 11px; color: var(--lx-ink3); margin-top: 2px; }
.tp-unit-p {
  display: flex; align-items: center; gap: 9px; margin-top: 7px;
  max-width: 330px;
}
.tp-unit-p .k { font-size: 11.5px; color: var(--lx-ink3); white-space: nowrap; }
.tp-unit-p .tp-bar { flex: 1; min-width: 60px; }
.tp-unit-p .v { font-size: 11.5px; color: var(--lx-ink2); font-family: var(--lx-num); white-space: nowrap; }
.tp-unit-r { display: flex; align-items: center; gap: 8px; flex: none; }

/* 五星难度 */
.tp-stars { display: inline-flex; gap: 1px; font-size: 10px; letter-spacing: 1px; vertical-align: middle; }
.tp-stars i { font-style: normal; color: #e6dff0; }
.tp-stars i.on { color: #fb7185; }

/* 「已完成」印章（截图里的斜置红章） */
.tp-stamp {
  display: inline-block; transform: rotate(-9deg);
  border: 2px solid var(--lx-red); border-radius: 5px;
  color: var(--lx-red); font-style: italic; font-weight: 800;
  letter-spacing: 2px; padding: 1px 9px; font-size: 12px;
  opacity: .92; white-space: nowrap;
  box-shadow: inset 0 0 0 1px rgba(225, 29, 72, .28);
}
/* 条目内联清单里的小印章：同一个「已完成」在窄列里连出三行，
   保持大章尺寸会把行高撑开、视觉上抢过任务名，所以单独收一档。 */
.tp-stamp.sm {
  font-size: 9.5px; padding: 0 5px; letter-spacing: 0;
  border-width: 1.5px; border-radius: 4px; transform: rotate(-6deg);
  box-shadow: inset 0 0 0 1px rgba(225, 29, 72, .2);
}
.tp-stamp.gray { border-color: var(--lx-ink3); color: var(--lx-ink3); box-shadow: none; }

/* 「开始实操」按钮（截图里的粉红实心小按钮） */
.tp-start {
  border: 0; cursor: pointer; font-family: inherit;
  background: linear-gradient(135deg, #f43f5e, #e11d48);
  color: #fff; font-size: 12px; font-weight: 700;
  padding: 7px 14px; border-radius: 8px; white-space: nowrap;
  box-shadow: 0 4px 12px rgba(225, 29, 72, .25);
  transition: .15s;
}
.tp-start:hover { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(225, 29, 72, .32); }
.tp-start.ghost {
  background: #fff; color: var(--lx-red); border: 1px solid #fbcfe0; box-shadow: none;
}
.tp-start.ghost:hover { background: var(--lx-red-soft); transform: none; }

/* 状态小标签 */
.tp-tag {
  display: inline-block; font-size: 10.5px; padding: 1px 7px; border-radius: 99px;
  background: #f4f1f7; color: var(--lx-ink2); white-space: nowrap;
}
.tp-tag.red { background: var(--lx-red-soft); color: var(--lx-red); }
.tp-tag.vio { background: var(--lx-violet-soft); color: var(--lx-violet); }
.tp-tag.green { background: var(--lx-green-soft); color: #0b8f6a; }
.tp-tag.amber { background: var(--lx-amber-soft); color: var(--lx-amber); }
/* F-46：「本场次不包含」用的中性灰 —— 不是错误，只是不在本场次范围内 */
.tp-tag.gray { background: #eef0f4; color: #7b8494; }

/* 展开的任务清单 */
.tp-lessons {
  margin: 2px 0 10px 50px; border-left: 2px solid var(--lx-line2); padding-left: 12px;
}
.tp-lesson {
  display: grid; grid-template-columns: 20px minmax(0, 1fr) auto;
  gap: 9px; align-items: center;
  padding: 8px 10px; border-radius: 9px; cursor: pointer; transition: .14s;
}
.tp-lesson:hover { background: #fff6f8; }
.tp-lesson .ix {
  width: 20px; height: 20px; border-radius: 50%; flex: none;
  border: 1px solid var(--lx-line); background: #fff;
  font-size: 10.5px; color: var(--lx-ink3);
  display: flex; align-items: center; justify-content: center; font-family: var(--lx-num);
}
.tp-lesson.done .ix { background: var(--lx-green); border-color: var(--lx-green); color: #fff; }
.tp-lesson-t { font-size: 12.5px; color: var(--lx-ink); min-width: 0; }
.tp-lesson-t b { font-weight: 600; }
.tp-lesson-t .s { display: block; font-size: 11px; color: var(--lx-ink3); }
.tp-lesson-r { display: flex; align-items: center; gap: 6px; }

/* --------------------------------------------------------------- 右窄栏卡 */
.tp-card {
  background: #fff; border: 1px solid var(--lx-line); border-radius: var(--tp-radius);
  box-shadow: var(--lx-sh); overflow: hidden;
}
/* 从页头「课程资料与上传」跳过来时闪一下：卡片在页底，滚到了也容易看丢 */
@keyframes tpFlash {
  0% { box-shadow: 0 0 0 0 rgba(225, 29, 72, .34); border-color: #ef9db5; }
  70% { box-shadow: 0 0 0 7px rgba(225, 29, 72, 0); border-color: #ef9db5; }
  100% { box-shadow: 0 0 0 0 rgba(225, 29, 72, 0); }
}
.tp-card.tp-flash { animation: tpFlash 1.3s ease-out 1; }
.tp-card-hd {
  padding: 11px 14px; border-bottom: 1px solid var(--lx-line2);
  font-size: 12.5px; font-weight: 800; color: var(--lx-ink);
  display: flex; align-items: center; gap: 6px;
}
.tp-card-bd { padding: 13px 14px; }

/* 能力图谱：能力词按掌握度着色，色深 = 掌握度 */
.tp-cloud { display: flex; flex-wrap: wrap; gap: 7px 9px; }
.tp-cloud b {
  font-weight: 600; font-size: 12px; cursor: default;
  padding: 2px 4px; border-radius: 5px; transition: .15s;
}
.tp-cloud b:hover { background: var(--lx-red-soft); }
.tp-cloud b.lv0 { color: #c9c2d6; }
.tp-cloud b.lv1 { color: #9a8fb0; }
.tp-cloud b.lv2 { color: #e11d48; }
.tp-cloud b.lv3 { color: #7c5cff; font-weight: 800; }
.tp-cloud b.lv4 { color: #0b8f6a; font-weight: 800; }

/* 主讲老师 */
.tp-teacher { display: flex; align-items: center; gap: 11px; }
.tp-teacher .av {
  width: 44px; height: 44px; border-radius: 50%; flex: none;
  background: linear-gradient(135deg, #fde2e8, #e9ddff);
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; color: var(--lx-red); font-weight: 800;
}
.tp-teacher b { display: block; font-size: 13px; }
.tp-teacher span { font-size: 11.5px; color: var(--lx-ink3); }

/* 公告（无公告时给插画位，与截图一致） */
.tp-empty-note {
  text-align: center; padding: 12px 4px 6px; color: var(--lx-ink3); font-size: 12px;
}
.tp-empty-note .ill {
  width: 72px; height: 52px; margin: 0 auto 8px; border-radius: 10px;
  background:
    radial-gradient(circle at 22% 30%, #fda4af 0 7px, transparent 8px),
    radial-gradient(circle at 78% 22%, #a5b4fc 0 5px, transparent 6px),
    radial-gradient(circle at 60% 70%, #6ee7b7 0 6px, transparent 7px),
    linear-gradient(135deg, #fff1f4, #f3efff);
  border: 1px solid var(--lx-line);
}

/* ------------------------------------------------------------- 任务页 */
.tp-taskbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: #fff; border: 1px solid var(--lx-line); border-radius: var(--tp-radius);
  padding: 9px 14px; margin-bottom: 12px; box-shadow: var(--lx-sh);
}
.tp-taskbar .bc {
  display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--lx-ink3);
  min-width: 0; flex-wrap: wrap;
}
.tp-taskbar .bc b { color: var(--lx-ink); font-size: 13px; }
.tp-taskbar .bc .sep { color: #ddd6e6; }
.tp-clock {
  font-family: var(--lx-num); font-size: 13px; color: var(--lx-ink2);
  background: #faf7fc; border: 1px solid var(--lx-line2); border-radius: 7px;
  padding: 3px 10px; letter-spacing: .5px;
}
.tp-tb-btns { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.tp-tb-btns button {
  border: 1px solid #e4d9f2; background: #f6f1ff; color: #6d4fd0;
  font-size: 12px; padding: 6px 12px; border-radius: 8px; cursor: pointer;
  font-family: inherit; transition: .15s; white-space: nowrap;
}
.tp-tb-btns button:hover { background: #efe7ff; }
.tp-tb-btns button.primary {
  background: linear-gradient(135deg, #f43f5e, #e11d48); border-color: transparent;
  color: #fff; font-weight: 700; box-shadow: 0 4px 12px rgba(225, 29, 72, .25);
}
.tp-tb-btns button.primary:hover { transform: translateY(-1px); }
.tp-tb-btns button:disabled { opacity: .55; cursor: not-allowed; transform: none; }

.tp-task-body {
  /* 左学习窗格（流式）｜ 拖动条 ｜ 右「开始任务」指令栏（定宽）。
     原来是反过来的：左栏写死 384px、右栏吃掉剩下的全部。左栏要装「任务目录 +
     图文 + 实训步骤」三大段，384px 下每行都被压得很短、一个任务要滚三四屏；
     右栏只有两步指令，却把大半个屏幕留成空白 —— 屏幕越宽越难看。
     现在把宽度让给真正有内容的那一侧，右栏收成一条栏（默认 30%，340—470px），
     中间那条可以拖、键盘也能调，宽度记在 localStorage，双击回默认。 */
  display: grid;
  grid-template-columns: minmax(0, 1fr) 14px var(--tp-rail);
  align-items: start;
}

/* 拖动条：平时是一条淡竖线 + 中间的小抓手（不做成纯 hover 才出现，
   否则没人知道这里能拖）；按住变主色，并在原位浮出当前宽度。 */
.tp-split {
  position: relative;
  /* 吸顶 + 一屏高：左栏很长，拖动条要是跟着格子拉满（上千像素），
     线会一直伸到右栏卡片下面的空白里，看着像页面裂缝。
     固定成一屏高并吸顶，滚到哪儿都能拖。 */
  align-self: start; position: sticky; top: 12px;
  height: calc(100vh - 160px); max-height: 720px; min-height: 300px;
  display: flex; align-items: center; justify-content: center;
  cursor: col-resize; touch-action: none; outline: none;
}
.tp-split::before {
  content: ''; position: absolute; top: 4px; bottom: 4px; left: 50%; width: 2px; margin-left: -1px;
  border-radius: 2px; background: linear-gradient(180deg, transparent, #e8e1f2 8%, #e8e1f2 92%, transparent);
  transition: background .15s, width .15s;
}
.tp-split .grip {
  position: relative; z-index: 1; width: 12px; height: 40px; border-radius: 7px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  background: #fff; border: 1px solid var(--lx-line); box-shadow: 0 1px 5px rgba(80, 40, 120, .10);
  opacity: .78; transition: opacity .15s, border-color .15s;
}
.tp-split .grip i { width: 2px; height: 2px; border-radius: 50%; background: #b6aacd; }
.tp-split:hover .grip, .tp-split:focus-visible .grip { opacity: 1; border-color: #f2b6c8; }
.tp-split:hover::before, .tp-split:focus-visible::before, .tp-split.on::before {
  width: 3px;
  background: linear-gradient(180deg, transparent, #f6bdcd 8%, var(--lx-red) 50%, #f6bdcd 92%, transparent);
}
.tp-split .tip {
  position: absolute; top: 50%; left: 50%; z-index: 2;
  transform: translate(-50%, -50%) scale(.94);
  padding: 3px 8px; border-radius: 8px; background: rgba(31, 24, 45, .88); color: #fff;
  font-size: 11px; font-variant-numeric: tabular-nums; white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity .12s, transform .12s;
}
.tp-split.on .grip { opacity: 0; }
.tp-split.on .tip { opacity: 1; transform: translate(-50%, -50%) scale(1); }
/* 拖动期间整页跟着变指针：指针移出那 14px 时不该突然变回箭头 */
body.tp-resizing, body.tp-resizing * { cursor: col-resize !important; user-select: none !important; }


/* 左：学习窗格 */
.tp-learn {
  background: #fff; border: 1px solid var(--lx-line); border-radius: var(--tp-radius);
  box-shadow: var(--lx-sh); overflow: hidden;
}
.tp-learn-hd {
  padding: 12px 14px 10px; border-bottom: 1px solid var(--lx-line2);
}
.tp-learn-hd .k { font-size: 11.5px; color: var(--lx-ink3); }
.tp-learn-hd .t { font-size: 13.5px; font-weight: 800; color: var(--lx-red); margin-top: 1px; }
.tp-learn-hd .meta { font-size: 11px; color: var(--lx-ink3); margin-top: 4px; display: flex; gap: 10px; flex-wrap: wrap; }

.tp-subtabs {
  display: flex; gap: 2px; padding: 0 10px; border-bottom: 1px solid var(--lx-line2);
  overflow-x: auto; scrollbar-width: none;
}
.tp-subtabs::-webkit-scrollbar { display: none; }
.tp-subtabs button {
  border: 0; background: none; cursor: pointer; font-family: inherit;
  font-size: 12px; color: var(--lx-ink3); padding: 9px 9px 8px;
  border-bottom: 2px solid transparent; white-space: nowrap; transition: .15s;
}
.tp-subtabs button.on { color: var(--lx-red); font-weight: 700; border-bottom-color: var(--lx-red); }

.tp-pane { padding: 13px 14px; }

/* 视频 / 图文卡 */
.tp-video {
  border-radius: 10px; overflow: hidden; background: #faf7fc;
  border: 1px solid var(--lx-line2); position: relative;
}
.tp-video video { width: 100%; display: block; background: #000; max-height: 220px; }
.tp-video-cap {
  display: flex; align-items: center; gap: 6px;
  padding: 7px 10px; font-size: 11.5px; color: var(--lx-ink2); background: #fff;
  border-top: 1px solid var(--lx-line2);
}
.tp-video-cap b { font-size: 12px; }
/* -------------------------------------------------- 本任务资源（第四十三轮）
   一个任务里可能同时有视频 / PPT / PDF / Word。卡片左边一个格式徽标（用字，不用图标：
   「PDF」「PPT」这两个词本身就是最快的识别信号），右边标题 + 文件名 + 大小。
   颜色只用来做二次区分，不承担识别责任 —— 色弱的人靠文字也能分清。 */
.tp-res-n {
  display: inline-block; margin-left: 6px; padding: 0 6px; border-radius: 99px;
  background: #f2eef7; color: var(--lx-ink2); font-size: 10.5px; font-weight: 700;
  vertical-align: 1px;
}
.tp-reslist { display: flex; flex-direction: column; gap: 6px; margin-bottom: 4px; }
.tp-rescard {
  display: grid; grid-template-columns: 38px minmax(0, 1fr) auto; align-items: center; gap: 9px;
  width: 100%; padding: 8px 10px; text-align: left; cursor: pointer;
  background: #fff; border: 1px solid var(--lx-line2); border-radius: 10px;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}
.tp-rescard:hover { border-color: #d9c9e8; box-shadow: 0 4px 12px rgba(80,40,120,.07); transform: translateY(-1px); }
.tp-rescard .cv { width: 64px; height: 40px; border-radius: 6px; overflow: hidden; flex: none; background: #f1eef8; box-shadow: 0 0 0 1px rgba(28, 24, 45, .06) inset; }
.tp-rescard .cv img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tp-rescard .ic {
  width: 38px; height: 38px; border-radius: 9px; display: flex; align-items: center; justify-content: center;
  font-size: 9.5px; font-weight: 800; letter-spacing: .3px; color: #fff; background: #94a3b8;
}
.tp-rescard .ic.p { background: linear-gradient(135deg,#e11d48,#fb7185); }
.tp-rescard .ic.o { background: linear-gradient(135deg,#d97706,#f59e0b); }
.tp-rescard .ic.w { background: linear-gradient(135deg,#1d4ed8,#3b82f6); }
.tp-rescard .ic.x { background: linear-gradient(135deg,#0f766e,#10b981); }
.tp-rescard .ic.v { background: linear-gradient(135deg,#7c3aed,#a855f7); }
.tp-rescard .ic.i { background: linear-gradient(135deg,#0891b2,#06b6d4); }
.tp-rescard .tx { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.tp-rescard .tx b { font-size: 12px; color: var(--lx-ink); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tp-rescard .tx em { font-style: normal; font-size: 10.5px; color: var(--lx-ink3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tp-rescard .go { font-size: 11px; color: var(--lx-red); font-weight: 600; padding-left: 4px; }
.tp-res-hint { font-size: 11px; color: var(--lx-ink3); margin: 2px 0 6px; }

/* 资源查看器 */
.tp-resview-hd { display: flex; align-items: center; gap: 10px; padding-bottom: 10px; border-bottom: 1px solid var(--lx-line2); }
.tp-resview-hd .ic {
  width: 42px; height: 42px; border-radius: 10px; flex: none; color: #fff; background: #94a3b8;
  display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 800;
}
.tp-resview-hd .ic.p { background: linear-gradient(135deg,#e11d48,#fb7185); }
.tp-resview-hd .ic.o { background: linear-gradient(135deg,#d97706,#f59e0b); }
.tp-resview-hd .ic.w { background: linear-gradient(135deg,#1d4ed8,#3b82f6); }
.tp-resview-hd .ic.x { background: linear-gradient(135deg,#0f766e,#10b981); }
.tp-resview-hd .ic.v { background: linear-gradient(135deg,#7c3aed,#a855f7); }
.tp-resview-hd .ic.i { background: linear-gradient(135deg,#0891b2,#06b6d4); }
.tp-resview-hd .tx { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 3px; }
.tp-resview-hd .tx b { font-size: 13.5px; color: var(--lx-ink); }
.tp-resview-hd .tx em { font-style: normal; font-size: 11px; color: var(--lx-ink3); }
.tp-resview-note { font-size: 12px; color: var(--lx-ink2); line-height: 1.7; padding: 8px 0 2px; }
.tp-doc { width: 100%; border: 0; background: #f3f4f6; border-radius: 10px; display: block; margin-top: 10px; }
.tp-doc-pdf { height: min(72vh, 720px); }
/* Office 在线预览（第四十五轮）：服务端把 docx/pptx/xlsx 翻成一整页 HTML，
   这里只是给它一个窗口。底色用预览页自己的浅灰，加载完成前也不会闪白。 */
.tp-doc-office { height: min(74vh, 760px); background: #f5f6f9; }
.tp-doc-tip { font-size: 11px; color: var(--lx-ink3); line-height: 1.7; margin-top: 8px; }
.tp-doc-video { width: 100%; max-height: 68vh; background: #000; border-radius: 10px; margin-top: 10px; }
.tp-doc-img { margin-top: 10px; text-align: center; background: #f8fafc; border-radius: 10px; padding: 8px; }
.tp-doc-img img { max-width: 100%; border-radius: 6px; }
.tp-doc-note { font-size: 12px; color: var(--lx-ink2); line-height: 1.75; background: #fbf8ff; border: 1px dashed #e2d6ee; border-radius: 8px; padding: 9px 11px; margin-top: 10px; }
.tp-doc-text {
  margin: 10px 0 0; max-height: 46vh; overflow: auto; padding: 12px 14px;
  background: #fcfcfd; border: 1px solid var(--lx-line2); border-radius: 10px;
  font-size: 12px; line-height: 1.85; color: var(--lx-ink2);
  white-space: pre-wrap; word-break: break-word; font-family: inherit;
}

.tp-figure { position: relative; }
.tp-figure img { width: 100%; display: block; border-radius: 10px; border: 1px solid var(--lx-line2); }
.tp-figure figcaption {
  font-size: 11px; color: var(--lx-ink3); margin-top: 6px; line-height: 1.6;
}

/* 正文块（任务摘要 / 步骤） */
.tp-h5 {
  font-size: 12px; font-weight: 800; color: var(--lx-ink);
  margin: 14px 0 6px; padding-left: 8px; border-left: 3px solid var(--lx-red);
}
.tp-h5:first-child { margin-top: 0; }
.tp-ul { margin: 0; padding-left: 17px; }
.tp-ul li { font-size: 12.5px; color: var(--lx-ink2); margin-bottom: 5px; line-height: 1.75; }
.tp-ul li b { color: var(--lx-ink); }
.tp-steps li { margin-bottom: 9px; }
.tp-steps .h { font-size: 12.5px; font-weight: 700; color: var(--lx-ink); }
.tp-steps .items { margin: 3px 0 0; padding-left: 16px; }
.tp-steps .items li { font-size: 12px; color: var(--lx-ink2); line-height: 1.7; }
.tp-case {
  /* 参考答案是多行文本（分点写的判分口径），不保留换行会被浏览器压成一段，
     教师分好的点全部糊在一起 —— 编辑端预览用 pre-wrap，这里必须一致。 */
  white-space: pre-wrap;
  font-size: 12.5px; color: var(--lx-ink2); line-height: 1.8;
  background: #fcfaff; border: 1px solid var(--lx-line2); border-radius: 10px;
  padding: 10px 12px;
}
.tp-kp { border-top: 1px dashed var(--lx-line2); padding: 9px 0; }
.tp-kp:first-child { border-top: 0; padding-top: 0; }
.tp-kp .t { font-size: 12.5px; font-weight: 700; color: var(--lx-ink); }
.tp-kp .d { font-size: 12px; color: var(--lx-ink2); line-height: 1.75; margin-top: 2px; }
.tp-warn { border-left: 3px solid var(--lx-amber); background: var(--lx-amber-soft); }
.tp-warn .t { color: #a56408; }

/* 右：开始任务 */
.tp-startpane {
  border-radius: var(--tp-radius); padding: 22px 20px 26px;
  border: 1px solid var(--lx-line);
  background:
    radial-gradient(120% 80% at 100% 0%, #f3e9ff 0%, transparent 55%),
    radial-gradient(100% 70% at 0% 100%, #ffe9ef 0%, transparent 55%),
    #fdfbff;
  box-shadow: var(--lx-sh);
  /* 右栏内容比左栏（图文 + 步骤）短很多。
     第四十四轮之前是「撑到一屏高 + 垂直居中」：标题「开始任务」落在半屏以下，
     与左栏「当前任务」差着一大截，屏幕越宽中间那块空得越明显。
     现在收成一条指令栏：只占内容高度 + 吸顶，往下读步骤时「进入系统」始终在
     视线里，剩下来的高度交给页面背景，不再画一块空渐变板。 */
  display: flex; flex-direction: column; justify-content: flex-start;
  padding: 20px 18px 22px;
  align-self: start;
  position: sticky;
  top: 12px;
}
.tp-startpane > h2 {
  margin: 6px 0 18px; text-align: center; font-size: 17px; font-weight: 800; color: var(--lx-ink);
  letter-spacing: 1px;
}
.tp-startpane > h2 .deco {
  display: block; width: 54px; height: 3px; margin: 9px auto 0; border-radius: 3px;
  background: linear-gradient(90deg, transparent, #d8c8f5, transparent);
}
.tp-startcard {
  /* 栏宽被拖窄时卡片跟着缩，不再硬撑 520px 溢出 */
  max-width: min(560px, 100%); margin: 0 auto; background: #fff;
  border: 1px solid var(--lx-line); border-radius: 12px;
  box-shadow: 0 10px 30px rgba(90, 50, 120, .07);
  padding: 6px 16px;
}
.tp-op { padding: 15px 0; position: relative; }
.tp-op + .tp-op { border-top: 1px dashed var(--lx-line2); }
.tp-op-h {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px; font-weight: 800; color: var(--lx-ink);
}
.tp-op-h .n {
  width: 20px; height: 20px; border-radius: 50%; flex: none;
  background: var(--lx-violet-soft); color: var(--lx-violet);
  font-size: 11px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}
.tp-op-b {
  /* 右栏收窄后（第四十四轮）按钮再跟文字挤一行，文字只剩 200 出头，
     「单据」「业务域」逐词折行、org-tree 被断成两行。改成竖向：
     说明占满整行，按钮落在下一行靠右 —— 窄栏里这样反而更好读。 */
  font-size: 12px; color: var(--lx-ink2); line-height: 1.75;
  margin: 6px 0 0 28px; display: flex; flex-direction: column; align-items: stretch; gap: 9px;
}
.tp-op-b .txt { flex: 1; min-width: 0; }
.tp-op-b code {
  background: #f6f2fb; border: 1px solid var(--lx-line2); border-radius: 5px;
  padding: 0 5px; font-size: 11.5px; color: #6d4fd0; white-space: nowrap;
}
.tp-op-b .tp-enter { align-self: flex-end; }
.tp-enter {
  border: 0; cursor: pointer; font-family: inherit; flex: none;
  background: linear-gradient(135deg, #7c5cff, #6366f1); color: #fff;
  font-size: 12px; font-weight: 700; padding: 8px 16px; border-radius: 8px;
  box-shadow: 0 4px 12px rgba(99, 102, 241, .26); transition: .15s;
}
.tp-enter:hover { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(99, 102, 241, .34); }
.tp-enter:disabled { opacity: .5; cursor: not-allowed; transform: none; }

/* 判据进度（任务页底部提示条） */
.tp-judge {
  max-width: min(560px, 100%); margin: 14px auto 0; font-size: 11.5px; color: var(--lx-ink3);
  display: flex; align-items: center; gap: 7px 9px; flex-wrap: wrap;
}
/* 两行：第一行「判据 + 进度 + 12/3」，第二行满宽「说明 + 印章」。
   挤在同一行时进度条会被压到 60px、说明尾巴折行、印章掉到第三行。 */
.tp-jg-row { display: flex; align-items: center; gap: 7px; flex: 1 1 100%; min-width: 0; }
.tp-jg-row .tp-bar { flex: 1 1 60px; min-width: 60px; }
.tp-jg-note { color: var(--lx-ink2); }
.tp-jg-note .tp-judge-note { flex: 1; min-width: 0; }
.tp-judge b { color: var(--lx-ink2); font-family: var(--lx-num); }

/* 底部前后导航 */
.tp-footbar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 14px; background: #fff; border: 1px solid var(--lx-line);
  border-radius: var(--tp-radius); padding: 9px 12px; box-shadow: var(--lx-sh);
}
.tp-footbar .hint { font-size: 11.5px; color: var(--lx-ink3); }
.tp-footbar button {
  border: 1px solid var(--lx-line); background: #fff; color: var(--lx-ink2);
  font-size: 12px; padding: 6px 12px; border-radius: 8px; cursor: pointer;
  font-family: inherit; transition: .15s;
}
.tp-footbar button:hover { border-color: #fbcfe0; color: var(--lx-red); }

/* 看板顶部动作条（发起正式考试 / 发起补考） */
.tp-actions {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  background: #fff; border: 1px solid var(--lx-line); border-radius: var(--tp-radius);
  padding: 10px 14px; box-shadow: var(--lx-sh); margin-bottom: 14px;
}
.tp-actions button {
  border: 1px solid #e4d9f2; background: #f6f1ff; color: #6d4fd0;
  font-size: 12px; padding: 6px 13px; border-radius: 8px; cursor: pointer;
  font-family: inherit; transition: .15s; white-space: nowrap;
}
.tp-actions button:hover { background: #efe7ff; border-color: #d8c8f5; }
.tp-actions .hint { font-size: 11.5px; color: var(--lx-ink3); }

/* ------------------------------------------------------------- 教师看板 */
.tp-kpis { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 10px; margin-bottom: 14px; }
.tp-kpi {
  background: #fff; border: 1px solid var(--lx-line); border-radius: 12px;
  padding: 11px 13px; box-shadow: var(--lx-sh);
}
.tp-kpi .k { font-size: 11.5px; color: var(--lx-ink3); }
.tp-kpi .v { font-size: 21px; font-weight: 800; color: var(--lx-ink); font-family: var(--lx-num); line-height: 1.3; }
.tp-kpi .v.red { color: var(--lx-red); }
.tp-kpi .v.vio { color: var(--lx-violet); }
.tp-kpi .x { font-size: 11px; color: var(--lx-ink3); }

.tp-tablewrap {
  background: #fff; border: 1px solid var(--lx-line); border-radius: var(--tp-radius);
  box-shadow: var(--lx-sh); overflow: auto;
}
.tp-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.tp-table th {
  text-align: left; font-size: 11.5px; font-weight: 700; color: var(--lx-ink3);
  padding: 10px 12px; background: #fdfbfe; border-bottom: 1px solid var(--lx-line);
  white-space: nowrap; position: sticky; top: 0; z-index: 1;
}
.tp-table td { padding: 9px 12px; border-bottom: 1px solid var(--lx-line2); vertical-align: middle; }
/* 表格单元格里的进度条是 flex 子项，不给 flex 就会按内容宽度算成 0 —— 只剩百分比数字 */
.tp-table .tp-bar { flex: 1 1 80px; min-width: 60px; }
.tp-table tr:hover td { background: #fffafb; }
.tp-table .num { font-family: var(--lx-num); }

/* ------------------------------------------- 场次范围外的章节 / 单元（F-46）
   不是「未开始」也不是「已完成」，而是「本场次没开这一章」：
   统一降饱和 + 虚线边，避免学生把它当成待办任务。 */
.tp-chap.off .dot { background: #c9ced8; }
.tp-chap.off h3 { color: var(--lx-ink3); }
.tp-unit.off { opacity: .78; background: #fcfcfd; }
.tp-unit.off:hover { background: #fcfcfd; box-shadow: none; }
.tp-unit.off .tp-unit-ic { filter: grayscale(1); opacity: .65; }
.tp-lesson.off { opacity: .78; }
.tp-lesson.off .tp-lesson-t b { color: var(--lx-ink3); }

/* ------------------------------------------------------------- 响应式 */
@media (max-width: 1200px) {  .tp-body { grid-template-columns: minmax(0, 1fr); }
  .tp-side { flex-direction: row; flex-wrap: wrap; }
  .tp-side > .tp-card { flex: 1; min-width: 240px; }
  .tp-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 980px) {
  /* 单列堆叠时没有「左右」可拖，拖动条必须整条拿掉 —— 留一条竖线在
     两段内容之间，会让人以为那是个分割线而不是控件。 */
  .tp-task-body { grid-template-columns: minmax(0, 1fr); }
  .tp-split { display: none; }
  .tp-learn { order: 2; }
  /* 单列时右栏排在最上面。此时再吸顶，往下读步骤它会一直压在上面挡内容 —— 取消 */
  .tp-startpane { order: 1; min-height: 300px; position: static; }
  .tp-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .tp-unit { grid-template-columns: 32px minmax(0, 1fr); }
  .tp-unit-r { grid-column: 1 / -1; justify-content: flex-end; }
  .tp-lessons { margin-left: 8px; }
  .tp-startpane { padding: 16px 12px 20px; }
}

/* ==========================================================================
   课程学习页 v2 · 分步改版（2026-11-06）
   --------------------------------------------------------------------------
   第 1 步：章 → 卡片
     改版前「章」只是背景上的一行小字，学生扫读时分不清哪些单元属于同一章，
     章完成度也只能挤在标题后面。现在章是一张独立卡片：
       左侧序号徽标（颜色跟完成度走）｜章名 + 一句话说明｜环形进度 + 分数｜简介｜折叠
     章体（.tp-chap-bd）单独承载单元列表，折叠只收章体、不收章头。
   ========================================================================== */
.tp-page .tp-chap {
  background: #fff; border: 1px solid var(--lx-line); border-radius: 16px;
  box-shadow: var(--lx-sh); overflow: hidden; margin-bottom: 14px;
}
.tp-chap-hd {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; margin: 0;
  border-bottom: 1px solid var(--lx-line2);
  background: linear-gradient(180deg, #fff, #fdfbfe);
}
.ch-no {
  width: 38px; height: 38px; border-radius: 12px; flex: none;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 15px; font-weight: 800; font-family: var(--lx-num);
  background: var(--c, #e11d48);
  box-shadow: 0 8px 18px -10px var(--c, #e11d48);
}
.ch-tt { flex: 1 1 auto; min-width: 0; }
.tp-chap-hd h3 { margin: 0; font-size: 14px; font-weight: 800; color: var(--lx-ink); letter-spacing: .2px; }
.ch-desc {
  margin: 3px 0 0; font-size: 11.5px; font-weight: 400; color: var(--lx-ink3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ch-prog { display: flex; align-items: center; gap: 8px; flex: none; }
.ch-prog-t { min-width: 46px; }
.ch-prog-t b { display: block; font-size: 12.5px; font-weight: 800; color: var(--lx-ink); line-height: 1.25; }
.ch-prog-t span { font-size: 10.5px; color: var(--lx-ink3); }
.tp-chap-hd .intro {
  flex: none; border: 1px solid var(--lx-line); background: #fbf9fc; color: var(--lx-ink2);
  font-size: 11.5px; padding: 5px 10px; border-radius: 9px;
  display: inline-flex; align-items: center; gap: 5px;
  cursor: pointer; font-family: inherit; transition: .15s;
}
.tp-chap-hd .intro:hover { color: var(--lx-red); background: var(--lx-red-soft); border-color: #fbd5e2; }
.ch-fold {
  flex: none; width: 28px; height: 28px; border: 0; background: none; border-radius: 8px;
  color: var(--lx-ink3); cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: .18s;
}
.ch-fold:hover { background: #f5effa; color: var(--lx-ink); }
.ch-fold svg { transition: transform .2s; }
.tp-chap.folded .ch-fold svg { transform: rotate(-90deg); }
.tp-chap.folded .tp-chap-hd { border-bottom-color: transparent; }
.tp-chap-bd { padding: 4px 8px 8px; }
.tp-chap-bd[hidden] { display: none; }
/* 资源页的「章内折叠」：只裁切卡片容器（.fold 由 resBodyHtml 按条数决定加不加），
   底部给一道渐隐，让「下面还有」这件事在视觉上说得清楚；章头与筛选条不受影响。
   学情页的章体不加 .fold，所以这条样式只作用于资源页。 */
.tp-chap-bd.fold { max-height: 620px; overflow: hidden; position: relative; }
.tp-chap-bd.fold::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 84px;
  background: linear-gradient(180deg, rgba(255,255,255,0), #fff 92%);
  pointer-events: none;
}
.tp-res-more {
  display: block; width: calc(100% - 16px); margin: 2px 8px 12px; padding: 9px 0;
  border: 1px solid var(--lx-line2); border-radius: 10px; background: #fff;
  color: var(--lx-ink2); font-size: 12.5px; cursor: pointer; transition: .15s;
}
.tp-res-more:hover { border-color: #d9c9f5; background: #fbf7ff; color: var(--lx-ink); }
/* 范围外（本场次未开设）：整卡降饱和 + 虚线边，与「未开始」区分开 */
.tp-page .tp-chap.off { background: #fcfcfd; border-style: dashed; box-shadow: none; }
.tp-chap.off .ch-no { background: #d7dbe3; box-shadow: none; }
.tp-chap.off .ch-desc { color: #b3b9c4; }

/* --------------------------------------------------------------------------
   第 2 步：单元行
     改版前三块信息纵向堆叠、进度条被 max-width 压到 330px、右侧按钮宽度随文案
     变化（「继续实操」比「开始实操」窄 8px），一列看下去参差不齐。
     现在：徽标按状态上色 ｜ 标题 + 摘要 + 元信息 + 通栏进度 ｜ 固定 132px 操作列。
   -------------------------------------------------------------------------- */
.tp-chap-bd .tp-unit {
  display: grid; grid-template-columns: 42px minmax(0, 1fr) 132px;
  gap: 14px; align-items: center;
  padding: 13px 12px 13px 10px;
  border: 0; border-radius: 12px; background: transparent;
  cursor: pointer; transition: background .16s;
}
.tp-chap-bd .tp-unit + .tp-unit { border-top: 1px solid var(--lx-line2); }
.tp-chap-bd .tp-unit:hover { background: linear-gradient(90deg, #fffafb, #fff); border-color: transparent; box-shadow: none; }
.tp-chap-bd .tp-unit.open { background: #fff8fa; border-color: transparent; box-shadow: none; }

/* 序号徽标：颜色承担状态语义 —— 绿=已完成 / 紫=进行中 / 橙=未开始 / 灰=范围外 */
.tp-unit .tp-unit-ic {
  width: 42px; height: 42px; border-radius: 13px; font-size: 14px; font-family: var(--lx-num);
  background: linear-gradient(135deg, #ffb27a, #f4623a);
  box-shadow: 0 8px 16px -10px rgba(244, 98, 58, .85);
}
.tp-unit.st-done .tp-unit-ic { background: linear-gradient(135deg, #45d6a4, #12b886); box-shadow: 0 8px 16px -10px rgba(18, 184, 134, .85); }
.tp-unit.st-doing .tp-unit-ic { background: linear-gradient(135deg, #a78bfa, #7c5cff); box-shadow: 0 8px 16px -10px rgba(124, 92, 255, .85); }
.tp-unit.st-todo .tp-unit-ic { background: linear-gradient(135deg, #ffcb9a, #ff9f6b); box-shadow: 0 8px 16px -10px rgba(255, 159, 107, .8); }

.tp-unit .tp-unit-t { font-size: 13.5px; font-weight: 700; gap: 8px; }
.tp-unit .tp-unit-t .sub {
  font-size: 10.5px; font-weight: 600; color: var(--lx-violet);
  background: var(--lx-violet-soft); padding: 1px 8px; border-radius: 99px;
}
.u-sum {
  margin-top: 3px; font-size: 11.5px; color: var(--lx-ink3);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.u-meta {
  margin-top: 4px; display: flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--lx-ink3); flex-wrap: wrap;
}
.u-sep { color: #ddd6e6; }

.tp-unit .tp-unit-p { max-width: none; margin-top: 8px; gap: 10px; }
.tp-unit .tp-unit-p .k { font-size: 10.5px; }
.tp-unit .tp-unit-p .tp-bar { flex: 1; min-width: 90px; height: 7px; background: #f2edf6; }
.tp-unit .tp-unit-p .v { min-width: 46px; text-align: right; font-size: 11.5px; }
.tp-unit .tp-unit-r { justify-content: flex-end; }
.tp-unit .tp-start {
  min-width: 104px; justify-content: center; display: inline-flex; align-items: center;
  gap: 3px; padding: 7px 12px;
}
.tp-unit .tp-start .ar { opacity: .65; margin-left: 2px; }

/* 已完成：绿胶囊（替代斜置红章，降低整屏噪声） */
.tp-page .tp-stamp {
  transform: none; font-style: normal; letter-spacing: 0; font-weight: 700;
  font-size: 11.5px; color: #0b8f6a; background: #ecfdf5;
  border: 1px solid #c7ecdd; border-radius: 99px; padding: 5px 11px;
  box-shadow: none; display: inline-flex; align-items: center; gap: 4px;
  white-space: nowrap; min-width: 104px; justify-content: center;
}
.tp-page .tp-stamp.sm { min-width: 0; font-size: 10px; padding: 2px 8px; border-radius: 99px; }

/* 任务清单：左缩进对齐单元标题，行尾补预计时长 */
.tp-chap-bd .tp-lessons { margin: 0 10px 10px 56px; padding-left: 12px; border-left: 2px solid #f2eaf6; }
.tp-chap-bd .tp-lesson { grid-template-columns: 20px minmax(0, 1fr) auto auto; gap: 10px; padding: 7px 10px; }
.tp-lesson-m { font-size: 10.5px; color: var(--lx-ink3); }

/* --------------------------------------------------------------------------
   第 3 步：顶部概览 + 学习工具条
     概览 = 环形主进度（我做到哪儿）+ 一行细分口径（这个数怎么算的）+ 场次属性胶囊。
     工具条 = 继续学习（下一步点哪儿）+ 搜索 + 状态筛选 + 收起全部 + 场次切换。
   -------------------------------------------------------------------------- */
.tp-overall {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  gap: 14px 22px; align-items: center;
  padding: 16px 20px; margin-bottom: 12px; border-radius: 16px;
  background: linear-gradient(118deg, #fff 0%, #fff7fa 48%, #f7f3ff 100%);
  border: 1px solid #f3e7ee;
}
.ov-score { display: flex; align-items: center; gap: 13px; flex: none; }
.ov-ring { flex: none; filter: drop-shadow(0 6px 14px rgba(225, 29, 72, .12)); }
.ov-score-t { min-width: 0; }
.tp-overall .big {
  display: flex; align-items: baseline; font-size: 27px; line-height: 1.15;
  font-weight: 800; color: var(--lx-red); letter-spacing: -.6px;
}
.tp-overall .big .unit { font-size: 11.5px; margin-left: 7px; letter-spacing: 0; }
.tp-overall .lbl { margin-top: 3px; font-size: 11.5px; color: var(--lx-ink3); max-width: 230px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ov-main { min-width: 0; }
.ov-line { display: flex; align-items: center; gap: 12px; }
.ov-line .tp-bar { flex: 1 1 auto; min-width: 120px; height: 8px; background: #efe8f4; }
.ov-line-t { font-size: 11.5px; color: var(--lx-ink3); white-space: nowrap; }
.ov-line-t b { font-size: 13px; color: var(--lx-ink); }
.tp-overall .meta { margin-top: 7px; font-size: 11.5px; color: var(--lx-ink3); line-height: 1.95; }
.ov-warn { color: #e8901b; }
.ov-aside { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.ov-chip {
  font-size: 10.5px; color: var(--lx-ink2); background: #fff;
  border: 1px solid var(--lx-line); border-radius: 99px; padding: 2px 9px; white-space: nowrap;
}

.tp-tools {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 12px; margin-bottom: 14px; border-radius: 14px;
  background: #fff; border: 1px solid var(--lx-line); box-shadow: var(--lx-sh);
}
.tp-continue {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  border: 0; cursor: pointer; font-family: inherit; font-size: 12px; font-weight: 700;
  color: #fff; background: linear-gradient(135deg, #f43f5e, #e11d48);
  padding: 8px 13px; border-radius: 10px; box-shadow: 0 5px 14px rgba(225, 29, 72, .22);
  transition: .16s; max-width: 340px;
}
.tp-continue:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 8px 18px rgba(225, 29, 72, .28); }
.tp-continue em {
  font-style: normal; font-weight: 500; opacity: .88; max-width: 170px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tp-continue:disabled {
  cursor: default; color: #0b8f6a; background: #ecfdf5;
  border: 1px solid #c7ecdd; box-shadow: none;
}
.tp-search {
  display: flex; align-items: center; gap: 6px; flex: none;
  border: 1px solid var(--lx-line); border-radius: 10px; padding: 5px 9px;
  background: #fbf9fc; color: var(--lx-ink3); cursor: text;
}
.tp-search:focus-within { border-color: #e8c8d6; background: #fff; box-shadow: 0 0 0 3px rgba(225, 29, 72, .06); }
.tp-search input {
  border: 0; outline: 0; background: none; font-family: inherit;
  font-size: 12px; color: var(--lx-ink); width: 148px;
}
/* 「资源包总览」：跳到 /pack 下的材料总清单（独立页，新窗口打开）。
   做成次要按钮而不是主色按钮 —— 它是查阅入口，不是当前页面要完成的事。 */
.tp-packlink {
  display: inline-flex; align-items: center; gap: 4px; flex: none;
  font-size: 12px; font-weight: 600; text-decoration: none;
  color: var(--lx-ink2); background: #f7f3fa; border: 1px solid var(--lx-line);
  padding: 6px 10px; border-radius: 10px; transition: .14s;
}
.tp-packlink:hover { color: var(--lx-red); border-color: #e8c8d6; background: #fff; }
.tp-filters { display: flex; gap: 2px; background: #f7f3fa; border-radius: 10px; padding: 3px; }
.tp-filters button {
  display: inline-flex; align-items: center; gap: 5px; border: 0; cursor: pointer;
  font-family: inherit; font-size: 12px; color: var(--lx-ink2);
  padding: 5px 9px; border-radius: 8px; transition: .14s; white-space: nowrap;
}
.tp-filters button b { font-size: 10.5px; font-weight: 700; color: var(--lx-ink3); }
.tp-filters button:hover { color: var(--lx-red); }
.tp-filters button.on { background: #fff; color: var(--lx-red); font-weight: 700; box-shadow: 0 1px 4px rgba(80, 40, 90, .1); }
.tp-filters button.on b { color: var(--lx-red); }
.tp-foldall {
  flex: none; border: 0; background: none; cursor: pointer; font-family: inherit;
  font-size: 11.5px; color: var(--lx-ink3); padding: 4px 6px; border-radius: 7px;
}
.tp-foldall:hover { color: var(--lx-red); background: var(--lx-red-soft); }
.tp-sess-slot { flex: none; display: flex; }

/* 筛选后无结果 */
.tp-none {
  padding: 28px 16px; text-align: center; font-size: 12.5px; color: var(--lx-ink3);
  background: #fff; border: 1px dashed var(--lx-line); border-radius: 14px;
}
/* hidden 属性必须显式压过 display:grid/flex，否则筛选不生效 */
.tp-page .tp-chap[hidden], .tp-page .tp-unit[hidden], .tp-page .tp-lessons[hidden] { display: none; }

/* --------------------------------------------------------------------------
   第 4 步：右窄栏
     能力图谱从「一堆彩色词」改成「排行榜」：名称 + 百分比 + 掌握度条，
     默认只显示掌握度最高的 8 项，其余折叠 —— 一屏能读完，也知道还差多少。
   -------------------------------------------------------------------------- */
.tp-card-hd .hd-x {
  margin-left: auto; font-size: 10.5px; font-weight: 500; color: var(--lx-ink3);
}
.tp-page .tp-cloud { display: flex; flex-direction: column; gap: 6px; }
.tp-page .tp-cloud b {
  display: grid; grid-template-columns: minmax(0, 1fr) 42px;
  gap: 2px 8px; align-items: center;
  padding: 6px 9px; border-radius: 9px; background: #fbf9fc;
  font-size: 11.5px; font-weight: 600; color: var(--lx-ink); cursor: default;
  transition: background .14s;
}
.tp-page .tp-cloud b:hover { background: #fff4f7; }
.tp-page .tp-cloud b[hidden] { display: none; }
.tp-cloud b .n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tp-cloud b .p { font-size: 10.5px; text-align: right; color: var(--lx-ink3); }
.tp-cloud b .cb {
  grid-column: 1 / -1; height: 4px; border-radius: 99px;
  background: #efe9f3; overflow: hidden; display: block;
}
.tp-cloud b .cb s { display: block; height: 100%; border-radius: 99px; background: var(--c, #d9d2e4); text-decoration: none; }
.tp-cloud b.lv1 { --c: #d6cfe2; }
.tp-cloud b.lv2 { --c: #f4708d; }
.tp-cloud b.lv3 { --c: #8b6cff; }
.tp-cloud b.lv4 { --c: #12b886; }
.tp-cloud b.lv4 .n { color: #0b8f6a; }
.tp-cloud b.lv3 .n { color: #5b3fd0; }
.tp-more {
  margin-top: 9px; width: 100%; border: 1px dashed var(--lx-line);
  background: #fbf9fc; color: var(--lx-ink2); font-family: inherit; font-size: 11.5px;
  padding: 6px; border-radius: 9px; cursor: pointer; transition: .15s;
}
.tp-more:hover { color: var(--lx-red); border-color: #fbd5e2; background: var(--lx-red-soft); }
.tp-abil-foot {
  margin-top: 9px; padding-top: 8px; border-top: 1px dashed var(--lx-line2);
  font-size: 10.5px; color: var(--lx-ink3);
}
.tp-abil-foot b { color: var(--lx-ink); font-size: 11.5px; }

/* 主讲老师卡 */
.tp-teacher { display: flex; align-items: center; gap: 11px; }
.tp-teacher .av {
  width: 42px; height: 42px; border-radius: 13px; flex: none;
  background: linear-gradient(135deg, #ffd9e4, #e6dcff);
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; color: var(--lx-red); font-weight: 800;
}
.tp-tinfo { min-width: 0; }
.tp-tinfo b { display: block; font-size: 13px; }
.tp-tinfo span { font-size: 11.5px; color: var(--lx-ink3); }
.tp-trow {
  display: flex; align-items: center; gap: 8px; margin-top: 9px;
  font-size: 11px; color: var(--lx-ink3);
}
.tp-trow span { flex: none; width: 38px; }
.tp-trow b {
  font-weight: 600; color: var(--lx-ink2); font-size: 11px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* 公告空态：给两行文字，而不是只有一个「暂无公告」 */
.tp-empty-note .t { font-size: 12px; color: var(--lx-ink2); }
.tp-empty-note .s { font-size: 10.5px; color: var(--lx-ink3); margin-top: 2px; }

/* --------------------------------------------------------------------------
   第 5 步：响应式
     断点口径：1360 收起概览右侧胶囊（场次属性在别处也能看到）；
     900 单元行从三列变两列（操作列落到第二行右对齐）；640 概览与章头再收一档。
   -------------------------------------------------------------------------- */
@media (max-width: 1360px) {
  .ov-aside { display: none; }
  .tp-overall { grid-template-columns: auto minmax(0, 1fr); }
}
/* ------------------------------------------------- 视图切换与形态筛选（第四十七轮）
   「按章节」是默认视图：教师维护时想的是「这一章备齐没」，不是「我上周传了什么」。
   「平铺」留给批量勾选与跨章对比。两种视图共用同一批行片段与同样的操作。 */
.ra-viewseg {
  display: inline-flex; border: 1px solid var(--lx-line); border-radius: 9px;
  overflow: hidden; background: #fff; flex: none;
}
.ra-viewseg button {
  border: 0; background: none; font-family: inherit; font-size: 11.5px;
  color: var(--lx-ink2); padding: 6px 11px; cursor: pointer; transition: .13s;
}
.ra-viewseg button + button { border-left: 1px solid var(--lx-line2); }
.ra-viewseg button.on { background: #fff1f5; color: var(--lx-red); font-weight: 700; }

.ra-zero {
  flex: none; border: 1px solid var(--lx-line); background: #fff; color: var(--lx-ink2);
  font-family: inherit; font-size: 11.5px; padding: 6px 11px; border-radius: 99px;
  cursor: pointer; transition: .13s; white-space: nowrap;
}
.ra-zero b { font-size: 10.5px; color: #b45309; margin-left: 2px; }
.ra-zero:hover { border-color: #fde68a; color: #b45309; }
.ra-zero.on { background: #fffbeb; border-color: #fde68a; color: #b45309; font-weight: 700; }

/* 形态条：与「分类」并列的第二维度 —— 按「怎么打开」筛 */
.ra-kinds { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; margin: -2px 0 10px; }
.ra-kchip {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--lx-line); background: #fff; color: var(--lx-ink2);
  font-family: inherit; font-size: 11.5px; padding: 5px 10px; border-radius: 99px;
  cursor: pointer; transition: .13s;
}
.ra-kchip i { width: 7px; height: 7px; border-radius: 2px; background: #94a3b8; }
.ra-kchip b { font-size: 10.5px; color: var(--lx-ink3); font-variant-numeric: tabular-nums; }
.ra-kchip:hover { border-color: #d9c9e8; }
.ra-kchip.on { background: #f6f1ff; border-color: #ddd0ff; color: #6d4fd0; font-weight: 700; }
.ra-kchip.on b { color: #6d4fd0; }
.ra-kchip.on i { background: currentColor; }
.ra-kchip.k-video i { background: #8b5cf6; } .ra-kchip.k-video.on { background: #f5f0ff; border-color: #ddd0ff; color: #6d28d9; }
.ra-kchip.k-image i { background: #0891b2; } .ra-kchip.k-image.on { background: #eefbfd; border-color: #bde8f0; color: #0e7490; }
.ra-kchip.k-pdf i { background: #e11d48; } .ra-kchip.k-pdf.on { background: #fff1f5; border-color: #f3c6d4; color: #b31f45; }
.ra-kchip.k-ppt i { background: #d97706; } .ra-kchip.k-ppt.on { background: #fffbeb; border-color: #fde68a; color: #b45309; }
.ra-kchip.k-word i { background: #2563eb; } .ra-kchip.k-word.on { background: #eff5ff; border-color: #c7dbff; color: #1d4ed8; }
.ra-kchip.k-excel i { background: #0f766e; } .ra-kchip.k-excel.on { background: #eefbf5; border-color: #bfe8dc; color: #0f766e; }

/* 形态徽标（行内） */
.rk {
  display: inline-block; min-width: 34px; text-align: center; padding: 1px 6px; border-radius: 6px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .2px; background: #f1f5f9; color: #475569;
  border: 1px solid #e2e8f0;
}
.rk.k-video { background: #f5f0ff; color: #6d28d9; border-color: #ddd0ff; }
.rk.k-image { background: #eefbfd; color: #0e7490; border-color: #bde8f0; }
.rk.k-pdf { background: #fff1f5; color: #b31f45; border-color: #f3c6d4; }
.rk.k-ppt { background: #fffbeb; color: #b45309; border-color: #fde68a; }
.rk.k-word { background: #eff5ff; color: #1d4ed8; border-color: #c7dbff; }
.rk.k-excel { background: #eefbf5; color: #0f766e; border-color: #bfe8dc; }

/* 按章节：章 → 任务 → 资料 */
.ra-sec { border-bottom: 1px solid var(--lx-line2); }
.ra-sec:last-child { border-bottom: 0; }
.ra-sec-hd {
  display: flex; align-items: center; gap: 9px; padding: 10px 13px;
  background: #fbfcfe; cursor: pointer; user-select: none;
}
.ra-sec-hd:hover { background: #f8f6fd; }
.ra-sec-hd .caret { color: #b9aed0; font-size: 12px; width: 12px; }
.ra-sec-hd .no {
  font-size: 10.5px; font-weight: 800; color: #7c5cff; background: #f3efff;
  border: 1px solid #e6ddff; border-radius: 6px; padding: 1px 6px;
}
.ra-sec-hd b { font-size: 12.5px; color: var(--lx-ink); flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ra-sec-hd .cnt { font-size: 11px; color: var(--lx-ink3); }
.ra-sec.off .ra-sec-hd { background: #fcfcfd; }

.ra-les-hd {
  display: flex; align-items: center; gap: 8px; padding: 7px 13px 6px 30px;
  border-top: 1px dashed var(--lx-line2);
}
.ra-les-hd .code {
  font-size: 10.5px; color: var(--lx-ink3); font-family: var(--lx-num);
  background: #f6f7fa; border-radius: 5px; padding: 1px 5px;
}
.ra-les-hd .tt { font-size: 11.5px; color: var(--lx-ink2); flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ra-les-hd .cnt { font-size: 10.5px; color: var(--lx-ink3); }

/* 章节视图里的资料行：grid，不用 table —— 分组的表头是「章 / 任务」，
   表格的列语义在这里不成立，硬套只会得到一堆空单元格。 */
.ra-sec .ra-row {
  display: grid; align-items: center; gap: 9px;
  grid-template-columns: 26px 54px minmax(0, 1fr) 76px 88px 148px;
  padding: 8px 13px 8px 30px; border-top: 1px solid var(--lx-line2);
}
.ra-sec .ra-row:hover { background: #fdfbff; }
.ra-sec .ra-row.picked { background: #fff8fa; }
.ra-sec .ra-row .ra-t b { font-size: 12.5px; }
.ra-sec .ra-row .ra-t em { font-size: 10.5px; }
.ra-sec .ra-row .num { font-size: 11.5px; color: var(--lx-ink2); white-space: nowrap; }
.ra-sec .ra-row .num b { font-size: 13px; color: var(--lx-ink); }
.ra-sec .ra-row .num em { font-style: normal; color: var(--lx-ink3); font-size: 10.5px; margin-left: 3px; }
.ra-sec .ra-row .ra-ops { display: flex; justify-content: flex-end; gap: 4px; }
.ra-sec .ra-row .ck { display: flex; }

/* 抽屉里的形态预览 */
.ra-media { margin: 4px 0 10px; }
.ra-media video { width: 100%; border-radius: 10px; background: #000; display: block; max-height: 210px; }
.ra-media img { width: 100%; border-radius: 10px; border: 1px solid var(--lx-line2); display: block; max-height: 220px; object-fit: contain; background: #f8fafc; }
.ra-media .cap { display: block; font-size: 10.5px; color: var(--lx-ink3); margin-top: 4px; }
.ra-media-hint {
  font-size: 11.5px; color: var(--lx-ink2); line-height: 1.7; margin: 4px 0 10px;
  background: #fbf8ff; border: 1px dashed #e2d6ee; border-radius: 8px; padding: 8px 10px;
}

/* hidden 属性会被 display:flex 盖掉（批量条 / 抽屉 · 遮罩都是 flex/fixed），
   必须显式关掉，否则「已选 0 项」的粉色条会一直挂在表格上方。 */
.ra-bulkbar[hidden], .ra-drawer[hidden], .ra-mask[hidden] { display: none !important; }

/* 操作列三个按钮：紧凑一点，132px 装不下会被 overflow:hidden 裁掉「删除」 */
.ra-ops { padding-left: 6px !important; padding-right: 6px !important; }
.ra-ops .tp-mini { margin-left: 3px; padding: 3px 7px; font-size: 11px; }
.ra-ops .tp-mini:first-child { margin-left: 0; }

@media (max-width: 1180px) {
  .tp-tools { gap: 8px; }
  .tp-search input { width: 118px; }
  .tp-continue em { max-width: 118px; }
  .ch-desc { max-width: 320px; }
}
@media (max-width: 900px) {
  /* 不急着把操作列换行：760px 下「42 + 文本 + 按钮」仍放得下，
     换成两行会让每行凭空高出 70px，一屏只剩两个单元。 */
  .tp-chap-bd .tp-unit { grid-template-columns: 42px minmax(0, 1fr) auto; gap: 10px; padding: 12px 8px; }
  .tp-unit .tp-unit-r { grid-column: auto; margin-top: 0; }
  .tp-continue em { display: none; }
  .tp-filters button b { display: none; }
  .tp-search { flex: 1 1 150px; }
  .tp-search input { width: 100%; }
  .ch-desc { display: none; }
  .u-sum { white-space: normal; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
}
@media (max-width: 640px) {
  .tp-overall { grid-template-columns: 1fr; gap: 10px; padding: 14px; }
  .tp-overall .big { font-size: 23px; }
  .ov-line-t { display: none; }
  .tp-tools { padding: 8px; }
  .tp-continue { width: 100%; justify-content: center; }
  .ch-prog { display: none; }
  .ch-no { width: 34px; height: 34px; font-size: 13px; }
  .tp-chap-hd { gap: 9px; padding: 12px; }
  .tp-chap-hd .intro { display: none; }
  .tp-chap-bd .tp-lessons { margin-left: 8px; }
  .tp-unit .tp-stamp, .tp-unit .tp-start { min-width: 0; }
}

/* 工具条换行时，场次下拉落到第二行也要靠右，不要孤零零吊在左边 */
.tp-sess-slot { margin-left: auto; }

/* 徽标顶部对齐标题（行高两行时居中会「掉到文字中间」），操作列仍垂直居中 */
.tp-chap-bd .tp-unit { align-items: start; }
.tp-unit .tp-unit-ic { margin-top: 1px; }
.tp-unit .tp-unit-r { align-self: center; }

/* ==========================================================================
   课程学习页 v3 · 六个子页签（2026-11-06）
   --------------------------------------------------------------------------
   共用骨架：课程条 → .tp-hero（页签身份 + 一句话说明 + 右侧关键数）→ 内容卡。
   页签之间不共享排版细节，各有各的卡：资源是图墙、团队是名单、评价是成绩表、
   分析是条图、考试是试卷卡、互动是提醒 + FAQ。
   ========================================================================== */
.tp-hero {
  display: flex; align-items: center; gap: 13px;
  background: #fff; border: 1px solid var(--lx-line); border-radius: 16px;
  box-shadow: var(--lx-sh); padding: 14px 18px; margin-bottom: 14px;
}
.tp-hero .hi {
  width: 40px; height: 40px; border-radius: 13px; flex: none;
  display: flex; align-items: center; justify-content: center;
  color: #fff; background: linear-gradient(135deg, #f43f5e, #7c5cff);
  box-shadow: 0 8px 18px -10px rgba(124, 92, 255, .9);
}
.tp-hero .ht { flex: 1 1 auto; min-width: 0; }
.tp-hero .ht h2 { margin: 0; font-size: 15px; font-weight: 800; color: var(--lx-ink); }
.tp-hero .ht p { margin: 2px 0 0; font-size: 11.5px; color: var(--lx-ink3); }
.tp-hero-stat { flex: none; text-align: right; }
.tp-hero-stat b { display: block; font-size: 22px; font-weight: 800; color: var(--lx-red); line-height: 1.15; letter-spacing: -.4px; }
.tp-hero-stat span { font-size: 10.5px; color: var(--lx-ink3); }
.tp-hero-stat em { display: block; font-style: normal; font-size: 10.5px; color: var(--lx-ink3); margin-top: 1px; }
.tp-hero-stat.wide b { font-size: 26px; }
.tp-hero-stat.wide { max-width: 260px; }

.tp-2col { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
.tp-2col > .tp-ai-card { grid-column: auto; }
.tp-nopad { padding: 0 !important; }
.tp-tip { margin-top: 8px; font-size: 10.5px; color: var(--lx-ink3); line-height: 1.8; }

/* ---- 资源：图墙 ---- */
.tp-res-bar { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.tp-res-bar button {
  border: 1px solid var(--lx-line); background: #fff; color: var(--lx-ink2);
  font-family: inherit; font-size: 11.5px; padding: 5px 11px; border-radius: 99px;
  cursor: pointer; transition: .14s;
}
.tp-res-bar button b { color: var(--lx-ink3); font-weight: 700; margin-left: 3px; }
.tp-res-bar button:hover { color: var(--lx-red); border-color: #fbd5e2; }
.tp-res-bar button.on { background: var(--lx-red-soft); border-color: #fbd5e2; color: var(--lx-red); font-weight: 700; }
.tp-res-bar button.on b { color: var(--lx-red); }
.tp-res-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(214px, 1fr)); gap: 12px; }
.tp-res {
  display: block; text-align: left; padding: 0; cursor: pointer; font-family: inherit;
  background: #fff; border: 1px solid var(--lx-line); border-radius: 12px; overflow: hidden;
  transition: .16s;
}
.tp-res:hover { border-color: #f3c9d8; box-shadow: 0 10px 24px -14px rgba(225, 29, 72, .45); transform: translateY(-1px); }
/* 封面（第六十九轮）：8:5 固定比例，图片懒加载 + 悬停轻微放大。
   以前是 118px 固定高的灰框，一屏 20 张全是空框；现在每张卡片自带缩略图。 */
.tp-res .ri { position: relative; display: block; aspect-ratio: 8 / 5; background: linear-gradient(135deg, #f5f2fb, #eef1fa); overflow: hidden; }
.tp-res .ri img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .35s ease; }
.tp-res:hover .ri img { transform: scale(1.045); }
.tp-res .ri .ph { display: flex; align-items: center; justify-content: center; height: 100%; color: #c9c2d6; }
.tp-res .ri .ph.file em { font-style: normal; font-size: 20px; font-weight: 800; letter-spacing: .06em; color: #b7aec9; }
/* 角标：类型 / 时长或页数 / 播放钮。深色半透明底，压在任何封面上都能读 */
.tp-res .cov-type { position: absolute; left: 8px; bottom: 8px; z-index: 2; font-size: 10px; font-weight: 800; letter-spacing: .05em; color: #fff; background: rgba(17, 24, 39, .62); border-radius: 6px; padding: 2px 7px; }
.tp-res .cov-badge { position: absolute; right: 8px; bottom: 8px; z-index: 2; font-style: normal; font-size: 10.5px; font-weight: 600; color: #fff; background: rgba(17, 24, 39, .66); border-radius: 6px; padding: 2px 7px; }
.tp-res .cov-play { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); z-index: 2; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: rgba(17, 24, 39, .46); color: #fff; font-style: normal; font-size: 15px; padding-left: 3px; box-shadow: 0 4px 14px rgba(0, 0, 0, .18); transition: .18s; }
.tp-res:hover .cov-play { background: rgba(225, 29, 72, .82); transform: translate(-50%, -50%) scale(1.06); }
.tp-res .rb { display: block; padding: 9px 11px 11px; }
.tp-res .rb b { display: block; font-size: 12px; font-weight: 700; color: var(--lx-ink); line-height: 1.5; }
.tp-res .rb em {
  display: block; font-style: normal; font-size: 10.5px; color: var(--lx-ink3);
  margin-top: 3px; line-height: 1.6;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.tp-res .rb .rm { display: block; font-size: 10px; color: #b8b0c6; margin-top: 5px; }
.tp-shot { width: 100%; border-radius: 10px; border: 1px solid var(--lx-line); display: block; }
.tp-shot-note { margin-top: 8px; font-size: 12px; color: var(--lx-ink2); }

/* ---- 团队 ---- */
.tp-kvr { display: flex; align-items: baseline; gap: 10px; padding: 6px 0; border-bottom: 1px dashed var(--lx-line2); font-size: 12px; }
.tp-kvr:last-child { border-bottom: 0; }
.tp-kvr span { flex: none; width: 76px; color: var(--lx-ink3); font-size: 11px; }
.tp-kvr b { color: var(--lx-ink); font-weight: 600; }
.tp-mem-row {
  display: grid; grid-template-columns: 34px minmax(0, 1fr) auto;
  gap: 10px; align-items: center; padding: 8px 16px;
  border-bottom: 1px solid var(--lx-line2); font-size: 12px;
}
/* 过滤掉的行用类名隐藏：网格布局会盖掉 UA 的 [hidden] */
.tp-mem-row.off { display: none; }
/* 名单工具条：检索框 + 计数。20 人以上翻名单找同学很费劲。 */
.tp-mem-tools {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 16px; border-bottom: 1px solid var(--lx-line2); background: #fcfafd;
}
.tp-mem-tools .tp-search { flex: none; }
.tp-mem-tools .tp-search input { width: 190px; }
.tp-mem-n { margin-left: auto; font-size: 10.5px; color: var(--lx-ink3); }
.tp-mem-row:last-child { border-bottom: 0; }
.tp-mem-row.me { background: #fffafb; }
.tp-mem-row .i { color: var(--lx-ink3); font-size: 11px; }
.tp-mem-row .n { color: var(--lx-ink); font-weight: 600; }
.tp-mem-row .n em {
  font-style: normal; font-size: 9.5px; color: var(--lx-red); background: var(--lx-red-soft);
  border-radius: 99px; padding: 1px 6px; margin-left: 6px;
}
.tp-mem-row .s { color: var(--lx-ink3); font-size: 11px; }
.tp-mem-row .b { justify-self: end; }

/* ---- 评价 ---- */
.tp-grade-h, .tp-grade-r {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) repeat(3, 78px) 72px 68px;
  gap: 8px; align-items: center; padding: 9px 16px; font-size: 12px;
}
.tp-grade-h { color: var(--lx-ink3); font-size: 10.5px; border-bottom: 1px solid var(--lx-line2); background: #fcfafd; }
.tp-grade-h span:not(:first-child), .tp-grade-r > span:not(.s) { text-align: right; }
.tp-grade-h span:last-child, .tp-grade-r > span:last-child { text-align: center; }
.tp-grade-r { border-bottom: 1px solid var(--lx-line2); }
.tp-grade-r:last-child { border-bottom: 0; }
.tp-grade-r .s { color: var(--lx-ink); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tp-grade-r .t { font-weight: 800; color: var(--lx-red); font-size: 13px; }

/* ---- 成绩行展开：这一场的分是怎么来的 ---- */
.tp-grade-r { cursor: pointer; transition: background .14s; }
.tp-grade-r:hover { background: #fdfbfe; }
.tp-grade-r.on { background: #fbf7ff; }
.tp-grade-r .s .cv {
  display: inline-block; width: 7px; height: 7px; margin-right: 7px;
  border-right: 1.6px solid #b8b0c6; border-bottom: 1.6px solid #b8b0c6;
  transform: rotate(-45deg); transition: transform .16s; vertical-align: 1px;
}
.tp-grade-r.on .s .cv { transform: rotate(45deg); border-color: var(--lx-violet); }
.tp-grade-d { padding: 12px 16px 14px; background: #fcfafd; border-top: 1px dashed var(--lx-line2); }
.tgd-h { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.tgd-h b { font-size: 12.5px; color: var(--lx-ink); }
.tgd-h .sp { flex: 1; }
/* 教师侧明细头部多一行「学生 · 学号」 */
.tgd-who { font-size: 12px; color: var(--lx-ink); font-weight: 600; }
.tgd-who + .tp-tag { margin-left: 2px; }
.tgd-total { font-size: 11.5px; color: var(--lx-ink2); }
.tgd-total b { font-size: 16px; color: var(--lx-red); margin: 0 2px; }
.tgd-body { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 12px; }
.tgd-calc {
  grid-row: 1 / span 3; align-self: start;
  background: #fff; border: 1px solid var(--lx-line);
  border-radius: 10px; padding: 10px 12px;
}
.tgd-line {
  display: grid; grid-template-columns: minmax(0, 1fr) 56px 54px 64px;
  gap: 6px; align-items: center; padding: 4px 0; font-size: 11px;
}
.tgd-line .k { color: var(--lx-ink2); }
.tgd-line .v { text-align: right; color: var(--lx-ink); }
.tgd-line .x { text-align: right; color: var(--lx-ink3); font-size: 10px; }
.tgd-line b { text-align: right; color: var(--lx-ink); }
.tgd-sum {
  display: flex; align-items: center; gap: 6px; margin-top: 6px; padding-top: 8px;
  border-top: 1px dashed var(--lx-line2); font-size: 11px; color: var(--lx-ink2);
}
.tgd-sum .sp { flex: 1; }
.tgd-sum b { font-size: 15px; color: var(--lx-red); }
.tgd-sec {
  background: #fff; border: 1px solid var(--lx-line);
  border-radius: 10px; padding: 9px 11px;
}
.tgd-sh { font-size: 10px; color: var(--lx-ink3); letter-spacing: .4px; margin-bottom: 6px; }
.tgd-kv {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; padding: 3px 0; font-size: 11.5px; color: var(--lx-ink2);
}
.tgd-kv b { color: var(--lx-ink); }
.tgd-list { display: grid; gap: 4px; }
.tgd-li {
  display: grid; grid-template-columns: minmax(0, 1fr) auto auto 64px;
  gap: 8px; align-items: center; font-size: 11px;
}
/* 标题是链接：点了去「我的交付物」并直接打开这一份 */
.tgd-li .n {
  color: var(--lx-ink); text-decoration: none;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  border-bottom: 1px dashed transparent;
}
.tgd-li a.n:hover { color: var(--lx-red); border-bottom-color: #f5c6d6; }
.tgd-li .st { color: var(--lx-ink3); font-size: 10px; }
.tgd-li .sc { text-align: right; color: var(--lx-ink); font-weight: 600; white-space: nowrap; }
/* 「分项 N」小胶囊：只在这份交付物有维度评语时出现 */
.tgd-dim {
  border: 1px solid #e5d9f7; background: #f7f2ff; color: var(--lx-violet);
  font-family: inherit; font-size: 9.5px; padding: 1px 7px; border-radius: 99px;
  cursor: pointer; white-space: nowrap; transition: .14s;
}
.tgd-dim:hover { background: #efe4ff; }

/* 评分维度弹窗 */
.tgd-dm-h { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.tgd-dm-h b { font-size: 12.5px; color: var(--lx-ink); }
.tgd-dm-h .sp { flex: 1; }
.tgd-dm-score { font-size: 11.5px; color: var(--lx-ink2); }
.tgd-dm-score b { font-size: 16px; color: var(--lx-red); margin-left: 2px; }
.tgd-dm { border: 1px solid var(--lx-line); border-radius: 10px; overflow: hidden; }
.tgd-dm-row { display: grid; grid-template-columns: 130px minmax(0, 1fr); gap: 10px; padding: 8px 12px; border-bottom: 1px solid var(--lx-line2); }
.tgd-dm-row:last-child { border-bottom: 0; }
.tgd-dm-row .k { font-size: 11px; color: var(--lx-ink3); }
/* 权重跟在维度名后面（第四十轮）：学生要先知道「这项占多少」，
   再看「我拿了几分」，顺序反了就会以为 26 分很低（其实是 30% × 86.7）。 */
.tgd-dm-row .k em { font-style: normal; font-size: 10px; color: var(--lx-ink3); margin-left: 4px; opacity: .85; }
.tgd-dm-row .v { font-size: 11.5px; color: var(--lx-ink); line-height: 1.75; }
.tgd-dm-row.num .v { text-align: right; font-weight: 600; }
.tgd-dm-row.sum { background: #fcfafd; }
.tgd-dm-row.sum .k { color: var(--lx-ink2); font-weight: 700; }
.tgd-dm-row.sum .v { text-align: right; font-weight: 800; color: var(--lx-red); }
.tgd-dm-row.sum em { font-style: normal; font-size: 10px; color: var(--lx-ink3); font-weight: 400; margin-left: 6px; }
.tgd-dm-c { margin-top: 10px; padding: 8px 11px; border-radius: 9px; background: #f4fbf8; font-size: 11.5px; color: #2c6b57; line-height: 1.8; }
.tgd-dm-c b { display: block; font-size: 9.5px; color: #0b8f6a; margin-bottom: 2px; letter-spacing: .3px; }
@media (max-width: 1100px) {
  .tgd-body { grid-template-columns: minmax(0, 1fr); }
  .tgd-calc { grid-row: auto; }
}
.tp-rev-row { display: flex; align-items: center; gap: 14px; padding: 11px 16px; border-bottom: 1px solid var(--lx-line2); }
.tp-rev-row:last-child { border-bottom: 0; }
.tp-rev-row .rl { flex: 1 1 auto; min-width: 0; }
.tp-rev-row .rl b { display: block; font-size: 12.5px; color: var(--lx-ink); }
.tp-rev-row .rl span { display: block; font-size: 11px; color: var(--lx-ink3); margin-top: 2px; line-height: 1.7; }
.tp-rev-row .rr { flex: none; text-align: right; }
.tp-rev-row .rr b { font-size: 18px; font-weight: 800; color: var(--lx-red); }
.tp-rev-row .rr em { font-style: normal; font-size: 10px; color: var(--lx-ink3); margin-left: 2px; }
/* 交付物按场次分组 + 得分下方的提交时间：六份评语常常一字不差，
   不标清「哪一场、什么时候交的」，学生没法把分数对回某次作业。 */
.tp-rev-g + .tp-rev-g { border-top: 1px solid var(--lx-line2); }
.tp-rev-gh {
  display: flex; align-items: center; gap: 8px; padding: 8px 16px;
  background: #fcfafd; border-bottom: 1px solid var(--lx-line2);
  font-size: 10.5px; color: var(--lx-ink3);
}
.tp-rev-gh b { margin-left: auto; font-weight: 700; color: var(--lx-ink2); }
.tp-rev-row .rr .at { display: block; font-style: normal; font-size: 9.5px; color: var(--lx-ink3); margin-top: 1px; }

/* 成绩表里「—」的两种来源：未发布（要等老师）与本场次不适用（不用等）。
   样式只是辅助，真正说清靠 title 与下方图例。 */
.tp-grade-r .v-lock { color: #b9b2c6; font-weight: 500; }
.tp-grade-r .v-na { color: #cfc7dd; font-weight: 400; }
.tp-grade-r .t.v-lock { color: #c9c1d6; }
.tp-legend {
  display: grid; gap: 4px; padding: 10px 16px 12px;
  border-top: 1px dashed var(--lx-line2);
  font-size: 10.5px; line-height: 1.75; color: var(--lx-ink3);
}
.tp-legend b { color: var(--lx-ink2); font-weight: 700; }
.tp-legend .lg {
  display: inline-block; width: 14px; height: 8px; border-radius: 3px;
  margin-right: 6px; vertical-align: 0;
}
.tp-legend .lg.lock { background: #e6e0ee; }
.tp-legend .lg.na {
  background: repeating-linear-gradient(45deg, #efeaf5, #efeaf5 2px, #fff 2px, #fff 4px);
  box-shadow: inset 0 0 0 1px #e6e0ee;
}
.tp-legend .lg.eff { background: linear-gradient(90deg, #f43f5e, #7c5cff); }
.tp-hero-stat b.dash { color: #d6cfe2; }

/* ---- 分析 ---- */
.tp-sbar-row { display: grid; grid-template-columns: minmax(0, 210px) minmax(0, 1fr) 96px; gap: 12px; align-items: center; padding: 6px 0; }
.tp-sbar-row .k { font-size: 11.5px; color: var(--lx-ink2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tp-sbar-row .b { height: 8px; border-radius: 99px; background: #f2edf6; overflow: hidden; }
.tp-sbar-row .b i { display: block; height: 100%; border-radius: 99px; background: linear-gradient(90deg, #f43f5e, #7c5cff); }
.tp-sbar-row .v { font-size: 11px; color: var(--lx-ink3); text-align: right; }
.tp-weak-row { display: grid; grid-template-columns: minmax(0, 1fr) 92px 44px; gap: 8px; align-items: center; padding: 5px 0; font-size: 11.5px; }
.tp-weak-row span { color: var(--lx-ink2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tp-weak-row .b { height: 6px; border-radius: 99px; background: #f2edf6; overflow: hidden; }
.tp-weak-row .b i { display: block; height: 100%; background: linear-gradient(90deg, #fbbf24, #f43f5e); border-radius: 99px; }
.tp-weak-row b { text-align: right; font-size: 11px; color: var(--lx-ink2); }
/* 全部答错（0%）的知识点：条形留空 + 数字标红，避免 3% 的「头发丝条」被当成没加载 */
.tp-weak-row.zero .b { background: #f7f2f8; }
.tp-weak-row.zero .b i { display: none; }
.tp-weak-row.zero b { color: var(--lx-red); }
.tp-trend-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 180px) 88px 76px; gap: 10px; align-items: center; padding: 6px 0; font-size: 11.5px; }
.tp-trend-row .n { color: var(--lx-ink2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tp-trend-row .b { height: 6px; border-radius: 99px; background: #f2edf6; overflow: hidden; }
.tp-trend-row .b i { display: block; height: 100%; background: linear-gradient(90deg, #7c5cff, #12b886); border-radius: 99px; }
.tp-trend-row b { text-align: right; color: var(--lx-ink); }
.tp-trend-row em { font-style: normal; font-size: 10.5px; color: var(--lx-ink3); text-align: right; }
/* 副标题单独一行：试卷名 + 「第几次 · 场次 · 日期」挤在同一行会互相截断 */
.tp-trend-row .n em {
  display: block; text-align: left; margin-top: 1px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 第四列：作答用时。原来这一列空着（模板四列、只渲染三格），右边缘总像缺一块。 */
.tp-trend-row .sp { font-size: 10.5px; color: var(--lx-ink3); text-align: right; white-space: nowrap; }

/* ---- 结课考试 ---- */
.tp-exam-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 14px; }
/* 单张试卷：一整行的横幅卡。auto-fill 会把唯一一张卡按 280px 排进第一格，
   右边空出四分之三的宽度 —— 看起来像还有内容没加载出来。 */
.tp-exam-grid.one { grid-template-columns: minmax(0, 1fr); }
.tp-exam-grid.one .tp-examcard {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 20px; align-items: center; padding: 16px 20px;
}
.tp-exam-grid.one .tp-examcard .eh,
.tp-exam-grid.one .tp-examcard .et,
.tp-exam-grid.one .tp-examcard .em { grid-column: 1; }
.tp-exam-grid.one .tp-examcard .et { margin-top: 7px; font-size: 15px; }
.tp-exam-grid.one .tp-examcard .em { margin-top: 4px; }
.tp-exam-grid.one .tp-examcard .ef { grid-column: 2; grid-row: 1 / span 3; margin-top: 0; min-width: 190px; }
/* 横幅卡里那根把「60 分钟」顶到最右的弹簧要收起来：整行都是它的，
   时长会离徽标十几厘米，读起来像另一个字段。 */
.tp-exam-grid.one .tp-examcard .eh .sp { display: none; }
.tp-exam-grid.one .tp-examcard .eh .dur { margin-left: 8px; }
.tp-examcard {
  background: #fff; border: 1px solid var(--lx-line); border-radius: 16px;
  box-shadow: var(--lx-sh); padding: 14px 16px;
}
.tp-examcard .eh { display: flex; align-items: center; gap: 6px; }
.tp-examcard .eh .dur { font-size: 10.5px; color: var(--lx-ink3); }
.tp-examcard .et { margin-top: 8px; font-size: 13.5px; font-weight: 700; color: var(--lx-ink); line-height: 1.5; }
.tp-examcard .em { margin-top: 3px; font-size: 10.5px; color: var(--lx-ink3); }
.tp-examcard .ef { margin-top: 12px; display: flex; align-items: center; gap: 10px; }
.tp-examcard .score { font-size: 22px; font-weight: 800; color: var(--lx-red); }
.tp-examcard .score em { font-style: normal; font-size: 10px; color: var(--lx-ink3); margin-left: 2px; }
.tp-examcard .score.dash { color: #d6cfe2; }
.tp-examcard .ef .tp-start { margin-left: auto; }

/* ---- 互动 ---- */
.tp-notes { display: flex; flex-direction: column; gap: 8px; }
.tp-note { display: flex; gap: 8px; align-items: flex-start; font-size: 12px; color: var(--lx-ink2); line-height: 1.7; }
.tp-note i { width: 6px; height: 6px; border-radius: 50%; margin-top: 7px; flex: none; background: #7c5cff; }
.tp-note.ok i { background: #12b886; }
.tp-note.warn i { background: #e8901b; }
.tp-ai-card { background: linear-gradient(135deg, #fff 0%, #fdf4f8 60%, #f5f1ff 100%); border-color: #f3e7ee; }
.tp-ai-card .ai-h { display: flex; align-items: center; gap: 7px; font-size: 13px; font-weight: 800; color: var(--lx-ink); }
.tp-ai-card p { margin: 7px 0 11px; font-size: 11.5px; color: var(--lx-ink3); line-height: 1.85; }
.tp-ai-card .ai-btns { display: flex; flex-wrap: wrap; gap: 7px; }
.tp-faq-i { border-bottom: 1px solid var(--lx-line2); padding: 0 16px; }
.tp-faq-i:last-child { border-bottom: 0; }
.tp-faq-i summary {
  cursor: pointer; padding: 11px 0; font-size: 12.5px; font-weight: 600; color: var(--lx-ink);
  list-style: none; position: relative; padding-right: 20px;
}
.tp-faq-i summary::-webkit-details-marker { display: none; }
.tp-faq-i summary::after {
  content: '▾'; position: absolute; right: 2px; top: 11px; color: var(--lx-ink3); font-size: 11px; transition: .15s;
}
.tp-faq-i[open] summary::after { transform: rotate(180deg); }
.tp-faq-i .a { padding: 0 0 12px; font-size: 11.5px; color: var(--lx-ink2); line-height: 1.95; }
.tp-faq-i .a b { color: var(--lx-ink); }

@media (max-width: 1100px) {
  .tp-2col { grid-template-columns: minmax(0, 1fr); }
  .tp-hero-stat { display: none; }
  .tp-grade-h, .tp-grade-r { grid-template-columns: minmax(0, 1.4fr) repeat(3, 62px) 60px 56px; padding: 9px 12px; }
}
@media (max-width: 760px) {
  .tp-res-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
  .tp-sbar-row { grid-template-columns: minmax(0, 1fr) 70px; }
  .tp-sbar-row .b { grid-column: 1 / -1; }
  .tp-trend-row { grid-template-columns: minmax(0, 1fr) 70px; }
  .tp-trend-row .b, .tp-trend-row em, .tp-trend-row .sp { display: none; }
  .tp-grade-h, .tp-grade-r { grid-template-columns: minmax(0, 1fr) 56px 56px; }
  .tp-grade-h span:nth-child(2), .tp-grade-r > span:nth-child(2),
  .tp-grade-h span:nth-child(3), .tp-grade-r > span:nth-child(3) { display: none; }
}

/* 子页签细节修整（2026-11-06 二轮） */
/* 名单：学号跟在姓名后面，而不是被挤到最右侧孤零零一列 */
.tp-mem-row { grid-template-columns: 34px minmax(0, 1fr) auto; padding: 9px 16px; }
.tp-mem-row .n .no {
  font-style: normal; font-family: var(--lx-num); font-size: 10.5px;
  color: #b8b0c6; margin-left: 9px; letter-spacing: .2px;
}
/* 资源缩略图取截图顶部（界面截图的信息都在上半部分，居中裁切常切到空白） */
.tp-res .ri img { object-position: top center; }
/* FAQ 展开箭头贴住问题文本，而不是飘到卡片最右缘 */
.tp-faq-i summary { display: flex; align-items: center; gap: 7px; }
.tp-faq-i summary .cv {
  width: 7px; height: 7px; flex: none; margin-top: -3px;
  border-right: 1.6px solid #b8b0c6; border-bottom: 1.6px solid #b8b0c6;
  transform: rotate(45deg); transition: transform .16s;
}
.tp-faq-i[open] summary .cv { transform: rotate(-135deg); margin-top: 3px; }
.tp-faq-i summary::after { content: none; }
/* 页签头说明字号提一档，深色一点：11.5px + ink3 在 1080 屏上几乎看不见 */
.tp-hero .ht p { font-size: 12px; color: var(--lx-ink2); }

/* 考试趋势：试卷名一行 + 「第几次 · 场次 · 日期」一行，右侧分数与用时各占一列。
   四列必须在同一行里：三列时「用时」会被挤到下一行的第一格，
   看起来像多出一条没有名字的记录。 */
.tp-trend-row { grid-template-columns: minmax(0, 1fr) minmax(0, 200px) 96px 70px; }
.tp-trend-row .n em { font-style: normal; font-size: 10px; color: #b8b0c6; }
.tp-trend-row > b { font-size: 12px; color: var(--lx-ink); }

/* ==========================================================================
   课程互动：教师公告 / 学生提问 / 教师回复（2026-11-06）
   ========================================================================== */
.tp-mini {
  border: 1px solid var(--lx-line); background: #fff; color: var(--lx-ink2);
  font-family: inherit; font-size: 11.5px; padding: 4px 11px; border-radius: 8px;
  cursor: pointer; transition: .14s; white-space: nowrap;
}
.tp-mini:hover { color: var(--lx-red); border-color: #fbd5e2; background: var(--lx-red-soft); }

/* 教师公告 */
.tp-ntcs { display: flex; flex-direction: column; gap: 9px; }
.tp-ntc {
  border: 1px solid var(--lx-line); border-left: 3px solid #e4d9f2;
  border-radius: 10px; padding: 9px 11px; background: #fcfbfd;
}
.tp-ntc.pin { border-left-color: var(--lx-red); background: #fffafb; }
.tp-ntc .h { display: flex; align-items: center; gap: 7px; }
.tp-ntc .h b { font-size: 12.5px; color: var(--lx-ink); }
.tp-ntc .h em { font-style: normal; font-size: 10px; color: #b8b0c6; }
.tp-ntc .h .pin {
  font-style: normal; font-size: 9.5px; color: #fff; background: var(--lx-red);
  border-radius: 99px; padding: 1px 6px; flex: none;
}
.tp-ntc p { margin: 5px 0 0; font-size: 11.5px; color: var(--lx-ink2); line-height: 1.85; white-space: pre-wrap; }
.tp-ntc .f { margin-top: 6px; font-size: 10px; color: #b8b0c6; }

/* 提问框 */
.tp-ask { border-bottom: 1px dashed var(--lx-line2); padding-bottom: 12px; margin-bottom: 12px; }
.tp-ta, .tp-in {
  width: 100%; box-sizing: border-box; font-family: inherit; font-size: 12.5px;
  color: var(--lx-ink); background: #fbf9fc; border: 1px solid var(--lx-line);
  border-radius: 10px; padding: 9px 11px; outline: none; resize: vertical; line-height: 1.8;
}
.tp-in { margin-bottom: 8px; }
.tp-ta:focus, .tp-in:focus { border-color: #e8c8d6; background: #fff; box-shadow: 0 0 0 3px rgba(225, 29, 72, .06); }
.tp-ask-f { display: flex; align-items: center; gap: 10px; margin-top: 8px; flex-wrap: wrap; }
.tp-ask-f .hint { flex: 1 1 auto; font-size: 10.5px; color: var(--lx-ink3); }
.tp-chk { display: flex; align-items: center; gap: 6px; font-size: 11.5px; color: var(--lx-ink2); margin: 2px 0 6px; }

/* 问答列表 */
.tp-qalist { display: flex; flex-direction: column; gap: 10px; }
.tp-qaitem {
  border: 1px solid var(--lx-line); border-radius: 11px; padding: 10px 12px; background: #fff;
}
.tp-qaitem.wait { border-left: 3px solid #e8901b; }
.tp-qaitem .qh { display: flex; align-items: center; gap: 8px; font-size: 11.5px; }
.tp-qaitem .qh b { color: var(--lx-ink); font-size: 12px; }
.tp-qaitem .qh .no { font-size: 10.5px; color: #b8b0c6; }
.tp-qaitem .qh .ls {
  font-size: 10px; color: var(--lx-violet); background: var(--lx-violet-soft);
  border-radius: 99px; padding: 1px 7px; max-width: 260px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.tp-qaitem .qh .at { font-size: 10px; color: #b8b0c6; }
.tp-qaitem .qq { margin-top: 6px; font-size: 12px; color: var(--lx-ink); line-height: 1.85; }
.tp-qaitem .qa {
  margin-top: 8px; padding: 8px 10px; border-radius: 9px; background: #f4fbf8;
  font-size: 11.5px; color: #2c6b57; line-height: 1.85;
}
.tp-qaitem .qa b { display: block; font-size: 10px; color: #0b8f6a; margin-bottom: 2px; letter-spacing: .3px; }
.tp-qaitem .qa em { display: block; font-style: normal; font-size: 10px; color: #8fb8a9; margin-top: 4px; }
.tp-qaitem .qwait { margin-top: 7px; font-size: 10.5px; color: var(--lx-ink3); }
.tp-qaitem .qf { margin-top: 8px; text-align: right; }

/* ---- 追问线程（2026-11-07） ----
   缩进 + 左侧竖线：让「原问 → 追问 1 → 追问 2」一眼看出层级。
   追问的回复用与首答相同的绿色块，但字号小一档 —— 是同一场对话，不是新话题。 */
.tp-fu {
  margin: 10px 0 0 10px; padding: 2px 0 2px 12px;
  border-left: 2px solid #ece5f3;
}
.tp-fu.wait { border-left-color: #f3c98b; }
.tp-fu .fh { display: flex; align-items: center; gap: 8px; font-size: 10.5px; }
.tp-fu .fh b { font-size: 10.5px; font-weight: 700; color: var(--lx-violet); letter-spacing: .2px; }
.tp-fu .fh .at { font-size: 10px; color: #b8b0c6; }
.tp-fu .fq { margin-top: 4px; font-size: 11.5px; color: var(--lx-ink); line-height: 1.85; }
.tp-fu .fa {
  margin-top: 6px; padding: 7px 9px; border-radius: 8px; background: #f4fbf8;
  font-size: 11px; color: #2c6b57; line-height: 1.8;
}
.tp-fu .fa b { display: block; font-size: 9.5px; color: #0b8f6a; margin-bottom: 2px; letter-spacing: .3px; }
.tp-fu .fa em { display: block; font-style: normal; font-size: 9.5px; color: #8fb8a9; margin-top: 3px; }
.tp-fu .qwait { margin-top: 5px; font-size: 10px; color: var(--lx-ink3); }
.tp-fu .qwait.od { color: #b45309; }
.tp-fu .qwait.od::before { content: '⏰ '; }
/* 追问入口：贴在条目右下，剩余次数写在按钮里（比另起一行说明省地方） */
.tp-qf { margin-top: 9px; display: flex; align-items: center; justify-content: flex-end; }
.tp-qf .n { font-size: 10px; color: var(--lx-ink3); }
.tp-qf .fc { margin-left: 6px; font-size: 9.5px; color: var(--lx-ink3); }
/* 已解决/重新打开：与「追问」并排，靠右；按下后立刻重绘，不留中间态 */
.tp-qf .tp-mini + .tp-mini { margin-left: 8px; }
.tp-mini.on { color: var(--lx-violet); border-color: #e5d9f7; background: #f7f2ff; }

/* ---- 答疑附件（提问框 / 追问弹窗 / 线程里） ---- */
.tp-pick {
  display: inline-flex; align-items: center; gap: 4px; cursor: pointer;
  border: 1px dashed var(--lx-line); border-radius: 8px;
  padding: 4px 9px; font-size: 11px; color: var(--lx-ink2); background: #fff;
  transition: .14s; white-space: nowrap;
}
.tp-pick:hover { color: var(--lx-red); border-color: #fbd5e2; background: var(--lx-red-soft); }
.tp-ask-pv { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.tp-ask-pv:empty { display: none; }
.tp-pvf {
  display: inline-flex; align-items: center; gap: 6px; max-width: 220px;
  padding: 3px 8px; border-radius: 8px; background: #f7f2ff;
  font-size: 10.5px; color: var(--lx-violet);
}
.tp-pvf b { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tp-pvf i { font-style: normal; cursor: pointer; color: #a99fbb; font-size: 12px; line-height: 1; }
.tp-pvf i:hover { color: var(--lx-red); }
.tp-fu-tools { display: flex; align-items: center; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.tp-fu-tools .tp-ask-pv { margin-top: 0; }
/* 附件缩略图：44px 方图，点开原图；非图片给扩展名角标 */
.tp-atts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.tp-att {
  display: block; width: 64px; text-decoration: none;
  border: 1px solid var(--lx-line); border-radius: 8px; overflow: hidden; background: #fff;
}
.tp-att:hover { border-color: #fbd5e2; }
.tp-att img, .tp-att .ft {
  display: flex; align-items: center; justify-content: center;
  width: 64px; height: 46px; object-fit: cover; background: #faf7fd;
  font-style: normal; font-size: 10px; font-weight: 700; color: #a99fbb; letter-spacing: .4px;
}
.tp-att em {
  display: block; padding: 2px 4px; font-style: normal; font-size: 9px;
  color: var(--lx-ink3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* 撤图：× 浮在缩略图右上角，常显但压暗（悬停时提亮）。
   不做「悬停才出现」——撤图是补救动作，用户是带着「贴错了」的念头来找按钮的，
   藏起来等于让他先猜一遍。只在服务端判定可撤时才渲染（can_delete）。 */
.tp-att-w { position: relative; display: inline-block; }
.tp-att-x {
  position: absolute; top: -6px; right: -6px; width: 17px; height: 17px;
  padding: 0; border-radius: 50%; cursor: pointer;
  border: 1px solid #f2cfdb; background: #fff; color: #c25b7c;
  font-family: inherit; font-size: 12px; line-height: 14px; text-align: center;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .08);
  opacity: .55; transition: opacity .14s, background .14s;
}
.tp-att-w:hover .tp-att-x, .tp-att-x:hover, .tp-att-x:focus {
  opacity: 1; background: var(--lx-red-soft); border-color: #f0b9cd;
}

/* 同学已回复的问答（折叠） */
.tp-qa-p { border-bottom: 1px solid var(--lx-line2); padding: 0 16px; }
.tp-qa-p:last-child { border-bottom: 0; }
.tp-qa-p summary {
  display: flex; align-items: center; gap: 7px; cursor: pointer; list-style: none;
  padding: 10px 0; font-size: 12px; color: var(--lx-ink); font-weight: 600;
}
.tp-qa-p summary::-webkit-details-marker { display: none; }
.tp-qa-p summary .cv {
  width: 7px; height: 7px; flex: none; margin-left: auto; margin-top: -3px;
  border-right: 1.6px solid #b8b0c6; border-bottom: 1.6px solid #b8b0c6;
  transform: rotate(45deg); transition: transform .16s;
}
.tp-qa-p[open] summary .cv { transform: rotate(-135deg); margin-top: 3px; }
.tp-qa-p .a { padding: 0 0 12px; font-size: 11.5px; color: var(--lx-ink2); line-height: 1.9; }
.tp-qa-p .a b { display: block; color: #2c6b57; font-weight: 600; }
.tp-qa-p .a span { display: block; margin-top: 5px; font-size: 10px; color: #b8b0c6; }

/* AI 引导条 */
.tp-ai-inline {
  display: flex; align-items: center; gap: 10px; justify-content: flex-end;
  margin: 8px 2px 0; font-size: 11px; color: var(--lx-ink3);
}

/* 资源卡上的「教师上传」角标 + 文件卡 / 资料列表 / 选文件框 */
.tp-res { position: relative; }
.tp-res .up {
  position: absolute; top: 8px; left: 8px; z-index: 1;
  font-size: 9.5px; color: #fff; background: rgba(225, 29, 72, .92);
  border-radius: 99px; padding: 1px 7px; letter-spacing: .2px;
}
.tp-filecard {
  display: flex; align-items: center; gap: 12px; padding: 16px;
  border: 1px dashed var(--lx-line); border-radius: 12px; background: #fbf9fc; color: var(--lx-ink3);
}
.tp-filecard b { display: block; font-size: 13px; color: var(--lx-ink); }
.tp-filecard span { font-size: 11px; color: var(--lx-ink3); }

.tp-filelist { display: flex; flex-direction: column; }
.tp-filerow {
  display: flex; align-items: center; gap: 11px; padding: 10px 2px;
  border-bottom: 1px solid var(--lx-line2);
}
.tp-filerow:last-child { border-bottom: 0; }
.tp-filerow .ic {
  width: 28px; height: 28px; border-radius: 9px; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--lx-violet-soft); color: var(--lx-violet);
}
.tp-filerow .n { flex: 1 1 auto; min-width: 0; }
.tp-filerow .n b { display: block; font-size: 12.5px; color: var(--lx-ink); }
.tp-filerow .n em { display: block; font-style: normal; font-size: 10.5px; color: var(--lx-ink3); margin-top: 1px; }
.tp-pickfile { margin-bottom: 10px; }
.tp-pickfile input[type=file] {
  width: 100%; box-sizing: border-box; font-family: inherit; font-size: 12px;
  border: 1px dashed var(--lx-line); border-radius: 10px; padding: 10px; background: #fbf9fc;
  color: var(--lx-ink2); cursor: pointer;
}
.tp-pickfile .tip { margin-top: 6px; font-size: 10.5px; color: var(--lx-ink3); }

/* 教师答疑卡内部：公告管理 + 提问列表分区 */
.tp-subhd {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; color: var(--lx-ink3); letter-spacing: .3px;
  margin: 2px 0 8px;
}
.tp-subhd em { font-style: normal; color: var(--lx-ink2); font-weight: 700; }
.tp-subhd::after { content: ''; flex: 1; height: 1px; background: var(--lx-line2); }
.tp-qasep { height: 1px; background: var(--lx-line2); margin: 14px 0 12px; }
.tp-ntclist { display: flex; flex-direction: column; }
.tp-ntcrow {
  display: flex; align-items: center; gap: 9px; padding: 7px 2px;
  border-bottom: 1px solid var(--lx-line2); font-size: 12px;
}
.tp-ntcrow:last-child { border-bottom: 0; }
.tp-ntcrow b { color: var(--lx-ink); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tp-ntcrow .pin {
  font-style: normal; font-size: 9.5px; color: #fff; background: var(--lx-red);
  border-radius: 99px; padding: 1px 6px; flex: none;
}
.tp-ntcrow .at { font-size: 10.5px; color: #b8b0c6; margin-left: auto; }
.tp-ntcrow .st { font-size: 10.5px; color: #0b8f6a; flex: none; }
.tp-ntcrow .st.off { color: #9a93ad; }
.tp-ntcrow.revoked b { color: #9a93ad; text-decoration: line-through; }

/* 上传弹窗里的字段标签 + 危险操作按钮 */
.tp-lbl { display: block; font-size: 11px; color: var(--lx-ink3); margin: 2px 0 5px; }
.tp-mini.danger { color: #c2410c; border-color: #fbd5c0; }
.tp-mini.danger:hover { color: #fff; background: #e2542a; border-color: #e2542a; }

/* 课程条页签上的未读红点（答疑回复） */
.tp-nav button { position: relative; }
.tp-nav button .nbadge {
  position: absolute; top: 6px; right: 2px;
  min-width: 15px; height: 15px; padding: 0 4px; box-sizing: border-box;
  border-radius: 99px; background: var(--lx-red); color: #fff;
  font-size: 9.5px; font-style: normal; font-weight: 700; line-height: 15px;
  text-align: center; box-shadow: 0 1px 3px rgba(225, 29, 72, .4);
}

/* 资源页筛选：章 + 分类两排，中间夹搜索 */
.tp-res-tools { display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.tp-res-tools .tp-res-bar { margin-bottom: 0; flex: 1 1 420px; }
.tp-res-tools .tp-search { flex: none; align-self: center; }
.tp-res-bar.cats { margin-bottom: 14px; }
.tp-res-bar.cats button.on { background: var(--lx-violet-soft); border-color: #ddd0ff; color: var(--lx-violet); }
.tp-res-bar.cats button.on b { color: var(--lx-violet); }
.tp-page .tp-res[hidden] { display: none; }
/* 公告「待发布」状态用琥珀色，和「已发布」的绿色分开 */
.tp-ntcrow .st.wait { color: #e8901b; }

/* 公告「发给谁」：列表里的范围文字 + 弹窗里的班级勾选 */
.tp-ntcrow .sc {
  font-size: 10.5px; color: var(--lx-ink3); flex: none;
  background: #f7f3fa; border-radius: 99px; padding: 1px 7px;
  max-width: 190px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tp-classpick {
  display: flex; flex-direction: column; gap: 2px;
  border: 1px solid var(--lx-line); border-radius: 10px;
  padding: 8px 10px; margin: 0 0 8px; background: #fbf9fc;
}
.tp-classpick .tp-chk { font-size: 11.5px; }
.tp-classpick[hidden] { display: none; }

/* 资源检索结果条 + 正文命中片段 */
.tp-res-hitl {
  display: flex; align-items: center; gap: 10px;
  font-size: 11.5px; color: var(--lx-ink2);
  background: var(--lx-red-soft); border: 1px solid #fbd5e2;
  border-radius: 10px; padding: 7px 12px; margin-bottom: 12px;
}
.tp-linkbtn {
  margin-left: auto; border: 0; background: none; cursor: pointer; font-family: inherit;
  font-size: 11.5px; color: var(--lx-red); text-decoration: underline; padding: 0;
}
.tp-res .rb .hit {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: 10.5px; color: #8a6a2a; background: #fffbe9;
  border-left: 2px solid #f3d68a; border-radius: 0 5px 5px 0;
  padding: 2px 6px; margin-top: 4px; line-height: 1.65;
}

/* 可点提醒（教师回复了你的提问 → 去互动页） */
.tp-note .tp-notego, .nt-go {
  color: var(--lx-red); text-decoration: none; font-size: 11.5px; font-weight: 600;
  white-space: nowrap; border-bottom: 1px dashed #f3b9ca; margin-left: 4px;
  padding: 0 1px;
}
/* 提醒条里的链接要能一眼看见：它常常是整条提醒唯一可点的东西 */
.notice .nt-go { font-size: 12px; }
.tp-note .tp-notego:hover, .nt-go:hover { border-bottom-style: solid; }

/* 非图片资料：缩略图位显示文件类型，而不是一个空框 */
.tp-res .ri .ph.file { background: linear-gradient(135deg, #f6f1ff, #fdf1f6); }
.tp-res .ri .ph.file em {
  font-style: normal; font-size: 19px; font-weight: 800; letter-spacing: 1.5px;
  color: #b9a8d6; font-family: var(--lx-num);
}

/* 答疑时限：超 24 小时显式标出来（教师端要知道积压在哪，学生端要知道能不能催） */
.tp-sla {
  font-size: 10.5px; color: #b45309; background: #fffbeb;
  border: 1px solid #fde68a; border-radius: 99px; padding: 1px 8px; flex: none;
}
.tp-qaitem .qwait.od, .tp-qaitem .qwait.od { color: #b45309; }
.tp-qaitem .qwait.od::before { content: '⏰ '; }

/* 资料收藏：卡片右上角星标 + 工具条「我的收藏」筛选 */
.tp-res .star {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  width: 22px; height: 22px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-style: normal; font-size: 13px; line-height: 1; cursor: pointer;
  color: #a99fbb; background: rgba(255, 255, 255, .85);
  box-shadow: 0 1px 4px rgba(60, 30, 70, .12); transition: .14s;
}
.tp-res .star:hover { color: #e8901b; transform: scale(1.08); }
.tp-res .star.on { color: #f59e0b; background: #fffbeb; }
.tp-starfilter {
  flex: none; display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--lx-line); background: #fff; color: var(--lx-ink2);
  font-family: inherit; font-size: 11.5px; padding: 5px 11px; border-radius: 99px;
  cursor: pointer; transition: .14s; white-space: nowrap;
}
.tp-starfilter b { font-size: 10.5px; color: var(--lx-ink3); }
.tp-starfilter:hover { color: #b45309; border-color: #fde68a; }
.tp-starfilter.on { background: #fffbeb; border-color: #fde68a; color: #b45309; font-weight: 700; }
.tp-starfilter.on b { color: #b45309; }
/* 教师就地补资料（第四十五轮）：与「我的收藏」并排，用主色的浅底区分
   —— 它是动作，不是筛选，不该长得跟筛选按钮一样。 */
.tp-upres {
  flex: none; display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid #f3c6d4; background: #fff5f8; color: #b31f45;
  font-family: inherit; font-size: 11.5px; font-weight: 600;
  padding: 5px 11px; border-radius: 99px; cursor: pointer;
  transition: .14s; white-space: nowrap;
}
.tp-upres:hover { background: #ffe9ef; border-color: #ef9db5; }

/* --------------------------------------------------------------------------
   课程条七个页签：窄屏不换行、可横滚、当前页签自动进入视野
   红圈里那一排就是这七个页签。1080 以下原来会把「结课考试」挤出去且没有
   任何提示「右边还有内容」，学生以为只有五个页签。
   -------------------------------------------------------------------------- */
.tp-coursebar { flex-wrap: nowrap; }
.tp-nav {
  overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
  scroll-behavior: smooth; min-width: 0;
}
.tp-nav::-webkit-scrollbar { display: none; }
.tp-nav button { flex: none; }
.tp-nav button:focus-visible { outline: 2px solid var(--lx-red); outline-offset: 2px; border-radius: 6px; }

@media (max-width: 1024px) {
  .tp-coursebar { flex-wrap: wrap; row-gap: 8px; }
  .tp-nav { order: 5; width: 100%; margin-left: -2px; }
  /* 右侧加一道渐隐，暗示「还能往右滑」 */
  .tp-nav { mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 22px), transparent 100%); }
}
@media (max-width: 640px) {
  .tp-nav button { padding-left: 10px; padding-right: 10px; font-size: 12.5px; }
}

/* 教师端资料行的查看统计：与上面的元信息同色但更弱，避免抢视线 */
.tp-filerow .n em.rv { color: #9a93ad; }

/* 教师端「没人看过」筛选按钮：和上传按钮并排，选中态用琥珀色以示「这是在筛异常」 */
.tp-mini.on { background: #fffbeb; border-color: #fde68a; color: #b45309; font-weight: 700; }

/* ==========================================================================
   课程资源管理（第四十六轮 · 独立页 #/teacher-res）
   --------------------------------------------------------------------------
   一屏之内要同时装下三件事，所以是「三块分区」而不是「一张长卡」：
     左 232px：分类 + 章节树（点章展开该章的任务）—— 管「垂直」，一眼看清
               资料铺在哪几章、哪一章是空的；
     中间自适应：工具条 + 表格 —— 管「横向」，搜索 / 分类 / 无人看过 / 排序 /
               多选批量，缩到某一份为止；
     右侧抽屉 380px：改标题、说明、分类、关联任务 + 元信息 —— 管「深度」，
               不跳页、不丢当前筛选。
   表格每行只保留三个判断：「叫什么、放哪儿、有没有人看」，其余进抽屉。
   ========================================================================== */
.ra-page { padding-bottom: 8px; }

/* 统计条：五格，窄屏折成两行 */
.ra-stat {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 10px; margin-bottom: 14px;
}
.ra-kpi {
  background: #fff; border: 1px solid var(--lx-line); border-radius: 12px;
  padding: 11px 13px 10px; box-shadow: var(--lx-sh);
}
.ra-kpi .k { font-size: 11.5px; color: var(--lx-ink3); }
.ra-kpi .v { font-size: 20px; font-weight: 800; color: var(--lx-ink); line-height: 1.35; font-variant-numeric: tabular-nums; }
.ra-kpi .v.vio { color: #7c5cff; }
.ra-kpi .v.red { color: var(--lx-red); }
.ra-kpi .x { font-size: 10.5px; color: var(--lx-ink3); }

.ra-body { display: grid; grid-template-columns: 232px minmax(0, 1fr); gap: 14px; align-items: start; }

/* 左树 */
.ra-side {
  background: #fff; border: 1px solid var(--lx-line); border-radius: 12px;
  box-shadow: var(--lx-sh); padding: 8px 8px 12px; position: sticky; top: 12px;
  max-height: calc(100vh - 160px); overflow: auto;
}
.ra-side-hd {
  display: flex; align-items: center; gap: 6px; padding: 6px 6px 9px;
  font-size: 11.5px; font-weight: 800; color: var(--lx-ink2);
}
.ra-grp {
  font-size: 10.5px; color: var(--lx-ink3); letter-spacing: .5px;
  padding: 10px 8px 5px; border-top: 1px dashed var(--lx-line2); margin-top: 6px;
}
.ra-node {
  display: flex; align-items: center; gap: 7px; width: 100%;
  border: 0; background: none; cursor: pointer; font-family: inherit;
  padding: 6px 8px; border-radius: 8px; font-size: 12.5px; color: var(--lx-ink2);
  text-align: left; transition: .13s;
}
.ra-node:hover { background: #f8f5fd; color: var(--lx-ink); }
.ra-node.on { background: #fff1f5; color: var(--lx-red); font-weight: 700; }
.ra-node .n { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ra-node b { font-size: 11px; color: var(--lx-ink3); font-variant-numeric: tabular-nums; }
.ra-node.on b { color: var(--lx-red); }
.ra-node .caret { width: 10px; color: #b9aed0; transition: transform .15s; font-size: 12px; }
.ra-node .caret.open { transform: rotate(90deg); }
.ra-node.lv1 { font-weight: 600; }
.ra-node.lv2 { padding-left: 26px; font-size: 12px; }
.ra-node .dot { width: 7px; height: 7px; border-radius: 50%; background: #cbd5e1; flex: none; }
.ra-node .dot.blue { background: #3b82f6; } .ra-node .dot.teal { background: #14b8a6; }
.ra-node .dot.violet { background: #8b5cf6; } .ra-node .dot.amber { background: #f59e0b; }
.ra-node .dot.gray { background: #94a3b8; }
.ra-side-empty { padding: 18px 10px; font-size: 12px; color: var(--lx-ink3); line-height: 1.9; }
.ra-side-empty span { font-size: 11px; }

/* 工具条 */
.ra-main { min-width: 0; }
.ra-tools {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  background: #fff; border: 1px solid var(--lx-line); border-radius: 12px;
  padding: 9px 12px; box-shadow: var(--lx-sh); margin-bottom: 10px;
}
.ra-search {
  display: flex; align-items: center; gap: 6px; flex: 1 1 260px; min-width: 200px;
  border: 1px solid var(--lx-line); border-radius: 9px; padding: 0 9px; background: #fcfcfe;
}
.ra-search svg { color: var(--lx-ink3); flex: none; }
.ra-search input {
  border: 0; outline: none; background: none; font-family: inherit;
  font-size: 12.5px; color: var(--lx-ink); padding: 7px 0; width: 100%;
}
.ra-seg button, .ra-tools .ra-link {
  border: 1px solid var(--lx-line); background: #fff; color: var(--lx-ink2);
  font-family: inherit; font-size: 11.5px; padding: 6px 11px; border-radius: 99px;
  cursor: pointer; transition: .13s; white-space: nowrap;
}
.ra-seg button:hover, .ra-tools .ra-link:hover { border-color: #f3c6d4; color: var(--lx-red); }
.ra-seg button.on { background: #fff1f5; border-color: #f3c6d4; color: var(--lx-red); font-weight: 700; }
.ra-sort {
  border: 1px solid var(--lx-line); border-radius: 9px; background: #fff;
  font-family: inherit; font-size: 11.5px; color: var(--lx-ink2); padding: 6px 8px; cursor: pointer;
}
.ra-tools .sp, .ra-bulkbar .sp { flex: 1; }
.ra-tools .ra-link { display: inline-flex; align-items: center; gap: 4px; }

/* 批量条：只在有勾选时出现，不占常态高度 */
.ra-bulkbar {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 8px 12px; margin-bottom: 8px; border-radius: 10px;
  background: #fff1f5; border: 1px solid #f6c9d7; font-size: 12px; color: #8d1836;
}
.ra-bulkbar b { font-size: 12px; }
.ra-bulkbar button {
  border: 1px solid #f3c6d4; background: #fff; color: #b31f45; font-family: inherit;
  font-size: 11.5px; padding: 4px 10px; border-radius: 8px; cursor: pointer;
}
.ra-bulkbar button:hover { background: #ffe9ef; }
.ra-bulkbar button.danger { color: #b91c1c; border-color: #f3c0c0; }
.ra-bulkbar .ra-link { border: 0; background: none; color: #8d1836; text-decoration: underline; padding: 0 4px; }

/* 表格 */
.ra-listwrap {
  background: #fff; border: 1px solid var(--lx-line); border-radius: 12px;
  box-shadow: var(--lx-sh); overflow: hidden;
}
/* 固定列宽：资料列吃掉剩余宽度，其余按表头声明走。
   不加 table-layout:fixed 时，长标题与长任务名会把整张表撑出容器，
   右侧「操作」列被裁掉 —— 用户看到的是「没有编辑按钮」。 */
.ra-table { width: 100%; table-layout: fixed; }
.ra-table thead th {
  font-size: 11.5px; color: var(--lx-ink3); font-weight: 600; background: #fbfcfe;
  border-bottom: 1px solid var(--lx-line2); padding: 9px 10px; text-align: left;
}
.ra-table thead th:nth-child(1) { padding-left: 12px; }
.ra-table tbody td { padding: 9px 10px; border-bottom: 1px solid var(--lx-line2); vertical-align: middle; overflow: hidden; }
.ra-table tbody tr:last-child td { border-bottom: 0; }
.ra-table tbody tr:hover td { background: #fdfbff; }
.ra-table tbody tr.ra-row.picked td { background: #fff8fa; }
.ra-t { min-width: 0; }
.ra-t b {
  display: block; font-size: 12.5px; color: var(--lx-ink); font-weight: 700;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ra-t em {
  display: block; font-style: normal; font-size: 10.5px; color: var(--lx-ink3);
  margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ra-note {
  display: block; font-size: 11px; color: var(--lx-ink2); margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* 任务名可能很长（「组织架构搭建（总公司 / 工厂 / 部门）」），最多两行 */
.ra-ls {
  font-size: 11.5px; color: var(--lx-ink2); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ra-ls .muted { color: var(--lx-ink3); }
.ra-table td.num { font-size: 11.5px; color: var(--lx-ink2); white-space: nowrap; }
.ra-table td.num b { font-size: 13px; color: var(--lx-ink); }
.ra-table td.num em { font-style: normal; color: var(--lx-ink3); margin-left: 4px; font-size: 10.5px; }
.ra-zero { color: #b45309; font-size: 11px; background: #fffbeb; border: 1px solid #fde68a; border-radius: 99px; padding: 1px 7px; }
.ra-up { font-size: 11px; color: var(--lx-ink2); }
.ra-up span { display: block; }
.ra-up em { font-style: normal; font-size: 10.5px; color: var(--lx-ink3); }
.ra-ops { white-space: nowrap; }
.ra-ops .tp-mini { margin-left: 4px; }

/* 右侧抽屉：不跳页、不丢筛选 */
/* 层级要卡在「悬浮 AI 入口(8002)」之上、「弹窗遮罩(9000)」之下：
   低了会被 AI 气泡压住保存按钮，高了删除确认弹窗会被抽屉盖住。 */
.ra-mask { position: fixed; inset: 0; background: rgba(30, 24, 45, .28); z-index: 8400; }
.ra-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; width: 380px; max-width: 92vw;
  background: #fff; z-index: 8500; display: flex; flex-direction: column;
  box-shadow: -12px 0 32px rgba(40, 30, 60, .16);
  animation: raSlide .18s ease-out;
}
@keyframes raSlide { from { transform: translateX(24px); opacity: .4; } to { transform: none; opacity: 1; } }
.ra-dw-hd {
  display: flex; align-items: center; gap: 8px; padding: 13px 16px;
  border-bottom: 1px solid var(--lx-line2);
}
.ra-dw-hd b { font-size: 13px; color: var(--lx-ink); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ra-x {
  border: 0; background: none; font-size: 18px; line-height: 1; color: var(--lx-ink3);
  cursor: pointer; padding: 0 2px;
}
.ra-x:hover { color: var(--lx-red); }
/* min-height:0 是关键：flex 子项默认 min-height:auto，内容比抽屉高时
   会把自己撑到 900+，把底部「保存 / 删除」顶出屏幕（视频预览一加就露出来）。 */
.ra-dw-bd { flex: 1; min-height: 0; overflow: auto; padding: 14px 16px 8px; }
.ra-field { margin-bottom: 11px; }
.ra-field label { display: block; font-size: 11.5px; color: var(--lx-ink3); margin-bottom: 4px; }
.ra-field .inp { width: 100%; }
.ra-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.ra-meta {
  border: 1px dashed var(--lx-line); border-radius: 10px; padding: 8px 11px; margin: 4px 0 12px;
  background: #fbfcfe; font-size: 11.5px;
}
.ra-meta > div { display: flex; gap: 8px; padding: 3px 0; }
.ra-meta span { color: var(--lx-ink3); width: 72px; flex: none; }
.ra-meta b { color: var(--lx-ink2); font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.ra-dw-ft {
  display: flex; align-items: center; gap: 8px; padding: 10px 16px;
  border-top: 1px solid var(--lx-line2); background: #fcfcfe;
}
.ra-dw-ft .sp { flex: 1; }
/* 抽屉底部的删除：靠左、红字、不加边框 —— 与右侧「保存」明确分开，
   既不误点，也不会被当成主按钮。 */
.ra-del {
  border: 0; background: none; font-family: inherit; font-size: 11.5px;
  color: #b91c1c; cursor: pointer; padding: 4px 2px;
}
.ra-del:hover { text-decoration: underline; }

@media (max-width: 1180px) {
  .ra-stat { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .ra-body { grid-template-columns: minmax(0, 1fr); }
  .ra-side { position: static; max-height: none; }
}
@media (max-width: 760px) {
  .ra-stat { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ra-table thead th:nth-child(4), .ra-table tbody td:nth-child(4),
  .ra-table thead th:nth-child(6), .ra-table tbody td:nth-child(6) { display: none; }
  .ra-drawer { width: 100vw; }
}

/* ==========================================================================
   课程内容管理（第四十八轮 · #/teacher-res 重做）
   --------------------------------------------------------------------------
   三层树 + 四块内容。左边给结构（章 → 单元 → 任务，带配齐状态点），
   右边给内容（任务目录 / 摘要 / 资料 / 参考答案），一块一个页签。
   与第四十七轮的资源页相比：导航从「分类 + 章节筛选」变成唯一的三层树，
   因为教师维护课程时的第一个问题是「这一章备齐没」，不是「我传过什么」。
   ========================================================================== */
.cm-grid { display: grid; grid-template-columns: 288px minmax(0, 1fr); gap: 14px; align-items: start; }

/* 左树：吸顶 + 自带滚动。一节 5 个单元、48 个任务，长树不能把整页顶下去。 */
.cm-tree {
  position: sticky; top: 12px; max-height: calc(100vh - 140px);
  display: flex; flex-direction: column; background: #fff;
  border: 1px solid var(--lx-line); border-radius: 14px; box-shadow: var(--lx-sh); overflow: hidden;
}
.cm-tree-hd {
  display: flex; align-items: baseline; gap: 8px; padding: 12px 14px 10px;
  border-bottom: 1px solid var(--lx-line2);
}
.cm-tree-hd b { font-size: 13px; color: var(--lx-ink); }
.cm-tree-hd .s { margin-left: auto; font-size: 10.5px; color: var(--lx-ink3); }
.cm-tree-tools {
  display: flex; gap: 6px; flex-wrap: wrap; padding: 8px 10px;
  border-bottom: 1px solid var(--lx-line2); background: #fcfcfe;
}
.cm-mini {
  border: 1px solid var(--lx-line); background: #fff; color: var(--lx-ink2);
  font-family: inherit; font-size: 11px; padding: 3px 8px; border-radius: 7px;
  cursor: pointer; transition: .13s; white-space: nowrap;
}
.cm-mini:hover { border-color: #f3c6d4; color: var(--lx-red); }
.cm-mini.on { background: #fff1f5; border-color: #f3c6d4; color: var(--lx-red); font-weight: 700; }
.cm-mini:disabled { opacity: .4; cursor: default; }
.cm-mini b {
  font-size: 9.5px; background: #fde68a; color: #92400e;
  border-radius: 99px; padding: 0 4px; margin-left: 3px;
}
.cm-tree-bd { flex: 1; min-height: 0; overflow: auto; padding: 6px 6px 14px; }

.cm-stage { border-bottom: 1px solid var(--lx-line2); }
.cm-stage:last-child { border-bottom: 0; }
.cm-node {
  display: flex; align-items: center; gap: 6px; width: 100%;
  border: 0; background: none; font-family: inherit; text-align: left;
  cursor: pointer; border-radius: 8px; padding: 6px 7px;
  color: var(--lx-ink2); font-size: 12.5px; transition: .12s;
}
.cm-node:hover { background: #faf7ff; }
.cm-node .caret { width: 10px; flex: none; color: #b9aed0; font-size: 12px; transition: transform .15s; }
.cm-node.open .caret { transform: rotate(90deg); }
.cm-node .nm { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cm-node .cnt { flex: none; font-size: 10.5px; color: var(--lx-ink3); font-variant-numeric: tabular-nums; }
.cm-node .no {
  flex: none; font-size: 9.5px; font-weight: 800; color: #7c5cff;
  background: #f3efff; border: 1px solid #e6ddff; border-radius: 5px; padding: 0 5px;
}
.cm-node.lv1 { font-weight: 700; color: var(--lx-ink); }
/* 树顶的「课程级资料」：它不在章序列里，用一条底边与下面的第 0～5 章分开，
   否则会长得像「第 6 章」或某个漏了章号的章。 */
.cm-node.cm-lv0 { margin-bottom: 8px; border-bottom: 1px dashed var(--lx-line); border-radius: 9px 9px 0 0; }
.cm-node.cm-lv0.open, .cm-node.cm-lv0:hover { background: #faf7ff; }
.cm-node.cm-lv0.on { background: #fff1f5; color: var(--lx-red); }
.cm-node.lv2 { padding-left: 20px; font-size: 12px; }
.cm-node.lv3 { padding-left: 34px; font-size: 11.5px; }
.cm-node.lv3.on { background: #fff1f5; color: var(--lx-red); font-weight: 700; }
.cm-node.lv3.on .cm-dot { border-color: #f3c6d4; }
.cm-miss {
  flex: none; font-size: 9.5px; color: #b45309; background: #fffbeb;
  border: 1px solid #fde68a; border-radius: 99px; padding: 0 5px;
}
.cm-dots { display: inline-flex; gap: 3px; flex: none; align-items: center; }
.cm-dot {
  width: 6px; height: 6px; border-radius: 50%; background: #e8edf3;
  border: 1px solid #dbe2ea; display: inline-block;
}
.cm-dot.on { background: #22c55e; border-color: #16a34a; }
.cm-empty { padding: 18px 10px; font-size: 12px; color: var(--lx-ink3); line-height: 1.9; }

/* 右主区 */
.cm-main { min-width: 0; }
.cm-head {
  display: flex; gap: 16px; align-items: flex-start;
  background: #fff; border: 1px solid var(--lx-line); border-radius: 14px;
  box-shadow: var(--lx-sh); padding: 14px 16px; margin-bottom: 10px;
}
.cm-head-l { flex: 1; min-width: 0; }
.cm-crumb { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 11px; color: var(--lx-ink3); }
.cm-crumb .sl { color: #cbd5e1; }
.cm-crumb .cm-unit-n { color: var(--lx-ink2); }
.cm-stage-n {
  font-size: 9.5px; font-weight: 800; color: #7c5cff;
  background: #f3efff; border: 1px solid #e6ddff; border-radius: 5px; padding: 0 5px;
}
.cm-head h2 { margin: 6px 0; font-size: 18px; line-height: 1.4; color: var(--lx-ink); }
.cm-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 11px; color: var(--lx-ink3); }
.cm-code {
  font-family: var(--lx-num); font-size: 10.5px; color: #6d4fd0;
  background: #f6f1ff; border: 1px solid #e6ddff; border-radius: 5px; padding: 0 5px;
}
.cm-stars { color: #f59e0b; letter-spacing: 1px; }
.cm-head-r { flex: none; width: 268px; text-align: right; }
.cm-flags { display: flex; gap: 5px; justify-content: flex-end; flex-wrap: wrap; }
.cm-flag {
  font-size: 10.5px; border-radius: 99px; padding: 2px 8px;
  border: 1px solid #e2e8f0; background: #f8fafc; color: #94a3b8;
}
.cm-flag.on { background: #f0fdf4; border-color: #bbf7d0; color: #15803d; }
.cm-flag i { font-style: normal; margin-left: 3px; opacity: .7; }
.cm-todo {
  display: inline-block; margin-top: 8px; font-size: 11px; color: #b45309;
  background: #fffbeb; border: 1px solid #fde68a; border-radius: 8px; padding: 3px 8px;
}
.cm-todo.ok { color: #15803d; background: #f0fdf4; border-color: #bbf7d0; }
.cm-warn {
  margin-bottom: 10px; padding: 8px 12px; font-size: 11.5px; line-height: 1.75;
  color: #9a3412; background: #fff7ed; border: 1px solid #fed7aa; border-radius: 10px;
}

/* 页签 */
.cm-tabs {
  display: flex; gap: 4px; padding: 5px; margin-bottom: 10px;
  background: #fff; border: 1px solid var(--lx-line); border-radius: 12px; box-shadow: var(--lx-sh);
}
.cm-tab {
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 5px;
  border: 0; background: none; font-family: inherit; font-size: 12.5px;
  color: var(--lx-ink2); padding: 8px 6px; border-radius: 8px; cursor: pointer; transition: .13s;
}
.cm-tab:hover { background: #faf7ff; color: var(--lx-ink); }
.cm-tab.on { background: var(--grad); color: #fff; font-weight: 700; }
.cm-tab i {
  font-style: normal; font-size: 10px; color: var(--lx-ink3);
  background: #f1f5f9; border-radius: 99px; padding: 0 5px;
}
.cm-tab.on i { background: rgba(255, 255, 255, .22); color: #fff; }

/* 内容盒 */
.cm-pane {
  background: #fff; border: 1px solid var(--lx-line); border-radius: 14px;
  box-shadow: var(--lx-sh); padding: 16px 18px;
}
.cm-note {
  font-size: 12px; line-height: 1.75; color: var(--lx-ink2);
  background: #fbf8ff; border: 1px dashed #e2d6ee; border-radius: 10px;
  padding: 9px 11px; margin-bottom: 12px;
}
.cm-sec-h { display: flex; align-items: center; gap: 8px; margin: 14px 0 8px; }
.cm-sec-h:first-child { margin-top: 0; }
.cm-sec-h b { font-size: 12.5px; color: var(--lx-ink); }
.cm-sec-h .cm-sub { font-size: 10.5px; color: var(--lx-ink3); }
.cm-sec-h .sp { flex: 1; }
.cm-hint { font-size: 10.5px; color: var(--lx-ink3); line-height: 1.7; }

/* 目录 */
.cm-tasks { border: 1px solid var(--lx-line2); border-radius: 10px; overflow: hidden; }
.cm-task {
  display: grid; grid-template-columns: 30px minmax(0, 1fr) 66px 142px;
  gap: 10px; align-items: center; padding: 8px 10px;
  border-bottom: 1px solid var(--lx-line2);
}
.cm-task:last-child { border-bottom: 0; }
.cm-task.on { background: #fff8fa; }
.cm-task .ix { font-size: 11px; color: var(--lx-ink3); text-align: center; font-variant-numeric: tabular-nums; }
.cm-task .tt { min-width: 0; }
.cm-task .tt b { display: block; font-size: 12.5px; color: var(--lx-ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cm-task .tt em { font-style: normal; font-size: 10.5px; color: var(--lx-ink3); }
.cm-task .ops { display: flex; gap: 4px; justify-content: flex-end; }
.cm-two { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 12px; }
.cm-card { border: 1px solid var(--lx-line2); border-radius: 10px; padding: 10px 12px; }
.cm-card > b { display: block; font-size: 12px; color: var(--lx-ink); margin-bottom: 6px; }
.cm-kv { display: flex; gap: 8px; font-size: 11.5px; padding: 3px 0; }
.cm-kv span { flex: none; width: 56px; color: var(--lx-ink3); }
.cm-kv b { font-weight: 600; color: var(--lx-ink2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cm-move { display: flex; gap: 8px; align-items: center; margin-top: 8px; flex-wrap: wrap; }
.cm-move .inp { flex: 1; min-width: 0; }

/* 表单 */
.cm-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.cm-field { margin-bottom: 12px; min-width: 0; }
.cm-field label { display: block; font-size: 11.5px; font-weight: 600; color: var(--lx-ink2); margin-bottom: 5px; }
.cm-field label i { font-style: normal; font-weight: 400; font-size: 10.5px; color: var(--lx-ink3); margin-left: 6px; }
.cm-field .cm-h { display: block; font-size: 10.5px; color: var(--lx-ink3); line-height: 1.65; margin-top: 4px; }
.cm-field .cm-h code {
  background: #f6f2fb; border: 1px solid var(--lx-line2); border-radius: 4px;
  padding: 0 4px; font-size: 10.5px; color: #6d4fd0;
}
.cm-ta { line-height: 1.75; resize: vertical; }
.cm-mono { font-family: ui-monospace, Consolas, "Courier New", monospace; font-size: 11.5px; }
.cm-ref { min-height: 220px; }
.cm-count { text-align: right; font-size: 10.5px; color: var(--lx-ink3); margin-top: 4px; }
.cm-ref-pv { white-space: pre-wrap; margin-bottom: 4px; }

.cm-savebar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 16px -18px -16px; padding: 10px 18px;
  border-top: 1px solid var(--lx-line2); background: #fcfcfe;
}

/* 资料清单 */
.cm-toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.cm-toolbar .sp { flex: 1; }
.cm-res { border: 1px solid var(--lx-line2); border-radius: 10px; overflow: hidden; }
.cm-res .ra-row {
  display: grid; align-items: center; gap: 10px;
  grid-template-columns: 54px minmax(0, 1fr) 84px 76px 156px;
  padding: 9px 10px; border-bottom: 1px solid var(--lx-line2);
}
.cm-res .ra-row:last-child { border-bottom: 0; }
.cm-res .ra-row:hover { background: #fdfbff; }
.cm-res .ra-t b { font-size: 12.5px; }
.cm-res .ra-t em { font-size: 10.5px; }
.cm-res .num { font-size: 11.5px; color: var(--lx-ink2); white-space: nowrap; }
.cm-res .num b { font-size: 13px; color: var(--lx-ink); }
.cm-res .ra-ops { display: flex; justify-content: flex-end; gap: 4px; }
.cm-res .ra-ops .tp-mini { margin: 0; }

@media (max-width: 1180px) {
  .cm-grid { grid-template-columns: minmax(0, 1fr); }
  .cm-tree { position: static; max-height: 420px; }
  .cm-head-r { width: 220px; }
}
@media (max-width: 860px) {
  .cm-head { flex-direction: column; }
  .cm-head-r { width: 100%; text-align: left; }
  .cm-flags { justify-content: flex-start; }
  .cm-grid2, .cm-two { grid-template-columns: minmax(0, 1fr); }
  .cm-task { grid-template-columns: 26px minmax(0, 1fr) 120px; }
  .cm-task .cm-dots { display: none; }
  .cm-res .ra-row { grid-template-columns: 48px minmax(0, 1fr) 128px; }
  .cm-res .cat, .cm-res .num { display: none; }
  .cm-tabs { flex-wrap: wrap; }
  .cm-tab { flex: 1 1 44%; }
}

/* 页头：一句话说清这一页维护什么，右边四个数（任务 / 单元 / 已配齐 / 待补）。
   「已配齐 / 待补」分开给，而不是一个百分比 —— 教师关心的是还有几件要做。 */
.cm-top { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 12px; }
.cm-top-l { flex: 1; min-width: 0; }
.cm-top-l h1 { margin: 0 0 4px; font-size: 20px; color: var(--lx-ink); }
.cm-top-l p { margin: 0; font-size: 12px; line-height: 1.75; color: var(--lx-ink3); }
.cm-top-l p b { color: var(--lx-ink2); }
.cm-top-r { flex: none; display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-end; }
.cm-kpi {
  min-width: 74px; text-align: center; background: #fff; border: 1px solid var(--lx-line);
  border-radius: 10px; padding: 6px 10px; font-size: 10.5px; color: var(--lx-ink3);
  box-shadow: var(--lx-sh);
}
.cm-kpi b { display: block; font-size: 17px; font-weight: 800; color: var(--lx-ink); font-variant-numeric: tabular-nums; line-height: 1.3; }
.cm-kpi.ok b { color: #15803d; }
.cm-kpi.warn b { color: #b45309; }
/* 与 KPI 并排的「资源包总览」：高度对齐 KPI 卡，弱化为线框按钮 */
.cm-packlink {
  display: inline-flex; align-items: center; align-self: stretch;
  padding: 0 12px; border-radius: 10px; text-decoration: none;
  font-size: 12px; font-weight: 600; color: var(--lx-ink2);
  background: #fff; border: 1px solid var(--lx-line); box-shadow: var(--lx-sh);
  transition: .14s;
}
.cm-packlink:hover { color: var(--lx-red); border-color: #e8c8d6; }
@media (max-width: 860px) {
  .cm-top { flex-direction: column; }
  .cm-top-r { justify-content: flex-start; }
}

/* --- 实训得分卡（第七十七轮） -------------------------------------------
   放在「判据」条下面：判据说「够不够」，得分卡说「好不好」。
   三段分用同一条样式，长短一眼可比；扣分项右对齐分数，扫一眼就知道哪条最贵。 */
.tp-score{margin-top:10px;border:1px solid var(--line);border-radius:12px;background:#fff;padding:12px 14px}
.tp-score .sc-h{display:flex;align-items:baseline;gap:8px}
.tp-score .sc-h span{font-size:12.5px;color:#6b7489}
.tp-score .sc-h b{font-size:26px;font-weight:800;line-height:1}
.tp-score .sc-h b.hi{color:#0f6b4d}
.tp-score .sc-h b.mid{color:#b26a00}
.tp-score .sc-h b.lo{color:#b42318}
.tp-score .sc-h i{font-style:normal;font-size:12px;color:#6b7489;background:#f3f5fa;border-radius:6px;padding:1px 7px}
.tp-score .sc-row{display:grid;grid-template-columns:34px 1fr 54px;grid-template-areas:"k bar v" "n n n";gap:2px 8px;margin-top:8px;align-items:center}
.tp-score .sc-row .k{grid-area:k;font-size:12px;color:#46506a}
.tp-score .sc-row .bar{grid-area:bar;height:6px;border-radius:4px;background:#eef1f7;overflow:hidden}
.tp-score .sc-row .bar i{display:block;height:100%;border-radius:4px;background:linear-gradient(90deg,#2f5bea,#5b8def)}
.tp-score .sc-row b{grid-area:v;font-size:12.5px;text-align:right;color:#1d2433}
.tp-score .sc-row b em{font-style:normal;font-size:11px;color:#8b93a7}
.tp-score .sc-row .n{grid-area:n;font-size:11.5px;color:#6b7489}
.tp-score .sc-iss{margin:10px 0 0;padding:0;list-style:none;border-top:1px dashed var(--line)}
.tp-score .sc-iss li{display:flex;gap:6px;align-items:baseline;font-size:11.8px;color:#46506a;padding:5px 0;border-bottom:1px dashed #f0f2f7}
.tp-score .sc-iss li b{color:#1d2433;font-weight:600;flex:none}
.tp-score .sc-iss li i{margin-left:auto;font-style:normal;color:#b42318;font-weight:600;flex:none}
.tp-score .sc-f{margin-top:8px;font-size:11px;color:#98a0b3}

/* --- 实训追踪（第七十七轮） ---------------------------------------------
   矩阵最多 70 列：每列只放步骤号（去掉 S 前缀），标题放 title 里，
   否则一屏塞不下，教师得横向拖半天才知道自己在看哪一步。 */
.tp-kpi{display:flex;gap:10px;flex-wrap:wrap;margin:4px 0 12px}
.tp-kpi .k{background:#fff;border:1px solid var(--line);border-radius:10px;padding:9px 16px;min-width:112px}
.tp-kpi .k b{display:block;font-size:20px;color:#1d2433;line-height:1.2}
.tp-kpi .k span{font-size:11.5px;color:#6b7489}
.tp-kpi .k.warn b{color:#b42318}
.tp-weak{display:flex;gap:7px;flex-wrap:wrap;align-items:center;margin-bottom:10px}
.tp-weak .t{font-size:12px;color:#6b7489;margin-right:2px}
.tp-weak button{font-size:12px;border:1px solid var(--line);background:#fff;border-radius:7px;padding:3px 9px;cursor:pointer;color:#46506a}
.tp-weak button b{color:#b26a00;margin-left:3px}
.tp-weak button.on{border-color:#2f5bea;color:#2f5bea}
.tp-weak button.on b{color:#2f5bea}
.tp-grid{overflow:auto;max-height:60vh;border:1px solid var(--line);border-radius:10px;background:#fff}
.tp-mx{border-collapse:separate;border-spacing:0;font-size:12px;width:max-content}
.tp-mx th{position:sticky;top:0;background:#f7f9fd;color:#46506a;font-weight:600;padding:5px 6px;border-bottom:1px solid var(--line);white-space:nowrap;z-index:2}
.tp-mx th.g{text-align:center;font-size:11px;color:#8b93a7;border-left:1px solid var(--line)}
.tp-mx th.stp{width:34px;text-align:center;font-size:11px;font-family:ui-monospace,Consolas,monospace}
.tp-mx thead tr:nth-child(2) th{top:26px}
.tp-mx td{border-bottom:1px solid #f2f4f8;padding:0;text-align:center}
.tp-mx td.nm{position:sticky;left:0;background:#fff;text-align:left;padding:6px 10px;min-width:118px;z-index:1;border-right:1px solid var(--line)}
.tp-mx td.nm em{display:block;font-style:normal;font-size:10.5px;color:#98a0b3}
.tp-mx td.tt{width:52px;padding:6px 4px;font-size:12px}
.tp-mx td.tt b{font-size:13px}
.tp-mx .cell{width:34px;height:30px;cursor:pointer;font-size:11.5px;color:#1d2433}
.tp-mx .cell:hover{outline:2px solid #2f5bea;outline-offset:-2px}
.tp-mx .c1{background:#d9f2e6}
.tp-mx .c2{background:#e8f6ee}
.tp-mx .c3{background:#f4f6e6}
.tp-mx .c4{background:#fdf1dc}
.tp-mx .c5{background:#fbe1dc;color:#8a2b1e}
.tp-mx .c0{background:#f4f5f8;color:#b6bccb}
.tp-mx .na{background:#f7f5fb;color:#c3b9d6}
.tp-mx b.c1{color:#0f6b4d}.tp-mx b.c2{color:#0f6b4d}.tp-mx b.c3{color:#6b6a1f}
.tp-mx b.c4{color:#b26a00}.tp-mx b.c5{color:#b42318}.tp-mx b.c0{color:#9aa1b2}
.tp-legend{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:10px;font-size:11.5px;color:#6b7489}
.tp-legend .lg{display:inline-block;padding:1px 8px;border-radius:5px;border:1px solid var(--line)}
.dm-h{display:flex;align-items:baseline;gap:10px;margin-bottom:10px}
.dm-h b{font-size:30px;color:#2f5bea;line-height:1}
.dm-h span{font-size:12.5px;color:#6b7489}
.dm-t{width:100%;border-collapse:collapse;font-size:12.5px}
.dm-t th,.dm-t td{border-bottom:1px solid var(--line);padding:7px 9px;text-align:left}
.dm-t th{background:#f7f9fd;color:#46506a;font-size:12px}
.dm-iss{margin-top:12px}
.dm-iss h4{margin:0 0 6px;font-size:12.5px;color:#46506a}
.dm-iss ul{margin:0;padding:0;list-style:none}
.dm-iss li{display:flex;gap:6px;font-size:12.3px;color:#46506a;padding:5px 0;border-bottom:1px dashed #eef1f7}
.dm-iss li b{flex:none;color:#1d2433}
.dm-iss li i{margin-left:auto;font-style:normal;color:#b42318;font-weight:600}
.tp-score .sc-row.skip .k,.tp-score .sc-row.skip b{color:#a3aaba}
.tp-score .sc-row.skip .bar{background:#f6f7fa}

/* --- 交前自检（第七十八轮） ---------------------------------------------
   与「扣分项」同一份数据，但换了目的：扣分项是判决书，自检是施工单。
   每条后面那行浅绿色的「改法」就是施工说明 —— 学生照着做就能把分拿回来。 */
.tp-score .sc-check{margin-top:10px;border-top:1px dashed var(--line);padding-top:8px}
.tp-score .sc-ch{display:flex;align-items:baseline;gap:8px;margin-bottom:2px}
.tp-score .sc-ch span{font-size:12px;font-weight:700;color:#1d2433}
.tp-score .sc-ch i{font-style:normal;font-size:11.5px;color:#8b93a7;margin-left:auto}
.tp-score .sc-check .sc-iss{border-top:0;margin-top:2px}
.tp-score .sc-iss li{flex-wrap:wrap;row-gap:3px}
.tp-score .sc-iss li em{flex-basis:100%;font-style:normal;font-size:11px;color:#0f6b4d;background:#f1faf5;border-left:2px solid #b6e3cd;border-radius:0 5px 5px 0;padding:2px 7px}
.tp-score .sc-iss li u{flex:none;text-decoration:none;font-size:10px;line-height:1.5;color:#6b4fd8;border:1px solid #ded6ff;background:#f6f3ff;border-radius:4px;padding:0 4px}
.tp-score .sc-more{font-size:11px;color:#98a0b3;margin-top:5px}
.tp-score .sc-check.ok .sc-ch i{color:#0f6b4d}
.dm-iss li em{flex-basis:100%;font-style:normal;font-size:11px;color:#0f6b4d;background:#f1faf5;border-left:2px solid #b6e3cd;border-radius:0 5px 5px 0;padding:2px 7px}
.dm-iss li u{flex:none;text-decoration:none;font-size:10px;color:#6b4fd8;border:1px solid #ded6ff;background:#f6f3ff;border-radius:4px;padding:0 4px}

/* --- 实训看板（第七十八轮） ---------------------------------------------
   矩阵回答「哪一步不会」，看板回答「该找谁」。两块并排在同一页，
   靠顶部的分段控件切换 —— 不另开一个菜单项，避免教师找不到。 */
.tp-tools{display:flex;align-items:center;gap:10px;flex-wrap:wrap;width:100%}
.tp-seg{display:inline-flex;border:1px solid var(--line);border-radius:8px;overflow:hidden;background:#fff}
.tp-seg button{border:0;background:#fff;padding:5px 14px;font-size:12.5px;color:#46506a;cursor:pointer}
.tp-seg button.on{background:#2f5bea;color:#fff}
.tp-board{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);gap:12px;margin-bottom:12px;align-items:start}
.tp-card{background:#fff;border:1px solid var(--line);border-radius:12px;padding:12px 14px;min-width:0}
.tp-card h4{margin:0 0 8px;font-size:13px;color:#1d2433;display:flex;align-items:baseline;gap:8px}
.tp-card h4 em{font-style:normal;font-size:11px;color:#98a0b3;font-weight:400}
.tp-radar{display:flex;justify-content:center;margin:-4px 0 2px}
.tp-radar svg{max-width:100%;height:auto}
.tp-card .tp-radar svg{max-width:330px}
.tp-empty-mini{font-size:11.5px;color:#98a0b3;padding:10px 2px}
.tp-ab{display:grid;grid-template-columns:96px 1fr 40px;align-items:center;gap:8px;margin-top:5px}
.tp-ab .n{font-size:11.5px;color:#46506a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-ab .b{height:5px;border-radius:3px;background:#eef1f7;overflow:hidden}
.tp-ab .b i{display:block;height:100%;border-radius:3px}
.tp-ab b{font-size:11.5px;text-align:right;color:#1d2433}
.tp-risk{margin:0;padding:0;list-style:none}
.tp-risk li{display:grid;grid-template-columns:22px 92px 34px 1fr auto;align-items:center;gap:7px;
  padding:6px 4px;border-bottom:1px dashed #eef1f7;cursor:pointer;font-size:12px}
.tp-risk li:hover{background:#f8faff}
.tp-risk .rk{width:20px;height:20px;border-radius:5px;display:flex;align-items:center;justify-content:center;
  font-size:10.5px;font-weight:700;color:#fff;background:#b6bccb}
.tp-risk .rk.high{background:#b42318}.tp-risk .rk.mid{background:#d98600}.tp-risk .rk.low{background:#5b6b8c}
.tp-risk .nm{color:#1d2433;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-risk .nm em{display:block;font-style:normal;font-size:10px;color:#98a0b3;font-weight:400}
.tp-risk .sc{font-family:var(--lx-num,ui-monospace);font-weight:700;color:#1d2433;text-align:right}
.tp-risk .rs{font-size:11px;color:#8b93a7;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-risk i{font-style:normal;font-size:11px;color:#2f5bea}
.tp-note{margin-top:8px;font-size:10.5px;color:#a3aaba;line-height:1.55}
.tp-bars{margin:0;padding:0;list-style:none}
.tp-bars li{display:grid;grid-template-columns:1fr 90px 38px;align-items:center;gap:8px;padding:4px 0;font-size:11.5px;cursor:default}
.tp-bars li[data-tp-sort]{cursor:pointer}
.tp-bars .n{color:#46506a;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-bars .b{height:5px;border-radius:3px;background:#eef1f7;overflow:hidden}
.tp-bars .b i{display:block;height:100%;border-radius:3px}
.tp-bars b{text-align:right;color:#1d2433;font-weight:600}
.tp-prof{display:grid;grid-template-columns:minmax(300px,.92fr) minmax(0,1.08fr);gap:16px}
.tp-prof h5{margin:12px 0 6px;font-size:12.5px;color:#46506a}
.tp-prof .l h5:first-child,.tp-prof .r h5:first-child{margin-top:0}
.tp-abt{width:100%;border-collapse:collapse;font-size:11.8px}
.tp-abt th,.tp-abt td{border-bottom:1px solid #f2f4f8;padding:4px 6px;text-align:left}
.tp-abt th{color:#8b93a7;font-weight:500;font-size:11px}
.tp-abt td.n{font-weight:700;text-align:right;width:44px}
.tp-abt td:first-child{white-space:nowrap}
.tp-abt .tp-mini-bar{min-width:72px}
.tp-abt td.n.bad{color:#b42318}
.tp-mini-bar{display:block;height:5px;border-radius:3px;background:#eef1f7;overflow:hidden;min-width:60px}
.tp-mini-bar i{display:block;height:100%;border-radius:3px}
.tp-mini-kpi{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px}
.tp-mini-kpi div{background:#f8fafd;border:1px solid #eef1f7;border-radius:8px;padding:6px 8px}
.tp-mini-kpi b{display:block;font-size:15px;color:#1d2433;font-family:var(--lx-num,ui-monospace);line-height:1.3}
.tp-mini-kpi span{font-size:10.5px;color:#8b93a7}
.tp-line{margin:8px 0 0;font-size:11.8px;color:#46506a;line-height:1.6}
.tp-adv{margin:4px 0 0;padding-left:16px;font-size:11.8px;color:#46506a;line-height:1.65}
.tp-adv li{margin-bottom:5px}
.tp-adv li b{color:#1d2433;margin-right:4px}
@media (max-width:1100px){
  .tp-board{grid-template-columns:minmax(0,1fr)}
  .tp-prof{grid-template-columns:minmax(0,1fr)}
  .tp-mini-kpi{grid-template-columns:repeat(3,minmax(0,1fr))}
}

/* 能力定位行：一行字回答「练这一步是为了哪样本事」 */
.tp-score .sc-ab{margin-top:8px;padding:6px 8px;border-radius:7px;background:#f7f9ff;border:1px solid #e8edfa;
  font-size:11.5px;color:#46506a;line-height:1.5}
.tp-score .sc-ab b{color:#2f5bea;font-size:13px;font-family:var(--lx-num,ui-monospace);margin:0 1px}

/* 生成交付物：主按钮旁给一个次要入口，避免学生以为「只能上传」 */
.tp-op-b .tp-enter.ghost{background:#fff;color:#46506a;border:1px solid var(--line);box-shadow:none}
.tp-op-b .tp-enter.ghost:hover{background:#f7f9fd;box-shadow:none;transform:none}
