/* ==========================================================================
   三班积分 — 设计系统 · 现代产品风
     · 浅灰底 + 白色卡片 + 一层极轻的投影，靠留白和层级分块
     · 主色靛蓝，扣分用玫红；圆角 8/10/14/20 四级
     · 数字一律等宽等宽排版（tabular-nums），分数一眼能对齐
     · 深浅两套主题，全部走 CSS 变量，不额外写第二份规则
   ========================================================================== */

/* ------------------------------- 变量 ------------------------------- */
:root {
  color-scheme: light;

  /* 纸与墨 */
  --bg: #f4f5f8;
  --surface: #ffffff;
  --surface-2: #f8f9fc;
  --surface-3: #eef0f5;
  --border: #e6e8ef;
  --border-strong: #d5d9e3;

  --text: #101322;
  --text-soft: #4c5468;
  --text-dim: #6b7285;

  /* 主色与语义色 */
  --primary: #4c6ef5;
  --primary-strong: #3b5bdb;
  --primary-soft: rgba(76, 110, 245, 0.1);
  --primary-ink: #ffffff;

  --danger: #e5484d;
  --danger-strong: #cc3b40;
  --danger-soft: rgba(229, 72, 77, 0.1);

  --success: #0e9f6e;
  --success-soft: rgba(14, 159, 110, 0.1);

  /* 圆角与阴影 */
  --radius: 14px;
  --radius-sm: 10px;
  --radius-xs: 8px;
  --radius-lg: 20px;
  --radius-pill: 999px;

  --shadow-xs: 0 1px 2px rgba(16, 24, 40, 0.04);
  --shadow-sm: 0 1px 3px rgba(16, 24, 40, 0.06), 0 1px 2px rgba(16, 24, 40, 0.04);
  --shadow: 0 6px 20px rgba(16, 24, 40, 0.07);
  --shadow-lg: 0 20px 48px rgba(16, 24, 40, 0.16);

  --header-bg: rgba(255, 255, 255, 0.86);
  --header-h: 62px;
  --maxw: 1180px;
  --ease: cubic-bezier(0.2, 0, 0.2, 1);

  --font: -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Helvetica Neue",
    Helvetica, Arial, sans-serif;
  --mono: "SF Mono", ui-monospace, "Cascadia Mono", "Roboto Mono", Consolas, "Liberation Mono", monospace;

  --label-size: 11.5px;
  --label-track: 0.08em;
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #0f1218;
  --surface: #171b23;
  --surface-2: #1c212b;
  --surface-3: #242a35;
  --border: #262c38;
  --border-strong: #333a48;

  --text: #e9ecf3;
  --text-soft: #a7b0c0;
  --text-dim: #737d8f;

  --primary: #7b91ff;
  --primary-strong: #97a8ff;
  --primary-soft: rgba(123, 145, 255, 0.16);
  --primary-ink: #0f1218;

  --danger: #ff6b70;
  --danger-strong: #ff8589;
  --danger-soft: rgba(255, 107, 112, 0.16);

  --success: #34d399;
  --success-soft: rgba(52, 211, 153, 0.16);

  --shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.25);
  --shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 24px 56px rgba(0, 0, 0, 0.55);

  --header-bg: rgba(15, 18, 24, 0.86);
}

/* ------------------------------- 翻页手感 ------------------------------- */
/*
 * 站点是多页面结构，翻页就是一次整页导航。要让切换"顺"，做了三件事：
 *   1. 用跨文档视图过渡（Chrome 126+）把白屏换成淡入淡出；
 *   2. 不支持的浏览器退化成内容淡入，不至于硬切；
 *   3. 顶栏/页脚预留好高度（见下方 min-height），切换时页面不会先塌一下再撑开。
 */
@view-transition {
  navigation: auto;
}

::view-transition-old(root) {
  animation: page-out 0.16s var(--ease) both;
}

::view-transition-new(root) {
  animation: page-in 0.2s var(--ease) both;
}

@keyframes page-out {
  to {
    opacity: 0;
  }
}

@keyframes page-in {
  from {
    opacity: 0;
  }
}

@supports not (view-transition-name: none) {
  .page,
  .board-shell,
  .auth-wrap {
    animation: page-in 0.18s var(--ease) both;
  }
}

/* 顶栏和页脚在脚本挂载之前也要占住位置，否则每次切页都会先塌后撑 */
.site-header {
  min-height: var(--header-h);
}

.site-footer {
  min-height: 96px;
}

/* ------------------------------- 基础 ------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/*
 * hidden 属性必须真的隐藏。
 * 我们自己给 .btn / .dock-row / .dojo-status 写了 display，会盖掉浏览器默认的
 * [hidden] { display: none }，所以这里补一条带 !important 的兜底。
 */
[hidden] {
  display: none !important;
}

html {
  font-size: 17px;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* 长短页面切换时滚动条不会突然出现/消失，避免整页横向抖一下 */
  scrollbar-gutter: stable;
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15.5px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
  display: flex;
  flex-direction: column;
}

body.no-scroll {
  overflow: hidden;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.3;
}

h1 {
  font-size: 1.95rem;
}

h2 {
  font-size: 1.2rem;
}

h3 {
  font-size: 1rem;
}

p {
  margin: 0 0 1em;
}

p:last-child {
  margin-bottom: 0;
}

a {
  color: var(--primary);
  text-decoration: none;
  transition: color 0.16s var(--ease);
}

a:hover {
  color: var(--primary-strong);
}

img,
svg {
  max-width: 100%;
}

/*
 * 键盘焦点环：用实色 + 一圈底色描边，深浅两套主题下都看得见
 * （之前只有 10% 透明度的主色，投影和大屏上几乎不可见；
 *   也不要在这里写 border-radius，否则胶囊按钮/圆形头像获焦会变形）
 */
:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 22%, transparent);
}

/* 老浏览器不支持 color-mix 时退回单层实色环，别丢焦点提示 */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  :focus-visible {
    box-shadow: none;
  }
}

::selection {
  background: var(--primary-soft);
  color: var(--text);
}

/* 等宽数字：分数一列在表格里必须能对齐 */
.num,
.mono {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* ------------------------------- 版式 ------------------------------- */
.container {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 28px;
}

.page {
  flex: 1 0 auto;
  padding: 36px 0 80px;
}

.page-head {
  display: flex;
  align-items: flex-end;
  gap: 20px;
  margin-bottom: 26px;
}

.page-head .page-head-main {
  min-width: 0;
}

.page-head h1 {
  font-size: 1.85rem;
  letter-spacing: -0.025em;
}

.page-head .sub {
  margin: 6px 0 0;
  color: var(--text-soft);
  font-size: 0.92rem;
}

/* 公共账号的「本次操作人」：挂在页头按钮旁边，短小不抢眼 */
.operator-bar {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 5px 3px 10px;
  font-size: 0.78rem;
  color: var(--text-soft);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
}

.operator-bar-label {
  white-space: nowrap;
}

.operator-bar-select {
  padding: 2px 8px;
  font: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
}

.operator-bar-select:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}

.page-head .page-head-actions {
  margin-left: auto;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

.section-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 32px 0 14px;
}

.section-head h2 {
  font-size: 1.02rem;
  letter-spacing: 0;
}

.section-head .hint,
.section-head .section-extra {
  margin-left: auto;
  color: var(--text-dim);
  font-size: 0.84rem;
}

.label {
  font-size: var(--label-size);
  letter-spacing: var(--label-track);
  text-transform: uppercase;
  color: var(--text-dim);
  font-weight: 600;
}

.muted {
  color: var(--text-soft);
}

.dim {
  color: var(--text-dim);
}

.small {
  font-size: 0.86rem;
}

.hint {
  color: var(--text-dim);
  font-size: 0.84rem;
  line-height: 1.6;
}

.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mb-0 {
  margin-bottom: 0;
}

.mt-2 {
  margin-top: 12px;
}

.mt-3 {
  margin-top: 18px;
}

.mt-4 {
  margin-top: 28px;
}

.hidden {
  display: none !important;
}

.row {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.stack-sm {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.stack-sm:empty {
  display: none;
}

.spacer {
  flex: 1 1 auto;
}

/* ------------------------------- 顶栏 ------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--header-bg);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--border);
}

.header-inner {
  display: flex;
  align-items: center;
  gap: 22px;
  height: var(--header-h);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--text);
  flex-shrink: 0;
}

.brand-mark {
  width: 22px;
  height: 22px;
  display: block;
  border-radius: 5px;
}

.brand-mark rect {
  fill: var(--text);
}

.brand-mark rect.is-accent {
  fill: var(--primary);
}

.brand-name {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: 0.01em;
}

.brand-sub {
  font-size: 0.78rem;
  color: var(--text-dim);
  padding-left: 10px;
  border-left: 1px solid var(--border);
  white-space: nowrap;
}

.nav {
  display: flex;
  align-items: center;
  gap: 2px;
}

.nav a {
  padding: 7px 13px;
  border-radius: var(--radius-pill);
  font-size: 0.92rem;
  color: var(--text-soft);
  transition: background 0.16s var(--ease), color 0.16s var(--ease);
}

.nav a:hover {
  background: var(--surface-2);
  color: var(--text);
}

.nav a[aria-current="page"] {
  background: var(--primary-soft);
  color: var(--primary);
  font-weight: 600;
}

.header-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* 头像方块：没有图片，只有首字 */
.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: var(--radius-pill);
  background: var(--primary-soft);
  color: var(--primary);
  font-size: 0.8rem;
  font-weight: 700;
  flex-shrink: 0;
}

.avatar.is-lg {
  width: 68px;
  height: 68px;
  font-size: 1.6rem;
  background: linear-gradient(135deg, var(--primary), var(--primary-strong));
  color: #fff;
  box-shadow: var(--shadow-sm);
}

/* 用户菜单 */
.user-menu {
  position: relative;
}

.user-menu-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 10px);
  min-width: 200px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 6px;
  z-index: 60;
  display: none;
  transform-origin: top right;
}

