/* 站点样式 —— 「纸墨」主题（2026-10-28 重设计）。
   设计意图：做题站点要像"一张安静的卷子"，不要像后台管理系统。
   · 暖纸色底 + 白卡片 + 墨色文字：长时间读题不刺眼；
   · 顶栏/页脚用墨色（深底浅字），和内容区形成清晰的"页面骨架"；
   · 唯一的强调色是朱砂（#b23a26），只用在动作与当前态上 ——
     满屏高亮色是"模板脸"的最大来源；
   · 标题用衬线字体（中文回退宋体），正文无衬线：层级靠字体切换而不是靠加粗。
   风格取向：极简、信息层级清楚、无外网依赖（不引 CDN，离线也能正常显示）。
   配色语义（success=绿/danger=红）与 constants.RESULT_LABEL_CLASS 对齐，
   判题结果徽标的颜色语义不能变。 */

:root {
  --paper: #f5f2ea;        /* 页面底：暖纸色 */
  --panel: #fffdf8;        /* 卡片：近白微暖 */
  --border: #e2dac9;
  --border-strong: #cfc4ad;
  --text: #26221a;         /* 墨色 */
  --muted: #7d7563;
  --accent: #b23a26;       /* 朱砂：动作、当前态、品牌标记 */
  --accent-dark: #8e2c1b;
  --ink: #26221a;          /* 顶栏/页脚深底 */
  --ink-soft: #3a352a;
  --cream: #f2ede1;        /* 深底上的文字 */
  --cream-dim: #b5ad9a;
  --success: #2f7d4f;
  --danger: #a12615;
  --warning: #9a6b0f;
  --info: #33608d;
  --scratch: #6b5aa0;      /* 积木（Scratch）通道的辅助色：低饱和紫藤，不与朱砂抢戏 */
  --radius: 4px;
  --shadow: 0 1px 2px rgba(38, 34, 26, .07), 0 2px 8px rgba(38, 34, 26, .04);
}

* { box-sizing: border-box; }

/* 页脚永远贴在视口最下面。
   ★ 做法是「整页当一根竖着的弹性盒子，让 <main> 吃掉剩余空间」，
     而不是给页脚 `position: fixed`：
       · fixed 会让页脚浮在内容之上，内容长的时候最后一段被盖住；
       · 而且 fixed 元素不占流，滚动到底时看起来"页脚下面还有一截空白"。
     `min-height: 100vh` 保证内容很短（比如空列表、报错页）时页脚也在最后一行。
     100dvh 是给手机浏览器地址栏伸缩用的：只写 100vh 时，移动端会出现
     "页脚被地址栏切掉一条"的问题，写两行让支持的浏览器用后者。 */
html { height: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--text);
  font: 15px/1.7 "Segoe UI", "Microsoft YaHei", "PingFang SC", Roboto, sans-serif;
}

/* 三段式：顶栏与页脚不参与伸缩（flex:0 0 auto），中间那段吃掉所有剩余高度。
   ★ 不写 `flex: 1` 简写：它等价于 `1 1 0%`，会把 <main> 的基准高度压成 0，
     里面 `height:100%` 的子元素就没有参照物了。
   ★★ `width: 100%` 不能省。`.container` 带着 `margin: 0 auto`，
      而在 flex 容器里**轴向 margin 设成 auto 会取消拉伸**（stretch）：
      弹性项目不再被拉满容器宽度，而是收缩到内容宽度后再居中。
      实测漏写这一行的后果：<main> 从 1180px 缩成 578px，
      每个页面宽度各不相同、表格也缩成一条 —— 看起来"居中了"，
      其实是布局塌了。 */
.site-header { flex: 0 0 auto; }
main.page { flex: 1 0 auto; width: 100%; }
.site-footer { flex: 0 0 auto; }

a { color: var(--text); text-decoration: underline; text-decoration-color: var(--border-strong); text-underline-offset: 3px; }
a:hover { color: var(--accent); text-decoration-color: var(--accent); }

