/* ============================================================================
   student.css —— 网页版「学生操作台」（pages/student.html）

   ★★ 两条铁规矩（2026-10-13 按用户反馈重写，之前在这里栽过跟头）：
      ① **一个颜色都不写死**，全部用站点的设计变量
         （fluent.css 的 :root 里那套 --bg-* / --fg-* / --stroke-* / --brand-*）。
         为什么：站点**自带深色主题** —— 它在 @media (prefers-color-scheme: dark)
         里把整套变量换成深色。所以只要我用变量，浅色/深色就自动都对；
         一旦写死 #fff / #222，用户的系统是深色时就变成
         "深底 + 深字 / 浅底 + 浅字"，糊成一片（2026-10-13 用户看到的正是这个）。
      ② **不自己搞主题开关**。主题跟着系统走，与网站其它页面完全一致；
         设置页里那两行只是说明，不是开关。

   ★ 类名统一带 stu- 前缀：全站共用 fluent.css，取前缀名最不容易撞上。
   ============================================================================ */

/* ---- 六屏切换：同一时刻只显示一屏（其余带 hidden 属性）----
   ★ 显式写 [hidden] 的规则：元素上同时有 .stu-view 的 display 时，
     浏览器默认那条 [hidden]{display:none} 会被更具体的规则压掉。 */
/* ★★ 页面底色自己兜住（**只在这一页**，不动全站样式表 fluent.css）：
   站点的整页底色是一个**写死的浅色渐变**（body::before，fixed 铺满视口、z-index:-2），
   它不跟深色变量走；而这一页的元素全部跟变量 ——
   于是深色系统下就成了"深色表格漂在浅色页面上"（2026-10-13 用户截图）。
   这里在本页范围内把底色按变量盖住；**浅色模式下一个像素都不变**。
   ★ 顶栏（.nav）在站点里是 rgba(252,253,255,.72) + !important 写死的浅色，
     要改它必须动 fluent.css（全站生效）—— 所以这里先不动，保持站点统一外观；
     你哪天说要改，我再动那一个文件。 */
html.stu-root, html.stu-root body { background: var(--bg-1); }