.user-menu[data-open="true"] .user-menu-panel {
  display: block;
  animation: pop 0.14s var(--ease);
}

@keyframes pop {
  from {
    opacity: 0;
    transform: translateY(-4px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.user-menu-panel-head {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 8px 10px 10px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
  font-size: 0.9rem;
}

.user-menu-panel-head .dim {
  font-size: 0.76rem;
}

.user-menu-panel a,
.user-menu-panel button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 10px;
  font-size: 0.9rem;
  font-family: inherit;
  color: var(--text-soft);
  background: none;
  border: 0;
  border-radius: var(--radius-xs);
  text-align: left;
  cursor: pointer;
  transition: background 0.14s var(--ease), color 0.14s var(--ease);
}

.user-menu-panel a:hover,
.user-menu-panel button:hover {
  background: var(--surface-2);
  color: var(--text);
}

.user-menu-panel .menu-sep {
  height: 1px;
  background: var(--border);
  margin: 5px 4px;
}

.mobile-nav {
  display: none;
}

/* ------------------------------- 页脚 ------------------------------- */
.site-footer {
  border-top: 1px solid var(--border);
  padding: 24px 0;
  margin-top: auto;
  font-size: 0.82rem;
  color: var(--text-dim);
  background: var(--surface);
}

.footer-inner {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  align-items: center;
}

.footer-inner .footer-mid {
  margin-left: auto;
}

.footer-inner a {
  color: var(--text-soft);
}

.footer-copy {
  width: 100%;
  padding-top: 12px;
  border-top: 1px solid var(--border);
  color: var(--text-dim);
  font-size: 0.78rem;
}

/* ------------------------------- 按钮 ------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 500;
  line-height: 1.4;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background 0.15s var(--ease), color 0.15s var(--ease), border-color 0.15s var(--ease),
    box-shadow 0.15s var(--ease), transform 0.08s var(--ease);
  white-space: nowrap;
  text-align: center;
}

.btn:hover {
  border-color: var(--primary);
  color: var(--primary);
}

.btn:active {
  transform: translateY(1px);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.btn:disabled:hover {
  border-color: var(--border-strong);
  color: var(--text);
}

.btn-primary {
  background: var(--primary);
  border-color: var(--primary);
  color: var(--primary-ink);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--primary) 30%, transparent);
}

.btn-primary:hover {
  background: var(--primary-strong);
  border-color: var(--primary-strong);
  color: var(--primary-ink);
}

.btn-ghost {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text-soft);
}

.btn-ghost:hover {
  background: var(--surface-2);
  border-color: var(--border-strong);
  color: var(--text);
}

.btn-danger {
  color: var(--danger);
  border-color: var(--danger);
  background: transparent;
}

.btn-danger:hover {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--primary-ink);
}

.btn-sm {
  padding: 5px 11px;
  font-size: 0.82rem;
  border-radius: var(--radius-xs);
}

.btn-block {
  width: 100%;
}

.btn.is-on {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

.btn-add.is-on {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

.btn-deduct.is-on {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}

/* 加减分切换：两枚按钮拼成一段 */
.btn-seg {
  flex: 1;
}

.spin {
  display: inline-block;
  animation: spin 0.9s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* ------------------------------- 表单 ------------------------------- */
.input,
.select,
.textarea {
  width: 100%;
  padding: 9px 12px;
  font-family: inherit;
  font-size: 0.92rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease), background 0.15s var(--ease);
}

.input:hover,
.select:hover,
.textarea:hover {
  border-color: var(--text-dim);
}

.input:focus,
.select:focus,
.textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-soft);
}

.input:disabled {
  background: var(--surface-2);
  color: var(--text-dim);
}

.input::placeholder,
.textarea::placeholder {
  color: var(--text-dim);
}

.textarea {
  min-height: 92px;
  resize: vertical;
  line-height: 1.6;
}

.select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' fill='none' stroke='%238b93a5' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-position: calc(100% - 12px) 50%;
  background-repeat: no-repeat;
  background-size: 12px 12px;
  padding-right: 32px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 14px;
}

.field > label,

.field .field-hint {
  font-size: 0.78rem;
  color: var(--text-dim);
  line-height: 1.5;
}

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 16px;
}

.form-grid .field.is-wide {
  grid-column: 1 / -1;
}

.search-box {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 200px;
}

.form-error {
  margin: 0 0 14px;
  padding: 9px 12px;
  font-size: 0.86rem;
  color: var(--danger);
  background: var(--danger-soft);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
}

/* ------------------------------- 卡片 / 面板 ------------------------------- */
.panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.panel-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
}

.panel-head h3 {
  font-size: 0.96rem;
}

.panel-head .panel-extra {
  margin-left: auto;
  font-size: 0.84rem;
  color: var(--text-dim);
}

.panel-body {
  padding: 18px;
}

.panel-body.is-flush {
  padding: 0;
}

/* ------------------------------- 数字卡片 ------------------------------- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
}

.stat {
  padding: 18px 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.2s var(--ease), transform 0.2s var(--ease);
}

.stat:hover {
  box-shadow: var(--shadow);
  transform: translateY(-1px);
}

.stat-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-dim);
}

.stat-value {
  display: flex;
  align-items: baseline;
  gap: 5px;
  margin-top: 8px;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.9rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.1;
}

.stat-value .unit {
  font-family: var(--font);
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--text-dim);
  letter-spacing: 0;
}

.stat-value.is-pos {
  color: var(--success);
}

.stat-value.is-neg {
  color: var(--danger);
}

.stat-hint {
  margin-top: 8px;
  font-size: 0.78rem;
  color: var(--text-dim);
}

/* 主卡片：唯一带渐变的地方，用来把班级总分拎出来 */
.stat.is-hero {
  background: linear-gradient(135deg, #5b7cfa 0%, #4c6ef5 45%, #3b5bdb 100%);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 10px 26px rgba(76, 110, 245, 0.28);
}

.stat.is-hero .stat-label {
  color: rgba(255, 255, 255, 0.82);
}

.stat.is-hero .stat-hint {
  color: rgba(255, 255, 255, 0.78);
}

.stat.is-hero .stat-value {
  font-size: 2.6rem;
}

.stat.is-hero .stat-value .unit {
  color: rgba(255, 255, 255, 0.8);
}

/* ------------------------------- 表格 ------------------------------- */
/* 批量操作条：勾了人才出现，省得占地方 */
.bulk-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  padding: 8px 12px;
  font-size: 0.85rem;
  color: var(--text-soft);
  background: var(--surface);
  border: 1px solid var(--primary);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  animation: rise-in 0.18s var(--ease) backwards;
}

.bulk-count {
  font-weight: 600;
  color: var(--text);
}

.bulk-hint {
  color: var(--text-dim);
  font-size: 0.78rem;
}

/* 勾选列窄一点，不抢姓名的位置 */
.table .cell-check {
  width: 34px;
  padding-right: 0;
  text-align: center;
}

.table .cell-check input {
  width: 15px;
  height: 15px;
  cursor: pointer;
}

.table thead .cell-check input {
  cursor: pointer;
}

.table-wrap {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow-x: auto;
}

/* 嵌在 .panel 里时不要再套一层卡片 */
.panel .table-wrap,
.panel-body .table-wrap {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}

.table th {
  text-align: left;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-dim);
  padding: 11px 16px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
  background: var(--surface-2);
}

.table th:first-child {
  border-top-left-radius: var(--radius);
}

.table th:last-child {
  border-top-right-radius: var(--radius);
}

.table td {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}

.table tbody tr:last-child td {
  border-bottom: 0;
}

.table tbody tr {
  transition: background 0.12s var(--ease);
}

.table tbody tr:hover {
  background: var(--surface-2);
}

/*
 * 前三名那一行：淡淡一层底色 + 左边一道主色细条。
 * 行上的 .is-top 一直是 JS 输出的，但之前没有任何样式落地，
 * 所以"前三名高亮"实际上从来没生效过。
 */
.table tbody tr.is-top {
  background: color-mix(in srgb, var(--primary) 6%, transparent);
}

.table tbody tr.is-top:hover {
  background: color-mix(in srgb, var(--primary) 10%, transparent);
}

.table tbody tr.is-top > td:first-child {
  box-shadow: inset 3px 0 0 var(--primary);
}

.table .cell-num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

.table .cell-rank {
  width: 62px;
}

.table .cell-actions {
  text-align: right;
  white-space: nowrap;
}

.table .cell-actions .btn + .btn {
  margin-left: 6px;
}

.table tr.is-muted td {
  color: var(--text-dim);
}

.rank-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 26px;
  height: 26px;
  padding: 0 6px;
  border-radius: var(--radius-pill);
  font-family: var(--mono);
  font-size: 0.8rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  background: var(--surface-3);
  color: var(--text-soft);
}

.rank-num.is-1 {
  background: var(--primary);
  color: var(--primary-ink);
  box-shadow: 0 2px 6px color-mix(in srgb, var(--primary) 40%, transparent);
}

.rank-num.is-2,
.rank-num.is-3 {
  background: var(--primary-soft);
  color: var(--primary);
}

