
:root {
  --bg: #0f1114; --panel: #181b20; --panel-raised: #20242a; --panel-soft: #121417;
  --line: #2b3037; --line-light: #3a424b;
  --text: #f6f2ee; --muted: #a1a6ac; --muted-2: #70777f;
  --win: #3ddc84;
  --lime: #DC3C3C; --lime-strong: #aa2a2a; --coral: #ff806d; --sky: #78c9ff; --yellow: #ffc861; --danger: #ef5c6d;
  --radius: 10px; --shadow: 0 16px 50px rgba(0,0,0,.24);
  --on-accent: #fff;

  --surface-control: #11161b; --surface-input: #0e1318; --surface-hover: #151b22; --surface-feature: #1a2023;
  --surface-modal: #11161c; --surface-slot: #12181e; --surface-role: #222b33;
  --surface-btn-2: #202830; --surface-btn-2-hover: #29333c; --surface-switch: #2c353d; --switch-knob: #9ca5aa; --switch-knob-on: #162007;
  --scrim-drawer: rgba(3,5,7,.72); --scrim-modal: rgba(3,5,7,.78);

  --track: #252e35; --slot-avatar-bg: #26313a;
  /* 胜方预测票数条的两段：A 队（左）蓝、B 队（右）红。
     这里单独起名字而不是直接用 --sky / --danger，是因为它们**必须是固定的**：
     两段的区别就是全部信息，而 --lime 会被「网站管理 → 特征色」覆盖 ——
     管理员把特征色改成蓝色，两段就变成同一个颜色，这条对比静默失效。
     颜色在这里是数据编码，不能跟着主题走。

     取的是比 --sky / --danger 更深的一档：那两档是给**深色底上的文字**用的浅色，
     铺成一大块底色后太亮，压在上面的白字读不出来（--sky 上的白字只有 1.9:1）。
     深下来之后白字分别是 4.9:1 和 5.0:1，不再需要那圈黑色阴影兜底。 */
  --tally-a: #2b76aa; --tally-b: #c33f52;

  /* 赛事勋章的四档金属色与绶带色。设计令牌里没有"铜/银/金/钻石"这种东西 —— 它们是
     **插图的材质**，不是界面配色：`--lime` 是红色，用它去画金属只会得到一块红。
     所以在这里写死。挂在 `:root` 而不是 `.medal-shelf` 上，因为悬停浮层挂在 `body`
     上（见 `4-pages-core.css` 的 `.medal-tip`）—— 挂在货架上时浮层够不到这些变量，
     `background: var(--medal-gold-mid)` 解析成空，"金"那个角标就变成深色小字印在深色
     面板上。想调金属质感，改这一个块就够。 */
  --medal-bronze-light: #f0b47a; --medal-bronze-mid: #b87333; --medal-bronze-dark: #6f3f16;
  --medal-silver-light: #f4f7fa; --medal-silver-mid: #b6bfc8; --medal-silver-dark: #6f7881;
  --medal-gold-light: #fff2bd; --medal-gold-mid: #f0c04a; --medal-gold-dark: #9c6a12;
  --medal-diamond-light: #d9f6ff; --medal-diamond-mid: #8ad6f2; --medal-diamond-dark: #3f86bd;
  --medal-ribbon-bronze: #8a4f22; --medal-ribbon-silver: #8b949c;
  --medal-ribbon-gold: #b8860b; --medal-ribbon-diamond: #4a8fbe;

  --avatar-player: #26313a; --avatar-team: #1c2a33;

  --snow: #fff; --ink: #000;

  --score-text: #f2f4f3; --score-win: #8fbf9e; --score-glow: #1d5c3c;
  --duel-tint: #12251c;

  /* 圆角尺度：新增样式从这里取值，不要再写死数值。
     原先 16 种圆角里有 5px/12px/13px 三档在尺度之外，现已归入相邻档。 */
  --radius-xs: 4px; --radius-input: 6px; --radius-btn: 7px; --radius-card: 8px;
  --radius-tile: 9px; --radius-lg: 11px; --radius-pill: 999px;
}

* { box-sizing: border-box; }
html, body { min-height: 100%; }
html { color-scheme: dark; }
/* 滚动条槽位常驻。
   管理页的五个选项卡高度差很大：选手管理列出 86 行（4982px，必然出滚动条），用户管理
   只有两行（1050px，不出）。滚动条一出一没，**整页可用宽度就在 1665 与 1680 之间跳**，
   于是每切一次选项卡，侧栏、标签、内容一起横移 15px —— 这就是"每个选项卡界面都没对齐、
   有轻微的左右偏移"。实测见 tools/admin_align_check.mjs。

   用的是 `overflow-y: scroll` 而不是 `scrollbar-gutter: stable`：实测后者在这个
   Chrome（140，Windows）上对根元素**不生效**（computed 值确实是 stable，宽度照样在
   1665/1680 之间跳），而 `overflow-y: scroll` 两种高度都稳定在 1665。
   代价是右侧永远有一条 15px 的滚动条 —— 比"点一下整页横向抖一下"划算。 */
html { overflow-y: scroll; }
/* 滚动条既然常驻，就得配得上深色主题。
   这是**上色**，不是隐藏：`.nav` 那种把滚动条整个藏掉的做法只用在那一处侧栏里，
   其余地方的滚动条必须看得见（能不能滚是信息）。 */
html { scrollbar-color: var(--line-light) transparent; }
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: transparent; }
/* 描边用透明色 + content-box 裁剪，画出来的滑块比轨道窄，四周留出呼吸。 */
::-webkit-scrollbar-thumb { border: 3px solid transparent; border-radius: var(--radius-pill); background: var(--line-light); background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: var(--muted-2); background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }
body {
  margin: 0;
  color: var(--text);
  background: var(--bg);
  font-family: Manrope, "Microsoft YaHei", sans-serif;
  letter-spacing: 0;
}
@keyframes page-enter { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: translateY(0); } }
@keyframes loading-pulse { 0%, 100% { opacity: .35; transform: scale(.96); } 50% { opacity: 1; transform: scale(1); } }
/* 进入动画挂在 `.is-entering` 上，而不是 `.content > *`——后者会让每次状态更新
   （筛选项、选地图、展开一行）都重播一遍页面过渡。现在只有"真的换了一页"才加这个类。 */
.content.is-entering > * { animation: page-enter .24s ease-out both; }
.loading-screen { min-height: 100vh; display: grid; place-items: center; align-content: center; gap: 18px; background: var(--bg); }
.loading-screen .brand-mark { animation: loading-pulse 1.1s ease-in-out infinite; }
.loading-line { width: 76px; height: 3px; border-radius: var(--radius-pill); background: var(--line); overflow: hidden; position: relative; }
.loading-line::after { content: ""; position: absolute; inset: 0; width: 45%; background: var(--lime); animation: loading-sweep 1s ease-in-out infinite; }
@keyframes loading-sweep { from { transform: translateX(-120%); } to { transform: translateX(240%); } }
@media (prefers-reduced-motion: reduce) { .content > *, .loading-screen .brand-mark, .loading-line::after { animation: none; } }
button, input, select, textarea { font: inherit; }
button { cursor: pointer; }
a { color: inherit; text-decoration: none; }
.app-shell { display: grid; grid-template-columns: 244px minmax(0, 1fr); min-height: 100vh; }
