/* ============================================================================
   页面级样式：总览 / 设置类表单 / 统计
   ============================================================================ */

/* ---------- 总览 ---------- */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin-bottom:14px}
.kpi{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:14px 16px;display:flex;flex-direction:column;gap:3px;
}
.kpi .k-l{font-size:12px;color:var(--ink3);font-weight:600}
.kpi .k-v{font-size:30px;font-weight:700;line-height:1.15;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.kpi .k-n{font-size:11.5px;color:var(--ink3)}
.kpi .k-n b{color:var(--brand);font-weight:600}

.card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:14px 16px;margin-bottom:12px;
}
.card-hd{display:flex;align-items:baseline;gap:9px;margin-bottom:11px;padding-bottom:9px;border-bottom:1px solid var(--line)}
.card-hd h2{font-size:14px;font-weight:700}
.card-hd .r{margin-left:auto;font-size:12px;color:var(--ink3);font-variant-numeric:tabular-nums}

/* 待办条：先回答「我现在该干什么」 */
.todo{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:12px 14px;margin-bottom:12px}
.todo-hd{display:flex;align-items:center;gap:9px;margin-bottom:10px}
.todo-hd b{font-size:13.5px}
.todo-hd .n{font-size:11.5px;font-weight:700;color:var(--warn);background:var(--warn-w);
  border:1px solid #e8d9b8;padding:1px 8px;border-radius:999px}
.todo-hd .r{margin-left:auto;font-size:12px;color:var(--ink3)}
.todo-items{display:flex;gap:9px;flex-wrap:wrap}
.todo-item{
  display:flex;align-items:center;gap:10px;padding:9px 12px;border-radius:var(--r-sm);
  border:1px solid var(--line2);background:var(--surface2);font-size:12.5px;color:var(--ink2);
  transition:border-color .12s var(--move),background .12s var(--move);
}
.todo-item:hover{border-color:var(--brand);background:var(--surface)}
.todo-item b{font-size:15px;font-weight:700;color:var(--warn);font-variant-numeric:tabular-nums}
.todo-item .go{font-size:12px;color:var(--brand);font-weight:600}
.todo-none{font-size:13px;color:var(--ink3);padding:4px 0}

/* 纯 CSS 柱状图：不引第三方图表库（本地应用也保持零依赖） */
.chart{display:flex;align-items:flex-end;gap:8px;height:130px;padding-top:8px}
.chart .bar{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;min-width:0}
.chart .bar i{
  width:100%;background:var(--brand);border-radius:3px 3px 0 0;min-height:3px;
  transition:height .3s var(--move);
}
.chart .bar span{font-size:10.5px;color:var(--ink3);white-space:nowrap}
.chart .bar em{font-size:10.5px;color:var(--ink2);font-style:normal;font-weight:600;font-variant-numeric:tabular-nums}

/* ---------- 总览 · 互动式趋势图（SVG，零依赖） ----------
   为什么整个图是一个固定 viewBox 而不是按容器宽度算坐标：
   柱子只要参与文档流，就会被「日期标签不许换行 + 卡片是 grid 子项」这两件事
   一起挤出容器（改版前实测：卡片横向溢出 230px，柱子高度被压到 3px）。
   放在 <svg> 里就与文档流无关，宽度只由卡片决定。 */
.ov-card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r);
  padding:14px 16px;margin-bottom:12px;min-width:0;
}
.split > .ov-card{margin-bottom:0}
.split{min-width:0}

.ov-range{display:flex;gap:2px;margin-left:auto;background:var(--surface3);border-radius:var(--r-sm);padding:2px}
.ov-seg{
  font-size:12px;line-height:1;padding:5px 10px;border-radius:4px;color:var(--ink2);
  font-variant-numeric:tabular-nums;transition:background .12s var(--move),color .12s var(--move);
}
.ov-seg:hover{color:var(--ink)}
.ov-seg[aria-pressed="true"]{background:var(--surface);color:var(--brand-ink);font-weight:700;box-shadow:var(--sh)}
.ov-seg[disabled]{opacity:.38;cursor:not-allowed}
.ov-seg[disabled]:hover{color:var(--ink2)}

.ov-plot{position:relative;width:100%;min-width:0}
.ov-svg{display:block;width:100%;height:220px;overflow:visible}
.ov-svg text{font-family:inherit;fill:var(--ink3)}

/* 网格线：浅色辅助，不与柱子抢注意力 */
.ov-grid{stroke:var(--line);stroke-width:1;shape-rendering:crispEdges}
.ov-axis{stroke:var(--line2)}
.ov-tick{font-size:11px;font-variant-numeric:tabular-nums}
.ov-xlbl{font-size:11px;font-variant-numeric:tabular-nums}