/* 分数 */
.score {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.score.is-pos {
  color: var(--success);
}

.score.is-neg {
  color: var(--danger);
}

.score.is-zero {
  color: var(--text-dim);
}

.person {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.person .person-main {
  min-width: 0;
}

.person-name {
  font-weight: 600;
  color: var(--text);
}

a.person-name:hover {
  color: var(--primary);
}

.person-meta {
  font-size: 0.78rem;
  color: var(--text-dim);
}

/* ------------------------------- 标签 ------------------------------- */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 9px;
  font-size: 0.76rem;
  font-weight: 500;
  color: var(--text-soft);
  background: var(--surface-3);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  white-space: nowrap;
}

.tag.is-accent {
  color: var(--danger);
  background: var(--danger-soft);
}

.tag.is-solid {
  background: var(--primary);
  color: #fff;
}

.tag.is-void {
  color: var(--text-dim);
  background: transparent;
  border: 1px dashed var(--border-strong);
}

.tag.is-pos {
  color: var(--success);
  background: var(--success-soft);
}

.chip-list {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.chip {
  display: inline-flex;
  align-items: center;
  padding: 5px 13px;
  font-family: inherit;
  font-size: 0.86rem;
  color: var(--text-soft);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: all 0.15s var(--ease);
}

.chip:hover {
  border-color: var(--border-strong);
  color: var(--text);
  background: var(--surface-2);
}

.chip[aria-pressed="true"] {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

.chip .chip-count {
  margin-left: 6px;
  font-family: var(--mono);
  font-size: 0.74rem;
  opacity: 0.75;
}

/* ------------------------------- 工具栏 ------------------------------- */
.toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.toolbar .field {
  margin: 0;
  flex-direction: row;
  align-items: center;
  gap: 7px;
}

.toolbar .field > label {
  white-space: nowrap;
}

.toolbar .input,
.toolbar .select {
  width: auto;
  min-width: 120px;
}

.toolbar .search-box .input {
  width: 230px;
}

/* ------------------------------- 列表：记录 ------------------------------- */
.record-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.record-item {
  display: grid;
  grid-template-columns: 76px 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
  border-radius: var(--radius-xs);
  transition: background 0.12s var(--ease);
}

.record-item:hover {
  background: var(--surface-2);
}

.record-item:last-child {
  border-bottom: 0;
}

.record-delta {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.02rem;
  font-weight: 700;
  text-align: right;
}

.record-delta.is-pos {
  color: var(--success);
}

.record-delta.is-neg {
  color: var(--danger);
}

.record-main {
  min-width: 0;
}

.record-title {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: 0.94rem;
}

.record-title .record-who {
  font-weight: 600;
  color: var(--text);
}

.record-reason {
  margin-top: 3px;
  font-size: 0.84rem;
  color: var(--text-soft);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.record-time {
  font-size: 0.76rem;
  color: var(--text-dim);
  white-space: nowrap;
  text-align: right;
}

.record-item.is-voided {
  opacity: 0.6;
}

.record-item.is-voided .record-reason {
  text-decoration: line-through;
}

/* 时间线（学生详情） */
.timeline {
  position: relative;
  padding-left: 20px;
}

.timeline::before {
  content: "";
  position: absolute;
  left: 5px;
  top: 8px;
  bottom: 8px;
  width: 2px;
  border-radius: 2px;
  background: var(--border);
}

.timeline .record-item {
  grid-template-columns: 1fr auto;
  padding-left: 8px;
}

.timeline .record-item::before {
  content: "";
  position: absolute;
  left: -19px;
  top: 20px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--primary);
}

.timeline .record-item.is-voided::before {
  border-color: var(--border-strong);
}

/* ------------------------------- 柱状 / 条 ------------------------------- */
.bars {
  display: flex;
  align-items: flex-end;
  gap: 4px;
  height: 100px;
  padding: 10px 2px 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.bar {
  flex: 1 1 0;
  min-width: 3px;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  height: 100%;
}

.bar .bar-fill {
  width: 100%;
  background: var(--primary);
  min-height: 2px;
  border-radius: 4px 4px 2px 2px;
  opacity: 0.85;
  transition: opacity 0.15s var(--ease);
}

.bar.is-neg .bar-fill {
  background: var(--danger);
}

.bar:hover .bar-fill {
  opacity: 1;
}

.bar-legend {
  display: flex;
  justify-content: space-between;
  margin-top: 8px;
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--text-dim);
}

/* 横向占比条 */
.meter {
  display: flex;
  align-items: center;
  gap: 10px;
}

.meter .meter-track {
  flex: 1 1 auto;
  height: 7px;
  background: var(--surface-3);
  border-radius: var(--radius-pill);
  overflow: hidden;
  min-width: 40px;
}

.meter .meter-fill {
  height: 100%;
  background: var(--primary);
  border-radius: var(--radius-pill);
}

.meter.is-neg .meter-fill {
  background: var(--danger);
}

.meter .meter-value {
  font-family: var(--mono);
  font-size: 0.84rem;
  font-weight: 600;
  min-width: 48px;
  text-align: right;
}

/* ------------------------------- 图表 ------------------------------- */
.chart {
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.chart-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 14px;
}

.chart-head h3 {
  font-size: 0.94rem;
}

.chart-head span {
  margin-left: auto;
  font-size: 0.78rem;
  color: var(--text-dim);
}

.chart-foot {
  margin-top: 12px;
  font-size: 0.78rem;
  color: var(--text-dim);
}

/* 图表骨架：左边一列刻度，右边是可拉伸的绘图区 */
.chart-frame {
  display: flex;
  align-items: stretch;
  gap: 8px;
  flex: 1;
  min-height: 0;
}

.chart-scale {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  flex: 0 0 auto;
  padding: 1px 0;
  font-family: var(--mono);
  font-size: 0.6rem;
  line-height: 1;
  color: var(--text-dim);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.chart-plot {
  position: relative;
  display: flex;
  flex: 1;
  min-width: 0;
  min-height: 0;
}

.chart-gridline {
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: currentColor;
  color: var(--border);
  opacity: 0.75;
  pointer-events: none;
}

/* SVG 里的网格线是 <line>，靠描边而不是背景 */
.chart-svg .chart-gridline {
  position: static;
  background: none;
  stroke: var(--border);
  stroke-width: 1;
  opacity: 0.9;
}

/* 只画横线，竖线会跟柱子抢注意力 */
.chart-cols {
  position: relative;
  display: flex;
  align-items: stretch;
  flex: 1;
  min-height: 0;
  gap: 4px;
}

.chart-col {
  position: relative;
  flex: 1 1 0;
  min-width: 3px;
}

.chart-bar {
  position: absolute;
  left: 0;
  right: 0;
  background: var(--primary);
  border-radius: 4px 4px 2px 2px;
  opacity: 0.9;
  transition: opacity 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

.chart-col:hover .chart-bar {
  opacity: 1;
  box-shadow: 0 0 0 1px var(--primary-strong), 0 6px 16px rgba(0, 0, 0, 0.35);
}

.chart-bar.is-neg {
  background: var(--danger);
  border-radius: 2px 2px 4px 4px;
}

/* 0 分的日子留一个小点，避免整列空着让人误以为没渲染 */
.chart-dot {
  position: absolute;
  left: 50%;
  bottom: 1px;
  width: 4px;
  height: 4px;
  margin-left: -2px;
  border-radius: 50%;
  background: var(--border-strong);
}

.chart-zero {
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--border-strong);
  opacity: 0.9;
  pointer-events: none;
}

.chart-axis {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  margin-top: 6px;
  font-family: var(--mono);
  font-size: 0.66rem;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}

.chart-svg {
  display: block;
  width: 100%;
}

/* 面积的颜色由 charts.js 里那条渐变决定（fill="url(#…)"），
   这里不要再写 fill，否则会盖掉渐变 */
.chart-area {
  opacity: 1;
}

/* 折线下面的渐变：颜色用 CSS 写，才能跟着深浅色走 */
.chart-stop-start {
  stop-color: var(--primary);
  stop-opacity: 0.34;
}

.chart-stop-mid {
  stop-color: var(--primary);
  stop-opacity: 0.07;
}

.chart-stop-end {
  stop-color: var(--primary);
  stop-opacity: 0;
}

.chart-line {
  fill: none;
  stroke: var(--primary);
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.chart-point-halo {
  fill: var(--primary);
  opacity: 0.22;
}

.chart-point {
  fill: var(--primary);
  stroke: var(--surface);
  stroke-width: 0.8;
}

.h-bars {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 0;
}

.h-bar-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px 10px;
  align-items: baseline;
  font-size: 0.84rem;
}

.h-bar-label {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--text-soft);
}

.h-bar-label em {
  margin-left: 6px;
  font-style: normal;
  font-size: 0.72rem;
  color: var(--text-dim);
}

.h-bar-value {
  font-family: var(--mono);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.h-bar-value.is-pos {
  color: var(--success);
}

.h-bar-value.is-neg {
  color: var(--danger);
}

.h-bar-track {
  grid-column: 1 / -1;
  height: 7px;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
  overflow: hidden;
}

.h-bar-fill {
  display: block;
  height: 100%;
  min-width: 3px;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--primary-strong), var(--primary));
}

.h-bar-fill.is-neg {
  background: linear-gradient(90deg, var(--danger-strong), var(--danger));
}

.chart-donut-wrap {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
}

.chart-donut {
  position: relative;
  flex: 0 0 auto;
  /* 跟着格子宽度走（而不是写死像素）：投影到大屏时会一起变大 */
  width: clamp(104px, 46%, 210px);
  aspect-ratio: 1;
  border-radius: 50%;
}

.chart-donut-svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.chart-donut-track {
  fill: none;
  stroke: var(--surface-3);
  stroke-width: 6.4;
}

.chart-donut-slice {
  fill: none;
  stroke-width: 6.4;
  transform-origin: 21px 21px;
}

.chart-donut-hole {
  position: absolute;
  inset: 22%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border-radius: 50%;
  background: transparent;
}

.chart-donut-hole strong {
  font-family: var(--mono);
  font-size: 1.15rem;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.chart-donut-hole span {
  font-size: 0.72rem;
  color: var(--text-dim);
}

.chart-legend-col {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
  font-size: 0.82rem;
  color: var(--text-soft);
}

.chart-legend-item {
  display: flex;
  align-items: baseline;
  gap: 7px;
  min-width: 0;
}

.chart-legend-item > span {
  white-space: nowrap;
}

.chart-legend-item b {
  font-family: var(--mono);
  font-size: 0.84rem;
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.chart-legend-item em {
  font-style: normal;
  font-size: 0.72rem;
  color: var(--text-dim);
}

.chart-legend-item .dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* 记录详情：弹窗里的字段清单 */
.detail-list {
  display: grid;
  gap: 12px;
}

.detail-row {
  display: grid;
  grid-template-columns: 82px 1fr;
  gap: 10px;
  align-items: baseline;
  font-size: 0.9rem;
}

.detail-row > span:first-child {
  font-size: 0.8rem;
  color: var(--text-dim);
}

.detail-row .detail-delta {
  font-family: var(--mono);
  font-size: 1.5rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.detail-row .detail-delta.is-pos {
  color: var(--success);
}

.detail-row .detail-delta.is-neg {
  color: var(--danger);
}

/* 看板上的记录行可以点开看详情 */
.record-item.is-clickable {
  cursor: pointer;
}

.record-item.is-clickable:hover {
  background: var(--surface-2);
}

/* ------------------------------- 分栏布局 ------------------------------- */
.split {
  display: grid;
  grid-template-columns: 1fr 350px;
  gap: 26px;
  align-items: start;
}

.split.is-even {
  grid-template-columns: 1fr 1fr;
}

/* ------------------------------- 空状态 ------------------------------- */
.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 48px 24px;
  text-align: center;
  color: var(--text-dim);
  font-size: 0.9rem;
}

.empty .empty-icon {
  width: 34px;
  height: 34px;
  margin-bottom: 6px;
  border-radius: 50%;
  background: var(--primary-soft);
  position: relative;
}

.empty .empty-icon::after {
  content: "";
  position: absolute;
  inset: 12px;
  border-radius: 50%;
  border: 2px solid var(--primary);
}

.empty strong {
  color: var(--text-soft);
  font-weight: 600;
}

.skeleton {
  background: linear-gradient(90deg, var(--surface-3) 25%, var(--surface-2) 37%, var(--surface-3) 63%);
  background-size: 400% 100%;
  border-radius: 6px;
  animation: shimmer 1.4s ease infinite;
}

.skeleton-line {
  height: 12px;
  margin: 8px 0;
  border-radius: 6px;
}

@keyframes shimmer {
  0% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0 50%;
  }
}

/* ------------------------------- 分页 ------------------------------- */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 22px 0 6px;
  flex-wrap: wrap;
}

.pagination button {
  min-width: 34px;
  height: 34px;
  padding: 0 10px;
  font-family: var(--mono);
  font-size: 0.84rem;
  color: var(--text-soft);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xs);
  cursor: pointer;
  transition: all 0.14s var(--ease);
}

.pagination button:hover:not(:disabled) {
  border-color: var(--primary);
  color: var(--primary);
}

.pagination button[aria-current="page"] {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}

.pagination button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.pagination .page-info {
  margin-left: 10px;
  font-size: 0.78rem;
  color: var(--text-dim);
}

/* ------------------------------- 提示条 ------------------------------- */
.toast-host {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  pointer-events: none;
  width: min(92vw, 460px);
}

.toast {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 16px;
  font-size: 0.9rem;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  max-width: 100%;
}

.toast.success {
  background: var(--success);
  border-color: var(--success);
  color: #fff;
}

.toast.error {
  background: var(--danger);
  border-color: var(--danger);
  color: #fff;
}

/* ------------------------------- 模态框 ------------------------------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 150;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: rgba(13, 18, 32, 0.45);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.modal[data-open="true"] {
  display: flex;
  animation: fade 0.16s var(--ease);
}

.modal-box {
  width: min(100%, 520px);
  max-height: 88vh;
  overflow-y: auto;
  background: var(--surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 24px 26px 22px;
  animation: rise 0.18s var(--ease);
}

.modal-box.is-wide {
  width: min(100%, 780px);
}

@keyframes fade {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes rise {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.99);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.modal-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 18px;
}

.modal-head h3 {
  font-size: 1.1rem;
}

.modal-head .modal-sub {
  font-size: 0.82rem;
  color: var(--text-dim);
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 22px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

/* ------------------------------- 加减分台 ------------------------------- */
.award-layout {
  display: grid;
  grid-template-columns: 1fr 390px;
  gap: 22px;
  align-items: start;
}

.pick-box {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.pick-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  font-size: 0.84rem;
  color: var(--text-soft);
}

.pick-toolbar .spacer {
  flex: 1;
}

.pick-search {
  padding: 11px 14px;
  margin: 0;
  border-bottom: 1px solid var(--border);
}

.pick-search .input,
.pick-search .select {
  flex: 1 1 0;
  min-width: 0;
}

.pick-list {
  max-height: 430px;
  overflow-y: auto;
  background: var(--surface);
}

.pick-group-head {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 6px 14px;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: var(--label-track);
  color: var(--text-dim);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}

.pick-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  user-select: none;
  transition: background 0.12s var(--ease);
}

