/* ==========================================================================
   爱刷刷 · 渐变毛玻璃特效层 (Performance Edition)  v2.0
   --------------------------------------------------------------------------
   优化目标：60fps 轻快流畅
   核心策略：
   · 卡片移除 backdrop-filter → 改用「不透明渐变」模拟玻璃（视觉几乎一致，GPU 开销降 ~10x）
   · 光斑移除 filter:blur → 改用 radial-gradient 自带柔化（免离屏渲染）
   · 流动边框改静态 → 仅 hover 时呈现（免每帧重绘 conic-gradient）
   · 阴影 9 层 → 3 层
   · 入场动画去 blur → 纯 transform + opacity（GPU 合成）
   · 加 contain 隔离渲染，移除 will-change 滥用
   · 动画时长整体缩短 → 更「轻快」
   保留：渐变毛玻璃观感 · 色彩玻璃 · 光斑 · 丰富登录动效（卡片扫光已移除）
   ========================================================================== */

/* ==========================================================================
   ① 调色板（不透明渐变版 —— 视觉等效玻璃，性能优先）
   ========================================================================== */

:root {
  /* ── 微噪点材质（让白色表面像实体材质，而非平面数字白）────── */
  /* ⚡ 原 --gx-grain 是一层 SVG feTurbulence 噪点，铺在每张卡片上。
     实测它对光栅开销的贡献高达 41%（RasterTask 662.9ms → 375.1ms）。
     成本不在 SVG 滤镜本身 —— 换成预渲染 PNG 噪点后仍是 654ms，
     说明贵的是「多一层背景图每次光栅都要重新平铺 + 混合」。
     它是 5.5% 不透明的纹理，肉眼几乎不可见，不值得，故整层移除。
     卡片表面现在 = 色相层 + 左上镜面高光 + 底色渐变，共 3 层。 */

  /* ── 卡片表面：噪点 + 左上镜面高光 + 垂直光照渐变 ────────── */
  --gx-face:
    radial-gradient(130% 92% at 14% -12%,
      #FFFFFF 0%,
      rgba(255,255,255,.72) 34%,
      rgba(255,255,255,.24) 58%,
      rgba(255,255,255,0) 78%),
    linear-gradient(172deg,
      #FFFFFF 0%,
      #FDFEFF 32%,
      #FAFBFF 66%,
      #F6F9FE 100%);
  --gx-face-hover:
    radial-gradient(130% 92% at 14% -12%,
      rgba(255,255,255,1) 0%,
      rgba(255,255,255,.70) 34%,
      rgba(255,255,255,.22) 58%,
      rgba(255,255,255,0) 78%),
    linear-gradient(172deg,
      #FFFFFF 0%,
      #FFFFFF 34%,
      #FCFEFF 68%,
      #F7FBFF 100%);

  /* ── 色相叠加（低透明度，叠在 face 上）─────────────────────── */
  /* 中性占位层：用于分组容器，保持背景层数仍为 4，避免层数错位 */
  --gx-neutral: linear-gradient(125deg, rgba(28,45,80,.040) 0%, rgba(28,45,80,.017) 45%, rgba(28,45,80,0) 78%);

  --gx-blue:   linear-gradient(125deg, rgba(0,122,255,0.095) 0%, rgba(0,122,255,0.034) 42%, rgba(0,122,255,0) 72%);
  --gx-purple: linear-gradient(125deg, rgba(175,82,222,0.09) 0%, rgba(175,82,222,0.032) 42%, rgba(175,82,222,0) 72%);
  --gx-teal:   linear-gradient(125deg, rgba(72,187,214,0.095) 0%, rgba(72,187,214,0.034) 42%, rgba(72,187,214,0) 72%);
  --gx-orange: linear-gradient(125deg, rgba(255,149,0,0.1) 0%, rgba(255,149,0,0.036) 42%, rgba(255,149,0,0) 72%);
  --gx-green:  linear-gradient(125deg, rgba(52,199,89,0.095) 0%, rgba(52,199,89,0.034) 42%, rgba(52,199,89,0) 72%);
  --gx-pink:   linear-gradient(125deg, rgba(255,45,85,0.088) 0%, rgba(255,45,85,0.032) 42%, rgba(255,45,85,0) 72%);

  /* ── 边缘高光（1 层替代原 4 层）───────────────────────────── */
  --gx-edge: inset 0 1px 0 rgba(255,255,255,.95), 0 0 0 0.5px rgba(255,255,255,.70);

  /* ── 高级阴影：内高光 + 底厚 + 描边 + 三级投影 + 环境光 ────── */
  --gx-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 1),               /* 顶部内高光 */
    inset 0 -1px 1px rgba(16, 24, 40, .022),            /* 底部内阴影（厚度）*/
    0 0 0 1px rgba(16, 24, 40, .072),                   /* 细描边 */
    0 1px 3px rgba(16, 24, 40, .060),                   /* 接触阴影 */
    0 5px 14px -4px rgba(16, 24, 40, .090),             /* 中近距（合并原中距+远距）*/
    0 18px 40px -14px rgba(16, 24, 40, .085);           /* 环境光（原 32px 层太贵，收敛）*/

  --gx-shadow-hover:
    inset 0 1px 0 rgba(255, 255, 255, 1),
    inset 0 -1px 1px rgba(0, 122, 255, .022),
    0 0 0 1px rgba(0, 122, 255, .105),                  /* 描边转蓝 */
    0 2px 6px rgba(16, 24, 40, .075),
    0 10px 22px -6px rgba(16, 24, 40, .100),
    0 26px 52px -18px rgba(0, 122, 255, .085);          /* 品牌色环境光 */

  /* ── 彩色投影（单层，轻）──────────────────────────────────── */
  --gx-glow-blue:   0 6px 20px rgba(0,122,255,.09);
  --gx-glow-purple: 0 6px 20px rgba(175,82,222,.09);
  --gx-glow-green:  0 6px 20px rgba(52,199,89,.09);
  --gx-glow-orange: 0 6px 20px rgba(255,149,0,.09);

  /* ── 动效（更快更干脆）────────────────────────────────────── */
  --gx-out:    cubic-bezier(.22, 1, .36, 1);
  --gx-spring: cubic-bezier(.34, 1.4, .64, 1);
  --gx-squish: cubic-bezier(.36, .07, .19, .97);

  --gx-t-fast: 140ms;
  --gx-t-base: 200ms;
  --gx-t-slow: 280ms;
}

[data-theme="dark"] {
  --gx-face:
    radial-gradient(130% 92% at 14% -12%,
      rgba(255,255,255,.115) 0%,
      rgba(255,255,255,.045) 40%,
      rgba(255,255,255,0) 76%),
    linear-gradient(152deg, #232327 0%, #1E1E22 52%, #1A1A1E 100%);
  --gx-face-hover:
    radial-gradient(130% 92% at 14% -12%,
      rgba(255,255,255,.155) 0%,
      rgba(255,255,255,.060) 40%,
      rgba(255,255,255,0) 76%),
    linear-gradient(152deg, #2A2A2F 0%, #25252A 52%, #1F1F24 100%);

  --gx-neutral: linear-gradient(125deg, rgba(0,0,0,.20) 0%, rgba(0,0,0,.08) 45%, rgba(0,0,0,0) 78%);

  --gx-blue:   linear-gradient(125deg, rgba(10,132,255,0.098) 0%, rgba(10,132,255,0.033) 42%, rgba(10,132,255,0) 72%);
  --gx-purple: linear-gradient(125deg, rgba(191,90,242,0.092) 0%, rgba(191,90,242,0.031) 42%, rgba(191,90,242,0) 72%);
  --gx-teal:   linear-gradient(125deg, rgba(100,210,255,0.09) 0%, rgba(100,210,255,0.031) 42%, rgba(100,210,255,0) 72%);
  --gx-orange: linear-gradient(125deg, rgba(255,159,10,0.082) 0%, rgba(255,159,10,0.028) 42%, rgba(255,159,10,0) 72%);
  --gx-green:  linear-gradient(125deg, rgba(48,209,88,0.092) 0%, rgba(48,209,88,0.031) 42%, rgba(48,209,88,0) 72%);
  --gx-pink:   linear-gradient(125deg, rgba(255,69,58,0.088) 0%, rgba(255,69,58,0.03) 42%, rgba(255,69,58,0) 72%);

  --gx-edge: inset 0 1px 0 rgba(255,255,255,.07), 0 0 0 0.5px rgba(255,255,255,.06);

  --gx-shadow:
    inset 0 1px 0 rgba(255,255,255,.065),
    0 0 0 1px rgba(255,255,255,.05),
    0 1px 2px rgba(0,0,0,.36),
    0 6px 16px -4px rgba(0,0,0,.42),
    0 20px 44px -16px rgba(0,0,0,.38);
  --gx-shadow-hover:
    inset 0 1px 0 rgba(255,255,255,.085),
    0 0 0 1px rgba(10,132,255,.16),
    0 2px 6px rgba(0,0,0,.42),
    0 12px 26px -8px rgba(0,0,0,.46),
    0 30px 60px -22px rgba(10,132,255,.16);

  --gx-glow-blue:   0 6px 20px rgba(10,132,255,.14);
  --gx-glow-purple: 0 6px 20px rgba(191,90,242,.14);
  --gx-glow-green:  0 6px 20px rgba(48,209,88,.14);
  --gx-glow-orange: 0 6px 20px rgba(255,159,10,.14);
}

/* ==========================================================================
   ② 卡片：不透明渐变玻璃（关键优化点）
   ========================================================================== */

.card,
.quiz-card,
.stat-card,
.subj-card,
.tool-item,
.tool-card,
.rec-item,
.set-row,
.wrong-subj,
.sr-item,
.sr-group,
.me-hero,
.me-btn,
.acct-btn,
.theme-item,
.choice-btn,
.type-card,
.type-pick,
.exam-bar,
.cmt,
.practice-card,
.dashboard-card,
.qcard,
.countdown,
.cd-card,
.notif-bar {
  position: relative;
  /* GPU 友好：隔离布局/绘制，避免影响兄弟节点 */

  background-image: var(--gx-blue), var(--gx-face) !important;
  background-color: transparent !important;
  /* 噪点层平铺、其余渐变层铺满（层数须与 background-image 一致）*/
  background-size: 100% 100%, 100% 100%, 100% 100% !important;
  background-repeat: no-repeat, no-repeat, no-repeat !important;

  /* 毛玻璃：模糊 + 提饱和（用户明确要求，取代早前为性能而做的移除）*/
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;

  border: none !important;
  /* 新阴影已包含内高光，不再单独叠加 --gx-edge */
  box-shadow: var(--gx-shadow) !important;
  /* 连续圆角（真正的 iOS 超椭圆，不支持的浏览器自动忽略）*/
  border-radius: 18px !important;
  corner-shape: squircle;

  /* 只过渡 GPU 属性 */
  transition:
    box-shadow var(--gx-t-base) var(--gx-out),
    transform var(--gx-t-base) var(--gx-spring),
    background-image var(--gx-t-base) var(--gx-out);
}

[data-theme="dark"] .card,
[data-theme="dark"] .quiz-card,
[data-theme="dark"] .stat-card,
[data-theme="dark"] .subj-card,
[data-theme="dark"] .tool-item,
[data-theme="dark"] .tool-card,
[data-theme="dark"] .rec-item,
[data-theme="dark"] .set-row,
[data-theme="dark"] .wrong-subj,
[data-theme="dark"] .sr-item,
[data-theme="dark"] .me-hero,
[data-theme="dark"] .me-btn,
[data-theme="dark"] .acct-btn,
[data-theme="dark"] .theme-item,
[data-theme="dark"] .choice-btn,
[data-theme="dark"] .type-card,
[data-theme="dark"] .exam-bar,
[data-theme="dark"] .cmt,
[data-theme="dark"] .qcard {
  border: 0.5px solid rgba(255,255,255,.055) !important;
}

/* ── 悬停：轻快（200ms）上浮 + 阴影加深 ───────────────────────── */
@media (hover: hover), (pointer: fine) {
  .card:hover,
  .stat-card:hover,
  .subj-card:hover,
  .tool-item:hover,
  .tool-card:hover,
  .rec-item:hover,
  .set-row:hover,
  .wrong-subj:hover,
  .sr-item:hover,
  .me-btn:hover,
  .theme-item:hover,
  .choice-btn:hover,
  .type-card:hover,
  .qcard:hover {
    background-image: var(--gx-blue), var(--gx-face-hover) !important;
    box-shadow: var(--gx-shadow-hover) !important;
    transform: translate3d(0, -3px, 0);
  }
}

/* ── 按压：快速挤压（90ms，干脆）──────────────────────────────── */
.subj-card:active,
.stat-card:active,
.tool-item:active,
.rec-item:active,
.set-row:active,
.wrong-subj:active,
.me-btn:active,
.acct-btn:active,
.theme-item:active,
.choice-btn:active,
.type-card:active {
  transform: translate3d(0, -1px, 0) scale(.985);
  transition: transform 90ms var(--gx-squish);
}

/* ── 悬停闪光扫过已移除 ──────────────────────────────────────────
   原来卡片悬停会有一道白色高光斜扫而过（::after，480ms）。用户反馈
   "太雷霆了"（过于抢眼），整块删除。悬停仍有上浮 3px + 阴影加深 +
   表面变亮，足以表达可交互。 */

/* ==========================================================================
   ③ 色相变体（按语义自动配色）
   ========================================================================== */

.gx-blue   { background-image: var(--gx-blue), var(--gx-face) !important; }
.gx-purple { background-image: var(--gx-purple), var(--gx-face) !important; }
.gx-teal   { background-image: var(--gx-teal), var(--gx-face) !important; }
.gx-orange { background-image: var(--gx-orange), var(--gx-face) !important; }
.gx-green  { background-image: var(--gx-green), var(--gx-face) !important; }
.gx-pink   { background-image: var(--gx-pink), var(--gx-face) !important; }

.gx-blue, .gx-purple, .gx-teal, .gx-orange, .gx-green, .gx-pink {
  background-size: 100% 100%, 100% 100%, 100% 100% !important;
  background-repeat: no-repeat, no-repeat, no-repeat !important;
}

/* 突出卡片：移除失效的 --gx-edge（0.5px 白环在白底不可见，且与描边重复）*/
.quiz-card { background-image: var(--gx-blue), var(--gx-face) !important; box-shadow: var(--gx-shadow), var(--gx-glow-blue) !important; }
.stat-card:nth-child(1) { background-image: var(--gx-blue), var(--gx-face) !important; }
.stat-card:nth-child(2) { background-image: var(--gx-green), var(--gx-face) !important; }
.stat-card:nth-child(3) { background-image: var(--gx-orange), var(--gx-face) !important; }
.stat-card:nth-child(4) { background-image: var(--gx-purple), var(--gx-face) !important; }
.tool-item:nth-child(1) { background-image: var(--gx-blue), var(--gx-face) !important; }
.tool-item:nth-child(2) { background-image: var(--gx-green), var(--gx-face) !important; }
.tool-item:nth-child(3) { background-image: var(--gx-purple), var(--gx-face) !important; }
.tool-item:nth-child(4) { background-image: var(--gx-orange), var(--gx-face) !important; }
.choice-btn:nth-child(1) { background-image: var(--gx-blue), var(--gx-face) !important; }
.choice-btn:nth-child(2) { background-image: var(--gx-purple), var(--gx-face) !important; }
.choice-btn:nth-child(3) { background-image: var(--gx-orange), var(--gx-face) !important; }
.choice-btn:nth-child(4) { background-image: var(--gx-teal), var(--gx-face) !important; }
.me-btn.reward-btn    { background-image: var(--gx-orange), var(--gx-face) !important; }
.set-row.done         { background-image: var(--gx-green), var(--gx-face) !important; }
.set-row.all          { background-image: var(--gx-blue), var(--gx-face) !important; }
.guest-card           { background-image: var(--gx-orange), var(--gx-face) !important; }
.subj-card            { background-image: var(--gx-blue), var(--gx-face) !important; }

/* ==========================================================================
   ④ 边框光：静态渐变（替代 conic 旋转动画）
   ========================================================================== */

/* ⚡ 原方案：conic-gradient + @property 角度动画 → 每帧重绘
   ✅ 新方案：静态角向渐变，hover 时增强透明度（零重绘）*/

.quiz-card,
.qcard,
.auth-card {
  position: relative;
}
.quiz-card::before,
.qcard::before,
.auth-card::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: linear-gradient(135deg,
    rgba(0, 122, 255, .42) 0%,
    rgba(90, 200, 250, .30) 22%,
    rgba(255, 255, 255, .10) 48%,
    rgba(175, 82, 222, .26) 78%,
    rgba(0, 122, 255, .36) 100%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  pointer-events: none;
  z-index: 3;
  opacity: .75;
  /* 只过渡 opacity，GPU 友好 */
  transition: opacity var(--gx-t-base) var(--gx-out);
}
.quiz-card:hover::before,
.qcard:hover::before,
.auth-card:hover::before {
  opacity: 1;
}
[data-theme="dark"] .quiz-card::before,
[data-theme="dark"] .qcard::before,
[data-theme="dark"] .auth-card::before {
  opacity: .50;
}

/* ==========================================================================
   ⑤ 光斑：radial-gradient 自柔化（免 filter:blur）
   ========================================================================== */

/* ⚡ 原：filter: blur(34px) → 强制离屏渲染
   ✅ 新：radial-gradient 天然柔和，零 filter 开销 */

.fx-orb {
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
  opacity: .55;
  /* 无 filter！ */
  background-image: radial-gradient(circle,
    rgba(0, 122, 255, .26) 0%,
    rgba(0, 122, 255, .12) 38%,
    rgba(0, 122, 255, .03) 62%,
    transparent 76%);
  /* 用 transform 做动画（GPU 合成，不重绘）*/
  animation: gx-orb-drift 14s ease-in-out infinite;
  will-change: transform;
}

.fx-orb.orb-a { width: 150px; height: 150px; top: -52px; right: -42px; }
.fx-orb.orb-b {
  width: 120px; height: 120px; bottom: -42px; left: -34px;
  background-image: radial-gradient(circle,
    rgba(175, 82, 222, .22) 0%, rgba(175, 82, 222, .09) 38%,
    rgba(175, 82, 222, .02) 62%, transparent 76%);
  animation-delay: -4.5s;
}
.fx-orb.orb-c {
  width: 104px; height: 104px; top: 30%; right: -28px;
  background-image: radial-gradient(circle,
    rgba(90, 200, 250, .24) 0%, rgba(90, 200, 250, .10) 38%,
    rgba(90, 200, 250, .02) 62%, transparent 76%);
  animation-delay: -9s;
}
[data-theme="dark"] .fx-orb {
  background-image: radial-gradient(circle,
    rgba(10, 132, 255, .30) 0%, rgba(10, 132, 255, .13) 38%,
    rgba(10, 132, 255, .03) 62%, transparent 76%);
}

/* 只动 transform（合成器线程，不触发重绘/重排）*/
@keyframes gx-orb-drift {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(12px, -14px, 0) scale(1.10); }
}

.card > *, .stat-card > *, .subj-card > *, .me-hero > *, .tool-item > * { position: relative; z-index: 1; }

/* ==========================================================================
   ⑥ 入场动画：纯 transform + opacity（去 blur）
   ========================================================================== */

/* ⚡ 原：filter: blur(10px) → 0 插值，每帧离屏模糊
   ✅ 新：只用 opacity + translate3d + scale，全 GPU 合成 */

@keyframes gx-card-in {
  from { opacity: 0; transform: translate3d(0, 16px, 0) scale(.975); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}

.card, .stat-card, .subj-card, .quiz-card, .choice-btn, .type-card,
.set-row, .tool-item, .rec-item, .cmt, .qcard, .exam-bar {
  animation: gx-card-in 380ms var(--gx-out) both;
}

/* ── 补全：之前漏掉一大批卡片类型，导致工具页 / 我的页 / 错题页 /
   倒计时 / 通知条 等切换时是"硬切"进来的，没有进入动画。 ────────── */
.tool-card,
.me-hero,
.theme-item,
.me-btn,
.acct-btn,
.wrong-q-item,
.wrong-subj,
.cd-card,
.notif-bar,
.result-hero,
.exam-item,
.scoring-row,
.practice-card,
.dashboard-card,
.countdown,
.type-pick,
.notif-item,
.folder-row {
  animation: gx-card-in 150ms var(--gx-out) both;
}
/* 列表类容器的子项也参与交错（与上面的 grid 规则同节奏）*/
.notif-list > *, .wrong-q-list > *, .cd-list > * { animation-delay: 0ms; }
.notif-list > *:nth-child(2), .wrong-q-list > *:nth-child(2), .cd-list > *:nth-child(2) { animation-delay: 16ms; }
.notif-list > *:nth-child(3), .wrong-q-list > *:nth-child(3), .cd-list > *:nth-child(3) { animation-delay: 32ms; }
.notif-list > *:nth-child(4), .wrong-q-list > *:nth-child(4), .cd-list > *:nth-child(4) { animation-delay: 48ms; }
.notif-list > *:nth-child(5), .wrong-q-list > *:nth-child(5), .cd-list > *:nth-child(5) { animation-delay: 64ms; }
.notif-list > *:nth-child(6), .wrong-q-list > *:nth-child(6), .cd-list > *:nth-child(6) { animation-delay: 80ms; }

/* ── 补全第二批：容器与列表行 ─────────────────────────────────
   上面那批之后仍有一批「框」没有任何入场动画（用脚本把 app.js 里
   所有 class 词元跟已带动画的类做过差集得出），一进页面就是"啪"地出现。 */
.group-card,
.guest-card,
.insight-box,
.upload-box,
.ti-box,
.cls-row,
.cls-res-row,
.fr-row,
.ins-row,
.se-row,
.tcfg-row,
.wr-row,
.toggle-row,
.tool-enable-row,
.notif-admin-item,
.notif-bar-item,
.cd-sec,
.sr-group,
.search-box,
.tag-item,
.folder-row,
.folder-chip,
.wrong-type-row,
.cd-empty,
.work-tip,
.guest-tip,
.insight-tip {
  animation: gx-card-in 150ms var(--gx-out) both;
}

/* 列表行的交错（同一容器内的兄弟依次浮现）*/
.fr-row:nth-child(2), .ins-row:nth-child(2), .se-row:nth-child(2),
.wr-row:nth-child(2), .cls-row:nth-child(2), .cls-res-row:nth-child(2),
.notif-admin-item:nth-child(2), .notif-bar-item:nth-child(2), .tag-item:nth-child(2),
.folder-row:nth-child(2), .tool-enable-row:nth-child(2) { animation-delay: 30ms; }
.fr-row:nth-child(3), .ins-row:nth-child(3), .se-row:nth-child(3),
.wr-row:nth-child(3), .cls-row:nth-child(3), .cls-res-row:nth-child(3),
.notif-admin-item:nth-child(3), .notif-bar-item:nth-child(3), .tag-item:nth-child(3),
.folder-row:nth-child(3), .tool-enable-row:nth-child(3) { animation-delay: 60ms; }
.fr-row:nth-child(4), .ins-row:nth-child(4), .se-row:nth-child(4),
.wr-row:nth-child(4), .cls-row:nth-child(4), .cls-res-row:nth-child(4),
.notif-admin-item:nth-child(4), .notif-bar-item:nth-child(4), .tag-item:nth-child(4),
.folder-row:nth-child(4), .tool-enable-row:nth-child(4) { animation-delay: 90ms; }
.fr-row:nth-child(5), .ins-row:nth-child(5), .se-row:nth-child(5),
.wr-row:nth-child(5), .cls-row:nth-child(5), .cls-res-row:nth-child(5),
.notif-admin-item:nth-child(5), .notif-bar-item:nth-child(5), .tag-item:nth-child(5),
.folder-row:nth-child(5), .tool-enable-row:nth-child(5) { animation-delay: 120ms; }
.fr-row:nth-child(6), .ins-row:nth-child(6), .se-row:nth-child(6),
.wr-row:nth-child(6), .cls-row:nth-child(6), .cls-res-row:nth-child(6),
.notif-admin-item:nth-child(6), .notif-bar-item:nth-child(6), .tag-item:nth-child(6),
.folder-row:nth-child(6), .tool-enable-row:nth-child(6) { animation-delay: 150ms; }

/* 标题类：无 .page-head 的视图也要有标题入场 */
.admin-head, .admin-title, .result-hero, .quiz-top, .sets-head {
  animation: gx-head-in 300ms cubic-bezier(.22, 1, .36, 1) both;
}

/* 交错延迟（缩短到 45ms，整体节奏更快）*/
.stat-row > *:nth-child(1), .g3 > *:nth-child(1), .subject-grid > *:nth-child(1) { animation-delay: 0ms; }
.stat-row > *:nth-child(2), .g3 > *:nth-child(2), .subject-grid > *:nth-child(2) { animation-delay: 45ms; }
.stat-row > *:nth-child(3), .g3 > *:nth-child(3), .subject-grid > *:nth-child(3) { animation-delay: 90ms; }
.stat-row > *:nth-child(4), .g3 > *:nth-child(4), .subject-grid > *:nth-child(4) { animation-delay: 135ms; }
.stat-row > *:nth-child(5), .subject-grid > *:nth-child(5) { animation-delay: 180ms; }
.stat-row > *:nth-child(6), .subject-grid > *:nth-child(6) { animation-delay: 225ms; }
.set-list > *:nth-child(1), .rec-list > *:nth-child(1) { animation-delay: 0ms; }
.set-list > *:nth-child(2), .rec-list > *:nth-child(2) { animation-delay: 40ms; }
.set-list > *:nth-child(3), .rec-list > *:nth-child(3) { animation-delay: 80ms; }
.set-list > *:nth-child(4), .rec-list > *:nth-child(4) { animation-delay: 120ms; }
.tool-grid > *:nth-child(1) { animation-delay: 0ms; }
.tool-grid > *:nth-child(2) { animation-delay: 45ms; }
.tool-grid > *:nth-child(3) { animation-delay: 90ms; }
.tool-grid > *:nth-child(4) { animation-delay: 135ms; }

/* ==========================================================================
   ⑦ 登录页动效（保留丰富度，去掉昂贵滤镜）
   ========================================================================== */

.auth-page {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(1100px 700px at 18% -10%, rgba(0, 122, 255, .14) 0%, transparent 56%),
    radial-gradient(900px 620px at 88% 8%,   rgba(175, 82, 222, .11) 0%, transparent 56%),
    radial-gradient(820px 680px at 50% 112%, rgba(90, 200, 250, .10) 0%, transparent 58%),
    var(--ios-bg) !important;
  background-attachment: fixed !important;
}

/* ── 光晕球：radial-gradient 替 filter:blur（性能关键）───────── */
.auth-page .blob {
  display: block !important;
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  /* ⚡ 移除 filter: blur(72px)！radial-gradient 自带柔化 */
  background-image: radial-gradient(circle,
    rgba(0, 122, 255, .30) 0%,
    rgba(0, 122, 255, .16) 32%,
    rgba(0, 122, 255, .05) 56%,
    transparent 72%);
  opacity: .85;
  will-change: transform;
  animation: gx-blob-float 20s ease-in-out infinite;
}
.blob.b1 { width: 520px; height: 520px; top: -180px; left: -140px; animation-delay: 0s; }
.blob.b2 {
  width: 460px; height: 460px; bottom: -180px; right: -120px;
  background-image: radial-gradient(circle,
    rgba(175, 82, 222, .26) 0%, rgba(175, 82, 222, .14) 32%,
    rgba(175, 82, 222, .04) 56%, transparent 72%);
  animation-delay: -6.5s;
}
.blob.b3 {
  width: 380px; height: 380px; top: 36%; right: 14%;
  background-image: radial-gradient(circle,
    rgba(90, 200, 250, .24) 0%, rgba(90, 200, 250, .12) 32%,
    rgba(90, 200, 250, .035) 56%, transparent 72%);
  opacity: .70;
  animation-delay: -13s;
}
[data-theme="dark"] .auth-page .blob {
  background-image: radial-gradient(circle,
    rgba(10, 132, 255, .34) 0%, rgba(10, 132, 255, .18) 32%,
    rgba(10, 132, 255, .05) 56%, transparent 72%);
}

/* 只动 transform */
@keyframes gx-blob-float {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  33%      { transform: translate3d(34px, -40px, 0) scale(1.10); }
  66%      { transform: translate3d(-26px, 26px, 0) scale(.94); }
}

/* ── 粒子：静态背景 + 缓慢位移（不重绘）──────────────────────── */
.auth-page::after {
  content: '';
  position: absolute;
  inset: -60px 0 0 0;
  background-image:
    radial-gradient(1.6px 1.6px at 14% 22%, rgba(255, 255, 255, .80), transparent),
    radial-gradient(1.4px 1.4px at 76% 16%, rgba(255, 255, 255, .62), transparent),
    radial-gradient(1.8px 1.8px at 32% 74%, rgba(255, 255, 255, .68), transparent),
    radial-gradient(1.3px 1.3px at 62% 82%, rgba(255, 255, 255, .56), transparent),
    radial-gradient(1.6px 1.6px at 88% 56%, rgba(255, 255, 255, .62), transparent),
    radial-gradient(1.2px 1.2px at 44% 44%, rgba(255, 255, 255, .52), transparent);
  animation: gx-particles 26s linear infinite;
  pointer-events: none;
  z-index: 0;
  opacity: .45;
  will-change: transform;
}
@keyframes gx-particles {
  0%   { transform: translate3d(0, 0, 0); }
  100% { transform: translate3d(0, -60px, 0); }
}
[data-theme="dark"] .auth-page::after {
  background-image:
    radial-gradient(1.6px 1.6px at 14% 22%, rgba(120, 190, 255, .70), transparent),
    radial-gradient(1.4px 1.4px at 76% 16%, rgba(180, 140, 255, .58), transparent),
    radial-gradient(1.8px 1.8px at 32% 74%, rgba(120, 200, 255, .62), transparent),
    radial-gradient(1.3px 1.3px at 62% 82%, rgba(180, 140, 255, .52), transparent),
    radial-gradient(1.6px 1.6px at 88% 56%, rgba(120, 190, 255, .58), transparent),
    radial-gradient(1.2px 1.2px at 44% 44%, rgba(180, 140, 255, .48), transparent);
}

/* ── 登录卡片：唯一的 backdrop-filter（数量=1，可接受）────────── */
.auth-card {
  position: relative;
  z-index: 2;
  background-image: var(--gx-blue), var(--gx-face) !important;
  /* 只此一处保留玻璃模糊，因它是焦点元素 */
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  border: 0.5px solid rgba(255, 255, 255, .60) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .95),
    0 2px 6px rgba(16, 24, 40, .05),
    0 14px 34px rgba(16, 24, 40, .07),
    0 40px 72px rgba(16, 24, 40, .07) !important;
  animation: gx-card-in 460ms var(--gx-out) both;
}
[data-theme="dark"] .auth-card {
  border-color: rgba(255, 255, 255, .09) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .07),
    0 2px 6px rgba(0, 0, 0, .30),
    0 14px 34px rgba(0, 0, 0, .36),
    0 40px 72px rgba(0, 0, 0, .34) !important;
}

/* ── Logo：旋转光环改静态渐变 + transform 旋转（GPU）─────────── */
.auth-logo .mark {
  position: relative;
  background: var(--grad);
  animation: gx-logo-pop 520ms var(--gx-spring) both;
}
@keyframes gx-logo-pop {
  from { opacity: 0; transform: scale(.70); }
  to   { opacity: 1; transform: scale(1); }
}
/* 外圈光环：静态 conic（不参与动画），用 transform 旋转整个元素 */
.auth-logo .mark::after {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: inherit;
  background: conic-gradient(
    rgba(0, 122, 255, .70) 0%,
    rgba(90, 200, 250, .80) 14%,
    rgba(175, 82, 222, .70) 28%,
    transparent 44%,
    transparent 100%);
  -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
  mask-composite: exclude;
  padding: 2px;
  /* ⚡ transform 旋转（合成器），而非 @property 角度（重绘）*/
  animation: gx-spin 3.8s linear infinite;
  pointer-events: none;
  will-change: transform;
}
@keyframes gx-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
/* 呼吸光晕：用 radial-gradient，无 filter */
.auth-logo .mark::before {
  content: '';
  position: absolute;
  inset: -22px;
  border-radius: 50%;
  background-image: radial-gradient(circle,
    rgba(0, 122, 255, .30) 0%, rgba(0, 122, 255, .12) 42%, transparent 70%);
  animation: gx-halo 3.6s ease-in-out infinite;
  pointer-events: none;
  z-index: -1;
  will-change: transform, opacity;
}
@keyframes gx-halo {
  0%, 100% { opacity: .55; transform: scale(1); }
  50%      { opacity: .92; transform: scale(1.14); }
}

.auth-logo h1 { animation: gx-card-in 380ms var(--gx-out) 120ms both; }
.auth-logo p  { animation: gx-card-in 380ms var(--gx-out) 180ms both; }

/* ── Tab 滑块（保持弹性，缩短时长）────────────────────────────── */
/* .auth-tabs 的对齐与滑块定义见 ㉛ */
[data-theme="dark"] .auth-tabs .slider {
  background-image: linear-gradient(150deg, #3A3A3E 0%, #313135 100%) !important;
}
.auth-tabs button { transition: color 180ms var(--gx-out); }

/* ── 输入框：聚焦环（用 box-shadow 呼吸，不用 backdrop-filter）── */
.auth-card .input {
  background-image: linear-gradient(150deg, #FFFFFF 0%, #FAFCFF 100%) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  border: 0.5px solid rgba(0, 122, 255, .14) !important;
  box-shadow: inset 0 1px 2px rgba(16, 24, 40, .03), 0 1px 2px rgba(16, 24, 40, .03) !important;
  transition: box-shadow 200ms var(--gx-out), transform 200ms var(--gx-out), border-color 200ms var(--gx-out) !important;
}
[data-theme="dark"] .auth-card .input {
  background-image: linear-gradient(150deg, #2A2A2E 0%, #242428 100%) !important;
  border-color: rgba(255, 255, 255, .08) !important;
}
.auth-card .input:hover {
  transform: translate3d(0, -1px, 0);
  box-shadow: inset 0 1px 2px rgba(16,24,40,.03), 0 4px 12px rgba(16,24,40,.06) !important;
}
.auth-card .input:focus {
  transform: translate3d(0, -1px, 0);
  border-color: rgba(0, 122, 255, .55) !important;
  box-shadow:
    inset 0 1px 2px rgba(16, 24, 40, .02),
    0 0 0 3.5px rgba(0, 122, 255, .14),
    0 6px 18px rgba(0, 122, 255, .12) !important;
  /* 呼吸动画（box-shadow）已移除：box-shadow 动画每帧重绘，
     想跟满刷新率就不能动画它。静态焦点环已经足够明显。 */
}
@keyframes gx-input-breathe {
  0%, 100% { box-shadow: inset 0 1px 2px rgba(16,24,40,.02), 0 0 0 3.5px rgba(0,122,255,.14), 0 6px 18px rgba(0,122,255,.12); }
  50%      { box-shadow: inset 0 1px 2px rgba(16,24,40,.02), 0 0 0 5px rgba(0,122,255,.09), 0 8px 22px rgba(0,122,255,.17); }
}

/* ── 主按钮：渐变底 + 光泽扫过（去掉 background-position 动画）── */
.auth-card .btn-primary {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* 静态渐变（原为 background-position 流动 → 每帧重绘）*/
  background-image: linear-gradient(120deg, #007AFF 0%, #2E90FF 48%, #5AC8FA 100%) !important;
  box-shadow:
    0 2px 6px rgba(0, 122, 255, .24),
    0 8px 20px rgba(0, 122, 255, .24),
    inset 0 1px 0 rgba(255, 255, 255, .26) !important;
  transition: transform 200ms var(--gx-spring), box-shadow 200ms var(--gx-out) !important;
}
.auth-card .btn-primary:hover {
  transform: translate3d(0, -2px, 0);
  box-shadow:
    0 4px 10px rgba(0, 122, 255, .28),
    0 12px 28px rgba(0, 122, 255, .30),
    inset 0 1px 0 rgba(255, 255, 255, .32) !important;
}
.auth-card .btn-primary:active {
  transform: translate3d(0, 0, 0) scale(.972);
  transition: transform 90ms var(--gx-squish) !important;
}
/* 按钮光泽扫过已按要求移除 */

/* ── 依次浮现 ─────────────────────────────────────────────────── */
.auth-hint { animation: gx-card-in 380ms var(--gx-out) 300ms both; }
/* 登录页表单字段的入场级联统一在 ⑨ 节 */
.auth-page .card:not(.auth-card) { animation: gx-card-in 420ms var(--gx-out) 340ms both; }

/* ── 主题钮：便宜的交互动效 ───────────────────────────────────── */
.auth-theme {
  transition: transform 260ms var(--gx-spring), box-shadow 200ms var(--gx-out) !important;
}
.auth-theme:hover { transform: rotate(18deg) scale(1.05); }
.auth-theme:active { transform: rotate(0) scale(.92); transition-duration: 90ms !important; }

/* ── 浮动标签：改成极低频率（8s），几乎不可感知开销 ───────────── */
@keyframes gx-label-float {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(0, -2px, 0); }
}
.auth-card .field label { animation: gx-label-float 8s ease-in-out infinite; }
.auth-card .field:nth-of-type(2) label { animation-delay: -4s; }

/* ==========================================================================
   ⑧ 骨架屏（简化渐变，降低重绘）
   ========================================================================== */

@keyframes gx-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.skeleton {
  background-image: linear-gradient(90deg,
    rgba(120, 120, 128, .07) 25%,
    rgba(120, 120, 128, .14) 50%,
    rgba(120, 120, 128, .07) 75%) !important;
  background-size: 200% 100% !important;
  animation: gx-shimmer 1.8s linear infinite !important;
}

/* ==========================================================================
   ⑨ 关键元素仍保留玻璃模糊（数量少，值得）
   ========================================================================== */

/* 顶栏 / 底栏 / 模态 —— 这些数量恒定且面积大，保留真玻璃 */
.topbar,
.mobile-nav {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
.modal, .dlg, .notif-pop, .toast, .qf-sheet {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* ==========================================================================
   ⑩ 可访问性 / 降级
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .fx-orb, .auth-page .blob, .auth-page::after,
  .auth-logo .mark, .auth-logo .mark::before, .auth-logo .mark::after,
  .auth-card, .auth-card .btn-primary, .auth-card .btn-primary::after,
  .auth-card .input:focus, .auth-card .field label, .skeleton {
    animation: none !important;
  }
  .card, .stat-card, .subj-card, .quiz-card, .choice-btn, .type-card,
  .set-row, .tool-item, .rec-item, .cmt, .qcard, .exam-bar, .auth-card {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* 移动端：进一步减负 */
@media (max-width: 640px) {
  .fx-orb { animation-duration: 18s; opacity: .45; }
  .auth-page .blob { animation-duration: 26s; }
  .auth-page::after { opacity: .30; }
}

/* 低端设备（核心数少 / 内存小）→ 关闭装饰动画 */
@media (max-width: 400px) {
  .fx-orb, .auth-page::after { display: none; }
  .auth-page .blob { animation: none; }
}

@media (prefers-contrast: more) {
  .auth-page .blob, .auth-page::after, .fx-orb { display: none; }
  .card, .stat-card, .subj-card { background-image: none !important; background: var(--card) !important; }
}

@media print {
  .auth-page .blob, .auth-page::after, .fx-orb { display: none !important; }
}

/* ==========================================================================
   ⑪ 精准清除：小元素不需要玻璃模糊（零视觉收益，纯 GPU 浪费）
   ========================================================================== */

.avatar,
.burger,
.modal-x,
.modal-close,
.notif-ico,
.nt-ico,
.subj-pin,
.notif-bar,
.admin-main,
.sb-clear,
.sb-ico,
.pager,
.tag-x,
.cls-chip-x,
.cmt-btn,
.notif-btn,
.auth-theme,
.dl-btn,
.rec-redo,
.ref-btn,
.cmt-open,
.comment-btn,
.speak-btn,
.link-btns button,
.list-ops button,
.item-ops button,
.row-ops button,
.td-actions button {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* ── 保留玻璃的大型悬浮层（统一 18px，降开销）──────────────────── */
.topbar,
.mobile-nav,
.sidebar,
.side-nav,
.admin-head,
.modal,
.dlg,
.notif-pop,
.toast,
.qf-sheet,
.cmt-modal,
.auth-card {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* ── 遮罩只需极轻模糊 ─────────────────────────────────────────── */
.sb-mask,
.cmt-mask {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* ── 全局：禁止装饰元素参与模糊 ───────────────────────────────── */
.fx-orb,
.auth-page .blob,
.auth-page::after,
.auth-page::before {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  filter: none !important;
}

/* ⚠️ 这里原本有 contain: layout style，已移除。
   contain: layout / paint 会让元素成为 position:fixed 后代的包含块 ——
   导致 main.container 内的弹窗遮罩无法铺满视口（只能盖住内容列）。
   性能收益远小于这个正确性代价，故整体去掉。 */
.admin-body,
.container,
.quiz-wrap,


/* ── 长列表：跳过屏外渲染 ─────────────────────────────────────── */
.set-list,
.rec-list,
.tool-grid,
.subject-grid,
.notif-list,
.cmt-list,


/* ==========================================================================
   ⑫ 全局渐变底图 —— 所有界面统一（微妙、克制、零性能成本）
   ========================================================================== */

/* ── 基础：斜向三段渐变 + 四点角落光晕（fixed 避免滚动重绘）────── */
/* ══════════════════════════════════════════════════════════════
   背景层改用「固定定位伪元素」—— 比 background-attachment:fixed 更可靠
   原因：body 有 height:100%，配合 fixed 在不同浏览器表现不一致
   ══════════════════════════════════════════════════════════════ */

body {
  background: transparent !important;
  background-color: transparent !important;
  background-image: none !important;
}

/* 背景层：固定在视口，z-index:-1 位于所有内容之下 */
body::before {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
  /* ══════════════════════════════════════════════════════════════
     真·多彩渐变 —— 跨 5 个色相：蓝 → 青 → 靛 → 紫 → 粉
     ══════════════════════════════════════════════════════════════ */
  background-image:
    /* ── 底部四色光斑（色相差异明显）── */
    radial-gradient(ellipse 880px 520px at 6% 104%,  rgba(56, 130, 255, .34) 0%, transparent 64%),   /* 蓝 */
    radial-gradient(ellipse 820px 500px at 94% 106%, rgba(168, 96, 255, .30) 0%, transparent 64%),   /* 紫 */
    radial-gradient(ellipse 700px 440px at 46% 112%, rgba(60, 200, 235, .24) 0%, transparent 66%),   /* 青 */
    radial-gradient(ellipse 620px 420px at 72% 108%, rgba(255, 130, 200, .17) 0%, transparent 68%),  /* 粉 */
    /* ── 主渐变：跨色相（非同一色系深浅）── */
    linear-gradient(166deg,
      #FFFFFF 0%,
      #F9FCFF 10%,
      #EFF7FF 20%,
      #E0EEFF 30%,     /* 淡蓝 */
      #E7F1FF 40%,     /* 蓝 */
      #DFF0FB 48%,     /* 蓝青 */
      #DEF1FB 54%,     /* 青蓝 */
      #E0E4FC 62%,     /* 蓝紫 */
      #E9DFFA 70%,     /* 浅紫 */
      #EFDEF6 78%,     /* 紫 */
      #F3E0F4 86%,     /* 紫粉 */
      #F8E2EF 93%,     /* 粉紫 */
      #FBE4EC 100%);   /* 粉 */
  background-repeat: no-repeat;
  background-size: 100% 100%;
}

/* 暗色背景层 */
[data-theme="dark"] body::before {
  background-image:
    radial-gradient(ellipse 880px 520px at 6% 104%,  rgba(30, 95, 210, .36) 0%, transparent 64%),
    radial-gradient(ellipse 820px 500px at 94% 106%, rgba(120, 55, 200, .34) 0%, transparent 64%),
    radial-gradient(ellipse 700px 440px at 46% 112%, rgba(25, 130, 180, .26) 0%, transparent 66%),
    radial-gradient(ellipse 620px 420px at 72% 108%, rgba(160, 45, 130, .18) 0%, transparent 68%),
    linear-gradient(166deg,
      #21232B 0%,
      #1E2029 12%,
      #1A1D28 24%,
      #171A27 36%,
      #141726 48%,
      #121525 58%,
      #101424 68%,
      #0D1120 80%,
      #0A0E1A 92%,
      #080B14 100%);
}

[data-theme="dark"] body {
  background-color: #0B0E15 !important;
  background-image:
    radial-gradient(ellipse 950px 480px at 10% 106%, rgba(20, 80, 180, .46) 0%, transparent 68%),
    radial-gradient(ellipse 880px 440px at 90% 108%, rgba(90, 45, 160, .42) 0%, transparent 68%),
    radial-gradient(ellipse 760px 400px at 50% 112%, rgba(25, 100, 170, .32) 0%, transparent 70%),
    linear-gradient(165deg,
      #1E2028 0%,
      #1C1E27 12%,
      #191C26 24%,
      #161A25 36%,
      #131724 48%,
      #101424 60%,
      #0D1120 72%,
      #0A0E1C 83%,
      #080B17 93%,
      #060912 100%);
  background-attachment: fixed !important;
  background-size: 100% 100% !important;
  background-repeat: no-repeat !important;
}
[data-theme="dark"] .auth-page {
  background-image:
    radial-gradient(1050px 720px at 14% -12%, rgba(10, 132, 255, .175) 0%, transparent 56%),
    radial-gradient(980px 660px at 92% 6%,   rgba(191, 90, 242, .135) 0%, transparent 56%),
    radial-gradient(900px 720px at 48% 116%, rgba(100, 210, 255, .115) 0%, transparent 58%),
    linear-gradient(180deg,
      #1A1B1F 0%,
      #1A1B1F 30%,
      #181A1E 50%,
      #16181D 70%,
      #14161B 100%) !important;
}

/* ── 手机端：背景层同步（改为 body::before，光斑略小省电）──────── */
@media (max-width: 860px) {
  body::before {
    background-image:
      radial-gradient(ellipse 620px 380px at 4% 102%,  rgba(56, 130, 255, .32) 0%, transparent 66%),
      radial-gradient(ellipse 580px 360px at 96% 104%, rgba(168, 96, 255, .28) 0%, transparent 66%),
      radial-gradient(ellipse 480px 300px at 48% 108%, rgba(60, 200, 235, .22) 0%, transparent 68%),
      radial-gradient(ellipse 420px 280px at 74% 106%, rgba(255, 130, 200, .15) 0%, transparent 70%),
      linear-gradient(166deg,
        #FFFFFF 0%,
        #F7FBFF 12%,
        #EAF4FF 24%,
        #E9F2FF 36%,
        #E2F0FC 46%,
        #E4E8FC 56%,
        #EBE0FA 68%,
        #F1DFF7 78%,
        #F5E1F4 88%,
        #FAE4EE 100%);
  }
}

/* ── 滚动容器内的渐变（随内容延伸，避免"截断"感）──────────────── */
.pane,
section {
  background-repeat: no-repeat;
  background-attachment: scroll;
}

/* ── 打印 / 高对比：移除装饰渐变 ───────────────────────────────── */
@media print {
  body, .admin-main, .admin-body, .auth-page {
    background-image: none !important;
    background: #fff !important;
  }
}
@media (prefers-contrast: more) {
  body, .admin-main, .admin-body, .auth-page {
    background-image: none !important;
    background-color: var(--ios-bg) !important;
  }
}

/* ==========================================================================
   ⑬ 科目卡片 · 置顶按钮锁定右上角（PC 端）
   ========================================================================== */

.subj-pin {
  position: absolute !important;
  top: 12px !important;
  right: 12px !important;
  left: auto !important;
  bottom: auto !important;
  width: 32px !important;
  height: 32px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  /* 层级高于光泽扫过层(::after z-index:2)与分类标签 */
  z-index: 6 !important;
  cursor: pointer !important;
  opacity: .62;
  transition: opacity 200ms var(--gx-out), transform 260ms var(--gx-spring),
              box-shadow 200ms var(--gx-out), background 200ms var(--gx-out);
}
.subj-pin:hover {
  opacity: 1 !important;
  transform: scale(1.10) !important;
  box-shadow: var(--gx-edge), 0 4px 12px rgba(0, 122, 255, .16) !important;
}
.subj-pin:active { transform: scale(.94) !important; }
.subj-pin.on {
  opacity: 1 !important;
  background: var(--brand) !important;
  color: #fff !important;
  border-color: transparent !important;
  box-shadow: 0 2px 10px rgba(0, 122, 255, .34) !important;
}

/* 分类标签避让置顶按钮：右上角留给置顶，类别标签改到左上内联 */
.subj-cat {
  z-index: 3 !important;
}

/* ==========================================================================
   ⑭ 透明化：让 body 的统一渐变透出来
   --------------------------------------------------------------------------
   这些容器原本用不透明背景，会盖住 body 的「顶部白→底部彩」渐变，
   造成「中间有色/两侧纯白」的割裂。统一改为透明。
   ========================================================================== */

.admin-main,
.admin-body,
.container,
.quiz-wrap,
.pane,
section,
main,
#app {
  background: transparent !important;
  background-color: transparent !important;
  background-image: none !important;
}

/* 注：.auth-page（登录页）保留自己的渐变 —— 它是独立全屏页 */

/* ==========================================================================
   ⑮ 登录页动效增强 v2 —— 更惊艳、层次更丰富
   --------------------------------------------------------------------------
   新增：背景渐变流动 · 双环反向旋转 · 多轨迹光晕 · 粒子闪烁
        · 卡片 3D 入场 · 输入框流光 · 按钮涟漪 · 精细 stagger
   原则：只用 transform / opacity / filter（GPU 友好），控制层数
   ========================================================================== */

/* ── ① 背景流动（波浪）已按要求移除 ───────────────────────────── */
.auth-page {
  animation: none !important;
}

/* ── ② 光晕球：三条不同轨迹（不再同步漂浮）────────────────────── */
.auth-page .blob.b1 { animation: blob-path-a 18s ease-in-out infinite; }
.auth-page .blob.b2 { animation: blob-path-b 22s ease-in-out infinite; }
.auth-page .blob.b3 { animation: blob-path-c 26s ease-in-out infinite; }

@keyframes blob-path-a {
  0%, 100% { transform: translate3d(0,0,0) scale(1); opacity: .42; }
  25%      { transform: translate3d(60px,-50px,0) scale(1.18); opacity: .58; }
  50%      { transform: translate3d(-30px,40px,0) scale(.88); opacity: .34; }
  75%      { transform: translate3d(44px,26px,0) scale(1.10); opacity: .52; }
}
@keyframes blob-path-b {
  0%, 100% { transform: translate3d(0,0,0) scale(1); opacity: .40; }
  30%      { transform: translate3d(-56px,44px,0) scale(1.16); opacity: .56; }
  60%      { transform: translate3d(36px,-38px,0) scale(.90); opacity: .32; }
}
@keyframes blob-path-c {
  0%, 100% { transform: translate3d(0,0,0) scale(1) rotate(0deg); opacity: .30; }
  40%      { transform: translate3d(-42px,-52px,0) scale(1.22) rotate(20deg); opacity: .48; }
  70%      { transform: translate3d(50px,34px,0) scale(.86) rotate(-14deg); opacity: .26; }
}

/* ── ③ 粒子：更密 + 闪烁 ──────────────────────────────────────── */
.auth-page::after {
  animation: gx-particles 26s linear infinite,
             auth-twinkle 4s ease-in-out infinite !important;
}
@keyframes auth-twinkle {
  0%, 100% { opacity: .30; }
  50%      { opacity: .62; }
}

/* ── ④ 卡片：3D 弹性入场 + 光泽扫过 ───────────────────────────── */
.auth-card {
  animation:
    auth-card-3d 900ms cubic-bezier(.22, 1, .36, 1) both !important;
  transform-style: preserve-3d;
}
@keyframes auth-card-3d {
  0%   { opacity: 0; transform: perspective(1200px) translate3d(0, 48px, 0) rotateX(12deg) scale(.90); }
  55%  { opacity: 1; transform: perspective(1200px) translate3d(0, -6px, 0) rotateX(-2deg) scale(1.015); }
  100% { opacity: 1; transform: perspective(1200px) translate3d(0, 0, 0) rotateX(0) scale(1); }
}
/* 呼吸光晕改为「伪元素 opacity」—— 纯合成器，能跟满屏幕刷新率。
   原来直接动画 box-shadow，等于每帧重绘整张卡片。 */
@keyframes auth-card-breathe {
  0%, 100% { opacity: .28; }
  50%      { opacity: 1; }
}
.auth-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow:
    0 4px 14px rgba(0, 122, 255, .10),
    0 20px 46px rgba(0, 122, 255, .10),
    0 52px 92px rgba(16, 24, 40, .08);
  opacity: 0;
  animation: auth-card-breathe 7s ease-in-out 1.2s infinite;
  pointer-events: none;
  z-index: -1;
}

/* ── 登录卡片「白色扫光条」已移除 ────────────────────────────────
   原来 .auth-card::after 是一道 .42 白的斜条，7 秒一轮从左扫到右
   （@keyframes auth-card-shine）。用户反馈"多了个从左往右的白色闪条"，
   整块删除。登录卡片保留：3D 弹性入场 + 呼吸光晕。 */
.auth-card > * { position: relative; z-index: 2; }

/* ── ⑤ Logo：已移除旋转光环（按要求）──────────────────────────── */
/* 光环脉动改为「伪元素 opacity + 轻微 scale」—— 合成器属性 */
@keyframes auth-halo-breathe {
  0%, 100% { opacity: .34; transform: scale(1); }
  50%      { opacity: .74; transform: scale(1.05); }
}
.auth-logo .mark::after {
  animation: auth-halo-breathe 4.6s ease-in-out .9s infinite !important;
  will-change: opacity, transform;
}

/* 外层反向环（用额外的 box-shadow 模拟，避免额外 DOM）*/
.auth-logo .mark {
  animation: auth-logo-pop2 700ms cubic-bezier(.34, 1.56, .64, 1) both !important;
}
@keyframes auth-logo-pop2 {
  0%   { opacity: 0; transform: scale(.40) rotate(-24deg); }
  60%  { opacity: 1; transform: scale(1.14) rotate(5deg); }
  100% { opacity: 1; transform: scale(1) rotate(0deg); }
}
@keyframes auth-logo-halo-pulse {
  0%, 100% { box-shadow: 0 4px 16px rgba(0,122,255,.28), inset 0 1px 0 rgba(255,255,255,.28), 0 0 0 0 rgba(0,122,255,.26); }
  50%      { box-shadow: 0 6px 24px rgba(0,122,255,.40), inset 0 1px 0 rgba(255,255,255,.34), 0 0 0 12px rgba(0,122,255,0); }
}

/* ── ⑥ Tab 滑块：弹性 + 文字流光 ─────────────────────────────── */
.auth-tabs button.active {
  background: linear-gradient(100deg, var(--ink) 30%, var(--brand) 50%, var(--ink) 70%);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  /* 文字流光（background-position）已移除：它每帧重绘，无法跟满高刷。
     静态渐变文字保留。 */
}
@keyframes auth-tab-shine {
  0%   { background-position: 120% 0; }
  100% { background-position: -120% 0; }
}

/* ── ⑦ 输入框：聚焦时的旋转光环 + 流光边框 ───────────────────── */
.auth-card .input {
  position: relative;
  transition: box-shadow 260ms var(--gx-out), transform 300ms var(--gx-spring),
              border-color 260ms var(--gx-out) !important;
}
.auth-card .input:focus {
  transform: translate3d(0, -2px, 0) !important;
  box-shadow:
    inset 0 1px 2px rgba(16,24,40,.02),
    0 0 0 3.5px rgba(0,122,255,.16),
    0 8px 24px rgba(0,122,255,.16) !important;
  /* 同上：动画 box-shadow 走主线程重绘，已移除 */
}
@keyframes auth-input-ring {
  0%, 100% { box-shadow: inset 0 1px 2px rgba(16,24,40,.02), 0 0 0 3.5px rgba(0,122,255,.16), 0 8px 24px rgba(0,122,255,.16); }
  50%      { box-shadow: inset 0 1px 2px rgba(16,24,40,.02), 0 0 0 6px rgba(0,122,255,.09), 0 12px 30px rgba(0,122,255,.22); }
}

/* ── ⑧ 主按钮：静态渐变（循环动画已按要求移除）────────────────── */
.auth-card .btn-primary {
  background-size: 100% 100% !important;
  background-position: 0% 50% !important;
  animation: none !important;
  box-shadow:
    0 2px 6px rgba(0, 122, 255, .24),
    0 8px 20px rgba(0, 122, 255, .24),
    inset 0 1px 0 rgba(255, 255, 255, .26) !important;
}
/* 悬停：轻微上浮 + 阴影加深（交互反馈，非循环动画）*/
.auth-card .btn-primary:hover {
  transform: translate3d(0, -2px, 0) !important;
  box-shadow:
    0 4px 10px rgba(0, 122, 255, .28),
    0 12px 28px rgba(0, 122, 255, .30),
    inset 0 1px 0 rgba(255, 255, 255, .32) !important;
}
/* 按压：回落 */
.auth-card .btn-primary:active {
  transform: translate3d(0, 0, 0) scale(.975) !important;
  transition: transform 90ms cubic-bezier(.36,.07,.19,.97) !important;
}
/* 涟漪 */
.auth-card .btn-primary::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(circle at 50% 50%, rgba(255,255,255,.55) 0%, transparent 62%);
  opacity: 0;
  transform: scale(.30);
  transition: opacity 460ms var(--gx-out), transform 460ms var(--gx-out);
  pointer-events: none;
}
.auth-card .btn-primary:active::before {
  opacity: 1;
  transform: scale(1.6);
  transition-duration: 0ms;
}

/* ── ⑨ 精细 stagger 入场（每个元素依次弹入）────────────────────
   ⚠️ 原来只写到 .field:nth-of-type(2)，但「注册」表单有 **4 个**字段
      （账号 / 昵称 / 密码 / 确认密码）—— 于是第 3、4 个
      （也就是「密码」和「确认密码」）完全没有入场动画。
   这里补齐到 6 个字段；同时把原来 560~620ms、最晚 640ms 才开始的节奏
   压缩到 300~320ms、最晚 435ms，更轻快。
     · 字段不含 backdrop-filter，位移完全免费，所以敢用 16~18px 的明显上升
     · 缓动带一点回弹（cubic-bezier(.34,1.3,.64,1)），收尾有弹性 */
.auth-logo { animation: auth-fade-in 300ms cubic-bezier(.22,1,.36,1) 30ms both; }
.auth-tabs { animation: auth-fade-in 300ms cubic-bezier(.22,1,.36,1) 110ms both; }

.auth-card .field { animation: auth-field-in 300ms cubic-bezier(.34,1.3,.64,1) both; }
.auth-card .field:nth-of-type(1) { animation-delay: 160ms; }
.auth-card .field:nth-of-type(2) { animation-delay: 215ms; }
.auth-card .field:nth-of-type(3) { animation-delay: 270ms; }
.auth-card .field:nth-of-type(4) { animation-delay: 325ms; }
.auth-card .field:nth-of-type(5) { animation-delay: 380ms; }
.auth-card .field:nth-of-type(6) { animation-delay: 435ms; }

/* 提交按钮（.btn-primary 带 !important，必须跟 !important 才压得住）*/
.auth-card .btn-primary          { animation: auth-btn-in 320ms cubic-bezier(.34,1.5,.64,1) 380ms both !important; }
.auth-card form .btn-ghost,
.auth-card form .btn-block:not(.btn-primary) { animation: auth-btn-in 320ms cubic-bezier(.34,1.5,.64,1) 380ms both; }
.auth-hint { animation: auth-fade-in 300ms cubic-bezier(.22,1,.36,1) 430ms both; }

@keyframes auth-field-in {
  0%   { opacity: 0; transform: translate3d(0, 16px, 0) scale(.97); }
  60%  { opacity: 1; transform: translate3d(0, -2px, 0) scale(1.006); }
  100% { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes auth-btn-in {
  0%   { opacity: 0; transform: translate3d(0, 18px, 0) scale(.95); }
  60%  { opacity: 1; transform: translate3d(0, -3px, 0) scale(1.015); }
  100% { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes auth-fade-in {
  from { opacity: 0; transform: translate3d(0, 10px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* ── ⑩ 主题切换按钮：悬停旋转 + 光晕 ─────────────────────────── */
.auth-theme {
  animation: gx-card-in 500ms var(--gx-out) 120ms both;
  transition: transform 420ms cubic-bezier(.34,1.56,.64,1),
              box-shadow 300ms var(--gx-out) !important;
}
.auth-theme:hover {
  transform: rotate(26deg) scale(1.12) !important;
  box-shadow: 0 6px 20px rgba(0,122,255,.24), 0 0 0 6px rgba(0,122,255,.08) !important;
}

/* ── ⑪ 游客提示卡：橙色脉动边框 ──────────────────────────────── */
.auth-page .card:not(.auth-card) {
  animation: gx-card-in 620ms var(--gx-out) 720ms both,
             auth-guest-pulse 5s ease-in-out infinite 1.5s;
}
@keyframes auth-guest-pulse {
  0%, 100% { box-shadow: inset 0 0 0 1px rgba(255,149,0,.20), 0 2px 8px rgba(255,149,0,.06); }
  50%      { box-shadow: inset 0 0 0 1px rgba(255,149,0,.34), 0 6px 20px rgba(255,149,0,.12); }
}

/* ── ⑫ 降级：尊重「减少动效」偏好 ─────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .auth-page, .auth-page .blob, .auth-page::after,
  .auth-card, .auth-logo .mark, .auth-logo .mark::after,
  .auth-tabs button.active, .auth-card .input:focus,
  .auth-card .btn-primary, .auth-card .btn-primary::before,
  .auth-page .card:not(.auth-card),
  .auth-logo, .auth-tabs, .auth-hint, .auth-theme,
  .auth-card .field:nth-of-type(1), .auth-card .field:nth-of-type(2) {
    animation: none !important;
  }
}

/* ── ⑬ 移动端减负（保留主要动效，减少并行层数）───────────────── */
@media (max-width: 640px) {
  .auth-page { animation-duration: 30s; }
  .auth-page::after { animation-duration: 34s, 5s; }
  .auth-logo .mark::after { animation-duration: 5.6s; }
}

/* ==========================================================================
   ⑯ 登录页背景动效增强 v3 —— 多层光影（更丰富）
   --------------------------------------------------------------------------
   移除：Logo 旋转、背景波浪
   新增：光束扫过 · 光晕核心脉动 · 环形波纹 · 粒子升级 · 星点漂移
   原则：全部 transform/opacity，GPU 友好
   ========================================================================== */

/* ── ① 光束扫过（两道斜向光带交错）───────────────────────────── */
.auth-page {
  position: relative;
  overflow: hidden;
}
.auth-page::before {
  content: '';
  position: absolute;
  inset: -70%;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(112deg,
      transparent 42%,
      rgba(0, 132, 255, .09) 47%,
      rgba(130, 205, 255, .16) 50%,
      rgba(0, 132, 255, .09) 53%,
      transparent 58%),
    linear-gradient(146deg,
      transparent 40%,
      rgba(175, 82, 222, .08) 46%,
      rgba(205, 160, 255, .14) 50%,
      rgba(175, 82, 222, .08) 54%,
      transparent 60%);
  animation: auth-beam 13s cubic-bezier(.45,0,.55,1) infinite;
}
@keyframes auth-beam {
  0%   { transform: translate3d(-52%, -28%, 0) rotate(0.01deg); opacity: .30; }
  42%  { opacity: .88; }
  100% { transform: translate3d(52%, 28%, 0) rotate(0.01deg); opacity: .30; }
}

/* ── ② 光晕球：核心脉动（内层光核呼吸）───────────────────────── */
.auth-page .blob {
  position: absolute;
  will-change: transform;
}
.auth-page .blob::after {
  content: '';
  position: absolute;
  inset: 30%;
  border-radius: 50%;
  pointer-events: none;
  animation: auth-core 6.5s ease-in-out infinite;
}
.blob.b1::after { background: radial-gradient(circle, rgba(0,122,255,.55) 0%, transparent 72%); }
.blob.b2::after { background: radial-gradient(circle, rgba(175,82,222,.50) 0%, transparent 72%); animation-delay: -2.2s; }
.blob.b3::after { background: radial-gradient(circle, rgba(90,200,250,.48) 0%, transparent 72%); animation-delay: -4.4s; }
@keyframes auth-core {
  0%, 100% { transform: scale(.78); opacity: .45; }
  50%      { transform: scale(1.32); opacity: 1; }
}

/* ── ③ 环形波纹（圈变大）已按要求移除 ─────────────────────────── */

/* ── ④ 粒子升级：三层不同速度 + 大小 ─────────────────────────── */
.auth-page::after {
  background-image:
    /* 大颗粒（慢）*/
    radial-gradient(2.2px 2.2px at 12% 20%, rgba(255,255,255,.90), transparent),
    radial-gradient(2.4px 2.4px at 78% 14%, rgba(255,255,255,.85), transparent),
    radial-gradient(2.0px 2.0px at 34% 72%, rgba(255,255,255,.88), transparent),
    radial-gradient(2.2px 2.2px at 66% 84%, rgba(255,255,255,.82), transparent),
    /* 中颗粒 */
    radial-gradient(1.6px 1.6px at 22% 46%, rgba(255,255,255,.78), transparent),
    radial-gradient(1.5px 1.5px at 88% 52%, rgba(255,255,255,.75), transparent),
    radial-gradient(1.7px 1.7px at 44% 88%, rgba(255,255,255,.72), transparent),
    radial-gradient(1.5px 1.5px at 58% 32%, rgba(255,255,255,.70), transparent),
    /* 小颗粒（密）*/
    radial-gradient(1.1px 1.1px at 8% 62%, rgba(255,255,255,.65), transparent),
    radial-gradient(1.0px 1.0px at 30% 12%, rgba(255,255,255,.62), transparent),
    radial-gradient(1.2px 1.2px at 52% 56%, rgba(255,255,255,.68), transparent),
    radial-gradient(1.0px 1.0px at 72% 68%, rgba(255,255,255,.60), transparent),
    radial-gradient(1.1px 1.1px at 92% 30%, rgba(255,255,255,.64), transparent),
    radial-gradient(1.0px 1.0px at 18% 92%, rgba(255,255,255,.58), transparent),
    radial-gradient(1.2px 1.2px at 84% 88%, rgba(255,255,255,.62), transparent),
    radial-gradient(1.0px 1.0px at 40% 36%, rgba(255,255,255,.56), transparent);
  animation: gx-particles 30s linear infinite,
             auth-twinkle 4.5s ease-in-out infinite !important;
  opacity: .55;
}

/* ── ⑤ 星点漂移（斜向缓慢移动的第二层光点）───────────────────── */
.auth-page .auth-card + .card::before,
.auth-page .card:not(.auth-card)::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background-image:
    radial-gradient(1.6px 1.6px at 20% 30%, rgba(0,132,255,.55), transparent),
    radial-gradient(1.4px 1.4px at 76% 22%, rgba(175,82,222,.50), transparent),
    radial-gradient(1.8px 1.8px at 40% 78%, rgba(90,200,250,.52), transparent),
    radial-gradient(1.4px 1.4px at 84% 70%, rgba(0,132,255,.48), transparent);
  animation: auth-stardrift 16s ease-in-out infinite;
  z-index: 0;
}
@keyframes auth-stardrift {
  0%, 100% { transform: translate3d(0, 0, 0); opacity: .5; }
  50%      { transform: translate3d(10px, -12px, 0); opacity: .9; }
}

/* ── ⑥ 背景色相缓慢偏移（不用 background-position，改用 overlay 透明度）── */
.auth-page > .blob.b3 {
  animation: blob-path-c 26s ease-in-out infinite,
             auth-hue-shift 18s ease-in-out infinite !important;
}
@keyframes auth-hue-shift {
  0%, 100% { filter: hue-rotate(0deg); }
  50%      { filter: hue-rotate(28deg); }
}

/* ── ⑦ 降级 ───────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .auth-page::before, .auth-page::after,
  .auth-page .blob::after,
  .auth-page .card:not(.auth-card)::before,
  .auth-page > .blob.b3 {
    animation: none !important;
  }
}
@media (max-width: 640px) {
  .auth-page::before { animation-duration: 18s; }
  .auth-page::after { animation-duration: 40s, 6s; }
  .auth-page > .blob.b3 { animation-duration: 32s, 24s; }
}

/* ==========================================================================
   ⑰ 卡片高级感增强 —— 分三级层次
   ========================================================================== */

/* ── L3 突出卡片：题目 / 科目 / 登录 / 结果 ──────────────────── */
.quiz-card,
.subj-card,
.auth-card,
.qcard,
.result-hero + .card {
  border-radius: 20px !important;
  /* ⚡ 原这里是另一份 7 层字面阴影 + 280/320ms 过渡，把全局 --gx-shadow 和
     ㉚ 的过渡设置全覆盖了（也导致 Vue 把 320ms 当成离场时长）。
     现在统一用变量、过渡调轻快。 */
  box-shadow: var(--gx-shadow) !important;
  transition:
    box-shadow 170ms cubic-bezier(.22, 1, .36, 1),
    transform 200ms cubic-bezier(.34, 1.4, .64, 1) !important;
}
@media (hover: hover), (pointer: fine) {
  .quiz-card:hover,
  .subj-card:hover,
  .qcard:hover {
    box-shadow: var(--gx-shadow-hover) !important;
    transform: translate3d(0, -2px, 0) !important;
  }
}

/* ── L2 标准卡片：统计 / 工具 / 记录 ─────────────────────────── */
.stat-card,
.tool-item,
.tool-card,
.rec-item,
.set-row,
.wrong-subj,
.exam-bar,
.choice-btn,
.type-card,
.me-hero {
  border-radius: 16px !important;
  box-shadow: var(--gx-shadow) !important;
  transition:
    box-shadow 160ms cubic-bezier(.22, 1, .36, 1),
    transform 190ms cubic-bezier(.34, 1.4, .64, 1) !important;
}
@media (hover: hover), (pointer: fine) {
  .stat-card:hover,
  .tool-item:hover,
  .tool-card:hover,
  .rec-item:hover,
  .set-row:hover,
  .wrong-subj:hover,
  .exam-bar:hover,
  .choice-btn:hover,
  .type-card:hover {
    box-shadow: var(--gx-shadow-hover) !important;
    transform: translate3d(0, -2px, 0) !important;
  }
}

/* ── L1 轻卡片：搜索项 / 评论 / 通知条 ───────────────────────── */
.sr-item,
.sr-group,
.cmt,
.notif-bar,
.me-btn,
.acct-btn,
.theme-item {
  border-radius: 14px !important;
  box-shadow: var(--gx-shadow) !important;
  transition:
    box-shadow 150ms cubic-bezier(.22, 1, .36, 1),
    transform 180ms cubic-bezier(.34, 1.4, .64, 1) !important;
}
@media (hover: hover), (pointer: fine) {
  .sr-item:hover,
  .sr-group:hover,
  .cmt:hover,
  .notif-bar:hover,
  .me-btn:hover,
  .acct-btn:hover,
  .theme-item:hover {
    box-shadow: var(--gx-shadow-hover) !important;
    transform: translate3d(0, -2px, 0) !important;
  }
}

/* ── 暗色模式：内阴影改为白色微光 ─────────────────────────────── */
[data-theme="dark"] .card,
[data-theme="dark"] .quiz-card,
[data-theme="dark"] .stat-card,
[data-theme="dark"] .subj-card,
[data-theme="dark"] .tool-item,
[data-theme="dark"] .rec-item,
[data-theme="dark"] .set-row,
[data-theme="dark"] .qcard {
  box-shadow: var(--gx-shadow) !important;
}

/* ==========================================================================
   ⑯b 层次：分组容器保持中性，只有可交互内容行吃色
   —— 原来容器和内容行同色，导致卡片边界糊成一片、无层次
   ========================================================================== */
.practice-card,
.exam-bar,
.dashboard-card,
.countdown,
.cd-card {
  background-image: var(--gx-neutral), var(--gx-face) !important;
}

/* ==========================================================================
   ⑰ 圆角分级：按元素尺寸给不同圆角（一律 18px 会让小控件显得臃肿廉价）
   ========================================================================== */

/* L3 大卡片 —— 20px */
.quiz-card,
.me-hero,
.qcard,
.practice-card,
.dashboard-card,
.cd-card,
.countdown,
.notif-bar {
  border-radius: 20px !important;
}

/* L2 标准卡片 —— 16px */
.card,
.stat-card,
.subj-card,
.rec-item,
.sr-item,
.tool-card,
.type-card,
.wrong-subj,
.exam-bar,
.cmt,
.guest-card {
  border-radius: 16px !important;
}

/* L1 小控件 —— 12px（按钮、列表行不该用卡片圆角）*/
.tool-item,
.set-row,
.sr-group,
.me-btn,
.acct-btn,
.theme-item,
.choice-btn,
.type-pick {
  border-radius: 12px !important;
}

/* ==========================================================================
   ⑱ 移动端：保留"高级感"必需的光影，只裁掉冗余层（7 层 → 5 层）
   —— 注：不能只留 3 层，否则卡片会塌成扁片，反而更廉价
   ========================================================================== */
@media (max-width: 860px) {
  .card,
  .quiz-card,
  .stat-card,
  .subj-card,
  .tool-item,
  .tool-card,
  .rec-item,
  .set-row,
  .wrong-subj,
  .qcard,
  .exam-bar,
  .choice-btn,
  .type-card,
  .me-hero,
  .sr-item,
  .sr-group,
  .cmt,
  .notif-bar,
  .me-btn,
  .acct-btn,
  .theme-item {
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, 1),
      inset 0 -1px 1px rgba(16, 24, 40, .016),
      0 0 0 1px rgba(16, 24, 40, .03),
      0 1px 2px rgba(16, 24, 40, .04),
      0 10px 22px -6px rgba(16, 24, 40, .06) !important;
  }
  [data-theme="dark"] .card,
  [data-theme="dark"] .stat-card,
  [data-theme="dark"] .subj-card,
  [data-theme="dark"] .tool-item,
  [data-theme="dark"] .rec-item,
  [data-theme="dark"] .me-hero,
  [data-theme="dark"] .qcard {
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, .06),
      0 0 0 1px rgba(255, 255, 255, .045),
      0 1px 2px rgba(0, 0, 0, .34),
      0 8px 18px -4px rgba(0, 0, 0, .38),
      0 20px 40px -12px rgba(0, 0, 0, .30) !important;
  }
}

/* ── 减少动效偏好：去掉悬停位移 ───────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .card:hover, .quiz-card:hover, .stat-card:hover, .subj-card:hover,
  .tool-item:hover, .rec-item:hover, .set-row:hover, .qcard:hover,
  .sr-item:hover, .cmt:hover, .me-btn:hover, .acct-btn:hover,
  .theme-item:hover, .choice-btn:hover, .type-card:hover {
    transform: none !important;
  }
}

/* ==========================================================================
   ⑲ 搜索栏修复：屏蔽浏览器原生清除按钮
   —— .sb-input 是 type="search"，Chrome/Safari 会自动渲染一个 ✕，
      应用自己又有 .sb-clear，导致「两个 ✕」，且原生那个位置不受控。
   ========================================================================== */
/* 容器已经有 focus-within 焦点环时，内部 input 不能再画一遍
   —— 否则同一个环渲染两层（外层 .search-box + 内层 input），视觉上"效果有误" */
.search-box .sb-input:focus,
.search-box input:focus,
.search-box .sb-input:focus-visible,
.search-box input:focus-visible {
  outline: none !important;
  background: transparent !important;
  box-shadow: none !important;
}

input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-results-button,
input[type="search"]::-webkit-search-results-decoration {
  -webkit-appearance: none !important;
  appearance: none !important;
  display: none !important;
  width: 0 !important;
  height: 0 !important;
}

/* ==========================================================================
   ⑳ 统一选中系统：品牌色深度胶囊 + 弹性动效
   —— 原选中态是一个扁平色块（transition: all 0.16s），既不立体也不流畅。
      这里统一为：弹性缩放 + 品牌色派生的三级阴影 + 顶部内高光。
      阴影一律用 color-mix 从 --brand 派生，避免品牌色与阴影色相不符。
   ========================================================================== */

/* 统一过渡：只过渡 GPU 友好属性，弹性缓动 380ms */
.chip,
.cat-chip,
.seg-btn,
.mode-btn,
.corr-type,
.tool-badge,
.nav-pill,
.theme-item,
.top-nav a,
.side-nav a,
.subj-pin,
.opt,
.ord,
.multi {
  transition:
    transform 380ms cubic-bezier(.34, 1.42, .5, 1),
    box-shadow 320ms cubic-bezier(.22, 1, .36, 1),
    background-color 240ms cubic-bezier(.22, 1, .36, 1),
    border-color 240ms cubic-bezier(.22, 1, .36, 1),
    color 200ms cubic-bezier(.22, 1, .36, 1) !important;
}

/* 选中「弹一下」——一次性，非循环 */
@keyframes gxSelPop {
  0%   { transform: translate3d(0, 0, 0) scale(.93); }
  55%  { transform: translate3d(0, -1.5px, 0) scale(1.06); }
  100% { transform: translate3d(0, -1px, 0) scale(1.035); }
}
@keyframes gxSelPopFlat {
  0%   { transform: scale(.95); }
  60%  { transform: scale(1.04); }
  100% { transform: scale(1); }
}

/* 品牌色实心胶囊：chip / cat-chip / mode-btn / corr-type */
.chip.active,
.cat-chip.on,
.mode-btn.on,
.corr-type.on {
  background-color: var(--brand, #8f93d8) !important;
  color: #fff !important;
  transform: translate3d(0, -1px, 0) scale(1.035);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .42),
    inset 0 2px 5px -1px rgba(255, 255, 255, .30),
    inset 0 -1px 1px rgba(0, 0, 0, .16),
    0 1px 2px rgba(16, 24, 40, .12),
    0 4px 10px -2px color-mix(in srgb, var(--brand, #8f93d8) 46%, transparent),
    0 12px 26px -6px color-mix(in srgb, var(--brand, #8f93d8) 34%, transparent) !important;
  animation: gxSelPop 440ms cubic-bezier(.34, 1.42, .5, 1);
}
.chip:active,
.cat-chip:active,
.mode-btn:active,
.corr-type:active,
.seg-btn:active,
.top-nav a:active,
.side-nav a:active,
.nav-pill:active,
.theme-item:active {
  transform: translate3d(0, 0, 0) scale(.955) !important;
  transition: transform 90ms cubic-bezier(.36, .07, .19, .97) !important;
}

/* 分段控件选中：iOS 白色凸起块 */
.seg-btn.on {
  background-color: var(--card, #fff) !important;
  color: var(--ink, #1c1c1e) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 1),
    0 0 0 .5px rgba(16, 24, 40, .05),
    0 1px 1px rgba(16, 24, 40, .05),
    0 3px 8px -2px rgba(16, 24, 40, .13),
    0 8px 20px -6px rgba(16, 24, 40, .10) !important;
  animation: gxSelPopFlat 400ms cubic-bezier(.34, 1.42, .5, 1);
}

/* 顶部导航选中：品牌色淡胶囊（原来是灰色填充，无色彩识别） */
.top-nav a.on {
  background-color: color-mix(in srgb, var(--brand, #8f93d8) 13%, transparent) !important;
  color: var(--brand, #8f93d8) !important;
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--brand, #8f93d8) 20%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, .55) !important;
}
.side-nav a.on,
.nav-pill.on {
  background-color: color-mix(in srgb, var(--brand, #8f93d8) 13%, transparent) !important;
  color: var(--brand, #8f93d8) !important;
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--brand, #8f93d8) 18%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, .5) !important;
}

/* 主题卡选中：品牌色环 + 外发光 */
.theme-item.on {
  box-shadow:
    0 0 0 2px var(--brand, #8f93d8),
    0 6px 16px -4px color-mix(in srgb, var(--brand, #8f93d8) 38%, transparent),
    0 14px 30px -10px color-mix(in srgb, var(--brand, #8f93d8) 26%, transparent) !important;
}

/* 选择题选项选中 */
.opt.sel,
.opt.ord.sel,
.opt.multi.sel {
  border-color: var(--brand, #8f93d8) !important;
  background-color: color-mix(in srgb, var(--brand, #8f93d8) 9%, transparent) !important;
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--brand, #8f93d8) 42%, transparent),
    0 4px 12px -3px color-mix(in srgb, var(--brand, #8f93d8) 34%, transparent) !important;
  transform: translate3d(0, -1px, 0);
}

/* 题号/多选 key 选中 */
.opt.ord.sel .key,
.opt.multi.sel .key {
  background-color: var(--brand, #8f93d8) !important;
  color: #fff !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .38), 0 2px 6px -1px color-mix(in srgb, var(--brand, #8f93d8) 50%, transparent);
}

/* 收藏置顶选中 */
.subj-pin.on {
  background-color: var(--brand, #8f93d8) !important;
  color: #fff !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .40),
    0 3px 10px -2px color-mix(in srgb, var(--brand, #8f93d8) 48%, transparent) !important;
}

/* ── 降级：不支持 backdrop-filter 的浏览器回到不透明表面 ───────── */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .card, .quiz-card, .stat-card, .subj-card, .tool-item, .tool-card,
  .rec-item, .set-row, .wrong-subj, .sr-item, .sr-group, .me-hero,
  .me-btn, .acct-btn, .theme-item, .choice-btn, .type-card, .exam-bar,
  .cmt, .practice-card, .dashboard-card, .qcard, .notif-bar {
    background-color: rgba(255, 255, 255, .97) !important;
  }
  [data-theme="dark"] .card, [data-theme="dark"] .stat-card,
  [data-theme="dark"] .subj-card, [data-theme="dark"] .practice-card {
    background-color: rgba(28, 28, 32, .97) !important;
  }
}

/* ── 移动端：模糊半径减半（毛玻璃是逐像素采样，手机上最贵）────── */
@media (max-width: 860px) {
  .card, .quiz-card, .stat-card, .subj-card, .tool-item, .tool-card,
  .rec-item, .set-row, .wrong-subj, .sr-item, .sr-group, .me-hero,
  .me-btn, .acct-btn, .theme-item, .choice-btn, .type-card, .exam-bar,
  .cmt, .practice-card, .dashboard-card, .qcard, .notif-bar {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  .chip.active, .cat-chip.on, .mode-btn.on, .corr-type.on,
  .seg-btn.on, .theme-item.on, .subj-pin.on {
    animation: none !important;
  }
}

/* ==========================================================================
   ㉑ 底栏毛玻璃修正
   —— 底栏原用 saturate(200%) + 82% 不透明，会把身后滚过的彩色科目图标
      放大成一团刺眼色块（选中胶囊下方出现绿/紫色块），与"高级"完全相反。
      降低饱和度放大、略提不透明度，保留玻璃感但不再"吃掉"身后内容。
      ⚠️ 这是既有问题（停用本文件后依然存在），非本轮引入。
   ========================================================================== */
.mobile-nav {
  background-color: rgba(250, 250, 251, .97) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
[data-theme="dark"] .mobile-nav {
  background-color: rgba(24, 24, 27, .97) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
/* 顶栏同理，但幅度更小（它身后是渐变底，色彩冲突不明显）*/
.topbar {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* ==========================================================================
   ㉒ 弹窗遮罩：全屏虚化
   —— 原来只有一层 rgba(20,15,50,.55) 半透明深色，背后内容清晰可读，
      既不聚焦也不高级。改为全屏 backdrop-filter 模糊 + 轻微降饱和。
      （配合移除 contain 的修复，遮罩现在能真正铺满整个视口）
   ========================================================================== */
.modal-mask {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  background-color: rgba(18, 14, 40, .42) !important;
}
[data-theme="dark"] .modal-mask {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  background-color: rgba(0, 0, 0, .52) !important;
}
/* .modal 的圆角/阴影/内边距统一在 ㉖ 章节里定义 */


/* ==========================================================================
   ㉓ 暗夜黑（dark）优化 —— 为夜间长时间阅读
   ① 卡片面 rgba(37,37,41,.82) 偏灰，在纯黑夜景里像一块块灰板 → 压暗贴近底色
   ② 色相 alpha .15，橙色叠在近黑底上会变成脏棕色 → 收敛到 .09
   ③ --ink 是 #FFFFFF，纯白配近黑底产生"光晕"(halation)，久看刺眼 → 降到 #E9EBF0
   ========================================================================== */
[data-theme="dark"] {
  --gx-glow-blue:   0 6px 20px rgba(10,132,255,.10);
  --gx-glow-purple: 0 6px 20px rgba(191,90,242,.10);
  --gx-glow-green:  0 6px 20px rgba(48,209,88,.10);
  --gx-glow-orange: 0 6px 20px rgba(255,159,10,.10);
  --label:   #E9EBF0;
  --ink:     #E9EBF0;
  --ink2:    #C3C8D4;
  --label-2: rgba(233, 235, 240, .62);
}

/* ==========================================================================
   ㉔ 工具箱「考试倒计时」重新设计
   原设计三段割裂：浮动标题+按钮 → 虚线空框 → 卡片，没有统一容器；
   空状态还用虚线框，看着像"没做完"。现在收敛为一张统一的玻璃卡。
   ========================================================================== */
.cd-sec {
  background-image: var(--gx-neutral), var(--gx-face) !important;
  background-size: 100% 100%, 100% 100%, 100% 100% !important;
  background-repeat: no-repeat, no-repeat, no-repeat !important;
  background-color: transparent !important;
  border-radius: 20px !important;
  padding: 18px 20px 20px !important;
  margin-bottom: 20px !important;
  box-shadow: var(--gx-shadow) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
.cd-head {
  align-items: center !important;
  margin-bottom: 16px !important;
  padding-bottom: 13px !important;
  border-bottom: .5px solid rgba(16, 24, 40, .07);
}
[data-theme="dark"] .cd-head { border-bottom-color: rgba(255, 255, 255, .07); }
.cd-h-t { font-size: 15px !important; font-weight: 640 !important; letter-spacing: -.012em; }
.cd-empty {
  background: color-mix(in srgb, var(--brand, #8f93d8) 6%, transparent) !important;
  border: none !important;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand, #8f93d8) 13%, transparent) !important;
  border-radius: 14px !important;
  padding: 24px 18px !important;
  font-size: 13.5px !important;
}
.cd-card {
  border: none !important;
  border-left: none !important;
  border-radius: 14px !important;
  position: relative;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 40, .055), 0 1px 2px rgba(16, 24, 40, .04) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
[data-theme="dark"] .cd-card { box-shadow: inset 0 0 0 1px rgba(255,255,255,.06) !important; }
.cd-card::before {
  content: '';
  position: absolute;
  left: 0; top: 12px; bottom: 12px;
  width: 3px;
  border-radius: 0 3px 3px 0;
  background: var(--brand, #8f93d8);
}
.cd-card.near::before  { background: #F59E0B; }
.cd-card.today::before { background: #EF4444; }
.cd-card.over::before  { background: #94A3B8; }
.cd-num b { font-variant-numeric: tabular-nums; letter-spacing: -.03em; }
.cd-op {
  border-radius: 9px !important;
  transition: background-color 200ms cubic-bezier(.22,1,.36,1),
              transform 260ms cubic-bezier(.34,1.42,.5,1) !important;
}
.cd-op:active { transform: scale(.90); }
.cd-op:hover  { background: color-mix(in srgb, var(--brand, #8f93d8) 14%, transparent) !important; }
.cd-op.danger:hover { background: rgba(239, 68, 68, .14) !important; }

/* ==========================================================================
   ㉕ 留言板（答题卡下方内联板块）重新设计
   原状：只有一条 border-top 虚线的「裸区块」，没有容器，和全站玻璃卡体系脱节；
        标题小、收起是裸文字、空态一行灰字、操作按钮是无样式文字。
   现在：统一成一张玻璃卡，并把内部层级（标题栏 / 空态 / 留言条目 / 回复 / 输入区）做出来。
   ========================================================================== */

/* ── 板块容器：玻璃卡 ─────────────────────────────────────────── */
.cmt-board {
  background-image: var(--gx-neutral), var(--gx-face) !important;
  background-size: 100% 100%, 100% 100%, 100% 100% !important;
  background-repeat: no-repeat, no-repeat, no-repeat !important;
  background-color: transparent !important;
  border: none !important;
  border-top: none !important;
  border-radius: 20px !important;
  padding: 16px 20px 18px !important;
  margin-top: 16px !important;
  box-shadow: var(--gx-shadow) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
/* 弹窗里的留言板（管理端）：在弹窗内不要再叠一层毛玻璃 */
.modal .cmt-board {
  background-image: none !important;
  background-color: transparent !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  padding: 0 !important;
  margin-top: 0 !important;
  border-radius: 0 !important;
}

/* ── 标题栏 ───────────────────────────────────────────────────── */
.cmt-board-head {
  align-items: center !important;
  margin-bottom: 14px !important;
  padding-bottom: 12px !important;
  border-bottom: .5px solid rgba(16, 24, 40, .07);
}
[data-theme="dark"] .cmt-board-head { border-bottom-color: rgba(255, 255, 255, .07); }
.cmt-board-title {
  font-size: 15px !important;
  font-weight: 640 !important;
  letter-spacing: -.012em;
  color: var(--ink) !important;
}

/* 展开/收起：裸蓝字 → 品牌色胶囊按钮 */
.cmt-toggle {
  background: color-mix(in srgb, var(--brand, #8f93d8) 11%, transparent) !important;
  color: var(--brand, #8f93d8) !important;
  border: none !important;
  border-radius: 999px !important;
  padding: 5px 14px !important;
  font-size: 12.5px !important;
  font-weight: 600 !important;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand, #8f93d8) 20%, transparent) !important;
  transition: background-color 200ms cubic-bezier(.22,1,.36,1),
              transform 300ms cubic-bezier(.34,1.42,.5,1) !important;
}
.cmt-toggle:hover  { background: color-mix(in srgb, var(--brand, #8f93d8) 18%, transparent) !important; }
.cmt-toggle:active { transform: scale(.94); }

/* ── 空状态：一行灰字 → 柔和品牌色提示块 ─────────────────────── */
.cmt-empty {
  background: color-mix(in srgb, var(--brand, #8f93d8) 6%, transparent) !important;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand, #8f93d8) 13%, transparent) !important;
  border-radius: 14px !important;
  padding: 22px 18px !important;
  text-align: center !important;
  font-size: 13.5px !important;
  color: var(--ink2) !important;
}

/* ── 留言条目：外层玻璃卡里不要再套玻璃卡 ─────────────────────── */
.cmt-list { gap: 10px !important; }
.cmt {
  background-image: none !important;
  background-color: rgba(120, 130, 155, .075) !important;
  border: none !important;
  border-radius: 14px !important;
  padding: 12px 14px !important;
  box-shadow: inset 0 0 0 1px rgba(16, 24, 40, .045) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
[data-theme="dark"] .cmt {
  background-color: rgba(255, 255, 255, .05) !important;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .05) !important;
}
.cmt-head { gap: 8px !important; margin-bottom: 5px !important; }
.cmt-name { font-size: 13.5px !important; font-weight: 620 !important; color: var(--ink) !important; }
.cmt-time { font-size: 11.5px !important; color: var(--ink3) !important; }
.cmt-body { font-size: 14px !important; line-height: 1.62 !important; color: var(--ink) !important; }

/* 昵称前加一个彩色圆点头像位（原来光秃秃一行名字）*/
.cmt-name::before {
  content: '';
  display: inline-block;
  width: 20px; height: 20px;
  border-radius: 50%;
  margin-right: 7px;
  vertical-align: -5px;
  background: linear-gradient(145deg, color-mix(in srgb, var(--brand, #8f93d8) 62%, #fff), var(--brand, #8f93d8));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45);
}
.cmt:nth-child(4n+1) .cmt-name::before { background: linear-gradient(145deg, #7FB2FF, #3B7BE0); }
.cmt:nth-child(4n+2) .cmt-name::before { background: linear-gradient(145deg, #C79BF0, #8B5CD6); }
.cmt:nth-child(4n+3) .cmt-name::before { background: linear-gradient(145deg, #7FD6B0, #38A87A); }
.cmt:nth-child(4n+4) .cmt-name::before { background: linear-gradient(145deg, #FFC177, #E8892B); }

/* ── 操作按钮：无样式文字 → 胶囊按钮 ─────────────────────────── */
.cmt-actions { gap: 4px !important; margin-top: 6px !important; }
.cmt-btn {
  background: transparent !important;
  border: none !important;
  border-radius: 999px !important;
  padding: 4px 11px !important;
  font-size: 12.5px !important;
  color: var(--ink3) !important;
  transition: background-color 200ms cubic-bezier(.22,1,.36,1),
              color 200ms cubic-bezier(.22,1,.36,1),
              transform 260ms cubic-bezier(.34,1.42,.5,1) !important;
}
.cmt-btn:hover  { background: rgba(120, 130, 155, .14) !important; color: var(--ink) !important; }
.cmt-btn:active { transform: scale(.92); }
.cmt-btn.liked {
  color: #EF4444 !important;
  background: rgba(239, 68, 68, .10) !important;
}
.cmt-btn.danger { color: #EF4444 !important; }
.cmt-btn.danger:hover { background: rgba(239, 68, 68, .12) !important; }
[data-theme="dark"] .cmt-btn.liked,
[data-theme="dark"] .cmt-btn.danger { color: #FF7B72 !important; }

/* ── 回复区：竖线 + 缩进 ─────────────────────────────────────── */
.cmt-replies {
  margin-top: 10px !important;
  padding-left: 0 !important;
  border-left: none !important;
  gap: 8px !important;
}
.cmt.rep {
  background-color: rgba(120, 130, 155, .06) !important;
  border: none !important;
  border-left: 2px solid color-mix(in srgb, var(--brand, #8f93d8) 32%, transparent) !important;
  border-radius: 0 12px 12px 0 !important;
  padding: 10px 12px !important;
  margin-left: 12px !important;
}
[data-theme="dark"] .cmt.rep { background-color: rgba(255, 255, 255, .04) !important; }

/* ── 输入区 ───────────────────────────────────────────────────── */
.cmt-reply-to {
  background: color-mix(in srgb, var(--brand, #8f93d8) 8%, transparent) !important;
  border-radius: 10px !important;
  padding: 7px 12px !important;
  margin-top: 10px !important;
  font-size: 12.5px !important;
}
.cmt-input-row {
  display: flex !important;
  align-items: center !important;
  gap: 10px !important;
  margin-top: 14px !important;
}
.cmt-input-row .input {
  flex: 1;
  background: rgba(120, 130, 155, .09) !important;
  border: none !important;
  border-radius: 13px !important;
  padding: 11px 15px !important;
  transition: background-color 220ms cubic-bezier(.22,1,.36,1),
              box-shadow 220ms cubic-bezier(.22,1,.36,1) !important;
}
.cmt-input-row .input:focus {
  background: var(--card, #fff) !important;
  box-shadow: 0 0 0 2px var(--brand, #8f93d8), var(--ring) !important;
}
.cmt-input-row .btn { border-radius: 13px !important; flex: none; }
.cmt-count {
  /* ios-skin.css:1183 给 .cmt-count 加过 background: var(--fill)，
     会在输入框下方渲染出一条通栏灰条，这里清掉 */
  background: transparent !important;
  box-shadow: none !important;
  font-size: 11.5px !important;
  color: var(--ink3) !important;
  text-align: right !important;
  margin-top: 6px !important;
}

/* ── 移动端：毛玻璃减半 ───────────────────────────────────────── */
@media (max-width: 860px) {
  .cmt-board {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    padding: 14px 15px 16px !important;
    border-radius: 18px !important;
  }
  .cmt-input-row { flex-wrap: wrap; }
}

/* ==========================================================================
   ㉖ 弹窗系统统一
   ──────────────────────────────────────────────────────────────────────────
   统一前的乱象：
   ① 遮罩三套：.modal-mask 模糊 18px / .sb-mask & .cmt-mask 只有 3px / .dlg-mask 用默认
   ② 关闭按钮两个类：.modal-close（8 处）与 .modal-x（6 处），样式来源不同
   ③ 材质在 style.css / ios-skin.css / liquid-glass.css 三处互相覆盖
   ④ share-modal / reward-modal 没有 .modal-body，内容直接挂 .modal 下 →
      吃不到内边距，按钮通栏压在圆角上
   ⑤ 手机端是 align-items:flex-end 的底部抽屉；且 .mobile-nav 的 z-index:1000
      高于 .modal-mask 的 200 → 弹窗底部按钮被悬浮底栏盖住
   ========================================================================== */

/* ── ① 遮罩：全部统一为全屏虚化 + 居中 ───────────────────────── */
.modal-mask,
.cmt-mask,
.dlg-mask {
  display: flex !important;
  /* 用 flex-start + 子元素 margin:auto 居中：
     这样弹窗高于视口时可正常滚动，不会像 align-items:center 那样被裁掉顶部 */
  align-items: flex-start !important;
  justify-content: center !important;
  padding: 24px !important;
  background-color: rgba(18, 14, 40, .42) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  /* ⚠️ 必须高于悬浮底栏（liquid-glass 把 .mobile-nav 抬到了 z-index:1000）*/
  z-index: 1200 !important;
  overflow-y: auto;
  overscroll-behavior: contain;
}
[data-theme="dark"] .modal-mask,
[data-theme="dark"] .cmt-mask,
[data-theme="dark"] .dlg-mask {
  background-color: rgba(0, 0, 0, .52) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
/* .sb-mask 不是弹窗遮罩（是搜索浮层），只统一观感，不动布局 */
.sb-mask {
  background-color: rgba(18, 14, 40, .28) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
[data-theme="dark"] .sb-mask { background-color: rgba(0, 0, 0, .42) !important; }

/* ── ② 弹窗本体：统一内边距 / 圆角 / 阴影 / 入场动效 ─────────── */
.modal {
  --md-x: 24px;   /* 左右内边距 */
  --md-y: 22px;   /* 上下内边距 */
  width: 100%;
  max-width: 560px;
  margin: auto !important;              /* 覆盖手机端的 margin-top:auto */
  padding: var(--md-y) var(--md-x) !important;
  gap: 13px;
  border-radius: 22px !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .55),
    0 0 0 .5px rgba(16, 24, 40, .06),
    0 12px 28px -8px rgba(16, 24, 40, .22),
    0 40px 80px -24px rgba(16, 24, 40, .30) !important;
  animation: mdIn 360ms cubic-bezier(.22, 1, .36, 1) both !important;
}
[data-theme="dark"] .modal {
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .08),
    0 0 0 .5px rgba(255, 255, 255, .06),
    0 12px 28px -8px rgba(0, 0, 0, .60),
    0 40px 80px -24px rgba(0, 0, 0, .70) !important;
}
@keyframes mdIn {
  from { opacity: 0; transform: translate3d(0, 14px, 0) scale(.965); }
  to   { opacity: 1; transform: none; }
}
/* 各类弹窗的宽度分级 */
.modal.share-modal, .modal.dlg, .modal.reward-modal { max-width: 420px; }
.modal.modal-wide, .modal.cmt-modal { max-width: 640px; }
.modal.acct-modal { max-width: 480px; }

/* ── ③ 标题栏 / 正文 / 页脚：负边距拉回通栏，保住分割线 ───────── */
.modal > .modal-head {
  margin: calc(-1 * var(--md-y)) calc(-1 * var(--md-x)) 0 !important;
  padding: 17px var(--md-x) 13px !important;
  border-bottom: .5px solid var(--sep, rgba(84, 84, 88, .36)) !important;
  gap: 10px !important;
}
.modal > .modal-head h3 {
  font-size: 17.5px !important;
  font-weight: 640 !important;
  letter-spacing: -.02em;
  color: var(--ink) !important;
}
.modal > .modal-body { padding: 0 !important; }
.modal > .modal-foot {
  margin: 0 calc(-1 * var(--md-x)) calc(-1 * var(--md-y)) !important;
  padding: 13px var(--md-x) 17px !important;
  border-top: .5px solid var(--sep, rgba(84, 84, 88, .36)) !important;
  gap: 10px !important;
}
.modal > .modal-foot .btn { min-height: 42px; }

/* ── ④ 关闭按钮：.modal-close 与 .modal-x 合并成同一套 ────────── */
.modal-close,
.modal-x {
  width: 30px !important;
  height: 30px !important;
  flex: none;
  border-radius: 50% !important;
  background: var(--fill, rgba(120, 120, 128, .12)) !important;
  border: none !important;
  box-shadow: none !important;
  color: var(--ink2) !important;
  font-size: 17px !important;
  line-height: 1 !important;
  display: flex !important;
  align-items: center;
  justify-content: center;
  transition: background-color 200ms cubic-bezier(.22, 1, .36, 1),
              color 200ms cubic-bezier(.22, 1, .36, 1),
              transform 260ms cubic-bezier(.34, 1.42, .5, 1) !important;
}
.modal-close:hover,
.modal-x:hover { background: var(--fill-2, rgba(120, 120, 128, .24)) !important; color: var(--ink) !important; }
.modal-close:active,
.modal-x:active { transform: scale(.88); }

/* ── ⑤ .dlg 保持居中版式，但共用材质与内边距 ─────────────────── */
.modal.dlg, .dlg {
  text-align: center;
  padding: 28px var(--md-x) 22px !important;
  gap: 0;
}
.dlg-ico {
  width: 54px; height: 54px;
  border-radius: 17px;
  margin: 0 auto 14px;
  font-size: 26px;
  background: var(--fill, rgba(120, 120, 128, .12));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
}
.dlg-ico.danger { background: rgba(255, 69, 58, .12); }
.dlg-title { font-size: 19px !important; font-weight: 640 !important; letter-spacing: -.02em; margin-bottom: 8px; color: var(--ink) !important; }
.dlg-msg { font-size: 14px !important; line-height: 1.65 !important; margin-bottom: 20px !important; color: var(--ink2) !important; }
.modal.dlg .dlg-foot,
.dlg .dlg-foot {
  margin: 0 !important;
  padding: 0 !important;
  border-top: none !important;
  gap: 10px !important;
}
.modal.dlg .dlg-foot .btn, .dlg .dlg-foot .btn { flex: 1; max-width: none; min-height: 44px; }

/* ── ⑥ 手机端：一律居中（原来是贴底抽屉），并躲开悬浮底栏 ───── */
@media (max-width: 860px) {
  .modal-mask, .cmt-mask, .dlg-mask {
    /* 四边等距 → 弹窗在视口里真正居中。
       底栏虽然 z-index:1000，但遮罩是 1200，底栏已被盖在遮罩之下，
       所以不需要为它留避让空间，居中即可 */
    padding: 16px !important;
  }
  .modal {
    --md-x: 18px;
    --md-y: 18px;
    max-width: 100% !important;
    max-height: calc(100vh - 32px) !important;
    max-height: calc(100dvh - 32px) !important;  /* 有动态视口单位时用它，避开地址栏 */
    border-radius: 20px !important;   /* 覆盖原来贴底用的 18px 18px 0 0 */
  }
  .modal.share-modal, .modal.dlg, .modal.reward-modal,
  .modal.modal-wide, .modal.cmt-modal, .modal.acct-modal { max-width: 100% !important; }
  .modal > .modal-head { padding: 15px var(--md-x) 12px !important; }
  .modal > .modal-head h3 { font-size: 16.5px !important; }
  .modal > .modal-foot { padding: 12px var(--md-x) 15px !important; flex-wrap: wrap; }
  .modal > .modal-foot .btn { flex: 1 1 auto; }
  .modal.dlg, .dlg { max-height: none !important; }
}

/* ==========================================================================
   ㉗ 切题卡顿修复（"点击下一题总是卡一下"）
   ──────────────────────────────────────────────────────────────────────────
   根因（实测定位）：
   app.js 里题目卡片是这样渲染的 ——
       <transition name="slide" mode="out-in">
         <div class="quiz-card" :key="idx">
   mode="out-in" 必须先跑完旧卡「离场」才插入新卡；而 Vue 的
   getTransitionInfo() 会把元素自身的 animation-duration **和**
   transition-duration 都当作离场时长。而卡片上同时挂着：
       · animation:  gx-card-in 380ms      （glass-effects 卡片入场动画）
       · transition: transform 320ms …     （卡片过渡）
   → Vue 判定离场要 380ms，排了一个 381ms 的兜底 setTimeout（已用 hook
     setTimeout 抓到：ms=381 :: at Gr (vue.global.prod.js)），
     新题目要等 380ms 才被插入 DOM。

   实测对照（MutationObserver 测题干真正更新的时刻）：
       基线                        440ms
       只去掉入场动画               385ms
       只去掉过渡 + 保留 120ms 入场  185ms
       动画和过渡都去掉              7~64ms   ← 采用

   结论：凡「每次交互都会被重建」的元素（题目卡、选项），
        都不能挂入场动画，也不能有常驻 transition。
   ========================================================================== */
.quiz-card,
.qcard {
  animation: none !important;
  transition: none !important;
}
/* 题目卡不是可点击的整体，悬停高亮没有意义；去掉可避免无过渡时的"跳变" */
@media (hover: hover), (pointer: fine) {
  .quiz-card:hover,
  .qcard:hover {
    transform: none !important;
    background-image: var(--gx-blue), var(--gx-face) !important;
    box-shadow: var(--gx-shadow), var(--gx-glow-blue) !important;
  }
}
/* 选项也是每题重建：入场动画会让每次切题都"飞入"一遍，既慢又晃眼 */
.opt {
  animation: none !important;
}

/* ── 「类似的地方」：视图切换也是 <transition mode="out-in"> ──────────
   .fade 是 250ms、.slide 是 140ms，out-in 意味着"离场跑完才入场"，

/* 列表类卡片的交错入场动画：460ms 偏慢，收敛到 300ms（仅首次出现才播） */
.card, .stat-card, .subj-card, .choice-btn, .type-card,
.set-row, .tool-item, .rec-item, .cmt, .exam-bar {
  animation-duration: 300ms !important;
}

/* ==========================================================================
   ㉘ 切换/点击动效流畅化
   ──────────────────────────────────────────────────────────────────────────
   实测（CDP Performance，一次「刷题 ⇄ 我的」往返切换）：
       基线                task=179.2ms  layout=20.0ms
       关毛玻璃            task=168.5ms   ← 毛玻璃不是主因
       关阴影过渡          task=155.2ms
       关入场动画          task=116.9ms   ← 主因（−35%）

   根因：入场动画用的是 `translate3d(...) + scale(...)`，而卡片上有
   `backdrop-filter`。**带 backdrop-filter 的元素一旦位移/缩放，浏览器每帧
   都要按新位置重新采样并重做一次背景模糊** —— 一屏十几张卡片同时动，
   就是肉眼可见的卡顿。

   对策：凡是带毛玻璃的元素，入场一律只用 opacity 渐变（不位移 → 不重算模糊）。
   位移只在「不带毛玻璃的小元素」上保留。
   ========================================================================== */

/* ── ① 重定义两个入场关键帧为「纯淡入」─────────────────────────
   同名 @keyframes 后定义者生效，所以这里覆盖掉上面的 translate+scale 版本。
   opacity 变化由合成器处理，不触发重绘、也不需要重算 backdrop-filter。 */
@keyframes gx-card-in {
  /* 带 4px 位移的轻快上升。实测位移距离对光栅开销影响极大：
       8px → RasterTask 366.7ms（+36%）
       4px → RasterTask 304.2ms（+13%）  ← 采用
       0px → RasterTask 269.9ms
     原因是卡片带 backdrop-filter，每移动一帧都要按新位置重算背景模糊。 */
  from { opacity: 0; transform: translate3d(0, 4px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}
@keyframes ios-fade-up {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ── ② 入场时长与交错：从 300/460ms + 最多 225ms 延迟，
       收敛到 240ms + 最多 120ms 延迟 ───────────────────────────── */
.card, .stat-card, .subj-card, .quiz-card, .choice-btn, .type-card,
.set-row, .tool-item, .rec-item, .cmt, .exam-bar, .qcard {
  animation-duration: 150ms !important;
}
.stat-row > *, .subject-grid > *, .g3 > * { animation-delay: 0ms !important; }
.stat-row > *:nth-child(2), .subject-grid > *:nth-child(2), .g3 > *:nth-child(2) { animation-delay: 16ms !important; }
.stat-row > *:nth-child(3), .subject-grid > *:nth-child(3), .g3 > *:nth-child(3) { animation-delay: 32ms !important; }
.stat-row > *:nth-child(4), .subject-grid > *:nth-child(4), .g3 > *:nth-child(4) { animation-delay: 48ms !important; }
.stat-row > *:nth-child(5), .subject-grid > *:nth-child(5), .g3 > *:nth-child(5) { animation-delay: 64ms !important; }
.stat-row > *:nth-child(6), .subject-grid > *:nth-child(6), .g3 > *:nth-child(6) { animation-delay: 80ms !important; }

/* ── ③ 视图切换：定义见 ㉚ ─────────────────────────────────── */


/* ── ⑤ 点击反馈：只让「不触发整块重绘」的属性参与过渡 ────────────
   原来卡片的悬停/选中过渡里带 box-shadow，大卡片上每帧重绘阴影很贵。
   这里把大卡片的过渡限制为 transform（阴影变化瞬时不参与动画），
   小控件（chip / 按钮）保留 box-shadow，因为它们面积小、开销可忽略。 */
.quiz-card, .qcard, .practice-card, .dashboard-card, .me-hero, .notif-bar {
  transition-property: transform !important;
}

/* ── ⑥ 尊重「减少动效」偏好 ─────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .card, .stat-card, .subj-card, .quiz-card, .choice-btn, .type-card,
  .set-row, .tool-item, .rec-item, .cmt, .exam-bar, .qcard { animation: none !important; }
  .fade-enter-active, .fade-leave-active,
  .slide-enter-active, .slide-leave-active { transition-duration: .01ms !important; }
}

/* ==========================================================================
   ㉙ 清掉触发布局的动画属性（width / padding / bottom）
   ========================================================================== */

/* ── ② 进度条宽度动画：width 会触发 layout ──────────────────────
   style.css / ios-skin.css 三处分别写了 .4s / .5s / 520ms，
   每题切换都要跑半秒的布局动画。收敛到 220ms。 */
.quiz-progress .bar { transition: width 220ms var(--gx-out) !important; }

/* ── ③ 登录页 Tab 滑块：width 300ms → 200ms ──────────────────── */
.auth-tabs .slider {
  transition: transform 300ms var(--gx-spring), width 200ms var(--gx-spring) !important;
}

/* ── ④ .container 的 padding-bottom 过渡 = 整页重排 ─────────────
   原来 `transition: padding-bottom .28s`，底部栏显隐时整个容器要
   重排 280ms。去掉过渡，瞬时完成。 */
.container { transition: none !important; }

/* ── ⑤ 底栏 bottom 过渡 + will-change:bottom ───────────────────
   bottom 是布局属性，动画它等于每帧重排；`will-change: bottom` 更会
   误导合成器去为布局属性建层（有害）。底栏位置本就只需要瞬时对齐。 */
.mobile-nav {
  transition: none !important;
  will-change: auto !important;
}

/* ==========================================================================
   ㉚ 过渡动画系统 —— 进入 + 退出 全部补齐（丝滑版）
   ──────────────────────────────────────────────────────────────────────────
   上一轮为了消除 out-in 的空白间隙，把离场做成了「瞬时移除」，结果变成
   闪屏切过去。这里恢复完整的进入/退出过渡，同时守住流畅度底线：

   · 主线仍是 opacity —— 合成器直接处理，不重绘、不重算 backdrop-filter
   · 位移幅度很小（10~22px），时长明确可控
   · out-in 的**离场一律短**（视图 130ms / 题目卡 90ms），
     否则"等旧页面演完"又会变回卡顿
   · 进出缓动不对称才自然：
       进入 = cubic-bezier(.22, 1, .36, 1)   快起慢收
       退出 = cubic-bezier(.4, 0, 1, 1)      慢起快收
   ========================================================================== */

/* ── ① 视图切换 .fade（科目 / 错题 / 统计 / 工具 / 我的 等 4 处）──
   ⚠️ 这里【刻意不加位移】。实测同一段切换：
        带 translateY  → layout 90.4ms
        仅 opacity     → layout 29.3ms   ← 3 倍差距
   因为 .fade 作用在整个 <section> 上，section 里全是带 backdrop-filter
   的卡片：整块一移动，浏览器每帧都要为每张卡片按新位置重算背景模糊。
   所以视图切换用「溶解」：旧页 140ms 淡出、新页 260ms 淡入，
   既不是闪屏，也不会有位移带来的重算。位移留给单张的题目卡和弹窗。 */
/* ✅ 现在可以加位移了。早前实测：给 .fade 加 8~16px 位移会让 RasterTask
   从 264.9ms 涨到 783.1ms（3 倍）—— 因为 section 里每张卡都有 backdrop-filter，
   整块移动 = 每帧为每张卡重算背景模糊。**现在毛玻璃已全部移除**，位移只是纯合成，
   代价极低，所以页面切换可以做「旧页上浮淡出 + 新页自下升起」的完整过渡。 */
/* ⚠️ out-in 的关键：离场时长 = 点击后「新界面开始出现前」的死等时间。
   实测（点击顶部导航 → 新 section 出现 / 完全可见）：
       离场 100ms → 出现 111~124ms，可见 157~206ms
   把离场压到 55ms，死等几乎减半；入场保持 170ms 的柔和淡入，
   所以看起来仍是"旧页快速溶解 → 新页轻柔浮现"，不是闪屏。 */
.fade-leave-active {
  transition: opacity 110ms cubic-bezier(.4, 0, 1, 1),
              transform 110ms cubic-bezier(.4, 0, 1, 1) !important;
}
.fade-leave-to {
  opacity: 0 !important;
  transform: translate3d(0, -10px, 0) !important;
}
.fade-enter-active {
  transition: opacity 200ms cubic-bezier(.22, 1, .36, 1),
              transform 260ms cubic-bezier(.22, 1, .36, 1) !important;
  will-change: opacity, transform;
}
.fade-enter-from {
  opacity: 0 !important;
  transform: translate3d(0, 16px, 0) !important;
}

/* ── ② 题目卡切换 .slide ──────────────────────────────────────────
   外面是 mode="out-in"，离场会门控新题插入，所以离场只给 90ms ——
   既有"旧题淡出"的交代，新题也能在约 0.1s 后出现。 */
.slide-leave-active {
  /* 外面是 out-in，离场时长 = 新题被插入前的等待，所以压到 60ms */
  transition: opacity 45ms cubic-bezier(.4, 0, 1, 1),
              transform 45ms cubic-bezier(.4, 0, 1, 1) !important;
}
.slide-leave-to {
  opacity: 0 !important;
  transform: translate3d(-16px, 0, 0) !important;
}
.slide-enter-active {
  transition: opacity 170ms cubic-bezier(.22, 1, .36, 1),
              transform 230ms cubic-bezier(.22, 1, .36, 1) !important;
  will-change: opacity, transform;
}
.slide-enter-from {
  opacity: 0 !important;
  transform: translate3d(20px, 0, 0) !important;
}

/* ── ③ 弹窗 .modal：遮罩整体淡入淡出 + 弹窗本体弹性升起 ───────────
   <transition name="modal"> 包的是 .modal-mask，所以要从父级选择器
   下钻到 .modal，才能让"弹窗本体"单独做形变。 */
.modal-enter-active { transition: opacity 190ms cubic-bezier(.22, 1, .36, 1) !important; }
.modal-leave-active { transition: opacity 140ms cubic-bezier(.4, 0, 1, 1) !important; }
.modal-enter-from, .modal-leave-to { opacity: 0 !important; }

.modal-enter-active .modal {
  transition: transform 340ms cubic-bezier(.34, 1.38, .5, 1),
              opacity 220ms cubic-bezier(.22, 1, .36, 1) !important;
}
.modal-leave-active .modal {
  transition: transform 150ms cubic-bezier(.4, 0, 1, 1),
              opacity 130ms cubic-bezier(.4, 0, 1, 1) !important;
}
.modal-enter-from .modal {
  opacity: 0 !important;
  transform: translate3d(0, 22px, 0) scale(.94) !important;
}
.modal-leave-to .modal {
  opacity: 0 !important;
  transform: translate3d(0, 10px, 0) scale(.97) !important;
}

/* ── ④ 移动端底栏 .nav-slide ────────────────────────────────────── */
.nav-slide-enter-active {
  transition: transform 340ms cubic-bezier(.22, 1, .36, 1), opacity 240ms ease !important;
}
.nav-slide-leave-active {
  transition: transform 200ms cubic-bezier(.4, 0, 1, 1), opacity 170ms ease !important;
}
.nav-slide-enter-from, .nav-slide-leave-to {
  transform: translateY(112%) !important;
  opacity: 0 !important;
}

/* ── ⑤ 【关键】把会被重建的元素的 animation-duration 归零 ──────────
   Vue 的 getTransitionInfo() 会同时读 transition-duration **和**
   animation-duration，然后取两者最大值作为离场时长。
   ㉘ 里为了让列表卡片入场更快写了 `animation-duration: 240ms !important`，
   这条命中了 .quiz-card —— 即使 ㉗ 已经把 animation-name 设为 none，
   计算出的 animation-duration 依然是 240ms，于是 Vue 认为
   离场要 240ms，排了 241ms 的兜底定时器（已用 hook setTimeout 抓到）。
   这里在最后把它们的 animation-duration 显式归零。 */
.quiz-card, .qcard, .opt {
  animation-duration: 0s !important;
}

/* ── ⑥ 尊重「减少动效」偏好 ─────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .fade-enter-active, .fade-leave-active,
  .slide-enter-active, .slide-leave-active,
  .modal-enter-active, .modal-leave-active,
  .nav-slide-enter-active, .nav-slide-leave-active {
    transition-duration: .01ms !important;
  }
  .modal-enter-from .modal, .modal-leave-to .modal { transform: none !important; }
  .fade-enter-from, .fade-leave-to,
  .slide-enter-from, .slide-leave-to { transform: none !important; }
}

/* ==========================================================================
   ㉛ 登录 / 注册 Tab 滑块「对不齐」修复 + 表单跟随方向
   ──────────────────────────────────────────────────────────────────────────
   现象：点「注册」时滑块动画看着"没顺着"。
   根因（已用注入同结构 DOM 量到实数）：
     style.css      .auth-tabs        { padding: 5px }
     ios-skin.css   .auth-tabs        { padding: 3px }      ← 覆盖了 padding
     style.css      .auth-tabs .slider{ width: calc(50% - 5px) }  ← 公式没跟着改
   滑块宽度是按 padding=5px 推的，而按钮实际宽 = 50% - 3px，于是：
       滑块宽 185px  vs  按钮宽 187px   → 窄 2px
       translateX(100%) 后左边缘再偏 2px → 右移时累计偏 4px
   修法：把 padding 与滑块宽度绑到同一个变量，以后改 padding 不会再错位。
   ========================================================================== */
.auth-tabs {
  --auth-tab-pad: 3px;
  padding: var(--auth-tab-pad) !important;
  position: relative;
  overflow: hidden;
}
.auth-tabs .slider {
  top: var(--auth-tab-pad) !important;
  bottom: var(--auth-tab-pad) !important;
  /* 绝对定位元素的百分比相对「padding box」，所以按钮宽 = 50% - pad，
     滑块宽度必须用同一公式，才与按钮严格等宽 */
  width: calc(50% - var(--auth-tab-pad)) !important;
  background-image: linear-gradient(150deg, #FFFFFF 0%, #F8FAFF 100%) !important;
  box-shadow:
    0 1px 3px rgba(16, 24, 40, .07),
    inset 0 1px 0 rgba(255, 255, 255, .95) !important;
  transition: transform 300ms cubic-bezier(.34, 1.4, .64, 1) !important;
  will-change: transform;
}
[data-theme="dark"] .auth-tabs .slider {
  background-image: linear-gradient(150deg, #3A3A3E 0%, #313135 100%) !important;
}

/* ── 表单跟随 Tab 方向滑动（原来只做淡入淡出，与滑块方向脱节）──────────
   用 :has() 读当前激活的按钮，决定进/出方向，这样来回切都对。 */
.auth-card:has(.auth-tabs button:nth-child(3).active) form.fade-enter-from { transform: translate3d(18px, 0, 0) !important; }
.auth-card:has(.auth-tabs button:nth-child(3).active) form.fade-leave-to   { transform: translate3d(-18px, 0, 0) !important; }
.auth-card:has(.auth-tabs button:nth-child(2).active) form.fade-enter-from { transform: translate3d(-18px, 0, 0) !important; }
.auth-card:has(.auth-tabs button:nth-child(2).active) form.fade-leave-to   { transform: translate3d(18px, 0, 0) !important; }

/* 离场要短：out-in 会先跑完离场才插入新表单，太长会中间空一拍 */
.auth-card form.fade-leave-active {
  transition: opacity 90ms linear, transform 90ms linear !important;
}
.auth-card form.fade-enter-active {
  transition: opacity 190ms cubic-bezier(.22, 1, .36, 1),
              transform 250ms cubic-bezier(.22, 1, .36, 1) !important;
}

/* ── 页面标题的轻快入场（.page-head 不含毛玻璃，位移是安全的）────── */
@keyframes gx-head-in {
  from { opacity: 0; transform: translate3d(0, 12px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}
.page-head { animation: gx-head-in 300ms cubic-bezier(.22, 1, .36, 1) both; }
.page-head h2 { animation: gx-head-in 340ms cubic-bezier(.22, 1, .36, 1) 20ms both; }
.page-head p  { animation: gx-head-in 340ms cubic-bezier(.22, 1, .36, 1) 60ms both; }

/* 卡片出场补一点位移（单张卡片移动的重算范围小，实测可接受）*/
@keyframes gx-card-rise {
  from { opacity: 0; transform: translate3d(0, 10px, 0) scale(.99); }
  to   { opacity: 1; transform: translate3d(0, 0, 0) scale(1); }
}

/* ==========================================================================
   ㉜ 加载态优化（骨架屏 + Spinner）
   ──────────────────────────────────────────────────────────────────────────
   发现的问题：
   `.skeleton` 上同时跑着**两套流光**：
     ① glass-effects / ios-skin 的 @keyframes gx-shimmer / ios-shimmer
        动画 background-position → **每帧重绘整个元素背景**（贵）
     ② style.css 的 `.skeleton::after` 动画 transform: translateX
        → GPU 合成（便宜）
   而且 ①（glass-effects 最后加载）实际生效，于是每个骨架屏元素
   都在同时做「重绘 + 合成」两份工作。加载期间一屏好几个骨架屏，非常浪费。

   修法：干掉 ①，只保留 ② 的 GPU 版本，并把扫光调得更顺（1.4s 线性）。
   ========================================================================== */

.skeleton {
  position: relative;
  overflow: hidden;
  /* 去掉 background-position 流光：改为纯色底 + 伪元素扫光 */
  background-image: none !important;
  background-color: rgba(120, 120, 128, .10) !important;
  background-size: auto !important;
  animation: none !important;
  border-radius: 8px;
}
[data-theme="dark"] .skeleton { background-color: rgba(255, 255, 255, .075) !important; }

/* 只留这一套：transform 平移的扫光，纯合成器处理 */
.skeleton::after {
  content: "" !important;
  position: absolute;
  inset: 0;
  transform: translateX(-100%);
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, .62) 50%,
    rgba(255, 255, 255, 0) 100%) !important;
  animation: shimmer 1.4s cubic-bezier(.4, 0, .2, 1) infinite !important;
  will-change: transform;
  pointer-events: none;
}
[data-theme="dark"] .skeleton::after {
  background: linear-gradient(90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, .08) 50%,
    rgba(255, 255, 255, 0) 100%) !important;
}

/* ── Spinner：品牌色圆环，只用 transform 旋转 ─────────────────── */
.spinner {
  border-width: 2.5px !important;
  border-style: solid !important;
  border-color: color-mix(in srgb, var(--brand, #8f93d8) 20%, transparent) !important;
  border-top-color: var(--brand, #8f93d8) !important;
  animation: spin .72s cubic-bezier(.45, .05, .55, .95) infinite !important;
  will-change: transform;
}

/* ── 加载文字：轻微呼吸，让等待"看得出在动"而不是静止卡住 ─────── */
@keyframes gx-loading-pulse {
  0%, 100% { opacity: .5; }
  50%      { opacity: 1; }
}
.loading-wrap { color: var(--ink3); }
.loading-wrap > span:not(.spinner) {
  animation: gx-loading-pulse 1.5s ease-in-out infinite;
}

/* 减少动效偏好 */
@media (prefers-reduced-motion: reduce) {
  .skeleton::after, .spinner, .loading-wrap > span:not(.spinner) { animation: none !important; }
}

/* ==========================================================================
   ㉝ 让动画跟满屏幕刷新率（高刷屏 120Hz）
   ──────────────────────────────────────────────────────────────────────────
   原理：只有 `transform` / `opacity` 由**合成器线程**驱动，能跟着屏幕刷新率走；
   一旦动画 `left` / `background-position` / `box-shadow` / `width`，
   就必须走主线程重绘，帧率被压在 60Hz 甚至更低。

   审计全站 @keyframes 发现 11 个动画在跑主线程属性，其中实际生效的：
     · .quiz-progress .bar::after  → left            （答题时全程在跑！）
     · .animated-bg / -soft        → background-position（类名未使用，死代码）
     · .skeleton                   → background-position（已被 ㉜ 覆盖，未生效）
     · .auth-card 呼吸 / Logo 光环 / 输入框聚焦 / Tab 流光 → box-shadow
   前面已把登录页那几处改成 opacity；这里把进度条光效也改成 transform。
   ========================================================================== */

/* ⚠️ 原版是 `0% { left: -100% } → 100% { left: 100% }`，
   left 每帧触发布局。该元素 width:100%，所以用 translateX 百分比等价替换。 */
@keyframes progressShine {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}
.quiz-progress .bar::after {
  left: 0 !important;
  will-change: transform;
}

/* ==========================================================================
   ㉞ 首屏加载：把「两个连续出现的 loading」合并成一个
   ──────────────────────────────────────────────────────────────────────────
   首屏实际会连续出现两个加载动画：
     ① index.html 里的启动占位 .boot-wrap（"正在进入爱刷刷…"）
     ② Vue 挂载后 AuthApp 的 .auth-auto（"正在为你自动进入…"）
   用户看到的就是"加载动画出现了两次"。

   处理：把 .auth-auto 变成与启动占位**完全一致**的全屏 loading ——
   同位置、同尺寸圆环、同文案、透明底（露出 .auth-page 自己的渐变，
   而启动占位的底色已经调成与 .auth-page 一致）。
   这样①②首尾相接、视觉上是一个连续的加载状态。
   ========================================================================== */

/* ⚠️ 有两样东西会为 fixed 后代创建包含块，必须都去掉，
   否则 .auth-auto 的 position:fixed 会相对卡片而不是视口：
     ① .auth-card 的入场动画带 transform
     ② .auth-card 的 backdrop-filter（毛玻璃）← 这个最容易漏 */
/* ⚠️ 会为 fixed 后代创建包含块的属性一共 4 个，这里必须全部清掉，
   否则 .auth-auto 的 position:fixed 会相对卡片而不是视口：
     ① transform（来自 3D 入场动画）
     ② transform-style: preserve-3d  ← 最隐蔽，实测就是它
     ③ backdrop-filter（毛玻璃）
     ④ filter / contain / will-change
   （之前排查"弹窗锁在内容列"那次是 contain，这次是 preserve-3d ——
     同一个坑的不同面目，写下来免得再踩。） */
.auth-card:has(.auth-auto) {
  animation: none !important;
  transform: none !important;
  transform-style: flat !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  filter: none !important;
}

.auth-auto {
  position: fixed !important;
  inset: 0 !important;
  z-index: 99998 !important;
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 14px !important;
  padding: 0 !important;
  color: #8a90a2 !important;
  font-size: 13.5px !important;
  /* ⚠️ 必须是**不透明**底。
     之前写成 transparent（想露出 .auth-page 的渐变），结果它背后的
     登录卡片（Logo + Logo 的光环圈 .mark::after）依然可见 ——
     加上覆盖层里的加载圈，屏幕上就出现了**两个圈**。
     这里用与 .auth-page / 启动占位完全相同的渐变把它盖住，
     于是整个首屏加载始终只有一个圆环。 */
  background:
    radial-gradient(1100px 700px at 18% -10%, rgba(0,122,255,.14) 0%, transparent 56%),
    radial-gradient(900px 620px at 88% 8%,   rgba(175,82,222,.11) 0%, transparent 56%),
    radial-gradient(820px 680px at 50% 112%, rgba(90,200,250,.10) 0%, transparent 58%),
    #F2F2F7 !important;
  background-attachment: fixed;
}
[data-theme="dark"] .auth-auto {
  color: #8a8f9c !important;
  background:
    radial-gradient(1050px 720px at 14% -12%, rgba(10,132,255,.175) 0%, transparent 56%),
    radial-gradient(980px 660px at 92% 6%,   rgba(191,90,242,.135) 0%, transparent 56%),
    radial-gradient(900px 720px at 48% 116%, rgba(100,210,255,.115) 0%, transparent 58%),
    linear-gradient(180deg, #1A1B1F 0%, #1A1B1F 30%, #181A1E 50%, #16181D 70%, #14161B 100%) !important;
  background-attachment: fixed;
}

/* 圆环尺寸/描边与启动占位对齐（模板里写了内联 30px/3px，必须 !important 才压得住）*/
.auth-auto .spinner {
  width: 34px !important;
  height: 34px !important;
  border-width: 2.5px !important;
}

/* ==========================================================================
   ㉟ 修复：选中选择题答案时整页错位
   ──────────────────────────────────────────────────────────────────────────
   实测（点选项前后对比 document.scrollHeight / 卡片高度 / 每个选项的 top）：
       cardH   509 → 511        （+2px）
       4 个选项 top 全部 +2px    ← 用户感觉的"页面错位一下"
       .opt 的 border-width   0px → 1px

   根因：基态 .opt 的边框是 `border: none`（0px，来自 ios-skin），
   而 `.opt.sel` 用了**简写** `border: 1.5px solid var(--brand)` ——
   简写会把 border-width 一起设上，于是选中瞬间边框从 0 变 1.5px，
   选项高度 +2~3px，整页跟着下移。

   修法：基态就给**同宽的透明边框**，选中只换颜色，宽度恒定不变。
   （.opt.correct / .opt.wrong / :hover 本来也只改颜色，不受影响。）
   ========================================================================== */
.opt {
  border-width: 1.5px !important;
  border-style: solid !important;
  border-color: transparent;
}

/* ── 同类排查：底栏选中项改了 font-weight，字宽变化会引起重排 ──────
   .mobile-nav a 是 flex:1 1 0，宽度由容器等分，所以不会挤压兄弟节点；
   但字号变化仍会触发该行重排。这里改成只改颜色、不加粗，避免重排。 */
.mobile-nav a.on {
  font-weight: 500 !important;
}

/* ==========================================================================
   ㊱ 移除毛玻璃后的「层提升」补偿
   ──────────────────────────────────────────────────────────────────────────
   去掉 backdrop-filter 后出现一个反直觉的回归：
   **毛玻璃本来会把卡片提升为独立合成层**，一旦移除，卡片就"降级"了 ——
   这时只要 section 发生位移（页面切换动画），浏览器就要**逐张重绘卡片的
   渐变背景**，代价比有毛玻璃时还高。

   实测（两次「刷题 ⇄ 我的」往返，CDP Tracing）：
       A 位移、无层提升                RasterTask = 1453.9ms   ← 爆炸
       B 去掉位移                      RasterTask =  397.1ms
       C 位移 + 卡片 will-change:transform  RasterTask = 362.4ms  ← 最好

   所以：显式给卡片声明 `will-change: transform`，把"合成层"这件事
   从 backdrop-filter 手中接过来。位移重新变成纯合成操作。
   ========================================================================== */
.card,
.quiz-card,
.stat-card,
.subj-card,
.tool-item,
.tool-card,
.rec-item,
.set-row,
.wrong-subj,
.sr-item,
.sr-group,
.me-hero,
.me-btn,
.acct-btn,
.theme-item,
.choice-btn,
.type-card,
.exam-bar,
.cmt,
.practice-card,
.dashboard-card,
.cd-sec,
.cmt-board,
.search-box,
.ti-box,
.guest-card,
.group-card,
.notif-bar,
.result-hero,
.qcard {
  will-change: transform;
}

/* ==========================================================================
   ㊲ 弹窗改为不透明
   ──────────────────────────────────────────────────────────────────────────
   毛玻璃（backdrop-filter）已经在 v65 全部移除，但弹窗本体底色仍是
   `--lg-thick: rgba(255,255,255,.80)` —— **没有模糊时，背后内容会"清晰地"
   透过来**（不是朦胧玻璃，而是像印在上面），观感很廉价。
   实测：.modal 背景 rgba(255,255,255,0.8)，backdrop-filter: none。

   处理：弹窗本体改成完全不透明；**遮罩保持半透明**（它是压暗层，本就该透）。
   ========================================================================== */
.modal,
.dlg,
.cmt-modal,
.qf-sheet,
.auth-card,
.sidebar,
.side-nav {
  background-color: #FFFFFF !important;
  background-image: none !important;
}
[data-theme="dark"] .modal,
[data-theme="dark"] .dlg,
[data-theme="dark"] .cmt-modal,
[data-theme="dark"] .qf-sheet,
[data-theme="dark"] .auth-card,
[data-theme="dark"] .sidebar,
[data-theme="dark"] .side-nav {
  background-color: #1C1C1E !important;
}

/* 具体弹窗变体：它们各自设过底色，一并覆盖 */
.share-modal,
.reward-modal,
.acct-modal,
.modal-wide,
.notif-pop,
.guest-card,
.cd-sec,
.cmt-board {
  background-color: #FFFFFF !important;
  background-image: var(--gx-neutral), var(--gx-face) !important;
}
[data-theme="dark"] .share-modal,
[data-theme="dark"] .reward-modal,
[data-theme="dark"] .acct-modal,
[data-theme="dark"] .modal-wide,
[data-theme="dark"] .notif-pop {
  background-color: transparent !important;
  background-image: var(--gx-neutral), var(--gx-face) !important;
}

/* Toast 同理（原来也是半透明液态玻璃）*/
.toast {
  background-color: #FFFFFF !important;
  background-image: none !important;
}
[data-theme="dark"] .toast { background-color: #1C1C1E !important; }

/* ==========================================================================
   ㊳ 去掉首屏加载的圆环动画
   ──────────────────────────────────────────────────────────────────────────
   用户："刷题首页加载动画，去掉这个过渡动画的圈吧，不需要这个"

   两处圆环一起去掉（保持首尾仍然接得上、也不会退回白屏）：
     ① index.html 启动占位里的 .boot-ring（已从 HTML 移除）
     ② App 内 .auth-auto 的 .spinner（模板里是内联 30px，需 !important）
   只保留「正在为你自动进入…」文字，并给它加了轻微的呼吸，
   让等待状态"看得出在动"而不是静止。
   ========================================================================== */
.auth-auto .spinner {
  display: none !important;
}

/* 文字呼吸（原来只有启动占位有，这里补上，保持两端一致）*/
@keyframes gx-boot-pulse {
  0%, 100% { opacity: .45; }
  50%      { opacity: 1; }
}
.auth-auto > p {
  animation: gx-boot-pulse 1.5s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .auth-auto > p { animation: none !important; }
}

/* ==========================================================================
   ㊴ 首次进入应用的入场动画（修"闪进去"）
   ──────────────────────────────────────────────────────────────────────────
   根因：Vue 的 `<transition>` **默认不在初次渲染时播放**（没写 appear），
   所以首屏应用内容是"硬切"上来的 —— 用户感觉"闪进去"。
   `<transition>` 的动画只覆盖**视图之间**的切换，覆盖不到首次挂载。
   这里用纯 CSS `animation` 补上：元素创建时自动播放一次，正合适。

   ⚠️ 分两层处理，因为 transform 会为 fixed 后代创建包含块：
      · .toast-layer(position:fixed) 挂在 `#app > div > div` 下
      · .modal-mask(position:fixed)  挂在 `main.container` 下
      → 这两个祖先**只能做 opacity**，绝不能加 transform，否则弹窗会被锁死
        （这个坑已经踩过两次：一次是 contain，一次是 preserve-3d）
      · .topbar 内部无 fixed 后代、.mobile-nav 自身就是 fixed 元素 → 可以安全位移
   ========================================================================== */
@keyframes appShellIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes appTopbarIn {
  from { opacity: 0; transform: translate3d(0, -12px, 0); }
  to   { opacity: 1; transform: none; }
}
@keyframes appMainIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes appNavIn {
  from { opacity: 0; transform: translate3d(0, 16px, 0); }
  to   { opacity: 1; transform: none; }
}

/* 只做 opacity：下面挂着 fixed 的 toast-layer / modal-mask */
#app > div {
  animation: appShellIn 260ms cubic-bezier(.22, 1, .36, 1) both;
}
main.container {
  animation: appMainIn 300ms cubic-bezier(.22, 1, .36, 1) 60ms both;
}
/* 可以安全位移的：顶栏下滑、底栏升起 */
.topbar {
  animation: appTopbarIn 340ms cubic-bezier(.22, 1, .36, 1) both;
}
.mobile-nav {
  animation: appNavIn 380ms cubic-bezier(.34, 1.3, .64, 1) 100ms both;
}

@media (prefers-reduced-motion: reduce) {
  #app > div, main.container, .topbar, .mobile-nav { animation: none !important; }
}

/* ==========================================================================
   ㊵ 刷题首页入场级联（卡片依次浮现）
   ──────────────────────────────────────────────────────────────────────────
   原来 11 张 `.subj-card` 用同一条 `gx-card-in 150ms` 且**没有交错**：
   同时出现、只上浮 4px —— 视觉上接近"直接出现"，所以用户感觉"没有淡入动画"。
   （那条 4px 的注释写于卡片还带 backdrop-filter 的时期：位移会让每帧重算
     背景模糊，8px 就 +36% 光栅开销。**现在毛玻璃已移除（v65）、卡片又已被
     `will-change: transform` 提升为独立层（v65 ㊱）**，位移不再触发重绘，
     所以可以放心把幅度、时长、层次都做足。）

   节奏：标题 → 搜索栏 → 分类胶囊 → 卡片逐张（40ms 步进，共 11 张）
   ========================================================================== */
@keyframes gx-subj-in {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: translate3d(0, 0, 0); }
}

/* ⚠️ 必须全部用 !important：
   上面（约 2563 行）有一组旧规则
     `.card, .stat-card, .subj-card, … { animation-duration: 150ms !important }`
     `.subject-grid > *:nth-child(n) { animation-delay: 16ms*n !important }`
   它们带 !important，光靠"写在后面"是压不过的 —— 这正是级联一直没生效的原因。*/
.page-head,
.search-box,
.cat-chip,
.subj-card {
  animation-name: gx-subj-in !important;
  animation-timing-function: cubic-bezier(.22, 1, .36, 1) !important;
  animation-fill-mode: both !important;
}
.page-head  { animation-duration: 320ms !important; animation-delay: 0ms !important; }
.search-box { animation-duration: 340ms !important; animation-delay: 70ms !important; }
.cat-chip   { animation-duration: 300ms !important; }
.subj-card  { animation-duration: 360ms !important; }

.cat-chip:nth-child(1) { animation-delay: 120ms !important; }
.cat-chip:nth-child(2) { animation-delay: 155ms !important; }
.cat-chip:nth-child(3) { animation-delay: 190ms !important; }
.cat-chip:nth-child(4) { animation-delay: 225ms !important; }
.cat-chip:nth-child(5) { animation-delay: 260ms !important; }

.subj-card:nth-child(1) { animation-delay: 150ms !important; }
.subj-card:nth-child(2) { animation-delay: 190ms !important; }
.subj-card:nth-child(3) { animation-delay: 230ms !important; }
.subj-card:nth-child(4) { animation-delay: 270ms !important; }
.subj-card:nth-child(5) { animation-delay: 310ms !important; }
.subj-card:nth-child(6) { animation-delay: 350ms !important; }
.subj-card:nth-child(7) { animation-delay: 390ms !important; }
.subj-card:nth-child(8) { animation-delay: 430ms !important; }
.subj-card:nth-child(9) { animation-delay: 470ms !important; }
.subj-card:nth-child(10) { animation-delay: 510ms !important; }
.subj-card:nth-child(11) { animation-delay: 550ms !important; }

@media (prefers-reduced-motion: reduce) {
  .page-head, .search-box, .cat-chip, .subj-card { animation: none !important; }
}

/* ⚠️ 安全重申：.quiz-card / .qcard 是 <transition name="slide"> 的直接目标，
   它的 animation-duration 会被 Vue 当作离场时长（曾导致 241ms 卡顿）。
   本段在文件最末，必须保证它们仍然没有动画。 */
.quiz-card,
.qcard {
  animation: none !important;
  animation-duration: 0s !important;
}

/* ==========================================================================
   ㊶ 科目卡「选择练习模式」按钮升级
   ──────────────────────────────────────────────────────────────────────────
   原状：扁平浅灰底（ios-skin 里 `background: var(--fill)`、`border: none`、
   `box-shadow: none`），hover 只是底色从 --fill 变 --glow，几乎看不出反馈。

   升级思路（只用 transform / color / box-shadow，不动盒模型尺寸）：
     · 基态：品牌色「柔和填充 + 同色细描边 + 顶部内高光」，像一个精致的胶囊
     · 悬停：填充变**实心品牌渐变**、文字转白、上浮 1px、投出品牌色光晕，
             并有一道**斜向高光扫过**（伪元素 translateX，纯合成）
     · 按下：轻微回压
   ⚠️ 描边宽度在基态就定好（1.5px），悬停只换颜色 —— 否则会像选择题选项那样
      引起整页位移（详见 ㉟）。
   ========================================================================== */
@keyframes gx-btn-sheen {
  from { transform: translateX(-170%) skewX(-18deg); }
  to   { transform: translateX(380%)  skewX(-18deg); }
}

.subj-set-btn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: block;
  margin-top: 12px;
  width: 100%;
  padding: 11px 14px;
  border-radius: 12px !important;
  font-size: 13.5px !important;
  font-weight: 620 !important;
  letter-spacing: .012em;
  cursor: pointer;

  /* 基态：柔和品牌填充 */
  background-color: color-mix(in srgb, var(--brand, #8f93d8) 11%, #fff) !important;
  background-image: none !important;
  color: var(--brand, #8f93d8) !important;
  /* 描边宽度固定，悬停只换色 */
  border: 1.5px solid color-mix(in srgb, var(--brand, #8f93d8) 24%, transparent) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .8),
    0 1px 2px color-mix(in srgb, var(--brand, #8f93d8) 12%, transparent) !important;

  transition:
    background-color 210ms cubic-bezier(.22, 1, .36, 1),
    border-color     210ms cubic-bezier(.22, 1, .36, 1),
    color            140ms linear,
    box-shadow       230ms cubic-bezier(.22, 1, .36, 1),
    transform        200ms cubic-bezier(.22, 1, .36, 1) !important;
  will-change: transform;
}

/* 斜向高光（默认隐藏，悬停时扫一次）*/
.subj-set-btn::after {
  content: '';
  position: absolute;
  top: -60%;
  bottom: -60%;
  left: 0;
  width: 42%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .62), transparent);
  transform: translateX(-170%) skewX(-18deg);
  opacity: 0;
  pointer-events: none;
}

/* ── 悬停：只在真有指针的设备上启用（触摸设备 :hover 会粘住，见 v61）── */
@media (hover: hover), (pointer: fine) {
  .subj-set-btn:hover {
    background-color: var(--brand, #8f93d8) !important;
    border-color: var(--brand, #8f93d8) !important;
    color: #FFFFFF !important;
    transform: translate3d(0, -1.5px, 0);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, .28),
      0 6px 18px color-mix(in srgb, var(--brand, #8f93d8) 42%, transparent),
      0 2px 6px color-mix(in srgb, var(--brand, #8f93d8) 26%, transparent) !important;
  }
  .subj-set-btn:hover::after {
    opacity: 1;
    animation: gx-btn-sheen 640ms cubic-bezier(.22, 1, .36, 1);
  }
}

.subj-set-btn:active {
  transform: translate3d(0, 0, 0) scale(.985);
  transition-duration: 90ms;
}

/* 键盘可达性：焦点环 */
.subj-set-btn:focus-visible {
  outline: none;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .8),
    0 0 0 3.5px color-mix(in srgb, var(--brand, #8f93d8) 26%, transparent) !important;
}

/* ── 暗色 ── */
[data-theme="dark"] .subj-set-btn {
  background-color: color-mix(in srgb, var(--brand, #8f93d8) 15%, #1C1C1E) !important;
  border-color: color-mix(in srgb, var(--brand, #8f93d8) 32%, transparent) !important;
  color: color-mix(in srgb, var(--brand, #8f93d8) 78%, #fff) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .06),
    0 1px 2px rgba(0, 0, 0, .3) !important;
}
@media (hover: hover), (pointer: fine) {
  [data-theme="dark"] .subj-set-btn:hover {
    background-color: color-mix(in srgb, var(--brand, #8f93d8) 88%, #fff) !important;
    border-color: color-mix(in srgb, var(--brand, #8f93d8) 88%, #fff) !important;
    color: #FFFFFF !important;
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, .22),
      0 6px 20px color-mix(in srgb, var(--brand, #8f93d8) 46%, transparent) !important;
  }
}

/* ⚠️ 必须补回手机端的 display:none！
   ㊶ 里给 `.subj-set-btn` 写了 `display: block`，它在本文件（最后加载）里，
   与 style.css 的 `@media (max-width:860px){ .subj-set-btn{display:none} }`
   **同优先级、但我们更靠后** → 直接把手机端的隐藏规则压掉了。
   结果：手机端科目卡里出现了桌面版的「选择练习模式」按钮，
   把卡片布局挤坏（标题被压成一字一行）。*/
@media (max-width: 860px) {
  .subj-set-btn { display: none !important; }
}

@media (prefers-reduced-motion: reduce) {
  .subj-set-btn, .subj-set-btn::after { transition: none !important; animation: none !important; }
}

/* ==========================================================================
   ㊷ 作品题（文字/表格/演示）「素材下载 + 考生文件夹」区重新设计
   ──────────────────────────────────────────────────────────────────────────
   原问题：ios-skin 把 `.dl-btn`（题目文件下载）和 `.work-file-btn`（考生文件夹）
   都压成了同一种样式 ——
       `background: var(--fill-3); border: 1.5px dashed var(--label-3); color: var(--ink2)`
   于是「下载按钮」「上传按钮」「拖放区」三者长得几乎一样，全是灰色虚线框，
   既看不出哪个是按钮，也没有主次。

   重设计为三级层次：
     · 题目文件下载  → 主按钮：品牌渐变实底 + 白字 + 下载图标 + 品牌色投影
     · 考生文件夹    → 次按钮：白底 + 品牌描边 + 品牌字，悬停填充品牌色
     · 拖放区        → 明确的「区域」：虚线描边 + 极浅品牌底 + 居中提示，
                        不与按钮争夺注意力，拖拽时整块高亮
   并用 `.work-wrap` 把整块收进一张浅色面板，形成"作答区"的整体感。
   ========================================================================== */

/* ── 容器：统一面板 ─────────────────────────────────────────── */
.work-wrap {
  margin-top: 14px;
  padding: 16px;
  border-radius: 16px;
  background: linear-gradient(180deg, #FCFDFF 0%, #F7F9FE 100%) !important;
  border: 1px solid color-mix(in srgb, var(--brand, #8f93d8) 14%, transparent) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .9),
    0 1px 2px rgba(16, 24, 40, .035) !important;
}
[data-theme="dark"] .work-wrap {
  background: linear-gradient(180deg, #202127 0%, #1C1D22 100%) !important;
  border-color: rgba(255, 255, 255, .07) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .045) !important;
}
/* 面板内的结果区不再自带卡片（避免卡中卡）*/
.work-wrap .work-result {
  background: transparent !important;
  box-shadow: none !important;
  border-radius: 0 !important;
}

/* ── 提示条：轻量信息条，去掉厚重底色 ─────────────────────────── */
.work-wrap .work-tip {
  font-size: 13px !important;
  line-height: 1.65;
  color: var(--ink2, #5b6070) !important;
  background: color-mix(in srgb, var(--brand, #8f93d8) 6%, transparent) !important;
  border: 1px solid color-mix(in srgb, var(--brand, #8f93d8) 13%, transparent) !important;
  border-left: 3px solid color-mix(in srgb, var(--brand, #8f93d8) 55%, transparent) !important;
  border-radius: 10px !important;
  padding: 10px 13px !important;
  margin-bottom: 14px !important;
}
[data-theme="dark"] .work-wrap .work-tip {
  background: rgba(255, 255, 255, .04) !important;
  border-color: rgba(255, 255, 255, .08) !important;
  border-left-color: color-mix(in srgb, var(--brand, #8f93d8) 70%, transparent) !important;
  color: var(--ink3, #9aa0ad) !important;
}

/* ── ① 题目文件下载：主按钮（品牌渐变实底）─────────────────────── */
.dl-bar {
  display: flex !important;
  flex-wrap: wrap !important;
  gap: 10px !important;
  margin: 0 0 16px !important;
  padding: 0 !important;
  background: none !important;      /* 去掉 ios-skin 的灰色药丸底 */
  box-shadow: none !important;
  border-radius: 0 !important;
}
.dl-btn {
  display: inline-flex !important;
  align-items: center;
  gap: 9px;
  padding: 12px 22px !important;
  border-radius: 12px !important;
  font-size: 14px !important;
  font-weight: 620 !important;
  letter-spacing: .01em;
  color: #FFFFFF !important;
  background-color: transparent !important;
  background-image: linear-gradient(135deg,
    var(--brand, #8f93d8) 0%,
    color-mix(in srgb, var(--brand, #8f93d8) 78%, #A855F7) 100%) !important;
  border: 1.5px solid transparent !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .26),
    0 4px 14px color-mix(in srgb, var(--brand, #8f93d8) 30%, transparent) !important;
  transition:
    transform 180ms cubic-bezier(.22, 1, .36, 1),
    box-shadow 220ms cubic-bezier(.22, 1, .36, 1),
    filter 160ms linear !important;
  will-change: transform;
}
.dl-btn-sm {
  padding: 10px 16px !important;
  font-size: 13px !important;
}
[data-theme="dark"] .dl-btn {
  background-image: linear-gradient(135deg,
    color-mix(in srgb, var(--brand, #8f93d8) 88%, #fff) 0%,
    color-mix(in srgb, var(--brand, #8f93d8) 62%, #A855F7) 100%) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .2),
    0 4px 16px rgba(0, 0, 0, .38) !important;
}

/* ── ② 考生文件夹：次按钮（白底 + 品牌描边）───────────────────── */
.work-file-label {
  position: relative;
  display: inline-block;
  cursor: pointer;
  border-radius: 12px;
}
.work-file {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
  z-index: 2;
  background: none !important;
  border: none !important;
  box-shadow: none !important;
}
.work-file-btn {
  display: inline-flex !important;
  align-items: center;
  gap: 9px;
  padding: 12px 22px !important;
  border-radius: 12px !important;
  font-size: 14px !important;
  font-weight: 620 !important;
  color: var(--brand, #8f93d8) !important;
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1.5px solid color-mix(in srgb, var(--brand, #8f93d8) 34%, transparent) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .9),
    0 1px 2px color-mix(in srgb, var(--brand, #8f93d8) 12%, transparent) !important;
  transition:
    background-color 200ms cubic-bezier(.22, 1, .36, 1),
    border-color 200ms,
    color 150ms linear,
    box-shadow 220ms cubic-bezier(.22, 1, .36, 1),
    transform 180ms cubic-bezier(.22, 1, .36, 1) !important;
  will-change: transform;
}
[data-theme="dark"] .work-file-btn {
  background-color: #232429 !important;
  border-color: color-mix(in srgb, var(--brand, #8f93d8) 42%, transparent) !important;
  color: color-mix(in srgb, var(--brand, #8f93d8) 76%, #fff) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05) !important;
}

/* 悬停：只在有指针的设备启用（触摸设备 :hover 会粘住，见 v61）*/
@media (hover: hover), (pointer: fine) {
  .dl-btn:hover {
    transform: translate3d(0, -1.5px, 0);
    filter: brightness(1.06);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, .3),
      0 8px 22px color-mix(in srgb, var(--brand, #8f93d8) 44%, transparent) !important;
  }
  .work-file-label:hover .work-file-btn {
    background-color: var(--brand, #8f93d8) !important;
    border-color: var(--brand, #8f93d8) !important;
    color: #FFFFFF !important;
    transform: translate3d(0, -1.5px, 0);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, .24),
      0 8px 22px color-mix(in srgb, var(--brand, #8f93d8) 42%, transparent) !important;
  }
  [data-theme="dark"] .work-file-label:hover .work-file-btn {
    background-color: color-mix(in srgb, var(--brand, #8f93d8) 88%, #fff) !important;
    border-color: color-mix(in srgb, var(--brand, #8f93d8) 88%, #fff) !important;
    color: #FFFFFF !important;
  }
}
.dl-btn:active,
.work-file-label:active .work-file-btn {
  transform: translate3d(0, 0, 0) scale(.975) !important;
  transition-duration: 90ms !important;
}

/* ── ③ 拖放区：明确的"区域"而非按钮 ───────────────────────────── */
.upload-box {
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  gap: 12px !important;
  width: 100%;
  padding: 20px 18px !important;
  border-radius: 14px !important;
  background-color: color-mix(in srgb, var(--brand, #8f93d8) 3.5%, #fff) !important;
  background-image: none !important;
  border: 1.5px dashed color-mix(in srgb, var(--brand, #8f93d8) 30%, transparent) !important;
  box-shadow: none !important;
  transition: background-color 200ms cubic-bezier(.22, 1, .36, 1),
              border-color 200ms cubic-bezier(.22, 1, .36, 1),
              box-shadow 200ms cubic-bezier(.22, 1, .36, 1) !important;
}
[data-theme="dark"] .upload-box {
  background-color: rgba(255, 255, 255, .035) !important;
  border-color: rgba(255, 255, 255, .13) !important;
}
/* 拖放区内部的提示文字不再自成一块 */
.upload-box .work-tip {
  background: none !important;
  border: none !important;
  padding: 0 !important;
  margin-bottom: 0 !important;
  text-align: center !important;
  max-width: 46em;
}
.drop-hint {
  font-size: 12.5px !important;
  color: var(--ink3, #9aa0ad) !important;
  background: none !important;
  border: none !important;
  text-align: center;
}

/* 拖拽中：整块高亮（原来只有一条 outline，不够明确）*/
.upload-box.dragging,
.re-grade.dragging {
  outline: none !important;
  background-color: color-mix(in srgb, var(--brand, #8f93d8) 10%, #fff) !important;
  border-color: var(--brand, #8f93d8) !important;
  border-style: solid !important;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--brand, #8f93d8) 14%, transparent) !important;
}
[data-theme="dark"] .upload-box.dragging,
[data-theme="dark"] .re-grade.dragging {
  background-color: color-mix(in srgb, var(--brand, #8f93d8) 16%, #1C1C1E) !important;
}

/* ── ④ 已选文件 chips ─────────────────────────────────────────── */
.file-chips {
  display: flex !important;
  flex-wrap: wrap !important;
  gap: 8px !important;
  justify-content: center;
  width: 100%;
  margin-top: 2px;
}
.file-chip {
  display: inline-flex !important;
  align-items: center;
  gap: 6px;
  font-size: 12.5px !important;
  font-weight: 500;
  padding: 5px 11px !important;
  border-radius: 999px !important;
  color: color-mix(in srgb, var(--ok, #10b981) 82%, #0b3b2c) !important;
  background-color: color-mix(in srgb, var(--ok, #10b981) 11%, #fff) !important;
  border: 1px solid color-mix(in srgb, var(--ok, #10b981) 26%, transparent) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .7);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.file-chip.folder-chip {
  color: var(--brand, #8f93d8) !important;
  background-color: color-mix(in srgb, var(--brand, #8f93d8) 11%, #fff) !important;
  border-color: color-mix(in srgb, var(--brand, #8f93d8) 26%, transparent) !important;
}
[data-theme="dark"] .file-chip {
  background-color: rgba(16, 185, 129, .14) !important;
  border-color: rgba(16, 185, 129, .3) !important;
  color: #6ee7b7 !important;
  box-shadow: none;
}
[data-theme="dark"] .file-chip.folder-chip {
  background-color: rgba(143, 147, 216, .16) !important;
  border-color: rgba(143, 147, 216, .34) !important;
  color: #c3c6ec !important;
}

/* ── ⑤ 评分点折叠：做成规整的手风琴 ─────────────────────────── */
.rubric {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid color-mix(in srgb, var(--brand, #8f93d8) 14%, transparent) !important;
  border-radius: 12px !important;
  padding: 0 !important;
  margin-bottom: 14px !important;
  overflow: hidden;
}
[data-theme="dark"] .rubric {
  background-color: #232429 !important;
  border-color: rgba(255, 255, 255, .08) !important;
}
.rubric summary {
  cursor: pointer;
  font-weight: 620 !important;
  color: var(--ink, #1c1f2b) !important;
  font-size: 14px !important;
  padding: 12px 15px !important;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 9px;
  transition: background-color 160ms linear;
}
.rubric summary::-webkit-details-marker { display: none; }
.rubric summary::before {
  content: '';
  width: 0; height: 0;
  flex: none;
  border-left: 5px solid currentColor;
  border-top: 4.5px solid transparent;
  border-bottom: 4.5px solid transparent;
  opacity: .5;
  transition: transform 200ms cubic-bezier(.22, 1, .36, 1);
}
.rubric[open] summary::before { transform: rotate(90deg); }
.rubric[open] summary { border-bottom: 1px solid color-mix(in srgb, var(--brand, #8f93d8) 12%, transparent); }
@media (hover: hover), (pointer: fine) {
  .rubric summary:hover { background-color: color-mix(in srgb, var(--brand, #8f93d8) 5%, transparent); }
}
.rp { padding: 9px 15px !important; }
.rp + .rp { border-top: 1px solid rgba(16, 24, 40, .05); }
[data-theme="dark"] .rp + .rp { border-top-color: rgba(255, 255, 255, .055); }
.rp-d {
  font-size: 13px !important;
  line-height: 1.7;
  color: var(--ink2, #5b6070) !important;
}

@media (prefers-reduced-motion: reduce) {
  .dl-btn, .work-file-btn, .upload-box, .rubric summary::before { transition: none !important; }
}

/* ==========================================================================
   ㊸ 题目顶栏「视频解析」「纠错」按钮强化
   ──────────────────────────────────────────────────────────────────────────
   原状：两个按钮都是**浅灰药丸 + 品牌色小字**，几乎看不出是按钮：
     · 视频解析 = .btn.btn-soft.btn-sm → ios-skin `.btn-soft{background:var(--fill)}`
     · 纠错     = .btn.btn-ghost.btn-sm.cmt-open → 被 `.cmt-open{background:var(--fill)}` 覆盖
   两者底色都是 --fill，长得几乎一样，也没有主次。

   重设计为**语义不同的两种醒目样式**：
     · 视频解析 → 品牌渐变实底 + 白字（与「题目文件下载」同一套视觉语言，属于主动作）
     · 纠错     → 暖橙（"报告问题"的语义色），与品牌色明显区分

   ⚠️ 只限定在 `.q-num`（题目顶栏）内：`.btn-soft` 全站有 8 处、
      `.cmt-open` 有 5 处，直接改基类会波及别处。
   ⚠️ 描边宽度在基态定死 1.5px，悬停只换色 —— 避免位移（㉟ 的教训）。
   ========================================================================== */
.q-num .btn-soft,
.q-num .cmt-open {
  padding: 7px 13px !important;
  border-radius: 10px !important;
  font-size: 12.5px !important;
  font-weight: 620 !important;
  gap: 6px;
  line-height: 1.25;
  border: 1.5px solid transparent !important;
  transition:
    background-color 190ms cubic-bezier(.22, 1, .36, 1),
    border-color 190ms cubic-bezier(.22, 1, .36, 1),
    color 140ms linear,
    box-shadow 210ms cubic-bezier(.22, 1, .36, 1),
    transform 180ms cubic-bezier(.22, 1, .36, 1),
    filter 150ms linear !important;
  will-change: transform;
}

/* ── ① 视频解析：品牌渐变实底 ───────────────────────────────── */
.q-num .btn-soft {
  color: #FFFFFF !important;
  background-color: transparent !important;
  background-image: linear-gradient(135deg,
    var(--brand, #8f93d8) 0%,
    color-mix(in srgb, var(--brand, #8f93d8) 76%, #A855F7) 100%) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .26),
    0 3px 10px color-mix(in srgb, var(--brand, #8f93d8) 32%, transparent) !important;
}
.q-num .btn-soft .mi,
.q-num .btn-soft .mi svg,
.q-num .btn-soft svg {
  color: #FFFFFF !important;
  stroke: #FFFFFF;
  opacity: 1 !important;
}

/* ── ② 纠错：暖橙（报告问题的语义色）───────────────────────── */
.q-num .cmt-open {
  color: color-mix(in srgb, var(--warn, #d99a2b) 84%, #5c3d00) !important;
  background-color: color-mix(in srgb, var(--warn, #d99a2b) 14%, #fff) !important;
  background-image: none !important;
  border-color: color-mix(in srgb, var(--warn, #d99a2b) 40%, transparent) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .72) !important;
  font-weight: 620 !important;
}

/* ── 悬停（仅指针设备；触摸端 :hover 会粘住，见 v61）────────── */
@media (hover: hover), (pointer: fine) {
  .q-num .btn-soft:hover {
    filter: brightness(1.07);
    transform: translate3d(0, -1px, 0);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, .32),
      0 6px 16px color-mix(in srgb, var(--brand, #8f93d8) 46%, transparent) !important;
  }
  .q-num .cmt-open:hover {
    background-color: var(--warn, #d99a2b) !important;
    border-color: var(--warn, #d99a2b) !important;
    color: #FFFFFF !important;
    transform: translate3d(0, -1px, 0);
    box-shadow:
      inset 0 1px 0 rgba(255, 255, 255, .24),
      0 6px 16px color-mix(in srgb, var(--warn, #d99a2b) 42%, transparent) !important;
  }
}

.q-num .btn-soft:active,
.q-num .cmt-open:active {
  transform: translate3d(0, 0, 0) scale(.965) !important;
  transition-duration: 90ms !important;
}

/* ── 暗色 ──────────────────────────────────────────────────── */
[data-theme="dark"] .q-num .btn-soft {
  background-image: linear-gradient(135deg,
    color-mix(in srgb, var(--brand, #8f93d8) 88%, #fff) 0%,
    color-mix(in srgb, var(--brand, #8f93d8) 60%, #A855F7) 100%) !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .2),
    0 3px 12px rgba(0, 0, 0, .4) !important;
}
[data-theme="dark"] .q-num .cmt-open {
  color: #F0C674 !important;
  background-color: rgba(217, 154, 43, .16) !important;
  border-color: rgba(217, 154, 43, .42) !important;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .05) !important;
}
@media (hover: hover), (pointer: fine) {
  [data-theme="dark"] .q-num .cmt-open:hover {
    background-color: #D99A2B !important;
    border-color: #D99A2B !important;
    color: #1A1400 !important;
  }
}

/* 手机端顶栏更紧凑 */
@media (max-width: 576px) {
  .q-num .btn-soft,
  .q-num .cmt-open {
    padding: 6px 10px !important;
    font-size: 12px !important;
    border-radius: 9px !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  .q-num .btn-soft, .q-num .cmt-open { transition: none !important; }
}

/* ==========================================================================
   ㊹ 通知弹窗：修正定位 + 加 × 关闭 + 点击外部关闭
   ──────────────────────────────────────────────────────────────────────────
   用户："点了通知图标，通知框不会消失，没有小叉叉关闭"

   三个问题：
   ① **定位失效**：style.css 写的是 `.notif-pop{position:absolute}`，
      但 `liquid-glass.css:458`（更晚加载）把它改成了 `position: relative` ——
      computed 实测就是 relative。于是弹窗变成**文档流内块**（把 .notif-wrap
      撑到 300×148），根本不是浮层。
   ② **没有 × 关闭按钮**（模板里只有一个 head 文字）
   ③ **没有点击外部关闭**：只有 `@click.self`（点弹窗自身空白才关），
      点在页面其它地方毫无反应。

   处理：
   · CSS 强制 `position: absolute` 并精确锚定到铃铛下方
   · 模板加 `.notif-x` 按钮（app.js，已改动基线）
   · 模板加 `.notif-backdrop`（全屏隐形层，`position: fixed; inset: 0`）——
     **用背景层实现"点击外部关闭"，不需要注册 document 监听**，最稳。
   ========================================================================== */
.notif-pop {
  position: absolute !important;
  top: calc(100% + 10px) !important;
  right: 0 !important;
  left: auto !important;
  width: 320px !important;
  max-width: calc(100vw - 24px) !important;
  z-index: 320 !important;
  overflow: hidden;
  transform-origin: top right;
  animation: notifIn 180ms cubic-bezier(.22, 1, .36, 1) both !important;
}
@keyframes notifIn {
  from { opacity: 0; transform: translate3d(0, -8px, 0) scale(.97); }
  to   { opacity: 1; transform: none; }
}
/* 点击外部关闭用的隐形全屏层（在弹窗之下、页面之上）*/
.notif-backdrop {
  position: fixed;
  inset: 0;
  z-index: 310;
  background: transparent;
  cursor: default;
}
/* 弹窗容器不要因为弹窗在流内而被撑高 */
.notif-wrap { position: relative; }

/* ── 头部 + × 关闭按钮 ─────────────────────────────────────── */
.notif-pop-head {
  display: flex !important;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 12px 12px 15px !important;
  font-weight: 620 !important;
}
.notif-x {
  flex: none;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--ink3, #9aa0ad);
  font-size: 19px;
  line-height: 1;
  cursor: pointer;
  transition: background-color 150ms linear, color 150ms linear, transform 160ms cubic-bezier(.22, 1, .36, 1);
  -webkit-tap-highlight-color: transparent;
}
@media (hover: hover), (pointer: fine) {
  .notif-x:hover {
    background-color: color-mix(in srgb, var(--ink3, #9aa0ad) 16%, transparent);
    color: var(--ink, #1c1f2b);
  }
}
.notif-x:active { transform: scale(.9); }
.notif-x:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand, #8f93d8) 30%, transparent);
}

/* 手机端：弹窗贴边、限制高度 */
@media (max-width: 576px) {
  .notif-pop {
    width: calc(100vw - 24px) !important;
    right: -6px !important;
    max-height: 60vh;
  }
  .notif-list { max-height: calc(60vh - 52px) !important; }
}
@media (prefers-reduced-motion: reduce) {
  .notif-pop { animation: none !important; }
  .notif-x { transition: none !important; }
}
