/* bg.css —— SPRINT 动态背景 + 色调 + 外观兑换（老师 2026-10-12 第 1 / 2 轮）
 * ============================================================================
 * 老师原话（第 1 轮）：
 *   「加 SPRINT 的背景图。现在的配色确实是 STEAM 的经典色调。但是 STEAM 自己
 *     其实已经早就支持使用者更改色调了。设置加上动态背景。
 *     你试试把 `video_WebTitle_batch.mp4` 作为背景常驻系统背景。评估一下对系统的
 *     压力大不大。」
 * 老师原话（第 2 轮，本次改动）：
 *   「外观的选择也做成需要用成就点数来解锁……静态便宜、动态贵。这不仅仅是自己
 *     使用的时候能看到，好友在查看你的个性主页的时候也能看到。」
 *   「色调可以开放（免费，不用点数），但是背景图需要成就点数解锁。」
 *
 * ★ 压力要点：视频只有 161 KB～0.95 MB / 4 秒，体积与网络开销可以忽略；
 *   真正持续消耗的是**解码**。所以这一层做了：
 *     · 只在需要时创建 <video>（关闭 / 省电 / 减少动效 / **静态背景** ⇒ 根本不建元素）
 *     · 标签页隐藏、窗口失焦 ⇒ **暂停解码**（现代浏览器也会自动降频，但不能指望）
 *     · 全局只此一个主背景视频、`muted+loop+playsinline`、无音轨参与
 *     · 关闭时移除元素（不是只 display:none —— 那样解码还在跑）
 *
 * ★★ 2026-10-12 第 2 轮的样式结构变化（对应 bg.js 里"装备 vs 本机开关"的拆分）：
 *   `data-bg` 属性 = **服务器装备的那张背景是什么类型**（none / grad / image / video），
 *   挂在 `html`（主背景）或 `.sp-bg-embed`（好友主页那一块）上。
 *   本机开关只在 `body.sp-bg-on` / `body.sp-bg-still` 上体现。
 *   两种状态**互不覆盖**：换台电脑/换个人看，画法一致、动不动各算各的。
 * ========================================================================== */

/* 背景层：贴在最底下，不拦鼠标。
   ★ `z-index: -1`（不是 0）：0 会落在"定位元素层"，反而**盖住**正文（CSS 绘制顺序）；
     -1 排在所有内容之下，而 html/body 的底色算"画布背景"、永远在最底 ⇒ 正好合适。
   ★ `background: transparent`：装备的渐变由 JS 内联写到这一层上（`element.style.background`），
     写死一个底色会把它盖住。真要纯色时，内联那条就是颜色（见下面的 `[data-bg="none"]` 兜底）。 */
.sp-bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  pointer-events: none;      /* 绝不能挡住任何点击 */
  background: transparent;
}
/* `bg-none`（免费默认）= 纯色底，零解码、零绘制开销。
   ★ 这条同时是"连接口都拉不到"时的最终兜底：一定有颜色，绝不白屏。 */
.sp-bg[data-bg="none"],
.sp-bg-embed[data-bg="none"] { background: #0e1621; }

.sp-bg .sp-bg-v {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;         /* 铺满、裁边、不变形 */
  opacity: .62;
  /* ★ 2026-10-12：**故意不用 `filter`**。视频是逐帧渲染的，任何全屏 filter
     （blur / saturate…）都会让 GPU **每帧**多做一次全屏采样。
     压暗交给下面那层静态 scrim（一次绘制、零逐帧成本）。 */
}

/* 静态图：单独一层，便于"换背景时把旧图摘掉"（bg.js 里按 `.sp-bg-img` 找）。 */
.sp-bg .sp-bg-img {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: .62;
}

/* 渐变背景的第二层（`preview.css2`，radial 那一条）：做成"光晕"叠在底色上。
   ★ 为什么用 `::before` 而不是再来一个 div：它纯装饰、不参与任何逻辑，
     也不会被 bg.js 的 `querySelector('.sp-bg-img')` 之类误伤。 */
.sp-bg[data-bg="grad"]::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--sp-bg-glow, none);
  opacity: .85;
}