.pick-row:last-child {
  border-bottom: 0;
}

.pick-row:hover {
  background: var(--surface-2);
}

.pick-row.is-checked {
  background: var(--primary-soft);
}

.pick-row input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--primary);
  margin: 0;
  flex-shrink: 0;
  cursor: pointer;
}

.pick-row .pick-name {
  font-size: 0.92rem;
  font-weight: 500;
}

.pick-row .pick-meta {
  margin-left: auto;
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-dim);
}

.pick-row .pick-meta.is-pos {
  color: var(--success);
}

.pick-row .pick-meta.is-neg {
  color: var(--danger);
}

/* 条目选择块 */
.cat-list {
  display: flex;
  flex-direction: column;
  gap: 7px;
  max-height: 280px;
  overflow-y: auto;
  padding: 2px;
}

.cat-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 13px;
  font-family: inherit;
  font-size: 0.9rem;
  text-align: left;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: all 0.14s var(--ease);
}

.cat-item:hover {
  border-color: var(--primary);
  background: var(--surface-2);
}

.cat-item[aria-pressed="true"] {
  border-color: var(--primary);
  background: var(--primary-soft);
  box-shadow: 0 0 0 1px var(--primary) inset;
}

.cat-item .cat-score {
  margin-left: auto;
  font-family: var(--mono);
  font-weight: 700;
  font-size: 0.86rem;
}

.cat-item .cat-score.is-pos {
  color: var(--success);
}

.cat-item .cat-score.is-neg {
  color: var(--danger);
}

.cat-item .cat-tag {
  font-size: 0.74rem;
  color: var(--text-dim);
}

.award-summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 15px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
}

.award-summary .award-total {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 1.15rem;
  font-weight: 700;
}

/* ------------------------------- 后台子导航 ------------------------------- */
.subnav {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  padding: 6px;
  margin-bottom: 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-xs);
}

/* 脚本注入之前是空的：别让一条空壳先闪一下 */
.subnav:empty {
  display: none;
}

.subnav a {
  padding: 7px 15px;
  font-size: 0.9rem;
  color: var(--text-soft);
  border-radius: var(--radius-sm);
  transition: background 0.15s var(--ease), color 0.15s var(--ease);
}

.subnav a:hover {
  background: var(--surface-2);
  color: var(--text);
}

.subnav a[aria-current="page"] {
  background: var(--primary-soft);
  color: var(--primary);
  font-weight: 600;
}

/* ------------------------------- 模块入口 ------------------------------- */
.module-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}

.module-card {
  display: block;
  padding: 18px 20px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.2s var(--ease), transform 0.2s var(--ease), border-color 0.2s var(--ease);
}

.module-card:hover {
  color: var(--text);
  border-color: var(--primary);
  box-shadow: var(--shadow);
  transform: translateY(-2px);
}

.module-card h3 {
  font-size: 1rem;
  margin-bottom: 3px;
}

.module-card p {
  margin: 0;
  font-size: 0.84rem;
  color: var(--text-dim);
  line-height: 1.5;
}

.module-card .module-count {
  display: flex;
  align-items: baseline;
  gap: 5px;
  margin-top: 14px;
  font-family: var(--mono);
  font-size: 1.55rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--primary);
}

.module-card .module-count span {
  font-family: var(--font);
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--text-dim);
  letter-spacing: 0;
}

/* ------------------------------- 学生详情 ------------------------------- */
.profile-head {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 22px 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.profile-head .profile-main {
  min-width: 0;
}

.profile-head h1 {
  font-size: 1.65rem;
  letter-spacing: -0.02em;
}

.profile-head .profile-meta {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 7px;
  font-size: 0.86rem;
  color: var(--text-dim);
}

.profile-score {
  margin-left: auto;
  text-align: right;
  padding-left: 20px;
}

.profile-score .score-big {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 3.1rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.04em;
}

.profile-score .score-big.is-pos {
  color: var(--success);
}

.profile-score .score-big.is-neg {
  color: var(--danger);
}

.profile-score .score-label {
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-dim);
}

.rank-plate {
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
  font-family: var(--mono);
}

.rank-plate .rank-n {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--primary);
}

.rank-plate .rank-of {
  font-size: 0.82rem;
  color: var(--text-dim);
}

/* ------------------------------- 登录页 ------------------------------- */
.auth-wrap {
  flex: 1 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 56px 20px 80px;
  background: radial-gradient(1100px 520px at 50% -8%, var(--primary-soft), transparent 65%);
}