.container { max-width: 1120px; margin: 0 auto; padding: 0 20px; }

/* ---------- 顶栏：墨色横杆 ---------- */
.site-header {
  background: var(--ink);
  color: var(--cream);
  position: sticky; top: 0; z-index: 20;
}
.header-inner { display: flex; align-items: center; gap: 28px; height: 60px; }
/* 品牌名：衬线 + 朱砂方块标记。方块用 ::before 画，不往模板里塞装饰元素。 */
.brand {
  font-family: Georgia, "Times New Roman", "Songti SC", SimSun, serif;
  font-size: 20px; font-weight: 700; letter-spacing: 1px;
  color: var(--cream); text-decoration: none;
  display: inline-flex; align-items: center; gap: 10px;
}
.brand::before {
  content: ""; width: 10px; height: 10px; background: var(--accent);
  flex: 0 0 auto;
}
.brand:hover { color: #fff; text-decoration: none; }
.nav { display: flex; gap: 4px; flex: 1; flex-wrap: wrap; }
.nav a {
  color: var(--cream-dim); text-decoration: none;
  padding: 4px 10px; border-radius: 3px;
}
.nav a:hover { color: var(--cream); background: var(--ink-soft); text-decoration: none; }
.user-box { display: flex; gap: 6px; align-items: center; }
.user-box a {
  color: var(--cream-dim); text-decoration: none;
  padding: 4px 10px; border-radius: 3px;
}
.user-box a:hover { color: var(--cream); background: var(--ink-soft); }

/* ---------- 页面 ---------- */
.page { padding: 32px 20px 56px; }
/* 衬线大标题：题名/页名一眼分层。中文回退宋体 —— 字重变化小，
   所以靠"衬线 + 字号"而不是靠加粗。 */
h1 {
  font-family: Georgia, "Times New Roman", "Songti SC", SimSun, serif;
  font-size: 27px; font-weight: 600; margin: 0 0 20px; line-height: 1.35;
}
h2 { font-size: 19px; margin: 30px 0 14px; font-weight: 600; }
h3 { font-size: 16px; margin: 20px 0 8px; font-weight: 600; }

.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  margin-bottom: 18px;
  box-shadow: var(--shadow);
}

.muted { color: var(--muted); }
.small { font-size: 13px; }
.right { text-align: right; }
.center { text-align: center; }
.nowrap { white-space: nowrap; }

/* ---------- 表格：去底色、只留分隔线（表格脸的重点就在这） ---------- */
table { width: 100%; border-collapse: collapse; background: var(--panel); }
th, td { padding: 9px 12px; border-bottom: 1px solid var(--border); text-align: left; }
th {
  background: transparent; font-weight: 600; color: var(--muted);
  font-size: 12.5px; letter-spacing: .06em; white-space: nowrap;
  border-bottom: 1px solid var(--border-strong);
}
tbody tr:hover { background: rgba(38, 34, 26, .028); }

/* 中文表格防「一列一个字」：给常见列宽下限，并允许长内容换行 */
table td { word-break: break-word; }
td.col-title { min-width: 220px; }
td.col-user { min-width: 90px; }
/* 编号/计数列（题号、通过数、提交 ID…）：居中。
   2026-10-29 用户反馈：表头左对齐、数字右对齐，视觉上"没对齐"。
   居中后表头与数据天然对齐，短数字列也更紧凑。
   ★ 表头没有 col-num class，用 center-col 补齐同一列的 <th>。 */
td.col-num { text-align: center; font-variant-numeric: tabular-nums; }
th.center-col, td.center-col { text-align: center; }

/* 排名榜：整表居中。
   ★ 用 `table.ranklist` 而不是给每个 <td> 加 class —— 少写 6 处容易漏，
     而且以后加列（比如"班级"）不用再补样式。
   （test_ranklist_page 钉着这条规则原文，改写法前先看测试。） */
table.ranklist th, table.ranklist td { text-align: center; }
table.ranklist td { font-variant-numeric: tabular-nums; }