/* 柱子：命中区永远在，柱子本身负责视觉 */
.ov-hit{fill:transparent}
.ov-bar{cursor:pointer;outline:none}
.ov-col{transition:opacity .12s var(--move)}
.ov-bar:hover .ov-col,.ov-bar.is-on .ov-col{opacity:1}
.ov-plot[data-focus]:not([data-focus=""]) .ov-bar:not(.is-on) .ov-col{opacity:.32}
.ov-plot[data-focus]:not([data-focus=""]) .ov-bar:not(.is-on){opacity:.75}
.ov-bar:focus-visible .ov-col{stroke:var(--ink);stroke-width:1.4}
.ov-bar:focus-visible .ov-hit{fill:var(--brand-w);fill-opacity:.55}
.ov-bar.is-on .ov-hit{fill:var(--brand-w);fill-opacity:.5}

/* 图例：可点开关。关掉的项整条变淡并划一道，不用额外文案解释 */
.ov-legend{display:flex;flex-wrap:wrap;gap:4px 12px;margin-top:8px}
.ov-lg-btn{
  display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--ink2);
  padding:2px 4px;border-radius:4px;
}
.ov-lg-btn:hover{color:var(--ink);background:var(--surface2)}
.ov-lg-btn i{width:9px;height:9px;border-radius:2px;flex:0 0 auto}
.ov-lg-btn.off{color:var(--ink3);text-decoration:line-through}
.ov-lg-btn.off i{opacity:.3}

/* 浮层：跟随被悬停/聚焦的柱子 */
.ov-tip{
  position:absolute;z-index:5;min-width:132px;padding:7px 9px;border-radius:var(--r-sm);
  background:var(--surface);border:1px solid var(--line2);box-shadow:var(--sh-pop);
  font-size:12px;color:var(--ink2);pointer-events:none;
}
.ov-tip[hidden]{display:none}
.ov-tip-h{font-weight:700;color:var(--ink);margin-bottom:4px;font-variant-numeric:tabular-nums}
.ov-tip-r{display:flex;align-items:center;gap:6px;line-height:1.6;white-space:nowrap}
.ov-tip-r i{width:8px;height:8px;border-radius:2px;flex:0 0 auto}
.ov-tip-l{flex:1}
.ov-tip-r b{font-variant-numeric:tabular-nums;color:var(--ink)}
.ov-tip-p{min-width:38px;text-align:right;color:var(--ink3);font-variant-numeric:tabular-nums}

/* 图注：默认一行合计；选中某天时换成当天明细 */
.ov-caption{
  display:flex;flex-wrap:wrap;align-items:center;gap:4px 12px;margin-top:4px;
  font-size:12px;color:var(--ink3);
}
.ov-caption b{color:var(--ink2);font-variant-numeric:tabular-nums}
.ov-cp{display:inline-flex;align-items:center;gap:4px}
.ov-link{font-size:12px;color:var(--brand);font-weight:600;padding:0 2px;border-radius:3px}
.ov-link:hover{text-decoration:underline}

.ov-empty{
  padding:26px 10px;text-align:center;font-size:13px;color:var(--ink3);
  border:1px dashed var(--line);border-radius:var(--r-sm);background:var(--surface2);
}

/* 骨架：不写内联样式 */
.ov-skel-l{height:13px;width:60%}
.ov-skel-v{height:30px;margin-top:8px}
.ov-skel-chart{height:200px}

.split{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media (max-width:1000px){.split{grid-template-columns:1fr}}

/* ---------- 计划类页面（导入/排班/信标） ---------- */
.form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 16px}
.form-grid .full{grid-column:1/-1}
.form-f{display:flex;flex-direction:column;gap:6px;min-width:0}
.form-f > label{font-size:12.5px;font-weight:600;color:var(--ink2)}
.form-f .hint{font-size:11.5px;color:var(--ink3);line-height:1.6}
.form-f input,.form-f select,.form-f textarea{
  min-width:0;width:100%;height:34px;padding:0 10px;border-radius:var(--r-sm);
  border:1px solid var(--line2);background:var(--surface);font-size:13px;
}
/* ⚠️ 复选框/单选框必须豁免上面那条 width:100%;height:34px。
   不豁免的话，一个裸 checkbox 会被拉成 229px 宽、34px 高的色块，
   标签文字被挤到下一行 —— 两个页面作者的实测截图都撞到了这个。
   这是**全局控件的职责**，所以修在 CSS 里，页面里不该各自写内联样式兜。 */