@media (prefers-color-scheme: dark) {
    html.stu-root body::before {
        background:
            radial-gradient(58% 44% at 8% 0%, rgba(15, 108, 189, .20) 0%, rgba(15, 108, 189, 0) 60%),
            linear-gradient(168deg, #1B1B1B 0%, #1F1F1F 46%, #232323 100%);
    }
}

/* ★★ 这一页必须**铺满屏幕、并且居中**（用户 2026-10-13 反馈：
     "布局排列占不满屏幕，右侧一个大空白，也不居中"）。
   原因（两条规则打架，别再把它们拆开看）：
     fluent.css 里的 .legal 是**文档页**用的：max-width: 820px + **margin: 0**
       —— 它故意左对齐，好让正文与页眉的 logo 对齐（那是文章页的要求）；
     student.css 里的 .stu-main 只改了 max-width。
     → 两者"特异度"相同，student.css 后加载所以 max-width 生效，
       但 .legal 的 **margin: 0** 原样留着 → 宽屏上正文被卡在 1500 宽、还贴在左边。
   这里把两件事都写全：**给一个足够宽的上下限 + 左右 auto 居中**。
     上限 2200：1920 及以下的屏幕就是完全铺满；再宽的屏幕（2K/带鱼屏）
     左右对称留白，而不是一边一条大空白。 */
.stu-main {
    max-width: 2200px;
    margin-left: auto;
    margin-right: auto;
}
.stu-view[hidden] { display: none; }

/* 首页：纵向排版（卡片行 → 两个圆按钮 → 底部信息）
   ★ 这里**故意不写 min-height: 100vh** —— 卡片行的高度已经按屏幕高度给了
     （见下面的 .stu-cards），再强行拉满，"内容少"时就又是一块空白。 */
#view-home { display: flex; flex-direction: column; }

/* ★ "文字型"几屏（缘由记录 / 每日整理 / 个人中心 / 设置）**不要跟着铺满 2200** ——
   容器放宽是为了首页那张宽表和量化表；这几屏是列表和表单，
   一行拉太宽反而不好读。给它们一个舒服的阅读宽度。
   （量化表 #view-sheets 不在此列：它列最多，越宽越少横向滚动。） */
#view-reasons, #view-daily, #view-profile, #view-settings { max-width: 980px; }

/* ★★ [hidden] 必须**真的**隐藏。
   原因：站点的 .btn 带 display: inline-flex，而**作者样式会盖过浏览器默认的
   [hidden] { display: none }** —— 于是 hidden 属性形同虚设。
   2026-10-13 用户截图里"表格已经显示出来了、左下角的『重新读取』还露着"就是这个。
   （!important 在这里是合适的：hidden 的元素本来就永远不该显示。） */
.stu-main [hidden] { display: none !important; }

/* ---- 通用小件 ---- */
.stu-ico { width: 24px; height: 24px; display: block; }
.stu-ico--big { width: 56px; height: 56px; }

.stu-msg { margin: 6px 0 10px; color: var(--fg-2); }
.stu-msg:empty { display: none; }
.stu-msg.msg--err { color: #C42B1C; }        /* 语义色：出错（浅深两色下都醒目） */
.stu-msg.msg--ok { color: #107C41; }

.stu-note {
    margin-left: 8px; font-size: .85em; color: var(--fg-3);
    border: 1px solid var(--stroke-2); border-radius: var(--radius-md); padding: 1px 6px;
}
.stu-empty { color: var(--fg-3); padding: 12px; text-align: center; }
.stu-empty[hidden] { display: none; }

/* ============================================================
   ① 首页
   ============================================================ */

/* 左上角：头像 + 账号名 */
.stu-account { display: flex; align-items: center; gap: 12px; margin: 6px 0 14px; }
.stu-avatar {
    width: 60px; height: 60px; padding: 0; border-radius: 30px; cursor: pointer;
    background: var(--bg-1); border: 1px solid var(--stroke-2);
    color: var(--fg-1);
    display: flex; align-items: center; justify-content: center;
}
.stu-avatar:hover { background: var(--bg-3); }
.stu-account__name {
    display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
    background: transparent; border: 0; cursor: pointer; font: inherit; padding: 4px 8px;
}
.stu-account__title { font-weight: 600; color: var(--fg-1); }
.stu-account__hint { font-size: .85em; color: var(--fg-3); }

/* 中段：左 = 消息中心，右 = 班级数据（只读表）
   ★★ 两块卡必须**等宽等高**（用户反馈"消息和班级数据面板大小不一"）：
      ① 列宽写 minmax(0, 1fr) 而不是 1fr —— 单个 1fr 的最小值是 auto，
         里面那张表格撑不下时会**把本列顶宽**，两块卡就不再等宽了（2026-10-13 修）；
      ② 高度交给栅格默认的 align-items: stretch，两张卡自然一样高；
      ③ 卡片内部各有自己的滚动区（消息列表 / 表格），并给同一个高度上限，
         这样两边"可视高度"也一致，不会一边长一边空。 */
.stu-cards {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
    align-items: stretch;
    /* ★★ 高度**跟着屏幕走**（用户 2026-10-13 反馈"占不满屏幕"）：
         高屏就把卡片撑高（表格能多显示几行），矮屏自动收一档；
         上下各夹一层，避免过矮（一体机 768）或过高（大屏 1440）。
         注意是**确定高度**而不是 min/max —— 有了它，卡片内部那两个滚动区
         才不会因为内容多寡把整页顶高/压塌。 */
    height: clamp(260px, 58vh, 620px);
}
@media (max-width: 900px) {
    /* 竖排（窄屏）：两块卡上下叠，高度回到自然值 + 下限，
       否则两块卡会被那个确定高度各挤成一半。 */
    .stu-cards { grid-template-columns: minmax(0, 1fr); height: auto; }
    .stu-card { min-height: 240px; }
}

.stu-card {
    background: var(--bg-1); border: 1px solid var(--stroke-2);
    border-radius: var(--radius-xl); padding: 12px 14px;
    display: flex; flex-direction: column;
    /* ★★ 防复发（2026-10-13）：栅格项 / 弹性项的 min-width 默认是 auto
         = **内容最小尺寸**，里面那张宽表会把它顶大 →
         在换成 minmax(0, 1fr) 之前，就表现为"两块卡宽度不一样"。
         这里显式写 0，**双保险**：即使将来列宽写法被人改回去，
         卡片也只会让内部滚动，而不会再把两列撑成一大一小。 */
    min-width: 0;
    /* ★ 高度**不在这里定**：由上面 .stu-cards 那一行的确定高度给定，
         卡片靠栅格默认的 stretch 拉平 → 两块严格等高（窄屏叠放时另给下限）。 */
    min-height: 0;
}
.stu-card__head {
    display: flex; align-items: center; gap: 8px; row-gap: 4px; flex-wrap: wrap;
    min-height: 32px;
    border-bottom: 1px solid var(--stroke-subtle); padding-bottom: 8px; margin-bottom: 8px;
}
.stu-card__title { font-weight: 600; color: var(--fg-1); }
.stu-card .stu-note { white-space: nowrap; }

/* 「桌面悬浮窗」那一组（开关是自绘的小滑块） */
.stu-dock { margin-left: auto; display: flex; align-items: center; gap: 6px; }
.stu-dock__label { font-size: .82em; color: var(--fg-3); }
.stu-dock__label--gap { margin-left: 8px; }
.stu-switch {
    width: 38px; height: 20px; border-radius: 10px; border: 1px solid var(--stroke-2);
    background: var(--bg-3); position: relative; cursor: pointer; padding: 0;
}
.stu-switch::after {
    content: ""; position: absolute; top: 1px; left: 1px; width: 16px; height: 16px;
    border-radius: 50%; background: var(--bg-1); border: 1px solid var(--stroke-2);
    transition: left .12s;
}
.stu-switch[aria-pressed="true"] { background: var(--brand-60); border-color: var(--brand-60); }
.stu-switch[aria-pressed="true"]::after { left: 19px; }

/* 消息条目：时间 + 「老师端 / 学生端」小标签 + 学生 + 加减 + 缘由
   ★ 列表在卡片里**撑满剩余空间**（flex: 1），高度上限与右边那张表一致（40vh）——
     两边可视高度一样，卡片等高时才不会一边满一边空。 */
.stu-msglist {
    /* ★ 撑满卡片的剩余空间（不再自己写 max-height：高度统一由卡片控制，
         否则会出现"卡片很高、列表只有半截"——最后一条被拦腰裁掉，很难看）。
       min-height: 0 是让 flex 子项**允许被压缩**，否则内容多时它会把卡片顶高。 */
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    padding-right: 4px;          /* 离滚动条远一点，不然最后几个字会被压住 */
}
.stu-msg-item { padding: 6px 4px; border-bottom: 1px solid var(--stroke-subtle); }
.stu-msg-item:last-child { border-bottom: 0; }
.stu-msg-line1 { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.stu-msg-at { color: var(--fg-3); font-size: .9em; }
.stu-msg-side {
    font-size: .82em; color: var(--fg-3); border: 1px solid var(--stroke-2);
    border-radius: var(--radius-md); padding: 0 6px;
}
.stu-msg-student { font-weight: 600; color: var(--fg-1); }
.stu-msg-delta { color: var(--fg-3); font-size: .92em; }
.stu-msg-reason { color: var(--fg-2); }

/* 两个圆按钮
   ★ 尺寸与间距收紧了：原来 150px 圆 + 110px 间距，整页被顶得很高，
     教室一体机（1366×768 这类）要滚动才能看全 —— 用户反馈的"显示不完整"。
     现在 132px + 间距 72px，短屏幕（高度 ≤820）再收一档。 */
.stu-hub {
    display: flex; justify-content: center; gap: 72px; margin: 16px 0 10px; flex-wrap: wrap;
}
.stu-hub__item { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.stu-circle {
    width: 132px; height: 132px; border-radius: 50%; padding: 0; cursor: pointer;
    background: var(--brand-60); border: 1px solid var(--brand-60);
    color: var(--fg-on-brand);
    display: flex; align-items: center; justify-content: center;
}
.stu-circle:hover { background: var(--brand-70); }
.stu-hub__label { font-size: 1rem; color: var(--fg-1); }

/* 屏幕不高（一体机常见 768）时：圆按钮、留白、卡片高度上限都再收一档，
   保证整页一屏看得完（不是靠裁掉内容，而是把上限整体下调）。 */
@media (max-height: 820px) {
    .stu-circle { width: 112px; height: 112px; }
    .stu-circle .stu-ico--big { width: 44px; height: 44px; }
    .stu-hub { gap: 56px; margin: 12px 0 8px; }
    .stu-account { margin: 2px 0 10px; }
    .stu-account .stu-avatar { width: 52px; height: 52px; }
    /* 卡片行高度也跟着收一档（矮屏上限 46vh），保证圆按钮与底部信息仍在屏内 */
    .stu-cards { height: clamp(240px, 46vh, 520px); }
}

.stu-legal {
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    color: var(--fg-3); font-size: .78em; text-align: center; margin: 10px 0 4px;
}

/* ============================================================
   ② 量化表：工具条 + 表格 + 撤销 + 详情
   ============================================================ */

.stu-toolbar {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 6px 0 12px;
}
.stu-toolbar__right { margin-left: auto; }
.stu-toolbar__title { font-weight: 600; color: var(--fg-1); }
.stu-toolbar__sub { color: var(--fg-3); font-size: .9em; }

/* ★ 找人框：一体机上要按得准，做大一点 */
.stu-find { width: 270px; min-height: 44px; font-size: 1rem; }

/* 撤销条：加减分之后 10 秒内出现（与桌面端同一个窗口） */
.stu-undo {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    background: var(--brand-100); border: 1px solid var(--stroke-2);
    border-radius: var(--radius-lg); padding: 10px 12px; margin-bottom: 12px;
}
.stu-undo[hidden] { display: none; }
.stu-undo__text { color: var(--fg-2); }

/* ---- 表格 ----
   ★★ 自适应（2026-10-13 按用户要求"随窗口、始终显示完整"）：
        · 列宽由 JS 给成 `minmax(最小, 权重fr)` —— 宽屏按权重分富余、窄屏收到最小值，
          所以正常情况下**每一列都看得见**，不会把最后一列挤到屏幕外；
        · 栅格铺满容器（width:100%），不再用 min-width:max-content：
          那个写法会把表格撑到"内容最小宽度"，窄窗口只能横着滚；
        · 窗口真的窄到 Σ最小值 都放不下时，这里仍然保留滚动兜底（不至于看不全）。
   ★ 行/表头都是同一个栅格，列宽由 JS 通过 CSSOM 设（不写 style 属性 —— CSP 拦后者）。 */
.stu-tablewrap {
    overflow: auto;
    /* 竖向高度跟着窗口走（不再写死 62vh）：窗口高就多显示几行，矮就少几行，
       但**永远留出工具栏/提示的位置**，不会把内容顶出去。 */
    max-height: calc(100vh - 250px);
    min-height: 200px;
    border: 1px solid var(--stroke-2); border-radius: var(--radius-lg);
}
.stu-hgrid { display: grid; align-items: stretch; width: 100%; }

/* ★★ 首页那张表在**卡片里**（不是整屏页），高度规则要另算：
      上面那条 max-height: calc(100vh - 250px) 是给量化表整屏用的，
      照搬到卡片里会把卡片顶得很高、下面留一大片空白。
      这里让它**撑满卡片剩余空间**（flex: 1），高度统一由卡片控制 →
      两张卡等高、表格框正好铺满，不会出现"卡片下半空白"。
      ★ 保留边框圆角：它标出"表格区域到哪儿为止"，
        比把框去掉、让空白漫在卡片里干净得多（2026-10-13 试过去掉，反而更乱）。 */
.stu-card .stu-tablewrap {
    flex: 1 1 auto;
    min-height: 0;
    min-width: 0;               /* 同上：允许它比内容窄，宽了就在自己内部横向滚动 */
    max-height: none;
    border: 1px solid var(--stroke-2);
    border-radius: var(--radius-lg);
}
/* 卡片里的格子比整屏那张表**更紧凑**（半屏宽要塞下 8 列，内边距很值钱） */
.stu-card .stu-hcell,
.stu-card .stu-cell { padding: 5px 6px; font-size: .88rem; }

.stu-hcell, .stu-cell {
    padding: 6px 8px; min-height: 44px;
    border-bottom: 1px solid var(--stroke-subtle);
    border-right: 1px solid var(--stroke-subtle);
    display: flex; align-items: center; justify-content: center;
    white-space: nowrap; font-size: .95rem;
    overflow: hidden;                 /* 内容再长也不许溢出到隔壁格子 */
}
.stu-hcell:last-child, .stu-cell:last-child { border-right: 0; }
.stu-hcell {
    font-weight: 600; color: var(--fg-2); background: var(--bg-3);
    position: sticky; top: 0; z-index: 1;
}
.stu-cell { color: var(--fg-1); background: var(--bg-1); min-width: 0; }
.stu-row:last-child .stu-cell { border-bottom: 0; }
.stu-cell--name { justify-content: flex-start; font-weight: 600; }

/* 纯文本内容：过长显示成"…"（套了一层 span 才能生效，见 js/student.js 的 cellFor） */
.stu-txt {
    min-width: 0; max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* 标红的行（等级低 / 手动标红）：只把名字染红，整行底色不动 */
.stu-row-flagged .stu-cell--name { color: #C42B1C; }

/* 「找人」命中的那一行：描一圈强调色。
   ★ 用描边而不是换底色：底色在深色主题下很难挑一个两边都好看的颜色。 */
.stu-row-hit .stu-cell { outline: 2px solid var(--brand-60); outline-offset: -2px; }

/* 计分格里的 − ＋（学生端在一体机上按，做够大 ——
   ★ 尺寸按"手指"来：桌面端那边这两颗就是 46 高，网页端给到 44×38，
     再大就会把行高撑得难受）
   ★★ 全部 `flex: none`：**谁都不许被压缩**。之前格子宽度不够时，
     flex 会把这几个元素按比例挤窄，视觉上就成了"按钮变形、叠在一起"
     （2026-10-13 用户报的正是这个）。宁可让格子横向滚动，也不许挤变形。 */
.stu-step { display: flex; align-items: center; gap: 6px; flex: none; }
.stu-step__btn {
    flex: none;
    width: 44px; height: 38px; padding: 0; font: inherit; font-size: 1.2rem; line-height: 1;
    border-radius: var(--radius-md); cursor: pointer;
    background: var(--bg-1); border: 1px solid var(--stroke-2); color: var(--fg-1);
}
.stu-step__btn:hover { background: var(--bg-3); }
.stu-step__btn:active { background: var(--brand-100); }
.stu-step__val {
    flex: none; min-width: 40px; text-align: center;
    font-weight: 600; color: var(--fg-1);
}

/* 表格格子里的小按钮（"写缘由"）：站点那个 .btn 左右各 20px 内边距，
   放进窄格子会被挤扁 —— 这里收紧内边距、保住高度。 */
.stu-cellbtn {
    flex: none;
    min-height: 34px;
    padding: 0 10px;
    font-size: .92rem;
    font-weight: 500;
}

.stu-detail {
    margin-top: 18px; background: var(--bg-1); border: 1px solid var(--stroke-2);
    border-radius: var(--radius-xl); padding: 16px;
}
.stu-detail[hidden] { display: none; }
.stu-detail__head { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
.stu-detail__title { font-weight: 600; font-size: 1.05rem; color: var(--fg-1); }
.stu-detail__head .btn { margin-left: auto; }
.stu-detail__row {
    display: flex; align-items: center; gap: 10px; padding: 6px 0;
    border-bottom: 1px solid var(--stroke-subtle);
}
.stu-detail__k { min-width: 120px; color: var(--fg-3); }
/* ★ 只读值（学号 / 姓名 / 总分…）要**明确**给主文字色：
   不给的话它就跟着站点 .legal 的次级灰走，深色下显得发虚（2026-10-13 验收时看到）。 */
.stu-detail__v { color: var(--fg-1); }
.stu-reason { width: 100%; font: inherit; padding: 8px; }

/* ============================================================
   ③ 缘由记录
   ============================================================ */
.stu-rrow {
    display: grid; grid-template-columns: 150px 1fr 130px 110px; gap: 8px;
    padding: 8px 10px; border-bottom: 1px solid var(--stroke-subtle); align-items: start;
}
.stu-rrow--head { font-weight: 600; color: var(--fg-2); background: var(--bg-3); }
.stu-rrow__at, .stu-rrow__file { color: var(--fg-3); font-size: .88em; }
.stu-rrow__reason { color: var(--fg-1); }
.stu-rrow__delta { font-weight: 600; color: var(--fg-1); }

/* ============================================================
   ④ 每日整理：两列（总分为正 / 总分为负）
   ============================================================ */
.stu-daily { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 700px) { .stu-daily { grid-template-columns: 1fr; } }
.stu-daily__col {
    border: 1px solid var(--stroke-2); border-radius: var(--radius-lg); padding: 8px 10px;
    background: var(--bg-1);
}
.stu-daily__head { font-weight: 600; padding-bottom: 6px; color: var(--fg-2); }
.stu-daily__head--pos { color: #107C41; }
.stu-daily__head--neg { color: #C42B1C; }
.stu-daily__row {
    display: flex; align-items: baseline; gap: 8px;
    padding: 5px 0; border-bottom: 1px solid var(--stroke-subtle);
}
.stu-daily__row:last-child { border-bottom: 0; }
.stu-daily__who { font-weight: 600; color: var(--fg-1); }
.stu-daily__day { color: var(--fg-3); font-size: .85em; }
.stu-daily__total { margin-left: auto; font-weight: 600; }
.stu-daily__total--pos { color: #107C41; }
.stu-daily__total--neg { color: #C42B1C; }

/* ============================================================
   ⑤ 个人中心
   ============================================================ */
.stu-profile { padding: 40px 0; text-align: center; }
.stu-profile__name { font-size: 1.6rem; font-weight: 600; color: var(--fg-1); margin-bottom: 10px; }

/* ============================================================
   ⑥ 设置
   ============================================================ */
.stu-setting {
    display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
    padding: 8px 0; border-bottom: 1px solid var(--stroke-subtle);
}
.stu-setting__label { min-width: 280px; color: var(--fg-1); }
.stu-setting__ctl { max-width: 260px; }

/* ============================================================
   ★★ 本页范围内的"组件重画"（2026-10-13 按用户反馈加）
   ------------------------------------------------------------
   站点 fluent.css 里的 .btn / .input 等**有写死的浅色**，例如
       .input { color:#000; background:#fff; border:1px solid rgba(0,0,0,.20) }
   它们不跟随深色变量。系统是深色时，这一页就成了
   "深色表格 + 白色输入框/白色按钮"的混搭 —— 用户 2026-10-13 看到的就是这个。

   这里用**设计变量**把这一页用到的几个组件重画一遍：
     · 作用域限定在 .stu-main 里面 —— 网站别的页面一个字都不变；
     · 颜色全部走变量 —— 浅色 / 深色自动都对；
     · 只覆盖颜色与描边，站点的尺寸/圆角/过渡照旧。
   ============================================================ */

.stu-main .btn {
    background: var(--bg-1);
    color: var(--fg-1);
    border: 1px solid var(--stroke-2);
}
.stu-main .btn:hover { background: var(--bg-3); }
.stu-main .btn:active { background: var(--brand-100); }

.stu-main .btn--primary {
    background: var(--brand-60); border-color: var(--brand-60); color: var(--fg-on-brand);
}
.stu-main .btn--primary:hover { background: var(--brand-70); border-color: var(--brand-70); }
.stu-main .btn--primary:active { background: var(--brand-80); }

.stu-main .btn--danger {
    background: transparent; border-color: #C42B1C; color: #C42B1C;
}
.stu-main .btn--danger:hover { background: rgba(196, 43, 28, .12); }

.stu-main .input {
    background: var(--bg-1);
    color: var(--fg-1);
    border: 1px solid var(--stroke-2);
    border-bottom-color: var(--stroke-2);
}
.stu-main .input:focus {
    border-color: var(--brand-60);
    box-shadow: inset 0 -2px 0 var(--brand-60);
}
.stu-main .input::placeholder { color: var(--fg-3); }

.stu-main .hint { color: var(--fg-3); }
.stu-main .label { color: var(--fg-2); }
.stu-main .empty { color: var(--fg-3); }

/* ---- 界面字号（设置页里选，挂在 html 上；只影响这一页的 rem 尺寸）---- */
[data-font="s"] { font-size: 15px; }
[data-font="m"] { font-size: 16px; }
[data-font="l"] { font-size: 18px; }

/* ============================================================
   ★★ 按窗口宽度收紧表格（与 js/student.js 的 colMin 一一对应）
   ------------------------------------------------------------
   列宽的最小值在 JS 里按窗口宽度算，这里把**按钮/内边距**收到同一档 ——
   两边必须一起改：只改一边，格子会装不下按钮（被裁掉）或白白留白。
   ============================================================ */
/* 窄屏：顺带把**页面左右留白**收掉（默认 24px 一侧，很占地方）——
   省下来的这 24px 正好够把最后一列（排名）留在屏幕里。 */
@media (max-width: 1180px) {
    .stu-main { padding-left: 12px; padding-right: 12px; }
    .stu-hcell, .stu-cell { padding: 6px 5px; font-size: .9rem; }
    .stu-step { gap: 4px; }
    .stu-step__btn { width: 36px; height: 34px; font-size: 1.05rem; }
    .stu-step__val { min-width: 32px; }
    .stu-cellbtn { padding: 0 8px; font-size: .86rem; }
}

@media (max-width: 980px) {
    .stu-main { padding-left: 8px; padding-right: 8px; }
    .stu-hcell, .stu-cell { padding: 5px 5px; font-size: .86rem; }
    .stu-step { gap: 3px; }
    .stu-step__btn { width: 32px; height: 32px; font-size: 1rem; }
    .stu-step__val { min-width: 28px; }
    .stu-cellbtn { padding: 0 6px; font-size: .82rem; min-height: 30px; }
}

@media (max-width: 640px) {
    .stu-hub { gap: 40px; }
    .stu-circle { width: 120px; height: 120px; }
    .stu-rrow { grid-template-columns: 1fr 110px; }
    .stu-rrow__file { display: none; }
}