.auth-card {
  width: min(100%, 420px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 34px 32px 28px;
}

.auth-card .auth-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 6px;
}

.auth-card h1 {
  font-size: 1.45rem;
  margin-bottom: 4px;
}

.auth-card .auth-sub {
  color: var(--text-dim);
  font-size: 0.88rem;
  margin-bottom: 24px;
}

.auth-card .field {
  margin-bottom: 16px;
}

.auth-foot {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--border);
  font-size: 0.82rem;
  color: var(--text-dim);
}

/* ------------------------------- 公告 ------------------------------- */
.notice {
  display: flex;
  gap: 12px;
  padding: 13px 16px;
  background: var(--primary-soft);
  border: 1px solid transparent;
  border-radius: var(--radius);
  font-size: 0.9rem;
  color: var(--text);
}

.notice a {
  color: var(--primary-strong);
  font-weight: 600;
}

.notice .notice-label {
  flex-shrink: 0;
  padding-top: 1px;
  font-size: 0.78rem;
  font-weight: 700;
  color: var(--primary);
  white-space: nowrap;
}

/* 分组榜的一行 */
.group-row {
  display: grid;
  grid-template-columns: 1fr 58px 76px 70px;
  gap: 10px;
  align-items: center;
  padding: 9px 0;
  font-size: 0.9rem;
}

.group-row .group-name {
  font-weight: 500;
}

.group-row .group-num {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  color: var(--text-dim);
  font-size: 0.84rem;
}

.group-row .group-num.is-strong {
  color: var(--text);
  font-weight: 700;
}

/* ------------------------------- 一屏看板 · 便当格 ------------------------------- */
/*
 * 看板是拿去投影的，所以这一页不跟站点其他页面共用浅色底：
 * 整页固定深色（近黑 #08080a），卡片比底色亮一档，靠 10px 的缝和 22px 的圆角
 * 把内容切成大小不一的格子——像一张拼贴海报，视线自然从中间的大数字往外扫。
 *
 * 页面本身不滚动；只有「最近加减分」「积分榜」在自己的格子里慢慢滚。
 * 载入时每张卡片按自己所在的位置从界面边缘飞进来（左/右/上/下），并依次错开。
 */
.board-page {
  --bg: #08080a;
  --surface: #141417;
  --surface-2: #1b1b20;
  --surface-3: #232329;
  --border: #232327;
  --border-strong: #35353d;

  --text: #f7f7f8;
  --text-soft: #a6a6b0;
  --text-dim: #6d6d78;

  --primary: #8ea2ff;
  --primary-strong: #aab8ff;
  --primary-soft: rgba(142, 162, 255, 0.14);
  --primary-ink: #0b0b0d;
  --danger: #ff7a7f;
  --success: #3ddc97;

  --radius: 18px;

  color-scheme: dark;
  background: var(--bg);
  overflow: hidden;
}

.board-page .site-footer {
  display: none;
}

.board-shell {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  gap: 8px;
  height: 100vh;
  padding: 8px 12px 10px;
  overflow: hidden;
}

/* 顶部细条：左边是标题与学期，右边是公告、更新时间、主题、登录 */
.board-bar {
  display: flex;
  align-items: center;
  gap: 14px;
  min-width: 0;
  height: 40px;
  padding: 0 6px;
}

.board-bar-main {
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
}

.board-brand {
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.board-sub {
  font-size: 0.74rem;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.board-bar-side {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
  min-width: 0;
}

.board-notice {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  max-width: 42ch;
  padding: 3px 10px;
  font-size: 0.72rem;
  color: var(--text-soft);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  white-space: nowrap;
  overflow: hidden;
}

.board-notice:empty {
  display: none;
}

.board-notice .notice-label {
  flex-shrink: 0;
  font-weight: 700;
  color: var(--primary);
}

.board-updated {
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--text-dim);
  white-space: nowrap;
}

/* 深色底上的主按钮：反白，比彩色更贴近这套海报风格 */
.board-page .btn-primary {
  color: var(--primary-ink);
  background: var(--text);
  border-color: var(--text);
}

.board-page .btn-primary:hover {
  background: #fff;
  border-color: #fff;
}

/* ------------------------------ 格子 ------------------------------ */

.bento {
  display: grid;
  gap: 10px;
  min-height: 0;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-template-rows: repeat(8, minmax(0, 1fr));
  grid-template-areas:
    "hero hero hero hero kpi kpi kpi kpi star star star star"
    "hero hero hero hero kpi kpi kpi kpi star star star star"
    "hero hero hero hero donut donut donut donut top top top top"
    "hero hero hero hero donut donut donut donut top top top top"
    "trend trend trend trend recent recent recent recent top top top top"
    "trend trend trend trend recent recent recent recent top top top top"
    "trend trend trend trend recent recent recent recent groups groups groups groups"
    "trend trend trend trend recent recent recent recent groups groups groups groups";
}

.bento-hero {
  grid-area: hero;
}

.bento-kpi {
  grid-area: kpi;
}

.bento-star {
  grid-area: star;
}

.bento-donut {
  grid-area: donut;
}

.bento-recent {
  grid-area: recent;
}

.bento-trend {
  grid-area: trend;
}

.bento-top {
  grid-area: top;
}

.bento-groups {
  grid-area: groups;
}

/* 卡片本体：一块比底色略亮的板，圆角大、边框极轻 */
.bento-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-width: 0;
  min-height: 0;
  padding: 13px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 22px;
  overflow: hidden;
}

/* 只有主格子带一层极淡的辉光，给大数字当背景 */
.bento-card.is-hero {
  background:
    radial-gradient(120% 88% at 8% 0%, rgba(142, 162, 255, 0.16), rgba(142, 162, 255, 0) 62%),
    var(--surface);
}

.bento-head {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 22px;
  min-width: 0;
}

.bento-label {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-soft);
  white-space: nowrap;
}