.form-f input[type="checkbox"],
.form-f input[type="radio"]{
  width:auto;height:auto;min-width:0;padding:0;flex:0 0 auto;margin:0;
  accent-color:var(--brand);
}
/* 复选框/单选 + 文字：整体一行，文字不换行到下面 */
.form-f .opt{display:inline-flex;align-items:center;gap:8px;font-size:13px;color:var(--ink2);line-height:1.5}
.form-f .opt > input{flex:0 0 auto}
.form-f textarea{height:auto;min-height:88px;padding:9px 10px;line-height:1.6;resize:vertical}
.form-f input:focus,.form-f select:focus,.form-f textarea:focus{border-color:var(--brand);outline:none}
.form-acts{display:flex;gap:9px;flex-wrap:wrap;align-items:center;margin-top:14px}

/* 危险提示条：会写库的页面必须一眼可辨 */
.danger-bar{
  display:flex;gap:11px;align-items:flex-start;padding:13px 15px;margin-bottom:12px;
  border-radius:var(--r);background:var(--danger-w);border:1px solid #e6c6c1;
  font-size:13px;line-height:1.7;color:var(--ink2);
}
.danger-bar b{color:var(--danger)}
.danger-bar .ic{color:var(--danger);flex:0 0 auto;margin-top:1px}

/* 统计块 */
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px}
.stat{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:14px 16px}
.stat b{display:block;font-size:28px;font-weight:700;line-height:1.15;font-variant-numeric:tabular-nums}
.stat span{display:block;margin-top:5px;font-size:12.5px;color:var(--ink3)}