/* 压一层暗罩：正文压在上面才看得清（视频亮的地方会糊字） */
.sp-bg .sp-bg-scrim {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 85% at 50% 0%,
      rgba(15, 22, 33, .46) 0%, rgba(15, 22, 33, .78) 58%, rgba(15, 22, 33, .94) 100%),
    linear-gradient(180deg, rgba(15, 22, 33, .38), rgba(15, 22, 33, .62));
}

/* ---- 背景开着的时候，把"壳"的底色让出来，背景才透得出来 ----
   只让**框架层**透明：顶栏 / 二级条 / 页脚 / 页面底色。
   内容是卡片（自带 --c-card 不透明底色）⇒ 可读性不受影响。 */
body.sp-bg-on { background: transparent; }
/* ★ 2026-10-19：**雅思 / ESL 世界的顶栏是白的**（layout.css 的 is-exam/is-esl 规则），
   不能被"背景开着"这条透明规则盖掉 —— 否则一开动态背景，那两个系统的顶栏就变深色，
   与白色页面撞在一起。排除这两个世界，SPRINT 原样不动。 */
body.sp-bg-on:not(.is-exam):not(.is-esl) .topbar {
  background: rgba(23, 26, 33, .78);
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
}
body.sp-bg-on .subbar,
body.sp-bg-on .foot { background: transparent; position: relative; z-index: 1; }
body.sp-bg-on .wrap,
body.sp-bg-on .view { position: relative; z-index: 1; }

/* 顶栏那个「外观」按钮（`.chip` 没有全局定义，所以自带一套，别去蹭别的页面的类） */
.sp-look {
  margin-right: 8px;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--c-line);
  background: var(--c-card-hi);
  color: var(--t-muted);          /* ★ 原来写的是 `--t-secondary`，那个变量**不存在**（主题里没有） */
  font-size: var(--fs-sm);
  font-family: var(--font);
  cursor: pointer;
}
.sp-look:hover { border-color: var(--c-accent); color: var(--t-bright); }
/* 「键盘」开关的"开着"态（2026-10-19）：透明键盘在屏上时按钮点亮，
   学生抬头就能看出这层键盘是开着的（状态与 sprint.kbd.float.on 一致）。 */
.sp-look.is-on {
  border-color: var(--c-accent);
  color: var(--t-bright);
  background: var(--c-accent-soft, rgba(47, 111, 237, .18));
}

/* 「静帧 / 系统要求减少动效」时：视频被暂停，露出来的其实是它的 poster 静帧。
   ★ 用 `visibility` 而不是 `display`：`display:none` 在部分浏览器上会把视频的
     解码器**整个拆掉**，回到动态模式时要重新初始化（会闪一下黑）。
     而 `visibility:hidden` 的元素浏览器**本来就不解码**（不绘制），省电效果一样。 */
body.sp-bg-on.sp-bg-still .sp-bg .sp-bg-v { visibility: hidden; }

/* ============================================================================
   色调（老师第 2 轮：「色调可以开放（免费，不用点数）」）
   ★ 强调色：覆盖 --c-accent / --c-accent-dim / --c-accent-deep。
     绿/金/红是语义色（对错、星级、危险），**不跟着换** —— 换了会让人误读。
   ★ 这五款**全部免费、全部可选**：色调不参与成就点数兑换，
     它的选择只存本机（`sprint.tone`）。
   ============================================================================ */