.bento-tag {
  margin-left: auto;
  font-size: 0.7rem;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 卡片里的小切换：每日/累计、构成/加分/扣分、小组/分布 */
.bento-tabs {
  display: inline-flex;
  gap: 2px;
  margin-left: auto;
  padding: 2px;
  background: rgba(255, 255, 255, 0.05);
  border-radius: var(--radius-pill);
}

.bento-tabs + .bento-tag {
  margin-left: 0;
}

.bento-tab {
  padding: 3px 10px;
  font-family: inherit;
  font-size: 0.7rem;
  color: var(--text-dim);
  background: transparent;
  border: 0;
  border-radius: var(--radius-pill);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.15s var(--ease), background 0.15s var(--ease);
}

.bento-tab:hover {
  color: var(--text);
}

.bento-tab.is-on {
  color: #0b0b0d;
  background: var(--text);
  font-weight: 600;
}

.bento-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

/* ------------------------------ 主格子：总分 ------------------------------ */

.hero-value {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin-top: auto;
}

.hero-value b {
  font-family: var(--mono);
  font-size: clamp(56px, 6.6vw, 118px);
  font-weight: 600;
  line-height: 0.9;
  letter-spacing: -0.045em;
  font-variant-numeric: tabular-nums;
}

.hero-unit {
  font-size: 1rem;
  color: var(--text-dim);
}

.hero-foot {
  display: flex;
  gap: 26px;
  margin-top: 12px;
}

.hero-foot > div {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.hero-foot b {
  font-family: var(--mono);
  font-size: 1.2rem;
  font-weight: 600;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

.hero-foot span {
  font-size: 0.7rem;
  color: var(--text-dim);
  white-space: nowrap;
}

.hero-spark {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  margin-top: 8px;
}

.hero-spark .chart-axis {
  display: none;
}

.hero-spark .chart-svg {
  flex: 1;
  min-height: 0;
}

/* ------------------------------ 四宫格小数据 ------------------------------ */

/* 四宫格小数据：这里用 .kpi-grid，避免和卡片自己的 .bento-kpi（只管 grid-area）撞名 */
/*
 * 四宫格小数据：这里用 .kpi-grid，避免和卡片自己的 .bento-kpi（只管 grid-area）撞名。
 *
 * 行列都写成 minmax(0, 1fr) 是关键：只写 1fr 时，行的最小高度等于内容高度，
 * 格子一矮内容就会把行撑开、溢出到下面的参与度上——看起来就是"叠在一起"。
 */
.kpi-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(2, minmax(0, 1fr));
  gap: 8px;
  flex: 1;
  min-height: 0;
}

/* 卡片底部那条参与度：多少人有记录 / 多少人还没得分 */
.kpi-meter {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 2px;
}

.kpi-meter-bar {
  height: 5px;
  overflow: hidden;
  background: var(--surface-3);
  border-radius: var(--radius-pill);
}

.kpi-meter-bar > span {
  display: block;
  width: 0;
  height: 100%;
  border-radius: var(--radius-pill);
  background: linear-gradient(90deg, var(--primary-strong), var(--primary));
  transition: width 0.9s var(--ease);
}

.kpi-meter-text {
  font-size: 0.68rem;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ------------------------------ 本周之星 ------------------------------ */

.star-list {
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 1;
  gap: 6px;
  min-height: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.star-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  min-height: 0;
  padding: 5px 9px;
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid transparent;
  border-radius: 12px;
}

/* 第一名单独描一层淡金，扫一眼就知道谁最猛 */
.star-row.is-first {
  background: linear-gradient(90deg, rgba(255, 208, 92, 0.16), rgba(255, 208, 92, 0.03));
  border-color: rgba(255, 208, 92, 0.3);
}

.star-rank {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  font-family: var(--mono);
  font-size: 0.67rem;
  font-weight: 700;
  color: var(--text-soft);
  background: rgba(255, 255, 255, 0.08);
  border-radius: 7px;
}

.star-row.is-first .star-rank {
  color: #2b1f00;
  background: #f3c552;
}

.star-row:nth-child(2) .star-rank {
  color: #1b1d24;
  background: #c7ccd8;
}

.star-row:nth-child(3) .star-rank {
  color: #1d1206;
  background: #c98a5a;
}

.star-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  font-size: 0.86rem;
  font-weight: 600;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.star-score {
  flex: 0 0 auto;
  font-family: var(--mono);
  font-size: 0.9rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.star-score.is-pos {
  color: var(--success);
}

.star-score.is-neg {
  color: var(--danger);
}

.kpi-tile {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-width: 0;
  min-height: 0;
  padding: 6px 10px;
  overflow: hidden;
  background: var(--surface-2);
  border-radius: 14px;
}

.kpi-tile b {
  font-family: var(--mono);
  font-size: clamp(1rem, 1.25vw, 1.45rem);
  font-weight: 600;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
}

.kpi-tile span {
  font-size: 0.68rem;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ------------------------------ 图表在格子里撑满 ------------------------------ */

.bento-body .chart {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
  padding: 0;
}

.bento-body .chart-head {
  margin-bottom: 6px;
}

.bento-body .chart-head h3 {
  font-size: 0.8rem;
  color: var(--text-soft);
}

.bento-body .chart-head span {
  font-size: 0.7rem;
}

.bento-body .chart-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.bento-body .chart-cols {
  flex: 1;
  min-height: 0;
}

.bento-body .chart-svg {
  flex: 1;
  min-height: 0;
}

.bento-body .chart-axis {
  font-size: 0.62rem;
  margin-top: 4px;
}

.bento-body .chart-donut-wrap {
  flex: 1;
  align-items: center;
  justify-content: center;
  gap: 16px;
}

.bento-body .h-bars {
  gap: 7px;
}

.bento-body .h-bar-row {
  font-size: 0.76rem;
  gap: 3px 8px;
}

.bento-body .h-bar-track {
  height: 5px;
}

.bento-body .chart-donut {
  width: clamp(92px, 42%, 176px);
}

/*
 * 圆环那格被压成两行之后，按宽度定尺寸会把圆撑出卡片（被 overflow 裁掉一截）。
 * 改成按高度定：高度撑满、宽度由 aspect-ratio 反推，永远装得下。
 */
.bento-donut .chart-donut-wrap {
  gap: 14px;
  min-height: 0;
}

.bento-donut .chart-donut {
  flex: 0 0 auto;
  width: auto;
  max-width: 46%;
  height: 100%;
  max-height: 100%;
  aspect-ratio: 1;
}

.bento-donut .chart-legend-col {
  gap: 8px;
}

.bento-donut .chart-legend-item {
  font-size: 0.8rem;
}

/* ------------------------------ 列表与榜单 ------------------------------ */

/* 这两张卡要一屏放下并自己滚，所以交给 board-panel-body 承担滚动 */
.bento-card.board-panel {
  padding-bottom: 0;
}

.bento-card.board-panel .board-panel-body {
  flex: 1;
  min-height: 0;
  margin: 0 -10px 0 -16px;
  padding: 2px 6px 10px 16px;
  overflow: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}

.bento-card.board-panel .board-panel-body::-webkit-scrollbar {
  width: 5px;
}

.bento-card.board-panel .board-panel-body::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border-radius: var(--radius-pill);
}

.bento-card.board-panel .board-panel-body::-webkit-scrollbar-track {
  background: transparent;
}

.board-page .record-item {
  grid-template-columns: 46px minmax(0, 1fr) auto;
  gap: 10px;
  padding: 8px 6px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 12px;
}

.board-page .record-item:hover {
  background: rgba(255, 255, 255, 0.045);
}

.board-page .record-delta {
  font-size: 0.96rem;
}

.board-page .record-title {
  font-size: 0.86rem;
  gap: 6px;
}

.board-page .record-reason {
  font-size: 0.76rem;
  margin-top: 2px;
}

.board-page .record-time {
  font-size: 0.7rem;
}

.board-table {
  width: 100%;
  border-collapse: collapse;
}

.board-table th {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: 4px 8px 6px;
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--text-dim);
  text-align: left;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}

.board-table td {
  padding: 6px 8px;
  font-size: 0.84rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.045);
}

.board-table tr:last-child td {
  border-bottom: 0;
}

.board-table .cell-rank {
  width: 40px;
}

.board-table .rank-num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 20px;
  height: 20px;
  font-family: var(--mono);
  font-size: 0.7rem;
  border-radius: 7px;
}

/* ------------------------------ 底部规则条 ------------------------------ */

.board-foot {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  height: 20px;
  padding: 0 6px;
  font-size: 0.7rem;
  color: var(--text-dim);
}

.board-rule {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.board-updated-foot {
  font-family: var(--mono);
  white-space: nowrap;
}

/* ------------------------------ 载入动画 ------------------------------ */

/*
 * 每张卡片按它贴着的那条边飞进来：左边的从左边、右边的从右边、上排从上、下排从下。
 * 依次错开 70ms，整体 0.6 秒左右收完；内容里的柱子/折线/圆环再晚一拍长出来。
 */
@keyframes bento-enter {
  from {
    opacity: 0;
    transform: translate3d(var(--enter-x, 0px), var(--enter-y, 0px), 0) scale(0.985);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) scale(1);
  }
}

.bento-card {
  animation: bento-enter 0.62s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--i, 0) * 70ms + 80ms);
}

.bento-card:nth-child(1) {
  --i: 0;
}

.bento-card:nth-child(2) {
  --i: 1;
}

.bento-card:nth-child(3) {
  --i: 2;
}

.bento-card:nth-child(4) {
  --i: 3;
}

.bento-card:nth-child(5) {
  --i: 4;
}

.bento-card:nth-child(6) {
  --i: 5;
}

.bento-card:nth-child(7) {
  --i: 6;
}

.bento-card[data-edge="left"] {
  --enter-x: -42px;
}

.bento-card[data-edge="right"] {
  --enter-x: 42px;
}

.bento-card[data-edge="top"] {
  --enter-y: -34px;
}

.bento-card[data-edge="bottom"] {
  --enter-y: 34px;
}

@keyframes bar-rise {
  from {
    opacity: 0.35;
    transform: scaleY(0);
  }
  to {
    opacity: 1;
    transform: scaleY(1);
  }
}

.bento-card .chart-bar {
  transform-origin: bottom center;
  animation: bar-rise 0.66s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--bi, 0) * 38ms + 0.32s);
}

/* 横条从左边长出来（scaleX 不触发布局，比动画 width 顺） */
@keyframes h-bar-grow {
  from {
    opacity: 0.4;
    transform: scaleX(0);
  }
  to {
    opacity: 1;
    transform: scaleX(1);
  }
}

.bento-card .h-bar-fill {
  transform-origin: left center;
  animation: h-bar-grow 0.6s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--bi, 0) * 70ms + 0.28s);
}

@keyframes line-draw {
  to {
    stroke-dashoffset: 0;
  }
}

.bento-card .chart-line {
  /* 一次画完：虚线长度取足够大，折线再怎么折也不会露出半截 */
  stroke-dasharray: 1000;
  stroke-dashoffset: 1000;
  animation: line-draw 1.05s cubic-bezier(0.4, 0, 0.2, 1) 0.32s forwards;
}

@keyframes area-in {
  to {
    opacity: 1;
  }
}

.bento-card .chart-area {
  opacity: 0;
  animation: area-in 0.8s ease 0.7s forwards;
}

@keyframes donut-in {
  from {
    opacity: 0;
    transform: rotate(-26deg) scale(0.9);
  }
  to {
    opacity: 1;
    transform: rotate(0) scale(1);
  }
}

.bento-card .chart-donut {
  animation: donut-in 0.9s cubic-bezier(0.22, 1, 0.36, 1) 0.32s both;
}

/*
 * 切换视角时容器会挂上 .chart-swap：
 * 里面的柱子/折线不再重播「从零长出来」，只保留外层的淡入淡出，
 * 否则每换一次视角都像重新加载了一遍。
 */
/*
 * 切换视角时容器会挂上 .chart-swap：
 *  - 柱子和横条照样"长出来"，但更快、错开更小，配合外层淡入；
 *  - 折线和圆环不再重画，跟着整块淡入就够了（重画会像重新加载）。
 */
.chart-swap .chart-bar {
  animation: bar-rise 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--bi, 0) * 24ms + 0.05s);
}

.chart-swap .h-bar-fill {
  animation: h-bar-grow 0.46s cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: calc(var(--bi, 0) * 40ms + 0.04s);
}

.chart-swap .chart-line {
  animation: none !important;
  stroke-dasharray: none;
  stroke-dashoffset: 0;
}

.chart-swap .chart-area {
  animation: none !important;
  opacity: 1;
}

.chart-swap .chart-donut {
  animation: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .bento-card,
  .bento-card .chart-bar,
  .bento-card .h-bar-fill,
  .bento-card .chart-line,
  .bento-card .chart-area,
  .bento-card .chart-donut,
  .chart-swap .chart-bar,
  .chart-swap .h-bar-fill {
    animation: none !important;
  }

  .chart-swap .chart-line,
  .bento-card .chart-line {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
  }

  .bento-card .chart-area {
    opacity: 1;
  }
}

/* 宽屏：连站点顶栏也收掉，整屏都是数据 */
@media (min-width: 1101px) {
  .board-page .site-header {
    display: none;
  }
}