/* ---------- 徽标（与 constants.RESULT_LABEL_CLASS 对应） ---------- */
.label {
  display: inline-block; padding: 1px 8px; border-radius: 3px;
  font-size: 12px; font-weight: 600; line-height: 18px; color: #fff;
}
.label-default { background: #8b8272; }
.label-info { background: var(--info); }
.label-success { background: var(--success); }
.label-warning { background: var(--warning); }
.label-danger { background: var(--danger); }

/* ---------- 按钮与表单 ---------- */
.btn {
  display: inline-block; padding: 7px 16px; border-radius: 3px; cursor: pointer;
  border: 1px solid var(--border-strong); background: var(--panel); color: var(--text);
  font-size: 14px; text-decoration: none;
}
.btn:hover { border-color: var(--ink); color: var(--ink); text-decoration: none; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn-primary:hover { background: var(--accent-dark); border-color: var(--accent-dark); color: #fff; }
.btn-danger { background: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger:hover { background: #7d1c0f; border-color: #7d1c0f; color: #fff; }
/* 积木编程入口：描边式辅助色按钮，主操作（提交代码）仍然是朱砂实心。 */
.btn-scratch { border-color: var(--scratch); color: var(--scratch); }
.btn-scratch:hover { background: rgba(107, 90, 160, .08); border-color: #584a88; color: #584a88; }
/* 表格行内的紧凑按钮：整行都是大按钮会变成"按钮墙"。 */
.btn-sm { padding: 3px 10px; font-size: 12.5px; }
/* 描边式危险操作：比实心红安静，适合出现在每一行里。 */
.btn-quiet-danger { border-color: var(--danger); color: var(--danger); background: transparent; }
.btn-quiet-danger:hover { background: var(--danger); border-color: var(--danger); color: #fff; }

/* 文件上传按钮：浏览器默认的 "Choose File" 灰按钮和整站风格脱节，
   用 ::file-selector-button 换成普通按钮脸（Chrome/Edge/Firefox 均支持）。 */
input[type=file] { font-size: 13px; color: var(--muted); }
input[type=file]::file-selector-button {
  padding: 6px 14px; margin-right: 10px; cursor: pointer;
  border: 1px solid var(--border-strong); border-radius: 3px;
  background: var(--panel); color: var(--text); font: inherit; font-size: 13px;
}
input[type=file]::file-selector-button:hover { border-color: var(--ink); color: var(--ink); }

input[type=text], input[type=password], input[type=email], input[type=number],
input[type=tel], input[type=search], input[type=url], input[type=date],
input[type=time], input[type=datetime-local], select, textarea {
  width: 100%; padding: 8px 10px; border: 1px solid var(--border-strong);
  border-radius: 3px; font: inherit; background: var(--panel); color: var(--text);
}
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent);
}
textarea { min-height: 120px; resize: vertical; font-family: ui-monospace, Consolas, monospace; }
label { display: block; margin: 12px 0 4px; color: var(--muted); font-size: 13px; }
.form-row { display: flex; gap: 16px; flex-wrap: wrap; }
.form-row > * { flex: 1 1 220px; }

.alert {
  background: #f5ecd7; border: 1px solid #dbc187; color: #6d4e08;
  padding: 11px 14px; border-radius: 3px; margin-bottom: 18px;
}
.alert-error { background: #f7e2dc; border-color: #d5988a; color: #7d1c0f; }
.alert-success { background: #e2eee5; border-color: #a7c6b1; color: #245c3a; }

/* ---------- 维护模式 ---------- */
/* 管理员横幅：开着维护时，管理员自己的页面顶部挂一条朱砂提醒。 */
.maint-banner {
  background: var(--accent); color: #fff; padding: 10px 14px;
  border-radius: 3px; margin-bottom: 18px; font-weight: 600;
}
.maint-banner a { color: #fff; text-decoration: underline; }
.maint-banner a:hover { color: var(--cream); }

/* 后台仪表盘上的开关行 */
.maint-switch { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.maint-state { margin: 0 0 4px; font-weight: 600; display: flex; align-items: center; gap: 8px; }
.maint-state .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--success); flex: 0 0 auto; }
.maint-state.on .dot { background: var(--accent); }
.maint-form { flex: 0 0 auto; }

/* 维护页（503）：自足的居中页，墨底反白。 */
.maint-body {
  background: var(--ink); color: var(--cream);
  min-height: 100vh; min-height: 100dvh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  margin: 0; padding: 24px; text-align: center;
}
.maint { max-width: 460px; }
.maint-mark {
  width: 14px; height: 14px; background: var(--accent); margin: 0 auto 28px;
}
.maint h1 {
  font-family: Georgia, "Times New Roman", "Songti SC", SimSun, serif;
  font-size: 30px; color: var(--cream); margin: 0 0 14px;
}
.maint-note { color: var(--cream-dim); margin: 6px 0; }
.maint-note a { color: var(--cream); }
.maint-footer {
  margin-top: 48px; font-size: 12px; color: var(--cream-dim);
  display: flex; gap: 16px; flex-wrap: wrap; justify-content: center;
}
.maint-footer a { color: var(--cream-dim); }
.maint-footer a:hover { color: var(--cream); }

/* 积木编程提示卡：紫藤左线与入口按钮同一颜色语义。 */
.scratch-card { border-left: 3px solid var(--scratch); }

/* ---------- 题面 ---------- */
.problem-body { line-height: 1.85; }
.problem-body pre {
  background: #f0ece1; border: 1px solid var(--border); border-radius: 3px;
  padding: 12px 14px; overflow: auto; font-family: ui-monospace, Consolas, monospace;
  font-size: 13.5px;
}
.problem-body code { background: #f0ece1; padding: 1px 5px; border-radius: 3px; }
.problem-meta span { margin-right: 18px; color: var(--muted); }

/* ---------- 榜单 ---------- */
.rank-table td.cell { text-align: center; color: #fff; font-variant-numeric: tabular-nums; }
.rank-table td.cell-empty { background: #ece7da; }
.rank-badge { display: inline-block; padding: 0 6px; border-radius: 3px; background: #efeadd; }

/* ---------- 题目分类 ----------
   分类页在 GESP 归并后只剩寥寥几项，用"标签"形态而不是列表 ——
   一眼能扫完，点击面积也够大（原先是行内 <a> 挤成一行，窄屏会折成一坨）。 */
.cat-list { display: flex; flex-wrap: wrap; gap: 10px; }
.cat-chip {
  display: inline-block; padding: 8px 16px; border-radius: 3px;
  border: 1px solid var(--border-strong); background: var(--panel);
  text-decoration: none; font-size: 15px;
}
.cat-chip:hover { border-color: var(--accent); color: var(--accent); }
/* GESP 是题量最大的入口，给一条朱砂左线做视觉锚点（与首页公告卡同一语言） */
.cat-chip-gesp { border-left: 3px solid var(--accent); font-weight: 600; }

/* 热更新重启中的横幅：朱砂左线 + 呼吸点，与"维护进行中"同一套语言。
   ★ 它出现的时间窗只有几秒（服务重启），所以不做过渡动画 ——
     淡入还没走完页面就刷新了。 */
.restart-banner { border-left: 4px solid var(--accent); }
.restart-banner strong { color: var(--accent); }

/* ---------- 类内筛选条（级别 / 语言） ---------- */
.filter-bar {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin: 0 0 16px; padding: 10px 12px;
  background: var(--panel); border: 1px solid var(--border); border-radius: 3px;
}
.filter-label {
  font-size: 12px; color: var(--muted); letter-spacing: .08em;
  margin-right: 2px;
}
.filter-label + .filter-chip { margin-left: 0; }
.filter-bar .filter-label:not(:first-child) { margin-left: 10px; }
.filter-chip {
  display: inline-block; padding: 3px 10px; border-radius: 3px;
  font-size: 13px; text-decoration: none; color: var(--text);
  border: 1px solid transparent;
}
.filter-chip:hover { border-color: var(--border-strong); color: var(--accent); }
/* 当前筛选：实心朱砂。只靠颜色不加粗 —— 加粗会让这一格的宽度跳变，整条筛选带抖一下 */
.filter-chip.on { background: var(--accent); color: #fff; }
.filter-chip.on:hover { color: #fff; }

/* 班级统计矩阵（人数 × 题数）。列可能有上百条：
   ★ 不能让它按 width:100% 硬挤 —— 挤到每列只剩三十来像素时，
     "AC" 会被 word-break 断成 "A" 换行 "C"，整张矩阵变成一列列字母，
     看着像数据坏了。宁可让外层卡片横向滚动。
   ★ width: auto + min-width: 100%：列少时仍然铺满，列多时按内容撑开。 */
table.matrix { width: auto; min-width: 100%; }
table.matrix th, table.matrix td { white-space: nowrap; }

/* ---------- 分页（标准页码组件） ---------- */
/* 居中排布：页码是一排"按钮"，靠左会显得页面没对齐。 */
.pager {
  display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
  justify-content: center; margin: 24px 0 8px;
}
.pager a, .pager span {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 34px; padding: 0 10px;
  border: 1px solid var(--border-strong); border-radius: 3px; background: var(--panel);
  color: var(--text); font-variant-numeric: tabular-nums; line-height: 1;
  text-decoration: none;
}
.pager a:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
/* 当前页：实心墨色，且不可点（用 span 而不是 a，避免"点了回到同一页"的假链接） */
.pager .cur {
  background: var(--ink); border-color: var(--ink); color: var(--cream); font-weight: 600;
}
/* 省略号与禁用态都不该看起来像可点的按钮 */
.pager .gap { border: 0; background: none; min-width: 20px; color: var(--muted); }
.pager .disabled { color: #b3ab99; background: transparent; border-color: var(--border); }
.pager .jump { margin-left: 6px; color: var(--muted); font-size: 12px; border: 0; background: none; }

/* ---------- 统计卡片 ---------- */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 14px; }
.stat {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 16px; box-shadow: var(--shadow);
}
/* 数字用衬线放大 —— 统计是首页的"脸"，值得单独一个字阶。 */
.stat .num {
  font-family: Georgia, "Times New Roman", "Songti SC", SimSun, serif;
  font-size: 30px; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1.2;
}
.stat .k { color: var(--muted); font-size: 13px; }

/* ---------- 首页专属 ---------- */
/* 头版：标题区不做渐变/大色块，靠"大衬线字 + 一条朱砂短线"定调。
   装饰越少，越不像模板。 */
.home-hero { padding: 18px 0 8px; }
.home-hero .rule { width: 44px; height: 3px; background: var(--accent); margin: 14px 0 0; }
.home-hero h1 { font-size: 34px; margin-bottom: 6px; }
.home-hero .sub { color: var(--muted); font-size: 15px; }
.home-stats { margin: 22px 0 30px; }
.news-item {
  background: var(--panel); border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: var(--radius); padding: 16px 20px; margin-bottom: 14px; box-shadow: var(--shadow);
}
.news-item h3 { margin: 0 0 8px; }

/* ---------- 页脚：墨色，与顶栏呼应 ---------- */
.site-footer {
  border-top: 0; background: var(--ink); color: var(--cream-dim);
  padding: 22px 0; margin-top: 40px;
}
.footer-inner {
  display: flex; flex-wrap: wrap; gap: 6px 20px;
  justify-content: center; align-items: center;
  color: var(--cream-dim); font-size: 12.5px;
}
.footer-link { color: var(--cream-dim); text-decoration: none; }
.footer-link:hover { color: var(--cream); text-decoration: underline; }
.footer-item { color: var(--cream-dim); }
/* 公安备案盾徽。官方图标是 62×67 的方形徽标，14px 高会把细节糊成一团，
   所以按 16px 给（与页脚文字同一行，视觉上不抢），宽度靠比例自适应。
   display:inline-block 去掉行内基线留白，否则图标会把行高撑开 2~3px。
   深底上给图标垫一小块亮色，盾徽线条才看得清。 */
.beian-icon {
  height: 16px; width: auto; display: inline-block; vertical-align: -3px; margin-right: 4px;
  background: var(--cream); border-radius: 2px; padding: 1px;
}

/* ---------- 代码编辑器区 ---------- */
.code-area {
  width: 100%; min-height: 340px; font-family: ui-monospace, Consolas, "Courier New", monospace;
  font-size: 13px; line-height: 1.55; tab-size: 4;
}
.vcode-img { height: 40px; border: 1px solid var(--border-strong); border-radius: 3px; cursor: pointer; }

@media (max-width: 720px) {
  .header-inner { height: auto; padding: 10px 0; flex-wrap: wrap; }
  .nav { order: 3; width: 100%; }
  h1 { font-size: 23px; }
  .home-hero h1 { font-size: 27px; }
}

/* ---------- 站点素材（后台可替换的整站图片，2026-11-05） ---------- */
/* 页头标志：只定高度，宽度自适应，保证换任意比例的图都不会把导航挤走。
   .brand 本身是 inline-flex + gap:10px，图片作为 flex 项自然垂直居中，
   不需要再补 margin / vertical-align（补了反而和 gap 叠成双倍间距）。 */
.brand-logo { height: 28px; width: auto; }
/* 有标志时藏掉 .brand::before 那个朱砂小方块：两个品牌标记并排会显得没对齐 */
.brand.has-logo::before { display: none; }

/* 首页横幅：只在后台设置过素材时渲染，容器本身不留高度 ---------- */
.home-banner { margin: 0 0 20px; }
.home-banner img {
  display: block; width: 100%; height: auto;
  border: 1px solid var(--border); border-radius: var(--radius);
}

/* ---------- 后台：素材管理 ---------- */
.tab-nav { display: flex; gap: 2px; margin: 0 0 16px; border-bottom: 1px solid var(--border); }
.tab-nav a {
  padding: 7px 14px; font-size: 14px; text-decoration: none; color: var(--muted);
  border: 1px solid transparent; border-bottom: none; border-radius: 3px 3px 0 0;
}
.tab-nav a:hover { color: var(--accent); }
/* 当前页签：白底 + 盖住那条下边框，视觉上与下面的内容连成一片 */
.tab-nav a.on {
  background: var(--panel); border-color: var(--border); color: var(--accent);
  margin-bottom: -1px; padding-bottom: 8px;
}

.asset-grid {
  display: grid; gap: 14px; margin-bottom: 22px;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
}
.asset-card { display: flex; gap: 14px; margin: 0; }
.asset-thumb {
  flex: 0 0 96px; height: 96px; display: flex; align-items: center; justify-content: center;
  background: var(--paper); border: 1px dashed var(--border-strong); border-radius: 3px;
  overflow: hidden; text-align: center;
}
.asset-thumb img { max-width: 100%; max-height: 100%; object-fit: contain; }
.asset-body { flex: 1 1 auto; min-width: 0; }
.asset-body h3 { margin: 0 0 2px; font-size: 16px; }
.asset-body p { margin: 4px 0; }
.asset-meta { color: var(--muted); font-variant-numeric: tabular-nums; }
.asset-form { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 6px 0 0; }
.asset-form input[type="file"] { max-width: 170px; font-size: 12px; }

.asset-table .asset-cell { text-align: center; }
.asset-table .thumb {
  width: 44px; height: 44px; object-fit: contain;
  background: #fff; border: 1px solid var(--border); border-radius: 3px;
}
/* 声音没有缩略图，用文字符号占位，避免出现一排破图 */
.asset-table .thumb-audio {
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 20px; color: var(--scratch);
}
.inline-form { display: inline-flex; align-items: center; gap: 6px; margin: 2px 0; }
.inline-form input[type="file"] { max-width: 190px; font-size: 12px; }