/* ============================================================================
   ★★★ 2026-10-18 老师：「选了成就商店里的颜色还是不明显，底色太深了，
   自定义的颜色覆盖不了底色的深」

   病根：这一节原来只改 --c-accent（按钮/边框这类强调色），
   **背景层（--c-bg / --c-deep / --c-card …）一个都没动** ⇒
   大面积的地板色从来不随色调变，所以「看着没变」不是错觉。

   现在每个色调给**一整套背景层**：只替换色相，饱和度与明度原样保留
   （明暗层次、文字对比度全不变，整页只是泛出那个色调）。
   STEAM 蓝仍是默认（不设 data-tone）。
   ========================================================================== */
:root[data-tone="teal"] {   /* 青绿 · 色相 174° */
  --c-deep:      #172120;
  --c-bg:        #1b3835;
  --c-card:      #162d2b;
  --c-card-hi:   #1f3f3c;
  --c-input:     #0e211f;
  --c-hover:     #2a5e59;
  --c-line:      #2a5551;
  --c-line-soft: #224945;
  --c-accent:    #4fd1c5;
  --c-accent-dim: #2f9e91;
  --c-accent-deep: #114b46;
}
:root[data-tone="violet"] {   /* 紫罗兰 · 色相 255° */
  --c-deep:      #191721;
  --c-bg:        #221b38;
  --c-card:      #1c162d;
  --c-card-hi:   #271f3f;
  --c-input:     #130e21;
  --c-hover:     #372a5e;
  --c-line:      #352a55;
  --c-line-soft: #2c2249;
  --c-accent:    #a58bf5;
  --c-accent-dim: #7c63c9;
  --c-accent-deep: #35245e;
}
:root[data-tone="amber"] {   /* 琥珀 · 色相 39° */
  --c-deep:      #211d17;
  --c-bg:        #382e1b;
  --c-card:      #2d2516;
  --c-card-hi:   #3f341f;
  --c-input:     #211a0e;
  --c-hover:     #5e4c2a;
  --c-line:      #55462a;
  --c-line-soft: #493b22;
  --c-accent:    #f2b544;
  --c-accent-dim: #c98d21;
  --c-accent-deep: #5c3d0a;
}
:root[data-tone="rose"] {   /* 玫瑰 · 色相 348° */
  --c-deep:      #211719;
  --c-bg:        #381b21;
  --c-card:      #2d161a;
  --c-card-hi:   #3f1f25;
  --c-input:     #210e12;
  --c-hover:     #5e2a34;
  --c-line:      #552a32;
  --c-line-soft: #49222a;
  --c-accent:    #f2778f;
  --c-accent-dim: #c9516a;
  --c-accent-deep: #5e1f2e;
}
/* steam（默认）不设 data-tone ⇒ 用 theme.css 里的经典 STEAM 蓝 */

/* steam（默认）不设 data-tone ⇒ 用 theme.css 里的经典 STEAM 蓝 */

/* ============================================================================
   外观设置面板（从顶栏「外观」按钮打开）
   ========================================================================== */
.sp-appear { display: flex; flex-direction: column; gap: 14px; min-width: 380px; max-width: 560px; }
.sp-appear-row { display: flex; flex-direction: column; gap: 6px; }
.sp-appear-lab { font-size: var(--fs-sm); color: var(--t-muted); }
.sp-appear-opts { display: flex; flex-wrap: wrap; gap: 8px; }
.sp-opt {
  padding: 7px 14px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--c-line); background: var(--c-card-hi);
  color: var(--t-primary); font-size: var(--fs-sm); font-family: var(--font);
}
.sp-opt:hover { border-color: var(--c-accent); color: var(--t-bright); }
.sp-opt.is-on {
  border-color: var(--c-accent);
  color: var(--t-bright);
  box-shadow: 0 0 0 2px rgba(102, 192, 244, .18);
  font-weight: 700;
}
.sp-tone { display: inline-flex; align-items: center; gap: 7px; }
.sp-tone i { display: block; width: 14px; height: 14px; border-radius: 50%; border: 1px solid rgba(255, 255, 255, .25); }
.sp-appear-note { font-size: var(--fs-sm); color: var(--t-muted); line-height: 1.6; }