/* 占比条 */
.bar-row{display:flex;align-items:center;gap:10px;margin-bottom:8px;font-size:12.5px}
.bar-row .lab{flex:0 0 96px;color:var(--ink2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.bar-row .track{flex:1;height:9px;border-radius:999px;background:var(--surface3);overflow:hidden;min-width:60px}
.bar-row .track i{display:block;height:100%;border-radius:999px;background:var(--brand)}
.bar-row .val{flex:0 0 62px;text-align:right;font-variant-numeric:tabular-nums;color:var(--ink2)}

/* 只读只看的说明文字 */
.note{font-size:12px;color:var(--ink3);line-height:1.75}
.note b{color:var(--ink2)}

/* ---------- 固定列（考勤矩阵这类「行 = 人、列 = 场次」的宽表） ----------
   .tbl 的表头已经自带 position:sticky;top:0（见 03-components.css），
   但「学号 / 姓名」这类标识列还必须横向钉住 —— 否则横向滚到第 8 场就分不清是谁。
   为什么做成工具类而不是写在页面里：页面不许写内联样式（PAGE-CONTRACT 红线 1），
   而这类需求不止一页（考勤表、以后可能的成绩矩阵都会要）。
   ⚠️ 背景色必须显式给：td 默认透明，钉住的列会透出后面滚过去的内容。
      `.tbl tbody tr:hover td` 的优先级更高，悬停底色仍然正确。
   ⚠️ 分隔线用 border-right 而不是 box-shadow：border-collapse 下阴影会被裁掉，
      而 border 能跟着 sticky 一起走。 */
.tbl th.tbl-pin,.tbl td.tbl-pin{
  position:sticky;z-index:2;background:var(--surface);
  border-right:1px solid var(--line2);
}
.tbl th.tbl-pin{z-index:3;background:var(--surface2)}   /* 表头的固定列压在表头其它格之上 */
.tbl tbody tr:hover td.tbl-pin{background:var(--surface2)}
.tbl tfoot td.tbl-pin{background:var(--surface2)}
.tbl th.tbl-pin-1,.tbl td.tbl-pin-1{left:0}
/* 第二固定列的偏移写 96px：学号是 12 位定长数字，列宽稳定；
   即使换了字号略微变宽，也只会差几个像素，不会重叠到看不清。 */
.tbl th.tbl-pin-2,.tbl td.tbl-pin-2{left:96px}

/* ---------- 排班课程表网格（自动排班预览） ---------- */
.coursegrid{min-width:720px}
.coursegrid th:first-child,.coursegrid td:first-child{width:74px;background:var(--surface2);font-weight:700;color:var(--ink2);text-align:center}
.coursegrid th{text-align:center}
.coursegrid td{vertical-align:top;padding:8px}
.coursegrid .wkrow{background:var(--surface3);font-weight:700;color:var(--ink2);text-align:left;padding:7px 10px}
.coursegrid .pcol{text-align:center}
.cc{background:var(--brand-w);border:1px solid var(--brand-t);border-radius:var(--r-sm);padding:7px 8px;font-size:11.5px;line-height:1.45}
.cc+.cc{margin-top:6px}
.cc .ct{font-weight:700;color:var(--brand-ink);font-size:12px}
.cc .cs{color:var(--ink2);margin-top:3px}
.cc .asst{margin-top:5px;padding-top:5px;border-top:1px dashed var(--brand-t);color:var(--ink2)}
.cc.flag{border-color:var(--warn);background:var(--warn-w)}
.cc .badge{font-size:10px;padding:0 5px;border-radius:999px;height:16px;display:inline-flex;align-items:center;margin-left:4px}
.cc .badge.ok{background:#e7f3ed;color:#1f6b4a}
.cc .badge.warn{background:var(--warn-w);color:var(--warn);border:1px solid #efd9b0}
.pairmark{cursor:help;font-size:10px}
.spemark{display:inline-flex;align-items:center;justify-content:center;width:13px;height:13px;border-radius:50%;background:var(--danger);color:#fff;font-size:10px;font-weight:700;cursor:help;line-height:1;vertical-align:middle}

/* 可折叠卡片标题的箭头 */
.card-caret{margin-left:8px;color:var(--ink3);font-size:11px;transition:transform .2s var(--move,cubic-bezier(.2,.7,.3,1));display:inline-block}

/* ---------- 排班周次横向表格（自动排班·手动排班） ---------- */
.wkbar{
  display:flex;flex-wrap:wrap;gap:6px;padding:10px 11px;
  background:var(--surface2);border:1px solid var(--line);border-radius:var(--r-sm);
}
.wk-cell{
  min-width:52px;padding:5px 8px;border-radius:var(--r-sm);
  border:1px solid var(--line2);background:var(--surface);color:var(--ink2);
  display:flex;flex-direction:column;align-items:center;gap:1px;cursor:pointer;
  transition:background .12s var(--move,linear),border-color .12s var(--move,linear),color .12s var(--move,linear);
  font-family:inherit;
}
.wk-cell .wn{font-size:13px;font-weight:700;line-height:1.15;font-variant-numeric:tabular-nums}
.wk-cell .ws{font-size:10px;line-height:1.2;color:var(--ink3)}
.wk-cell:hover:not([disabled]){background:var(--brand-w);border-color:var(--brand-t);color:var(--brand-ink)}
.wk-cell:hover:not([disabled]) .ws{color:var(--brand-ink)}
/* 当前周：描边强调 */
.wk-cell.cur{border-color:var(--brand);border-width:2px;padding:4px 7px}
.wk-cell.cur .ws{color:var(--brand-ink);font-weight:600}
/* 已排周：灰底、打勾、不可点 */
.wk-cell.done{background:var(--surface3);border-color:var(--line);color:var(--ink3);cursor:not-allowed}
.wk-cell.done .wn{text-decoration:line-through;opacity:.75}
.wk-cell.done .ws{color:var(--ink3)}

/* 已过期且未排班：灰色、不可点（排了也没意义） */
.wk-cell.past{
  background:var(--surface3);
  border-color:var(--line);
  color:var(--ink3);
  opacity:.62;
  cursor:not-allowed;
}
.wk-cell.past .wn{color:var(--ink3);font-weight:600}
.wk-cell.past .ws{color:var(--ink3);opacity:.9}
/* 已排：可点击（查看该周课表），悬停给一点反馈 */
.wk-cell.done{cursor:pointer}
.wk-cell.done:hover{background:var(--brand-w);border-color:var(--brand-t)}
.wk-cell.done:hover .wn{opacity:1;text-decoration:none}
.wk-cell.done:hover .ws{color:var(--brand-ink)}

/* ---------- 排班课程表：可滚动 + 可缩放 + 可全屏 ---------- */
.grid-zoom{
  margin-top:10px;border:1px solid var(--line);border-radius:var(--r-sm);
  background:var(--surface);display:flex;flex-direction:column;
}
.grid-tools{
  display:flex;align-items:center;gap:6px;flex-wrap:wrap;
  padding:6px 8px;border-bottom:1px solid var(--line);background:var(--surface2);
  border-radius:var(--r-sm) var(--r-sm) 0 0;
}
.grid-tools .btn.sm{height:24px;padding:0 8px;font-size:12px}
.grid-scroll{
  overflow:auto;             /* 横向 + 纵向都能滚 */
  max-height:62vh;           /* 默认高度，点「全屏」后解除 */
  -webkit-overflow-scrolling:touch;
}
.grid-zoom.is-full{
  position:fixed;inset:0;z-index:200;margin:0;border-radius:0;
  border:0;background:var(--surface);
}
.grid-zoom.is-full .grid-scroll{max-height:none;flex:1;height:auto}
.grid-zoom.is-full .grid-tools{border-radius:0}
/* 缩放在 .grid-scroll 内部对表格生效 */
.grid-scroll > table{transform-origin:top left}
.coursegrid{min-width:820px}     /* 保证 5 天列不被挤扁，超出就横向滚动 */

/* ============================================================
   问题反馈页（2026-10-28）
   管理端「运维 → 问题反馈」用；按班级分组，每条显示提交人身份。
   ============================================================ */
.fb-group { margin-bottom: 16px; }
.fb-item {
  padding: 14px 0;
  border-top: 1px solid var(--line, #EDF1F3);
}
.fb-item:first-of-type { border-top: 0; }

.fb-row1 {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.fb-who { font-size: 14px; font-weight: 600; color: var(--ink, #111); }
.fb-role {
  font-size: 11px;
  font-weight: 500;
  color: var(--muted, #696969);
  background: #F3F6F8;
  border-radius: 999px;
  padding: 1px 7px;
  margin-left: 2px;
}
.fb-time { margin-left: auto; font-size: 12px; color: var(--muted, #696969); font-variant-numeric: tabular-nums; }

/* 提交人身份行：年级·专业·班号 / 学号 / 班级全称 */
.fb-identity {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}
.fb-id-chip {
  font-size: 12px;
  color: #1A7A62;
  background: #EAF7F1;
  border-radius: 6px;
  padding: 2px 8px;
  line-height: 1.6;
}
.fb-id-chip.mono { font-variant-numeric: tabular-nums; }

.fb-content {
  margin-top: 9px;
  font-size: 14px;
  color: var(--ink, #111);
  line-height: 1.65;
  white-space: pre-wrap;
  word-break: break-word;
}
.fb-row2 {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 11px;
  flex-wrap: wrap;
}
.fb-phone { font-size: 13px; color: var(--muted, #696969); }
.fb-phone a { color: #1A7A62; text-decoration: none; }
.fb-phone a:hover { text-decoration: underline; }
/* ============================================================
   学习内容管理页（2026-10-28）
   ============================================================ */
.lm-seg {
  border: 1px solid var(--line, #EDF1F3);
  border-radius: 10px;
  padding: 12px 14px;
  margin-bottom: 12px;
  background: #FCFDFD;
}
.lm-seg-hd {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 10px;
}
.lm-seg-no {
  font-size: 12px;
  font-weight: 700;
  color: var(--muted, #696969);
  margin-right: auto;
}
.lm-seg .form-f { margin-bottom: 10px; }
.lm-seg .form-f:last-child { margin-bottom: 0; }
.lm-seg textarea.fld { resize: vertical; min-height: 84px; font-family: inherit; }

.lm-img-row {
  display: flex;
  gap: 8px;
  align-items: center;
}
.lm-img-row .fld { flex: 1; }

/* ★ 2026-10-30 修复「管理端预览与小程序显示不一致」：
   原来 max-width:220px / max-height:140px + object-fit:cover 会**裁切**图片（1.57:1），
   而小程序端是按 16:9 完整显示 → 管理员看到的构图和学生看到的不一样。
   现在改成 16:9 容器 + contain（完整显示不裁切），与小程序完全一致。 */
.lm-preview {
  display: block;
  width: 100%;
  max-width: 360px;
  aspect-ratio: 16 / 9;
  margin-top: 8px;
  border-radius: 8px;
  border: 1px solid #EDF1F3;
  background: #F5F8F9;
  object-fit: contain;
}

.tag.off { background: #F3F6F8; color: #98A5B0; }
.tag.vz { background: #EEF4FC; color: #3B7CBF; }
/* ============================================================
   图片选择器 / 裁剪器 / 素材库（2026-10-28）
   ============================================================ */

/* ---------- 裁剪（2026-10-30 升级：左侧拖动裁剪 + 右侧实时预览） ---------- */
.crop-wrap { padding: 4px 0; }
.crop-main { display: flex; gap: 16px; align-items: flex-start; flex-wrap: wrap; }
.crop-stage {
  position: relative;
  flex: 0 0 auto;
  background: #2a2f35;
  border-radius: 8px;
  overflow: hidden;
  user-select: none;
  touch-action: none;
}
.crop-img { display: block; max-width: none; pointer-events: none; }
.crop-box {
  position: absolute;
  border: 2px solid #2BB89A;
  box-shadow: 0 0 0 9999px rgba(0,0,0,.45);
  cursor: move;
  box-sizing: border-box;
}
/* 四角把手 */
.crop-h {
  position: absolute;
  width: 14px; height: 14px;
  background: #fff;
  border: 2px solid #2BB89A;
  border-radius: 3px;
  z-index: 2;
}
.crop-h[data-d="nw"] { left: -8px; top: -8px; cursor: nwse-resize; }
.crop-h[data-d="ne"] { right: -8px; top: -8px; cursor: nesw-resize; }
.crop-h[data-d="sw"] { left: -8px; bottom: -8px; cursor: nesw-resize; }
.crop-h[data-d="se"] { right: -8px; bottom: -8px; cursor: nwse-resize; }
/* 四边把手 */
.crop-e { position: absolute; background: #2BB89A; border-radius: 3px; z-index: 2; }
.crop-e[data-d="n"] { left: 50%; top: -6px; width: 34px; height: 6px; margin-left: -17px; cursor: ns-resize; }
.crop-e[data-d="s"] { left: 50%; bottom: -6px; width: 34px; height: 6px; margin-left: -17px; cursor: ns-resize; }
.crop-e[data-d="w"] { top: 50%; left: -6px; width: 6px; height: 34px; margin-top: -17px; cursor: ew-resize; }
.crop-e[data-d="e"] { top: 50%; right: -6px; width: 6px; height: 34px; margin-top: -17px; cursor: ew-resize; }

/* 右侧预览 */
.crop-side { flex: 1 1 200px; min-width: 200px; }
.crop-side-label { font-size: 12px; color: #696969; margin-bottom: 8px; font-weight: 600; }
.crop-prev-box {
  background: #F5F8F9; border: 1px solid #E7EDF1; border-radius: 8px;
  padding: 8px; display: flex; align-items: center; justify-content: center;
  min-height: 80px;
}
.crop-prev-clip {
  position: relative; overflow: hidden; border-radius: 4px; background: #fff;
  box-shadow: 0 0 0 1px #EEF2F4 inset;
}
.crop-prev-img { position: absolute; display: block; max-width: none; }
.crop-ratios { display: flex; gap: 6px; margin-top: 10px; flex-wrap: wrap; }
.crop-ratios button {
  border: 1px solid #E7EDF1; background: #fff; color: #5c6b73;
  padding: 5px 12px; border-radius: 999px; font-size: 12px; cursor: pointer; font-family: inherit;
}
.crop-ratios button.on { background: #2BB89A; border-color: #2BB89A; color: #fff; font-weight: 600; }
.crop-size { margin-top: 10px; font-size: 12px; color: #1A7A62; font-weight: 600; }
.crop-tips { margin-top: 12px; font-size: 12px; color: #696969; line-height: 1.6; text-align: center; }

/* ---------- 选择器 ---------- */
.picker-tabs { display: flex; gap: 6px; margin-bottom: 14px; border-bottom: 1px solid #EDF1F3; }
.pk-tab {
  border: 0; background: transparent; padding: 8px 14px; font-size: 13px; font-weight: 600;
  color: var(--muted, #696969); cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.pk-tab.on { color: #1A7A62; border-bottom-color: #2BB89A; }

.pk-hint { font-size: 12px; color: var(--muted, #696969); margin-top: 8px; line-height: 1.6; }
.pk-preview { margin-top: 12px; }
.pk-prev-card { display: flex; align-items: center; gap: 12px; padding: 10px; border: 1px solid #EDF1F3; border-radius: 10px; }
.pk-prev-card img { width: 88px; height: 88px; object-fit: cover; border-radius: 8px; flex: 0 0 auto; }
.pk-prev-info { flex: 1; display: flex; flex-direction: column; gap: 3px; font-size: 12px; color: var(--ink, #111); }

/* ---------- 素材库 ---------- */
.pk-lib-bar { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; }
.pk-lib-bar .fld { flex: 1; }
.pk-lib-stat { font-size: 12px; color: var(--muted, #696969); margin-bottom: 10px; }
.pk-lib-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 10px;
  max-height: 380px;
  overflow-y: auto;
  padding: 2px;
}
.pk-asset {
  border: 1px solid #EDF1F3;
  border-radius: 10px;
  padding: 8px;
  background: #fff;
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.pk-asset img { width: 100%; height: 92px; object-fit: cover; border-radius: 6px; background: #F5F7F8; }
.pk-asset-name {
  font-size: 12px; font-weight: 600; color: var(--ink, #111);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pk-asset-meta { font-size: 11px; color: var(--muted, #696969); }
.pk-asset-acts { display: flex; gap: 6px; margin-top: 2px; }
.btn.xs { font-size: 11px; padding: 3px 9px; border-radius: 6px; }
.pk-asset-acts .btn { flex: 1; }
/* ============================================================
   权限管理页（2026-10-30）
   ============================================================ */
.pm-tabs { display: flex; gap: 8px; margin-bottom: 14px; }
.pm-tab {
  border: 1px solid #E7EDF1; background: #fff; color: #5c6b73;
  padding: 9px 22px; border-radius: 999px; font-size: 13px; font-weight: 600; cursor: pointer;
  font-family: inherit;
}
.pm-tab.on { background: #2BB89A; border-color: #2BB89A; color: #fff; }

.pm-toolbar { display: flex; align-items: center; gap: 14px; margin-bottom: 10px; }
.pm-allsel { font-size: 12.5px; color: #333; display: flex; align-items: center; gap: 7px; cursor: pointer; }

.pm-tbl td { vertical-align: middle; }
.pm-check { text-align: center; }
.pm-row-on { background: #F0FBF6; }
.pm-tag { font-size: 11.5px; padding: 3px 10px; border-radius: 999px; background: #EEF4FC; color: #2F6FBF; font-weight: 600; }
.pm-tag-def { background: #F1F4F6; color: #69767F; }
.pm-tag-none { background: #FDECE6; color: #C0392B; }

.pm-panel { margin-top: 16px; }
.pm-perms {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 10px; margin: 6px 0 4px;
}
.pm-perm {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 12px; border: 1px solid #E7EDF1; border-radius: 10px; background: #FBFCFD; cursor: pointer;
}
.pm-perm:hover { background: #F4FBF8; }
.pm-perm input { margin-top: 2px; }
.pm-perm-main { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.pm-perm-main b { font-size: 13px; color: #111; font-weight: 600; }
.pm-perm-main .muted { font-size: 11.5px; line-height: 1.45; }

.pm-actions { display: flex; align-items: center; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
/* ===== 首页轮播管理（2026-10-31） ===== */
.bn-list { display: flex; flex-direction: column; gap: 10px; }
.bn-card { display: flex; gap: 12px; align-items: center; border: 1px solid #EDF1F3; border-radius: 10px; padding: 10px; background: #FBFCFD; }
.bn-thumb { width: 132px; height: 74px; border-radius: 8px; overflow: hidden; background: #F1F4F6; display: flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.bn-thumb img { width: 100%; height: 100%; object-fit: cover; }
.bn-main { flex: 1; min-width: 0; }
.bn-line1 { display: flex; align-items: center; gap: 8px; font-size: 13.5px; }
.bn-type { font-size: 11px; padding: 2px 8px; border-radius: 999px; background: #EAF9F3; color: #1A7A62; font-weight: 600; }
.bn-off { font-size: 11px; color: #C0392B; }
.bn-line2 { font-size: 11.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bn-ops { display: flex; gap: 5px; flex: 0 0 auto; }
.bn-prev { display: block; margin-top: 8px; width: 100%; max-width: 360px; aspect-ratio: 16/9; object-fit: contain; background: #F5F8F9; border: 1px solid #EDF1F3; border-radius: 8px; }

/* ===== 学习内容（分类）管理（2026-10-31） ===== */
.li-tabs { display: flex; gap: 8px; margin: 4px 0 12px; }
.li-tab { border: 1px solid #E7EDF1; background: #fff; color: #5c6b73; padding: 8px 20px; border-radius: 999px; font-size: 13px; font-weight: 600; cursor: pointer; font-family: inherit; }
.li-tab.on { background: #2BB89A; border-color: #2BB89A; color: #fff; }
.li-cover { width: 84px; height: 48px; object-fit: cover; border-radius: 6px; border: 1px solid #EDF1F3; }
/* 系统默认轮播（2026-10-31） */
.bn-defaults { margin-top: 14px; border: 1px dashed #D8E2E8; border-radius: 10px; padding: 10px 12px; background: #FAFCFD; }
.bn-defhead { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; font-size: 13px; }
.bn-defhead .muted { font-size: 11.5px; }
.bn-defrow { display: flex; align-items: center; justify-content: space-between; padding: 7px 4px; border-bottom: 1px solid #F0F4F6; font-size: 13px; }
.bn-defrow:last-child { border-bottom: none; }
.bn-defname { font-weight: 600; color: #111; }
.bn-builtin { font-size: 11px; color: #69767F; background: #EEF1F4; padding: 4px 6px; border-radius: 4px; }
/* ===== 文章编辑器（2026-10-31） ===== */
.li-cat-sel { font-size: 12px; padding: 4px 6px; border: 1px solid #E7EDF1; border-radius: 6px; background: #fff; color: #333; font-family: inherit; margin-right: 6px; }
.ae-wrap { max-height: 62vh; overflow-y: auto; padding-right: 4px; }
.ae-title { width: 100%; border: 0; border-bottom: 2px solid #EEF3F6; font-size: 22px; font-weight: 800; color: #111; padding: 8px 2px 12px; outline: none; font-family: inherit; }
.ae-title::placeholder { color: #B6C2CC; font-weight: 600; }
.ae-meta { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; margin: 12px 0; font-size: 12.5px; color: #5c6b73; }
.ae-sel, .ae-num { font-size: 12.5px; padding: 5px 8px; border: 1px solid #E7EDF1; border-radius: 6px; background: #fff; color: #333; font-family: inherit; margin-left: 4px; }
.ae-num { width: 64px; }
.ae-cover { margin: 8px 0 16px; }
.ae-cover img { display: block; width: 100%; max-height: 240px; object-fit: contain; background: #F5F8F9; border: 1px solid #EDF1F3; border-radius: 10px; }
.ae-cover-add { width: 100%; padding: 22px; border: 2px dashed #D8E2E8; border-radius: 10px; background: #FAFCFD; color: #69767F; font-size: 13px; cursor: pointer; font-family: inherit; }
.ae-cover-ops { margin-top: 8px; }
.ae-sec-label { font-size: 12px; font-weight: 700; color: #8a97a3; letter-spacing: 1px; margin: 18px 0 8px; }
.ae-block { border: 1px solid #EDF1F3; border-radius: 10px; padding: 12px; margin-bottom: 10px; background: #FCFDFE; }
.ae-block-bar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.ae-block-no { font-size: 11.5px; color: #8a97a3; font-weight: 600; }
.ae-block-ops { display: flex; gap: 5px; }
.ae-op { font-size: 12px; padding: 3px 9px; border: 1px solid #E7EDF1; background: #fff; border-radius: 6px; color: #5c6b73; cursor: pointer; font-family: inherit; }
.ae-op:disabled { opacity: .35; }
.ae-op-del { color: #C0392B; border-color: #F3D9D9; }
.ae-h { width: 100%; border: 0; background: transparent; font-size: 16px; font-weight: 700; color: #111; padding: 4px 2px 8px; outline: none; font-family: inherit; }
.ae-h::placeholder { color: #B6C2CC; font-weight: 500; }
.ae-p { width: 100%; border: 0; background: transparent; font-size: 14px; line-height: 1.8; color: #333; padding: 4px 2px; outline: none; resize: vertical; font-family: inherit; }
.ae-p::placeholder { color: #B6C2CC; }
.ae-img { margin-top: 8px; }
.ae-img-add { font-size: 12.5px; padding: 8px 12px; border: 1px dashed #D8E2E8; border-radius: 8px; background: #fff; color: #69767F; cursor: pointer; font-family: inherit; }
.ae-img-prev { position: relative; display: inline-block; }
.ae-img-prev img { display: block; max-width: 320px; max-height: 180px; border-radius: 8px; border: 1px solid #EDF1F3; }
.ae-img-del { margin-top: 6px; font-size: 11.5px; padding: 3px 10px; border: 1px solid #F3D9D9; background: #fff; color: #C0392B; border-radius: 6px; cursor: pointer; font-family: inherit; }
.ae-addseg { width: 100%; padding: 12px; border: 2px dashed #D8E2E8; border-radius: 10px; background: #FAFCFD; color: #1A7A62; font-size: 13px; font-weight: 600; cursor: pointer; font-family: inherit; margin-bottom: 6px; }
.ae-video { display: flex; flex-direction: column; gap: 8px; }
.ae-inline { width: 100%; padding: 9px 11px; border: 1px solid #E7EDF1; border-radius: 8px; font-size: 13px; color: #111; font-family: inherit; }
.ae-empty { color: #8a97a3; font-size: 13px; padding: 16px 0; text-align: center; }
/* 栏目管理（2026-10-31） */
.cm-list { display: flex; flex-direction: column; gap: 8px; }
.cm-row { display: flex; align-items: center; gap: 8px; }
.cm-row .cm-name { flex: 1; max-width: 240px; }
.cm-tag { font-size: 11px; color: #1A7A62; background: #EAF9F3; padding: 3px 8px; border-radius: 999px; }