/* 窄屏：放不下一屏，退回单列滚动，卡片顺序不变 */
@media (max-width: 1100px) {
  .board-page {
    overflow: auto;
  }

  .board-page .site-footer {
    display: block;
  }

  .board-shell {
    height: auto;
    grid-template-rows: none;
    gap: 10px;
    padding: 10px 12px 24px;
  }

  .board-bar {
    height: auto;
    flex-wrap: wrap;
    gap: 6px 12px;
  }

  .board-bar-side {
    width: 100%;
    flex-wrap: wrap;
  }

  .board-notice {
    max-width: 100%;
  }

  .bento {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    grid-template-areas: none;
  }

  .bento-hero,
  .bento-kpi,
  .bento-star,
  .bento-donut,
  .bento-recent,
  .bento-trend,
  .bento-top,
  .bento-groups {
    grid-area: auto;
  }

  .bento-card {
    min-height: 200px;
  }

  .bento-card.is-hero {
    min-height: 260px;
  }

  .bento-body {
    min-height: 150px;
  }

  .hero-spark {
    min-height: 80px;
  }

  .bento-card.board-panel .board-panel-body {
    max-height: 320px;
  }
}

/* 矮屏（1366×768 之类）：内边距和字号再收一档，保证还是一屏 */
/*
 * 900 上下（1440×900、1600×900 这类）：卡片只有两行高，
 * 小数据的内边距和字号先收一档，避免格子里的数字和标签互相挤。
 */
@media (max-height: 980px) and (min-width: 1101px) {
  .kpi-tile {
    padding: 5px 9px;
  }

  .kpi-tile b {
    font-size: clamp(0.95rem, 1.15vw, 1.3rem);
  }
}

/*
 * 矮屏（1366×768、1280×720 这类投影/笔记本）：把固定开销全部压一档，
 * 让小卡片里那 100 来像素装得下三行星星、四块小数据或六根横条。
 */
@media (max-height: 800px) and (min-width: 1101px) {
  .board-shell {
    gap: 6px;
    padding: 6px 10px 8px;
  }

  .board-bar {
    height: 30px;
  }

  .board-foot {
    height: 16px;
    font-size: 0.66rem;
  }

  .bento {
    gap: 8px;
  }

  .bento-card {
    gap: 6px;
    padding: 10px 13px;
    border-radius: 18px;
  }

  .bento-card.board-panel {
    padding-bottom: 0;
  }

  .bento-head {
    min-height: 18px;
  }

  .bento-label {
    font-size: 0.74rem;
  }

  .hero-value b {
    font-size: clamp(44px, 5vw, 78px);
  }

  .hero-foot {
    gap: 16px;
    margin-top: 6px;
  }

  .hero-foot b {
    font-size: 1rem;
  }

  .kpi-grid {
    /* 矮屏上四块小数据排成一行，横着铺开比 2×2 更省高度 */
    grid-template-columns: repeat(4, minmax(0, 1fr));
    grid-template-rows: minmax(0, 1fr);
  }

  .kpi-tile {
    padding: 5px 9px;
  }

  .kpi-tile b {
    font-size: clamp(1rem, 1.2vw, 1.3rem);
  }

  .kpi-meter-bar {
    height: 4px;
  }

  .star-row {
    padding: 3px 8px;
  }

  .star-name {
    font-size: 0.8rem;
  }

  .bento-body .h-bars {
    gap: 5px;
  }

  .bento-body .h-bar-track {
    height: 4px;
  }

  .bento-body .h-bar-row {
    font-size: 0.72rem;
  }
}

/* ------------------------------- 快速记分（头像墙） ------------------------------- */
/*
 * 这一页的规矩是「一屏点完」：页面不滚动，学生的格子按可用面积自动铺满——
 * 人少时格子大、头像大，人多时自动多分几列，永远不用上下滑。
 * 列数（--cols）和头像大小（--avatar）由 award-quick.js 的 fitGrid() 现算，
 * 窗口一变就重算，所以投到投影上也一样铺满。
 */
.quick-page {
  height: 100vh;
  height: 100dvh;
  /* 盖掉通用 .page 的上下留白：这一页要顶满整屏 */
  padding: 0;
  overflow: hidden;
}

.quick-page .site-footer {
  display: none;
}

.quick-shell {
  /* 盖掉 .container 的 1180px 上限：宽屏上头像墙要铺到左右两边 */
  width: 100%;
  max-width: none;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  gap: 10px;
  height: calc(100vh - var(--header-h));
  height: calc(100dvh - var(--header-h));
  padding: 10px 18px 12px;
  overflow: hidden;
}