/* ★ 这个弹窗要比默认的 400px 宽：背景卡是"缩略图 + 名字"两列排的。
   只加宽这一处，不动 components.css 里全站共用的 `.modal`。 */
.modal:has(.sp-appear) { max-width: 560px; }
.sp-appear { width: 100%; }

/* ---------- 背景兑换区 ---------- */
.sp-bg-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 2px;
}
.sp-bg-cat {
  flex: 0 0 100%;
  font-size: var(--fs-xs);
  color: var(--t-dim);
  margin-top: 4px;
}
.sp-bgcard {
  flex: 0 0 104px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px;
  border-radius: var(--r-md);
  border: 1px solid var(--c-line);
  background: var(--c-card-hi);
  color: var(--t-primary);
  font-family: var(--font);
  font-size: var(--fs-xs);
  text-align: left;
  cursor: pointer;
}
.sp-bgcard:hover { border-color: var(--c-accent); }
.sp-bgcard.is-on {
  border-color: var(--c-accent);
  box-shadow: 0 0 0 2px rgba(102, 192, 244, .22);
}
/* ★★ 未拥有 = 置灰 + 不可点。
   为什么给「置灰」而不是「不显示」：老师这一轮的重点是"要让学生知道背景要点数换"
   ——藏起来他会以为系统坏了（同好友页那句「把人藏起来，学生会以为是系统坏了」）。
   ★ `disabled` 由 JS 设（浏览器连 click 都不派发），样式这里是第二道观感。 */