/* 标题和右上角按钮压成一行，给头像墙多留高度 */
.quick-head {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.quick-head h1 {
  font-size: 1.2rem;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.quick-head .sub {
  min-width: 0;
  font-size: 0.74rem;
  color: var(--text-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.quick-head .page-head-actions {
  flex-wrap: nowrap;
  margin-left: auto;
}

.quick-toolbar {
  margin: 0;
  padding: 6px 10px;
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.quick-toolbar .search-box {
  flex: 1 1 180px;
  max-width: 300px;
}

.quick-toolbar .label strong {
  font-family: var(--mono);
  font-size: 0.95rem;
  color: var(--text);
}

/* 头像墙本体：只吃剩下的高度，不滚动 */
.dojo-grid-wrap {
  min-height: 0;
  overflow: hidden;
}

/* 人数多到最小格子都放不下时才允许在这里滚（正常情况不会出现） */
.dojo-grid-wrap.is-scroll {
  overflow: auto;
}

.dojo-grid {
  display: grid;
  height: 100%;
  /* 具体值由 award-quick.js 按屏幕宽度算好写进 --dojo-gap，两边用同一个数 */
  gap: var(--dojo-gap, 8px);
  grid-template-columns: repeat(var(--cols, 6), minmax(0, 1fr));
  grid-auto-rows: minmax(0, 1fr);
  align-content: stretch;
}

.dojo-student {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: calc(var(--avatar, 56px) * 0.1);
  min-width: 0;
  min-height: 0;
  padding: 6px 4px;
  overflow: hidden;
  font-family: inherit;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: clamp(10px, 1.3vw, 18px);
  cursor: pointer;
  user-select: none;
  transition: transform 0.12s var(--ease), box-shadow 0.12s var(--ease), border-color 0.12s var(--ease);
}

.dojo-student:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}

.dojo-student:active {
  transform: translateY(0) scale(0.985);
}

.dojo-student:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
  border-color: var(--primary);
}

/* 已选中又被键盘聚焦：两套指示同时给出，别互相覆盖 */
.dojo-student.is-picked:focus-visible {
  outline: 3px solid var(--primary-strong);
  outline-offset: 3px;
}

.dojo-student.is-picked {
  border-color: var(--primary);
  box-shadow: 0 0 0 2px var(--primary), var(--shadow);
}

/* 选中的对勾放左上角，右上角留给分数 */
.dojo-student.is-picked::after {
  content: "✓";
  position: absolute;
  top: 5px;
  left: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
  font-size: 0.64rem;
  line-height: 1;
}

.dojo-avatar {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: var(--avatar, 56px);
  height: var(--avatar, 56px);
  border-radius: 50%;
  color: #fff;
  font-size: calc(var(--avatar, 56px) * 0.42);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.02em;
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.14);
}

.dojo-name {
  max-width: 100%;
  overflow: hidden;
  font-size: clamp(10px, calc(var(--avatar, 56px) * 0.3), 19px);
  font-weight: 650;
  line-height: 1.15;
  text-align: center;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* 学号 · 小组 */
.dojo-meta {
  max-width: 100%;
  overflow: hidden;
  font-family: var(--mono);
  font-size: clamp(9px, calc(var(--avatar, 56px) * 0.21), 13px);
  line-height: 1.2;
  color: var(--text-dim);
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* 名字和学号打包，宽卡片时可以整体挪到头像右边 */
.dojo-text {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  min-width: 0;
  max-width: 100%;
}

/*
 * 格子很宽时（人少、屏幕大）：头像在左、名字在右，
 * 否则一张 400×140 的横条卡片中间会空一大块。
 */
.dojo-grid.is-wide .dojo-student {
  flex-direction: row;
  justify-content: center;
  align-items: center;
  gap: calc(var(--avatar, 56px) * 0.24);
  padding: 0 calc(var(--avatar, 56px) * 0.3);
}

.dojo-grid.is-wide .dojo-text {
  align-items: flex-start;
}

.dojo-grid.is-wide .dojo-name,
.dojo-grid.is-wide .dojo-meta {
  text-align: left;
}

.dojo-score {
  position: absolute;
  top: 5px;
  right: 6px;
  padding: 1px 6px;
  font-family: var(--mono);
  font-size: clamp(9px, calc(var(--avatar, 56px) * 0.19), 12px);
  font-weight: 600;
  line-height: 1.5;
  color: var(--text-dim);
  background: var(--surface-2);
  border-radius: var(--radius-pill);
}

.dojo-score.is-pos {
  color: var(--success);
  background: var(--success-soft);
}

.dojo-score.is-neg {
  color: var(--danger);
  background: var(--danger-soft);
}

/* 记分时从头像上飘起来的 +2 */
.dojo-float {
  position: absolute;
  top: 22%;
  left: 50%;
  font-family: var(--mono);
  font-size: calc(var(--avatar, 56px) * 0.34);
  font-weight: 700;
  pointer-events: none;
  animation: float-up 0.9s var(--ease) forwards;
}

.dojo-float.is-pos {
  color: var(--success);
}

.dojo-float.is-neg {
  color: var(--danger);
}

@keyframes float-up {
  0% {
    opacity: 0;
    transform: translate(-50%, 8px) scale(0.9);
  }
  20% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -34px) scale(1.05);
  }
}

/* 底部常驻的加减分条：跟着布局走，不再浮在页面上 */
.quick-dock {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
}

.dock-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.dock-label {
  flex: 0 0 auto;
  padding: 3px 10px;
  font-size: 0.74rem;
  font-weight: 700;
  border-radius: var(--radius-pill);
}

.dock-label.is-pos {
  color: var(--success);
  background: var(--success-soft);
}

.dock-label.is-neg {
  color: var(--danger);
  background: var(--danger-soft);
}

.dock-label.is-operator {
  color: var(--primary);
  background: var(--primary-soft);
}

.dojo-pill.is-operator[aria-pressed="true"] {
  color: #fff;
  background: var(--primary);
  border-color: var(--primary);
}

.dojo-pill.is-operator[aria-pressed="false"] {
  color: var(--text-soft);
}

.dock-pills {
  display: flex;
  gap: 8px;
  min-width: 0;
  overflow-x: auto;
  padding-bottom: 2px;
  scrollbar-width: thin;
}

.dojo-pill {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  font-family: inherit;
  font-size: 0.84rem;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.12s var(--ease);
}

.dojo-pill:hover {
  background: var(--surface);
}

.dojo-pill.is-add:hover {
  border-color: var(--success);
  color: var(--success);
}

.dojo-pill.is-deduct:hover {
  border-color: var(--danger);
  color: var(--danger);
}

.dojo-pill b {
  font-family: var(--mono);
  font-size: 0.8rem;
}

.dojo-pill.is-add b {
  color: var(--success);
}

.dojo-pill.is-deduct b {
  color: var(--danger);
}

.dojo-pill:disabled {
  opacity: 0.5;
  cursor: progress;
}

/*
 * 状态行：高度写死，平时是提示语，记完分变成「已给谁记了多少 + 撤销」。
 * 高度固定是关键——撤销按钮出现/消失都不会把下面那条加减分条顶动，
 * 头像墙也就不会因为重新布局而跳一下。
 */
.dojo-status {
  display: flex;
  align-items: center;
  gap: 10px;
  height: 26px;
  min-height: 26px;
  font-size: 0.8rem;
  color: var(--text-soft);
  white-space: nowrap;
}

.dojo-status > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dojo-status .btn {
  flex: 0 0 auto;
  margin-left: auto;
}

/* 窄屏：底部导航占了一条，减掉它的高度，其余照旧铺满 */
@media (max-width: 760px) {
  .quick-shell {
    height: calc(100vh - var(--header-h) - 62px);
    height: calc(100dvh - var(--header-h) - 62px);
    gap: 8px;
    padding: 8px 10px 8px;
  }

  .quick-head {
    gap: 8px;
  }

  .quick-head .sub {
    display: none;
  }

  .quick-head .page-head-actions .btn {
    padding: 4px 8px;
    font-size: 0.76rem;
  }

  .quick-toolbar {
    padding: 5px 8px;
  }

  .quick-toolbar .search-box {
    flex: 1 1 120px;
  }

  .dock-label {
    display: none;
  }

  .dojo-pill {
    padding: 6px 10px;
    font-size: 0.8rem;
  }

  .quick-dock {
    padding: 8px 10px;
    gap: 6px;
  }
}

/* ------------------------------- 全局动效 ------------------------------- */
/*
 * 全站一套克制的入场节奏（看板除外，它有自己的便当格动画）：
 *   · 标题栏、面板、统计卡、模块卡：淡入 + 10px 上浮
 *   · 表格行、记录行、选择行：只淡入（行多，位移会花）
 *   · 网格类列表按位置错开一点，避免整页"一起蹦"
 *   · 全部用 backwards 而不是 both：动画结束后把样式交还给元素本身，
 *     否则 hover 的位移会被动画末帧的 transform: none 盖掉
 */
@keyframes rise-in {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes card-pop {
  from {
    opacity: 0;
    transform: scale(0.94);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.page-head {
  animation: rise-in 0.34s var(--ease) backwards;
}

/* 登录页那张卡片稍微"抬起来"一点 */
.auth-card {
  animation: rise-in 0.38s var(--ease) backwards;
}

.panel {
  animation: rise-in 0.34s var(--ease) backwards;
}

.stat,
.module-card,
.cat-item {
  animation: rise-in 0.32s var(--ease) backwards;
}

.pick-row,
.record-item {
  animation: fade-in 0.2s var(--ease) backwards;
}

.table tbody tr {
  animation: fade-in 0.18s var(--ease) backwards;
}

/* 快速记分的头像卡片：轻轻弹出来 */
.dojo-student {
  animation: card-pop 0.28s var(--ease) backwards;
}

/* 看板有自己的挂载动画，行内条目不再淡入一遍 */
.board-page .record-item {
  animation: none;
}

/* 网格里的第 2~6 个错开 45ms，看起来是"依次落位"而不是整块闪一下 */
.stat-grid > .stat:nth-child(2),
.module-grid > .module-card:nth-child(2),
.cat-list > .cat-item:nth-child(2),
.pick-list > .pick-row:nth-child(2) {
  animation-delay: 45ms;
}

.stat-grid > .stat:nth-child(3),
.module-grid > .module-card:nth-child(3),
.cat-list > .cat-item:nth-child(3),
.pick-list > .pick-row:nth-child(3) {
  animation-delay: 90ms;
}

.stat-grid > .stat:nth-child(4),
.module-grid > .module-card:nth-child(4),
.cat-list > .cat-item:nth-child(4),
.pick-list > .pick-row:nth-child(4) {
  animation-delay: 135ms;
}

.stat-grid > .stat:nth-child(5),
.module-grid > .module-card:nth-child(5),
.cat-list > .cat-item:nth-child(5),
.pick-list > .pick-row:nth-child(5) {
  animation-delay: 180ms;
}

.stat-grid > .stat:nth-child(6),
.module-grid > .module-card:nth-child(6),
.cat-list > .cat-item:nth-child(6),
.pick-list > .pick-row:nth-child(6) {
  animation-delay: 225ms;
}

/* 提示条从下往上冒出来 */
@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.toast {
  animation: toast-in 0.24s var(--ease) backwards;
}

/* 按钮按下时 1px 下沉，配合已有的 hover 变色 */
.btn:active:not(:disabled) {
  transform: translateY(1px);
}

/* ------------------------------- 响应式 ------------------------------- */
/* 看板在窄屏的布局见上方「一屏看板 · 便当格」里的同名媒体查询 */

@media (max-width: 1000px) {
  .split,
  .award-layout,
  .split.is-even,

  .stat-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .module-grid {
    grid-template-columns: repeat(2, 1fr);
  }

}

@media (max-width: 760px) {
  html {
    font-size: 16px;
  }

  .container {
    padding: 0 16px;
  }

  .page {
    padding: 22px 0 88px;
  }

  .page-head {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .page-head h1 {
    font-size: 1.6rem;
  }

  .page-head .page-head-actions {
    margin-left: 0;
    width: 100%;
  }

  .page-head .page-head-actions .btn {
    flex: 1 1 auto;
  }

  .nav,
  .header-actions .btn-label,
  .brand-sub {
    display: none;
  }

  .header-inner {
    gap: 12px;
  }

  /* 手机端底部标签栏 */
  .mobile-nav {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 50;
    gap: 4px;
    padding: 7px 10px calc(7px + env(safe-area-inset-bottom));
    background: var(--header-bg);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    border-top: 1px solid var(--border);
  }

  .mobile-nav a {
    flex: 1 1 0;
    padding: 9px 4px;
    text-align: center;
    font-size: 0.8rem;
    color: var(--text-soft);
    border-radius: var(--radius-sm);
  }

  .mobile-nav a[aria-current="page"] {
    color: var(--primary);
    background: var(--primary-soft);
    font-weight: 600;
  }

  .site-footer {
    padding-bottom: 70px;
  }

  .stat-grid {
    grid-template-columns: 1fr 1fr;
    gap: 10px;
  }

  .stat {
    padding: 14px 15px;
  }

  .stat-value {
    font-size: 1.45rem;
  }

  .stat.is-hero {
    grid-column: 1 / -1;
  }

  .stat.is-hero .stat-value {
    font-size: 2.1rem;
  }

  .record-item {
    grid-template-columns: 64px 1fr;
    gap: 10px;
    padding: 12px 10px;
  }

  .record-time {
    grid-column: 2;
    text-align: left;
  }

  .award-layout {
    gap: 16px;
  }

  .pick-list {
    max-height: 320px;
  }

  .form-grid {
    grid-template-columns: 1fr;
  }

  .profile-head {
    flex-wrap: wrap;
    padding: 18px;
  }

  .profile-score {
    margin-left: 0;
    text-align: left;
    width: 100%;
    padding-left: 0;
    padding-top: 14px;
    border-top: 1px solid var(--border);
  }

  .profile-score .score-big {
    font-size: 2.5rem;
  }

  .toolbar .search-box,
  .toolbar .search-box .input,
  .toolbar .input,
  .toolbar .select {
    width: 100%;
    min-width: 0;
  }

  .toolbar .field {
    width: 100%;
  }

  .table th,
  .table td {
    padding: 10px 12px;
  }

  .modal {
    padding: 14px;
    align-items: flex-end;
  }

  .modal-box {
    width: 100%;
    max-height: 86vh;
    border-radius: var(--radius-lg);
    padding: 20px 18px 18px;
  }

  .module-grid {
    grid-template-columns: 1fr;
  }

  .board-page .board-bar-side {
    gap: 6px;
  }

  .board-page .hero-value b {
    font-size: 52px;
  }

  .board-page .hero-foot {
    gap: 16px;
  }

  .subnav {
    gap: 2px;
    padding: 5px;
  }

  .subnav a {
    padding: 6px 11px;
    font-size: 0.84rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