.sp-bgcard.is-locked,
.sp-bgcard[disabled] {
  cursor: not-allowed;
  opacity: .45;
  filter: grayscale(.7);
}
.sp-bgcard.is-locked:hover { border-color: var(--c-line); }
.sp-bgthumb {
  position: relative;
  width: 100%;
  height: 56px;
  border-radius: var(--r-sm);
  border: 1px solid var(--c-line-soft);
  background-color: #0e1621;
  background-size: cover;
  background-position: center;
}
.sp-bgthumb.is-none {
  background-image:
    linear-gradient(135deg, rgba(255, 255, 255, .06), rgba(255, 255, 255, 0)),
    linear-gradient(180deg, #1b2838, #0e1621);
}
/* 动态项的两个角标：▶ 和 "720p"（老师要求"一眼看出哪个是动的、多大"） */
.sp-bgplay {
  position: absolute;
  left: 4px;
  top: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: rgba(6, 12, 19, .72);
  color: #fff;
  font-size: 9px;
  line-height: 1;
}
.sp-bghd {
  position: absolute;
  right: 4px;
  bottom: 4px;
  padding: 0 4px;
  border-radius: 3px;
  background: rgba(6, 12, 19, .72);
  color: var(--t-primary);
  font-size: 10px;
  line-height: 16px;
}
.sp-bgcap { display: flex; align-items: baseline; gap: 4px; }
.sp-bgname { color: var(--t-bright); font-size: var(--fs-sm); }
.sp-bgstate { margin-left: auto; color: var(--t-dim); font-size: 10px; white-space: nowrap; }
.sp-bgstate.is-locked { color: var(--c-gold); }
.sp-bgline { color: var(--t-dim); font-size: 10px; }
.sp-bgline.is-locked { color: var(--c-gold); }
/* 「去成就商店换」那条路标：横跨一整行（它不属于任何一张卡） */
.sp-bggo {
  flex: 0 0 100%;
  margin-top: 4px;
  text-align: left;
  color: var(--c-gold);
  border-color: rgba(212, 175, 55, .45);
}
.sp-bggo:hover { border-color: var(--c-gold); color: var(--t-bright); }

/* ============================================================================
   ★★ 好友的个性主页：把他装备的背景铺在这一块上（老师第 2 轮点名的重点）
   ----------------------------------------------------------------------------
   老师原话：「这不仅仅是自己使用的时候能看到，**好友在查看你的个性主页的时候也能看到**。」

   ★ 为什么是"顶部一条 hero"而不是"整页铺满"：
     整页铺满就得把 `.view` / 卡片全做成半透明，正文可读性和现有页面（商店、成就、
     好友名单）的观感都会被改掉；一条 hero 已经能让访客一眼认出"这是他挑的背景"，
     而且**不碰任何别人的样式**（本次改动只允许动 bg.css）。
   ========================================================================== */
.fr-hero {
  position: relative;
  overflow: hidden;
  border-radius: var(--r-md);
  border: 1px solid var(--c-line);
  background: #0e1621;              /* 底色兜底：背景画不出来也不白 */
  margin-bottom: var(--gap);
  min-height: 148px;
}
.sp-bg-embed { position: absolute; inset: 0; }
.sp-bg-embed[data-bg="none"] { background: #0e1621; }
/* 渐变背景的"光晕"层（同主背景层那套，见上） */
.sp-bg-embed[data-bg="grad"]::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--sp-bg-glow, none);
  opacity: .85;
}
.sp-bg-embed .sp-bg-v {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: .62;
}
/* 静帧/省电时：藏掉视频、露出 poster（同主背景层那条的道理） */
.sp-bg-embed[data-bg="still"] .sp-bg-v { visibility: hidden; }
/* 同样的暗罩：压一层，保证 hero 上的名字/编号可读（老师的要求里明确写了"压同样的暗罩"） */
.sp-bg-embed-scrim {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 85% at 50% 0%,
      rgba(15, 22, 33, .46) 0%, rgba(15, 22, 33, .78) 58%, rgba(15, 22, 33, .94) 100%),
    linear-gradient(180deg, rgba(15, 22, 33, .38), rgba(15, 22, 33, .62));
}
.fr-hero-in {
  position: relative;
  z-index: 1;                        /* 必须抬起来，否则被上面那两层盖住 */
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px 18px;
  min-height: 148px;
  flex-wrap: wrap;
}
.fr-hero-av { flex: 0 0 auto; line-height: 0; }
.fr-hero-info { flex: 1 1 240px; min-width: 0; }
.fr-hero-name {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  color: var(--t-bright);
  font-size: var(--fs-xl);
}
.fr-hero-sub {
  margin-top: 4px;
  color: var(--t-primary);
  font-size: var(--fs-sm);
  letter-spacing: .5px;
}
.fr-hero-hint {
  margin-top: 6px;
  color: var(--t-muted);
  font-size: var(--fs-xs);
  line-height: 1.6;
}
/* 键帽预览那一块（`.kbd` 组件本身自带样式，这里只管它外面那圈） */
.fr-hero-kbd {
  flex: 0 0 100%;
  max-width: 360px;
  padding: 8px 10px 10px;
  border-radius: var(--r-md);
  border: 1px solid var(--c-line);
  background: rgba(22, 32, 45, .78);
}
.fr-hero-kbd-lab {
  display: block;
  margin-bottom: 6px;
  color: var(--t-muted);
  font-size: var(--fs-xs);
}
.fr-hero-kbd-fb { color: var(--t-primary); font-size: var(--fs-sm); }

/* 好友名单里那个「看主页」入口 */
.fr-open {
  padding: 3px 8px;
  border-radius: var(--r-sm);
  border: 1px solid var(--c-line);
  background: transparent;
  color: var(--t-muted);
  font-size: var(--fs-xs);
  font-family: var(--font);
  cursor: pointer;
}
.fr-open:hover { border-color: var(--c-accent); color: var(--t-bright); }

@media (max-width: 640px) {
  .sp-appear { min-width: 0; }
  .sp-bgcard { flex: 0 0 calc(50% - 5px); }
  .fr-hero-kbd { max-width: none; }
}
