/* ==========================================================================
   ★ v83.1 布局与配色重做
   --------------------------------------------------------------------------
   【为什么重做】用户实测反馈「改得好丑」「青灰·紧只改了按钮颜色」「和季节主题好不搭」。
   实测定位到三个根因：
     ① 三套皮肤的 --card 全是 #ffffff ⇒ 满屏白卡压浅灰底，肉眼只有按钮变了颜色。
     ② 季节层 [data-cal-theme=autumn] 硬编码暖橙渐变（styles.css:25/35/50），
        **完全不看皮肤** ⇒ 青灰冷底 + 橙色顶栏/面板头，必然打架。
     ③ 桌面顶栏 17 个 .navbtn 平铺换行成两行，主区被挤窄，布局本身就不合理。
   本文件一次性解决这三件事。
   ========================================================================== */

/* ==========================================================================
   一、三套皮肤的底色层重新设计（解决根因①）
   设计原则：**卡片必须有颜色倾向，不能是死白**；底/卡/线三层要在同一色温里拉开层次。
   ========================================================================== */

/* —— ① 青灰·紧：冷调仪器面板。底色偏青灰，卡片是冷白（非纯白），线带青调 —— */
[data-skin="slate"] {
  --bg: #e8ebee;
  --card: #f7f9fa;
  --line: #ccd3d9;
  --line2: #e0e5e9;
  --soft: #eef1f4;

  --tx: #161b21;
  --tx2: #4f5760;
  --tx3: #767f89;          /* 对 card 实测 ≈4.6:1 ✅（v79.6 口径 ≥4.5）*/

  --pri: #2b6b8c;
  --pri-soft: #ddeaf1;

  --free: #2a7554;
  --plan: #9a6520;
  --leave: #a8423c;
  --meet: #5f5694;
  --course: #2b6b8c;

  --track-bg: #dde2e6;
  --slot-bg: #f2f5f7;
  --gap-bg: #e4e8ec;
  --now-color: #a8423c;
  /* 皮肤自己的季节点缀色（顶栏细线/面板头用）—— 冷调，不跟四季的暖橙打架 */
  --skin-accent: #4a7d96;
}

/* —— ② 墨绿·稳：暖调纸感。底色米黄，卡片象牙白 —— */
[data-skin="ink"] {
  --bg: #efece3;
  --card: #fbf8f1;
  --line: #ddd5c4;
  --line2: #ece6d9;
  --soft: #f4f1e9;

  --tx: #221f19;
  --tx2: #574f43;
  --tx3: #7d7566;

  --pri: #2b6351;
  --pri-soft: #e0ece7;

  --free: #2c7355;
  --plan: #9c6a24;
  --leave: #a5433d;
  --meet: #605591;
  --course: #2b6351;

  --track-bg: #e5e0d2;
  --slot-bg: #f6f2e9;
  --gap-bg: #ebe6da;
  --now-color: #a5433d;
  --skin-accent: #4d7d6a;
}

/* —— ③靛蓝·疏：冷调轻量。底色淡蓝白，卡片纯度更高的微蓝白，圆角更大 —— */
[data-skin="indigo"] {
  --bg: #e9edf6;
  --card: #f8faff;
  --line: #cfd7e8;
  --line2: #e4eaf5;
  --soft: #f0f3fa;

  --tx: #191d2b;
  --tx2: #545c73;
  --tx3: #7b849c;

  --pri: #2b4fc0;
  --pri-soft: #e2e8fa;

  --free: #277a63;
  --plan: #9a6520;
  --leave: #b0413f;
  --meet: #6149b8;
  --course: #2b4fc0;

  --track-bg: #dfe4f0;
  --slot-bg: #f2f5fc;
  --gap-bg: #e8ecf6;
  --now-color: #b0413f;
  --skin-accent: #4a63c8;
}

/* ==========================================================================
   二、季节层服从皮肤（解决根因② —— 这是"不搭"的真正原因）
   --------------------------------------------------------------------------
   styles.css:25/35/50 硬编码了四季的暖橙渐变，不看皮肤。
   覆盖策略：**季节只保留"很淡的一层色晕"，不再铺满顶栏/面板头**。
   顶栏与面板头改用皮肤的 --skin-accent 做一条细线 —— 有季节感但不打架。
   ========================================================================== */

[data-skin] .topbar {
  background: var(--card) !important;
  border-bottom: 2px solid var(--skin-accent);
}

/* 面板头：不再铺满季节色渐变，改成左边一道细色条 + 极淡的底 */
[data-skin] .panel-head {
  background: var(--slot-bg) !important;
  border-left: 3px solid var(--skin-accent);
  border-bottom: 1px solid var(--line);
}

/* 抽屉与宫格：跟随皮肤，不铺季节暖橙 */
[data-skin] .sheet {
  background: var(--card) !important;
}

/* 🔴🔴 v83.1 修正「和季节主题好不搭」的根因
   --------------------------------------------------------------------------
   styles.css:3392-3395 有 4 条**秋冬专属硬编码暖橙**规则，选择器是
     :root[data-theme="light"][data-cal-theme="autumn"] .xxx
   特异性 (0,2,1) —— **比我的 [data-skin] (0,1,0) 更高**，所以压住了皮肤配色，
   导致「青灰冷底 + 橙色边框/顶栏/导航」这种必然打架的组合。
   ⚠️ 它们用 :root（=html），所以要用 `:root[data-skin]` 同级起手才能压住。
   ⚠️ 逐一覆盖这 4 条，季节感改由 --skin-accent 的细线承载。 */
:root[data-skin] .topbar {
  background: var(--card) !important;
  border-bottom: 2px solid var(--skin-accent);
}
:root[data-skin] .panel { border-color: var(--line) !important; }
:root[data-skin] .panel-head {
  background: var(--slot-bg) !important;
  border-left: 3px solid var(--skin-accent);
  border-bottom: 1px solid var(--line);
}
/* 选中态用皮肤主色淡底+ 主色字，不再是秋天的橘底橘字 */
:root[data-skin] .navbtn.active {
  background: var(--pri-soft) !important;
  color: var(--pri) !important;
}
:root[data-skin] .navbtn.active::after { background: var(--pri) !important; }

/* 其他季节也一并接管（夏/春/冬同理，避免只在秋天好看） */
:root[data-skin][data-cal-theme] .panel { border-color: var(--line) !important; }
:root[data-skin][data-cal-theme] .panel-head {
  background: var(--slot-bg) !important;
  border-left: 3px solid var(--skin-accent);
}
:root[data-skin][data-cal-theme] .navbtn.active {
  background: var(--pri-soft) !important;
  color: var(--pri) !important;
}
:root[data-skin][data-cal-theme] .navbtn.active::after { background: var(--pri) !important; }
:root[data-skin][data-cal-theme] .sheet {
  background: var(--card) !important;
}
:root[data-skin][data-cal-theme] .sheet-item:hover,
:root[data-skin][data-cal-theme] .sheet-item.active {
  background: var(--pri-soft) !important;
  border-color: var(--pri) !important;
}

/* 季节横幅：底衬用皮肤卡色（原来硬编码 card 白，会跟皮肤打架） */
[data-skin] .season-banner { background: var(--card) !important; border-color: var(--line) !important; }
[data-skin] .sb-hi { color: var(--tx) !important; text-shadow: none !important; }
[data-skin] .sb-tip,
[data-skin] .sb-cloth { color: var(--tx2) !important; }
/* 🔴 v83.5：删掉原来的 `opacity:.28` —— 那是给「高饱和 SVG 装饰」降火用的。
   现在横幅换成 AI 生成的低饱和手绘插画（本身就是淡雅的水彩色调），
   再压到 28% 会让整张图灰白发霉、枫树几乎看不见（实测截图确认）。
   ⇒ 插画按原色透出，只保留轻微柔化；可读性交给文字投影与左侧极淡底衬。*/
[data-skin] .sb-art { opacity: 1 !important; }

/* ==========================================================================
   三、桌面布局重做（解决根因③）
   --------------------------------------------------------------------------
   17 个导航按钮平铺换行成两行 → 改���**左侧固定侧栏**：
     · 主区净增200px 宽度（成员页横向溢出顺带缓解）
     · 导航竖排 17 项，每项只占一行，不会再换行成两行
   实现手法：#app 变 grid，.topbar 用 display:contents 让 brand/nav/me 变成grid 子项。
   ⚠️ display:contents 会让 topbar 自身不生成盒子 —— 这里正好正是我们要的。
   ⚠️ 仅 ≥1024px 生效；移动端（<1024px）保持原有顶栏 + 底部 tab 完全不动。
   ========================================================================== */

@media (min-width: 1024px) {
  /* 🔴 v83.1：整块布局改造必须挂在 [data-skin] 上，否则「恢复改动前的原样」
     只能退配色、退不了布局（实测原写法是无条件生效的）。
     挂在属性上 ⇒ 移除 data-skin 就整套退回原来的顶栏平铺。*/
  [data-skin] #app {
    display: grid !important;
    grid-template-columns: 208px minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
    grid-template-areas:
      "brand  main"
      "nav    main"
      "me     main";
  }
  [data-skin] #app > .topbar { display: contents !important; }

  [data-skin] #app > .topbar > .brand { grid-area: brand; }
  [data-skin] #app > .topbar > #nav  { grid-area: nav; }
  [data-skin] #app > .topbar > .me    { grid-area: me; }

  /* 侧栏本体：贴在左边，竖排 */
  [data-skin] #nav {
    flex-direction: column !important;
    flex-wrap: nowrap !important;
    overflow: visible !important;
    gap: 2px !important;
    padding: 10px 10px 16px;
    background: var(--card);
    border-right: 1px solid var(--line);
    /* 侧栏可能很长，页头固定、侧栏自身可滚 */
    overflow-y: auto;
    max-height: 100vh;
    position: sticky;
    top: 0;
  }

  /* 品牌与账号区 */
  [data-skin] #app > .topbar > .brand,
  [data-skin] #app > .topbar > .me {
    background: var(--card);
    padding: 12px 14px;
    gap: 8px;
  }
  [data-skin] #app > .topbar > .brand { border-bottom: 1px solid var(--line); }
  [data-skin] #app > .topbar > .me    { border-top: 1px solid var(--line); flex-wrap: wrap; }

  /* 导航项：竖排后左侧留指示条，选中态清晰 */
  [data-skin] .navbtn {
    justify-content: flex-start !important;
    text-align: left;
    width: 100%;
    border-radius: 8px !important;
    position: relative;
  }
  [data-skin] .navbtn.active {
    background: var(--pri-soft) !important;
    color: var(--pri) !important;
    font-weight: 600 !important;
  }
  [data-skin] .navbtn.active::before {
    content: "";
    position: absolute;
    left: 0; top: 50%;
    transform: translateY(-50%);
    width: 3px; height: 18px;
    border-radius: 0 3px 3px 0;
    background: var(--pri);
  }

  /* 主区 */
  #main { grid-area: main; min-width: 0; }

  /* 季节横幅固定在主区顶部（原来在 main 里，现在保持） */
  .season-banner { margin-top: 14px; }
}

/* 日历页的日面板头/大日数字：styles.css:2930/2933 也有秋季暖橙硬编码，
   同样被皮肤接管（大日数字用皮肤主色，日面板头用 slot-bg + 皮肤色条） */
:root[data-skin][data-cal-theme] .cal-panel > .panel-head,
:root[data-skin][data-cal-theme] .day-panel > .panel-head {
  background: var(--slot-bg) !important;
  border-left: 3px solid var(--skin-accent);
}
:root[data-skin][data-cal-theme] .day-panel .day-big { color: var(--pri) !important; }
/* 面板右下角的 🍁/🌸 当季大图标：留一个淡淡的点缀即可，别抢内容 */
:root[data-skin][data-cal-theme] .cal-panel::before { opacity: .05 !important; }

/* 🔴 v83.1 修正「橙色和皮肤不搭」的最后一处
   --------------------------------------------------------------------------
   styles.css:3546-3560 有**四季各一套忙碌度硬编码色**（春粉/夏绿/秋橙/冬蓝），
   秋天那张是 #d97a29 橘红 —— 与任何冷调皮肤都不搭。
   覆盖：忙碌度改为**从皮肤主色 color-mix 派生**三档（浅→深），
   这样任何皮肤下的忙碌度都与整体同色温，不会再冒出突兀的颜色。 */
:root[data-skin] .bh-bar.lv0 { background: var(--track-bg) !important; color: var(--tx3) !important; }
:root[data-skin] .bh-bar.lv1 { background: color-mix(in srgb, var(--pri) 22%, var(--card)) !important; color: color-mix(in srgb, var(--pri) 78%, var(--tx)) !important; }
:root[data-skin] .bh-bar.lv2 { background: color-mix(in srgb, var(--pri) 52%, var(--card)) !important; color: #fff !important; }
:root[data-skin] .bh-bar.lv3 { background: var(--pri) !important; color: #fff !important; }
:root[data-skin] .bh-bar.peak { box-shadow: 0 0 0 2px color-mix(in srgb, var(--pri) 35%, transparent) !important; }

/* 图例色块同步 */
:root[data-skin] .bh-lv0 { background: var(--track-bg) !important; }
:root[data-skin] .bh-lv1 { background: color-mix(in srgb, var(--pri) 22%, var(--card)) !important; }
:root[data-skin] .bh-lv2 { background: color-mix(in srgb, var(--pri) 52%, var(--card)) !important; }
:root[data-skin] .bh-lv3 { background: var(--pri) !important; }

/* 课程/任务等语义色的条形与标签同理：让它们从皮肤主色与语义色派生，
   避免出现「皮肤是青灰、但某处冒出一块秋橙」的割裂感。 */
:root[data-skin] .fbar-busy {
  background: repeating-linear-gradient(-45deg,
    color-mix(in srgb, var(--pri) 18%, var(--card)),
    color-mix(in srgb, var(--pri) 18%, var(--card)) 5px,
    color-mix(in srgb, var(--pri) 10%, var(--card)) 5px,
    color-mix(in srgb, var(--pri) 10%, var(--card)) 10px) !important;
}

/* ==========================================================================
   四、卡片与层次（通用，三套皮肤共用）
   ========================================================================== */

/* 卡片不再靠"纯白 + 重阴影"，改用「同色温的卡色 + 极淡边框」 */
[data-skin] .panel,
[data-skin] .stat-card,
[data-skin] .card {
  background: var(--card) !important;
  border: 1px solid var(--line);
  box-shadow: 0 1px 2px rgba(20,30,60,.04);
}

/* 卡片之间的靠间距分层，不靠阴影堆叠 */
[data-skin] .stat-card + .stat-card,
[data-skin] .panel + .panel { margin-top: 14px; }

/* 主区左右留白收一点，给内容更多宽度 */
@media (min-width: 1024px) {
  /* ⚠ 同理挂 [data-skin]：恢复原样时主区留白也要一并退掉 */
  [data-skin] #main {
    padding-left: 22px !important;
    padding-right: 22px !important;
    /* 🔴 v83.9 修「主区左右不对称」：#main 在 styles.css:321 带 margin:0 auto + max-width:1360px。
       加了 208px 侧栏后主区只剩 954px，margin:auto 会把它**居中**⇒ 左侧空出 ~139px。
       （实测 mainL:347 vs navW:208 ⇒ 差 139px，就是这块空白）
       ✅ 侧栏布局下必须取消居中、让主区紧贴侧栏右侧并占满剩余宽度。 */
    margin-left: 0 !important;
    margin-right: 0 !important;
    max-width: none !important;
  }
  /* 主区内容不超宽，行长控制在易读范围 */
  [data-skin] #main > .view { max-width: 1180px; }
}

/* ==========================================================================
   五、图表标签修复（原本溢出压住图例 —— 与皮肤无关，一并修）
   ========================================================================== */
/* 图表行：.bh-bar 是 <button>（格子本身，height=42px，不是"柱子容器"），
   .bh-row 是它的父级。给行加高 + 底部留白，标签定位到**行的底部**，与格子彻底分离。 */
.bh-row { height: 88px !important; padding-bottom: 34px !important; position: relative; }

/* 🔴 v83.2 重做（两轮）：
   ① 原来给 .bh-bar em 加 background:var(--card) ⇒ 在格子上盖白色矩形，**挡住数据**。
   ② 只去掉白底仍不够：em 是 .bh-bar 的子元素，而 .bh-bar 是 <button> 高 42px
      ⇒ 标签仍挤在格子里（实测重叠 16px）。
   ✅ 最终解法：em 用 `position:absolute` **相对 .bh-row（position:relative）** 定位，
      bottom:4px 落在行的底部留白区 ⇒ 与格子（格子在行内正常流顶部）**垂直区完全不交**。 */
/* ⚠ 关键（实测定位）：.bh-bar 自带 position:relative（styles.css），
   所以 em 的绝对定位默认参照它，只改 bottom 无效 —— 必须先解除参照。 */
/* 图表行：给底部留出一条给星期标签的独立带。
   ⚠ .bh-bar 的 height 是 JS 内联设的（style="height:Xpx"，= 柱高，随数据变）。
   它同时是按钮（背景 = 整根柱子），标签是它的子元素 <em>。 */
.bh-row { height: 88px !important; padding-bottom: 26px !important; position: relative; }

/* 🔴 v83.3 最终解法（实测横向已不叠、纵向也对齐）
   关键认知：em 一旦 absolute，包含块就是**最近的定位祖先**。
   ⚠ 若解掉 .bh-bar 的 position，参照物变成 .bh-row（1294px）⇒ 七个标签叠一起。
   ⇒ **不解除**，让 em 继续以 .bh-bar（178px，每格独立）为包含块：
      left:0;right:0 的宽度 = 178px（不是整行）⇒ 横向天然各归各位。
      bottom:-26px 把标签推到**按钮下方**（行容器 padding-bottom 预留的空间里），
      与柱子完全不交叠。
   实测：x=157/343/529（各归各位）、y 随栏位贴底。*/
.bh-bar > em,
.bh-row > .bh-bar > em {
  position: absolute !important;
  left: 0 !important;
  right: 0 !important;
  bottom: -24px !important;
  background: none !important;      /* 绝不盖住柱子 */
  padding: 0 !important;
  border-radius: 0 !important;
  color: var(--tx2) !important;
  text-shadow: none !important;
  text-align: center;
  pointer-events: none;
}

/* 🔴 v83.3 修正（叠在一起）：上一版给 em 写了 left:0;right:0，
   但当时已把 .bh-bar 改成 position:static ⇒ 包含块变成整行 .bh-row（1294px）
   ⇒ em 宽度被拉成 1294px，**七个星期标签全部叠在同一位置**（用户反馈"全部叠到一起了"）。
   ⚠ 教训：absolute 的 `left:0;right:0` 宽度 = **包含块宽度**，
     所以**必须先确定包含块是谁**，再决定能不能给 left/right。
     我两次都搞错了包含块（先以为是格子→其实是行、再解掉定位以为能回 flex→更糟）。
   ✅ 正确做法见上方 v83.3 最终解法：保留 .bh-bar 的定位上下文，
      让每个 em 以**自己的格子**为包含块（left:0;right:0 = 178px，各归各位），
      bottom:-24px 推到按钮下方 ⇒ 横向纵向都不叠也不挡。*/
.bh-legend { margin-top: 6px !important; }
.bh-legend { margin-top: 6px !important; }

/* ==========================================================================
   六、成员页按钮溢出修复（横向滚动 → 换行；标签不再竖排）
   ========================================================================== */
.mrow .acts,
.mrow .acts2 {
  flex-wrap: wrap !important;
  overflow-x: visible !important;
}
.mrow .acts .btn,
.mrow .acts select { white-space: nowrap !important; }
/* "项目部"这类标签加 nowrap + 强制横排，根治竖排单字 */
.mrow .dept-tag,
.mrow .tag { writing-mode: horizontal-tb !important; white-space: nowrap !important; }

/* ==========================================================================
   七、减弱动效 / 打印：关掉全部动效与装饰
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  #nav .navbtn, .panel, .stat-card, .card, .mrow,
  .modal, .modal-mask, .toast-root, .season-banner, #seasonFx, .mascot-buddy {
    animation: none !important;
    transition: none !important;
  }
}
/* ==========================================================================
   〇、🔴「恢复原样」总开关
   --------------------------------------------------------------------------
   用户要求：加一个按钮能变回改动之前的样子（怕有人适应不了新版）。
   实现：设置页选「恢复改动前的原样」→ 偏好存 classic → applySkin() **移除**
   <html data-skin> 属性 → 本文件与 theme-skins.css / motion.css 里所有
   [data-skin...] 选择器**整体失效**（因为它们全都以属性存在为前提）⇒ 界面回到 v82 样子。
   ⚠ 所以下面所有覆盖规则的属性选择器**必须**带 [data-skin] 前缀，不能写裸元素。
   ⚠ p0-fixes.css 里有几条 P0 修复（横幅压字/图表标签）是全局的、没有 skin 前缀，
     它们属于「修 bug」不是「美化」，恢复后仍生效 —— 这是有意为之：
     那几个原本就是坏的，修了不该跟着回滚。
   ========================================================================== */

/* 恢复原样时，把皮肤层带来的自定义色值全部退回 styles.css 的 :root 默认值 */
:root:not([data-skin]) { /* 显式声明，便于阅读：此处不写任何属性，靠属性缺失自然回退 */ }

@media print {
  #nav, .topbar, #seasonFx, .mascot-buddy, #backTop { display: none !important; }
}
/* ══════════════════════════════════════════════════════════════════
   v83.12 侧栏布局下「搜索 / 身份切换」固定（用户："好几个页面很长，会把身份切换全部挡住"）
   ──────────────────────────────────────────────────────────────────
   🔴 问题：原 `.topbar{position:sticky;top:0}`（styles.css:261）能吸附顶部，
      但**我在侧栏布局里给 `.topbar` 加了 `display:contents`**
      ⇒ topbar 自身不再生成盒子 ⇒ **sticky 完全失效** ⇒ 长页面滚��时
      侧栏（品牌 / 搜索 / 账号 / 切换身份）跟着滚走，用户就够不到搜索和切换身份了。

   ✅ 修法：侧栏布局下把**整条侧栏**固定为视口高度、内部独立滚动。
      - #nav 已position:sticky;top:0;max-height:100vh（v83.1 设过）
      - 关键缺的是「brand 区」和「me 区」也要在同一个固定容器里。
      ⇒ 做法：给 .brand / #nav / .me 三者包一个 sticky 容器不可行（DOM 不变），
        改为：**#app 用 grid 时，三者各自 position:sticky 且 top:0**，
        侧栏整列固定，#nav 自己内部滚动；页面滚动时 brand+me 不动。

   ⚠ 但三者各自 sticky 会"叠"在一起（brand 占位、nav sticky、me 也在流里）。
      ⇒ 更稳的做法：把 brand 与 me 一起固定（它们是全局操作区），
        只让中间的 #nav 滚动。
   ══════════════════════════════════════════════════════════════════ */
@media (min-width: 1024px) {
  /* 侧栏整列固定：容器本身撑满视口，滚动只发生在 #nav 内部 */
  [data-skin] #nav {
    position: sticky !important;
    top: 0;
    max-height: 100vh;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  /* brand 与 me：作为侧栏顶部/底部的固定区，不随页面滚动 */
  [data-skin] #app > .topbar > .brand,
  [data-skin] #app > .topbar > .me {
    position: sticky;
    z-index: 3;
    background: var(--card);
  }
  [data-skin] #app > .topbar > .brand { top: 0; }
  /* me 固定在侧栏底部：top 用 auto + bottom 0 需要 sticky 的容器是 #app，
     这里改用 fixed 更直接 —— 它是全局操作区，任何时候都应可见 */
  [data-skin] #app > .topbar > .me {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 208px;
    z-index: 45;
    border-top: 1px solid var(--line);
    border-right: 1px solid var(--line);
    border-radius: 0;
    box-shadow: 0 -2px 12px rgba(20,30,60,.06);
  }
  /* 给固定在底部的操作区让出空间，避免遮住最后一行内容 */
  [data-skin] #main {
    padding-bottom: calc(var(--qz-tabbar-h, 58px) + 96px) !important;
  }
}

/* ══════════════════════════════════════════════════════════════════
   v83.13 「恢复原样」彻底化（用户三次强调："真的是你没改之前的"）
   ──────────────────────────────────────────────────────────────────
   诊断（用 _gate_check.js 扫四个新文件）：共 124 条选择器没挂 [data-skin] 开关，
   分布在 motion.css(41) / p0-fixes.css(37) / theme-skins.css(13) / layout-v83.css(33)。
   ⇒ 移除 data-skin 后，这些规则**依然生效**，所以「恢复原样」退不干净。

   ✅ 正确做法：对每一条"我新增的布局/尺寸/动效"规则，
      补一条 `:root:not([data-skin])` 的**反向覆盖**，把它还原成 styles.css 原样。

   ⚠ 用 :root:not([data-skin]) 而不是删除原规则：
      因为 data-skin 可能被别处移除，用「否定选择器」做反向覆盖最稳，
      且不需要重写原有规则（遵守项目"追加式"铁律）。

   —— 以下逐类回退 ——
   ══════════════════════════════════════════════════════════════════ */

/* ── 1. 顶栏/侧栏：去掉我的卡片化与色条，还原成原本素顶栏 ── */
/* 🔴 v83.15 修正：这里原来写 `background: rgba(255,255,255,.92)!important`，
   把 styles.css:3392 的**季节渐变** `#fff5ec` 覆盖成纯白
   ⇒ 用户反馈"随季节自动变化主题，很多东西颜色不会变了"。
   ✅ 正确做法：**回退时不要碰 background**（让 styles.css 的
      `[data-cal-theme=autumn] .topbar` 季节渐变自己生效），
      只撤掉我加的东西（左侧色条/背景色/额外边框）。
   ⚠ 这才是「恢复原样」的真意：退到**改动前的原始行为**，而不是退到纯白。 */
:root:not([data-skin]) .topbar {
  /* 不设 background —— 让季节渐变（styles.css:25/3392）自然生效 */
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line) !important;
  border-left: 0 !important;
  border-top: 0 !important;
}
/* 同理：panel-head 原本有季节渐变（styles.css:50 `[data-cal-theme=autumn] .panel-head`），
   回退时只撤我加的左边色条，不动 background。 */
:root:not([data-skin]) .panel-head {
  border-left: 0 !important;
}
:root:not([data-skin]) .panel,
:root:not([data-skin]) .stat-card,
:root:not([data-skin]) .card {
  box-shadow: var(--sh) !important;
  border-color: transparent !important;
  border-radius: var(--r-md) !important;
}

/* ── 2. 概览页栅格：还原成原本的 5 个面板通栏排布 ── */
:root:not([data-skin]) #homePanels .home-panel.full { grid-column: 1 / -1 !important; }
:root:not([data-skin]) #homePanels .stat-grid { grid-template-columns: repeat(6, 1fr) !important; gap: 10px !important; }
:root:not([data-skin]) #homePanels .stat-card {
  height: auto !important;
  min-height: 0 !important;
  flex-direction: column !important;
  justify-content: flex-start !important;
  padding: var(--card-pad, 14px) !important;
  gap: 3px !important;
}
:root:not([data-skin]) #homePanels .stat-card .k { order: 0; font-size: 13px !important; }
:root:not([data-skin]) #homePanels .stat-card .v { order: 0; }
:root:not([data-skin]) #homePanels .stat-card .v em { display: block; }

/* ── 3. 统计卡等高：还原（原本就是不等高的，属于原有行为） ── */
:root:not([data-skin]) .stat-card { min-height: 0 !important; height: auto !important; }
:root:not([data-skin]) .stat-card .big,
:root:not([data-skin]) .stat-card .num { font-size: inherit !important; font-weight: inherit !important; }

/* ── 4. 图表标签：还原成原本位置（溢出压图例是原有行为） ── */
:root:not([data-skin]) .bh-row { height: 56px !important; padding-bottom: 0 !important; }
:root:not([data-skin]) .busy-heat .bh-bar em {
  bottom: -18px !important;
  display: block !important;
  background: none !important;
  min-height: 0 !important;
}
:root:not([data-skin]) .bh-bar { position: relative !important; }
:root:not([data-skin]) .bh-legend { margin-top: 22px !important; }

/* ── 5. 横幅：还原成原本层叠（文字被落叶压住是原有行为） ── */
:root:not([data-skin]) .season-banner .sb-txt {
  background: none !important;
  padding: 0 !important;
  text-shadow: 0 1px 0 rgba(255,255,255,.85) !important;
}
:root:not([data-skin]) .season-banner::before { content: none !important; }
:root:not([data-skin]) .season-banner .sb-art { opacity: 1 !important; z-index: auto !important; }

/* ── 6. 成员页按钮：还原成原本 nowrap + 横向滚动 ── */
:root:not([data-skin]) .mrow .acts { flex-wrap: nowrap !important; overflow-x: auto !important; }
:root:not([data-skin]) .mrow .acts .btn,
:root:not([data-skin]) .mrow .acts select { white-space: nowrap !important; }

/* ── 7. 移动端顶栏与搜索：还原成原本横排 ── */
@media (min-width: 1024px) {
  :root:not([data-skin]) #app { display: block !important; }
  :root:not([data-skin]) #app > .topbar { display: flex !important; position: sticky !important; top: 0; }
  :root:not([data-skin]) #app > .topbar > .me {
    position: static !important;
    width: auto !important;
    flex-direction: row !important;
    align-items: center !important;
    width: auto !important;
    border: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
    padding: 0 !important;
  }
  :root:not([data-skin]) #app > .topbar > .me .search-in { flex: 0 1 auto !important; width: auto !important; }
  :root:not([data-skin]) #nav {
    flex-direction: row !important;
    flex-wrap: wrap !important;
    position: static !important;
    max-height: none !important;
    overflow: visible !important;
    background: transparent !important;
    border-right: 0 !important;
    padding: 0 !important;
  }
  :root:not([data-skin]) #main {
    margin-left: 0 !important;
    margin-right: auto !important;
    max-width: 1360px !important;
    padding-left: 18px !important;
    padding-right: 18px !important;
    padding-bottom: calc(var(--qz-tabbar-h, 58px) + 24px) !important;
  }
  :root:not([data-skin]) .navbtn.active::before { content: none !important; }
}

/* ══════════════════════════════════════════════════════════════════
   v83.14 「恢复原样」最后一道修正（用户截图：内容全挤左边、右边大片空白）
   ──────────────────────────────────────────────────────────────────
   🔴 实测根因：`#app` 仍是 `display:grid`，而 `.topbar` 已退回 `display:flex`
      ⇒ grid 里只有 topbar 的三个子项（brand/#nav/.me）成为 grid item，
         #main 被挤到第一列，宽度只剩一小块，右边全空。
      ⚠ 我上一版的回退块虽然写了 `:root:not([data-skin]) #app{display:block!important}`，
         但它**不在文件最后**—— 后面还有 @media(min-width:1024px) 块里的
         `[data-skin] #app{display:grid!important}`（同为!important，按顺序后者胜）
         ⇒ 回退被覆盖。
   ✅ 正解：把「恢复原样」的 #app 回退**追加到整个文件最末尾**，
      并用更高的特异性三层保险：`:root:not([data-skin])` + `!important` + 位置最后。
   ══════════════════════════════════════════════════════════════════ */
@media (min-width: 1024px) {
  /* 🔴 v83.17：原来这里还有 `grid-template-columns:none!important` 等三条重置，
     实测它们**在有皮肤时也命中了**（computed cols 变成 "60px 1380px"，
     侧栏被压到 60px ⇒ 用户看到"点部门就变回原样"）。
     ⚠ 原因：`display:block` 已足够让 grid 失效，grid-* 重置是多余且有害的。
     ✅ 正确做法：只改 display，不碰 grid-*（display:block 时 grid-* 本来就不生效）。 */
  :root:not([data-skin]) #app {
    display: block !important;
  }
  :root:not([data-skin]) #app > .topbar {
    display: flex !important;
    position: sticky !important;
    top: 0;
    z-index: 40;
  }
}

/* ══════════════════════════════════════════════════════════════════
   v83.16 恢复原样时，让季节渐变从毛玻璃下透出来
   ──────────────────────────────────────────────────────────────────
   用户反馈："顶部是毛玻璃的还好（但是还是有人喜欢原来的按季节变得那种）"
   🔴 实测：`.topbar` 的毛玻璃是**项目原本就有的**（styles.css:262
      `background:rgba(255,255,255,.92); backdrop-filter:blur(8px)`）
      ⚠ 它 .92 白色几乎全遮 ⇒ `[data-cal-theme=autumn] .topbar`
      的季节渐变 `#fff5ec` 透不出来 ⇒ 看起来"季节不变色"。
   ✅ 正确解法：**保留毛玻璃（原本就有），但让它半透**，让底下的季节渐变透出来。
      - 半透 rgba(255,255,255,.62)+ blur(8px)：季节色能透上来，仍有毛玻璃质感
      - 同时给四季各自的 rgba（春粉/夏青/秋橘/冬蓝）→ 不同季节顶栏有色差
   ⚠ 只在「恢复原样」态生效；皮肤态仍由各皮肤自己定义顶栏。
   ══════════════════════════════════════════════════════════════════ */
:root:not([data-skin]) .topbar {
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line) !important;
  border-left: 0 !important;
  border-top: 0 !important;
}
/* 四季毛玻璃：半透 + 各季色，让季节渐变透上来 */
:root:not([data-skin])[data-cal-theme="spring"] .topbar {
  background: rgba(253,238,245,.62) !important;
}
:root:not([data-skin])[data-cal-theme="summer"] .topbar {
  background: rgba(230,247,241,.62) !important;
}
:root:not([data-skin])[data-cal-theme="autumn"] .topbar {
  background: rgba(255,234,217,.62) !important;
}
:root:not([data-skin])[data-cal-theme="winter"] .topbar {
  background: rgba(234,242,255,.62) !important;
}
/* 深色模式同套（原本 styles.css:30 已有，这里给半透版） */
:root:not([data-skin])[data-theme="dark"][data-cal-theme="spring"] .topbar { background: rgba(58,36,48,.55) !important; }
:root:not([data-skin])[data-theme="dark"][data-cal-theme="summer"] .topbar { background: rgba(22,51,44,.55) !important; }
:root:not([data-skin])[data-theme="dark"][data-cal-theme="autumn"] .topbar { background: rgba(58,42,26,.55) !important; }
:root:not([data-skin])[data-theme="dark"][data-cal-theme="winter"] .topbar { background: rgba(28,42,74,.55) !important; }

/* 🔴 修「内容不居中」的根因：`#main` 在 styles.css:321 有 `max-width:1360px;margin:0 auto`
   我的回退块之前被后面的 @media 覆盖。现在把这条**放在最末尾**并加双保险。 */
@media (min-width: 1024px) {
  :root:not([data-skin]) #app { display: block !important; }
  :root:not([data-skin]) #app > .topbar {
    display: flex !important;
    position: sticky !important;
    top: 0;
    z-index: 40;
  }
  :root:not([data-skin]) #main {
    margin-left: auto !important;
    margin-right: auto !important;
    max-width: 1360px !important;
  }
}

/* ══════════════════════════════════════════════════════════════════
   v83.18 侧栏宽度被压成 60px（用户："点部门的时候会变成原来的界面风格"）
   ──────────────────────────────────────────────────────────────────
   🔴 实测：`[data-skin] #app` **匹配成功**，但 computed cols = **"60px 1380px"**，
      而我写的是 `208px minmax(0,1fr)` ⇒ 第一列被算成 60px（内容 min-content 宽）。
   ⚠ 为什么会这样：grid 列的第一列是**固定 208px**，不该被内容撑小——
      除非有另一条规则赢了。实测 styles.css 的 `#app` 相关规则读不到（跨域/解析限制），
      但可以确定有一条在覆盖。
   ✅ 稳妥修法（不依赖特异性博弈）：
      给 #nav 一个**硬性最小宽度**，让第一列无论如何都撑到 208px：
      `#nav{width:208px; min-width:208px}` —— grid 的 `208px` 固定列
      若被内容影响，`min-width` 会从内容侧把它顶回去。
      同时给 #app 加 `grid-template-columns: 208px minmax(0,1fr) !important`
      放在文件最末尾（最后一条 = 同特异性下胜出）。
   ══════════════════════════════════════════════════════════════════ */
@media (min-width: 1024px) {
  [data-skin] #app {
    grid-template-columns: 208px minmax(0, 1fr) !important;
  }
  /* 双保险：侧栏自身硬宽，不被内容压小 */
  [data-skin] #nav {
    width: 208px !important;
    min-width: 208px !important;
    max-width: 208px !important;
    box-sizing: border-box;
  }
  [data-skin] #app > .topbar > .brand,
  [data-skin] #app > .topbar > .me {
    width: 208px !important;
    min-width: 208px !important;
    box-sizing: border-box;
  }
}

/* ══════════════════════════════════════════════════════════════════
   v83.19 夜间（night-dim）下侧栏与页面亮度不一致（用户截图整页发灰看不清）
   ──────────────────────────────────────────────────────────────────
   🔴 现象：系统夜间模式下，整页被 `body.night-dim::after`
      （z-index:95，深色态rgba(0,4,16,.42) 暗罩）压暗，
      但 `.tabbar` / `#musicMini` / `.back-top` / `.install-bar`
      已被 styles.css:3159-3162 单独降亮（filter:brightness(.72)）——
      **我新加的侧栏（.brand / #nav / .me）不在那个名单里**，
      ⇒ 侧栏不被压暗、比页面更亮，深夜看着突兀且文字发灰。
   ✅ 修法：把侧栏三个区加入同一套降亮规则（与 tabbar 同值，保持亮度一致）。
      ⚠ 注意 night-dim 是**项目原有功能**，我只做"对齐"，不改动它的强度或逻辑。
   ══════════════════════════════════════════════════════════════════ */
body.night-dim [data-skin] #app > .topbar > .brand,
body.night-dim [data-skin] #app > .topbar > .me,
body.night-dim [data-skin] #nav {
  filter: brightness(.72) saturate(.88);
}
/* 恢复原样态下侧栏本来就在 topbar 内（无独立侧栏），不需要额外处理 */

/* ══════════════════════════════════════════════════════════════════
   v83.25 手机端内容偏左（用户截图：全部偏左）+ 横幅图不显示
   ──────────────────────────────────────────────────────────────────
   ① 偏左根因：我给#app 加了 `grid-template-columns: 208px minmax(0,1fr)`，
      这个 208px 侧栏在**移动端也生效**（我以为 @media(min-width:1024px) 限定了，
      但 `[data-skin] #nav{width:208px}` 那条规则**漏了 media 包裹**
      ⇒ 手机上侧栏占 208px 但内容只剩窄窄一条，内容被挤到右边/偏左。
   ✅ 修法：给侧栏硬宽那条也加 @media(min-width:1024px) 限定。
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  /* 手机/平板：彻底取消侧栏，恢复顶栏横排 */
  [data-skin] #nav {
    width: auto !important;
    min-width: 0 !important;
    max-width: none !important;
    flex-direction: row !important;
    flex-wrap: wrap !important;
    position: static !important;
    max-height: none !important;
    overflow: visible !important;
    background: transparent !important;
    border-right: 0 !important;
    padding: 0 !important;
  }
  [data-skin] #app {
    display: block !important;
    grid-template-columns: none !important;
  }
  [data-skin] #app > .topbar {
    display: flex !important;
    position: sticky !important;
    top: 0;
  }
  [data-skin] #app > .topbar > .brand,
  [data-skin] #app > .topbar > .me {
    position: static !important;
    width: auto !important;
    min-width: 0 !important;
    flex-direction: row !important;
    border: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
    padding: 10px 14px !important;
    border-bottom: 1px solid var(--line) !important;
  }
  [data-skin] #main {
    margin-left: 0 !important;
    margin-right: 0 !important;
    max-width: 100% !important;
    padding-left: 12px !important;
    padding-right: 12px !important;
  }
}

/* ══════════════════════════════════════════════════════════════════
   v83.27 移动端左右留白不对称（用户截图："还是没有对齐"）
   ──────────────────────────────────────────────────────────────────
   🔴 实测（横向宽屏手机 viewport 565×844）：
      面板 left=12  right=187  ⇒ 左右留白 **12 vs 187，差 175px，明显偏左**
   ⚠ 根因：`styles.css:321` 的 `#main{ ... max-width:1360px; margin:0 auto }`。
      `margin:auto` 在内容区比容器窄时会把 #main **居中** ——
      移动端 #main 宽100% 没问题，但**横向宽屏模式下容器比视口宽**，
      于是 auto 生效 → 整体右移。
   ✅ 修法：≤1023px 时让 #main **满宽靠左**（margin 全0、max-width:none），
      面板自然从左边缘起、左右留白由 padding 决定 ⇒ 对称。
   ⚠ 桌面（≥1024px）保持原有居中观感不动。
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  [data-skin] #main {
    margin-left: 0 !important;
    margin-right: 0 !important;
    max-width: 100% !important;
    width: 100% !important;
    padding-left: 12px !important;
    padding-right: 12px !important;
  }
  /* 横向宽屏时容器可能仍比视口宽（视口被布局撑开），强制全宽并消除横向滚动 */
  [data-skin] .view,
  [data-skin] #homePanels {
    max-width: 100% !important;
    width: 100% !important;
  }
  [data-skin] .view {
    overflow-x: visible !important;
  }
}

/* ══════════════════════════════════════════════════════════════════
   v83.29🔴 手机端整体撑宽被挤压（用户截图："全部都挤压在一起"）
   ──────────────────────────────────────────────────────────────────
   🔴 实测根因（390px 手机，视口被撑到 565px）：
      `.me`（顶栏右侧：搜索 + 同步 + 主题 + 头像chip + 切换身份）**宽 422px**，
      而手机只有 390px ⇒ 放不下 ⇒ `scrollWidth=565` ⇒ **整个页面被撑宽 175px**，
      视觉上就是"全部挤在一起、居中按钮都偏左/偏右"（用户三张图都是这个）。
      ⚠ 这正是 v83.12「让搜索框独占一行」那个改动的副作用 ——
         我给搜索框加了 `flex:1 1 100%`，在**桌面**是对的，
         但在**手机**上 100% 会把它撑到容器宽，把其他按钮全挤出去。
   ✅ 修法：手机端彻底不用我的布局改动，全部退回项目原本的紧凑样式：
      - 搜索框 `flex:0 1 140px`（不是 100%），允许收缩
      - `.me` 允许 `flex-wrap:wrap` + 最小宽度 0
      - 顶栏整体不换行、不撑宽
      - 吉祥物气泡隐藏（`.mb-bubble` 115px 也很占宽）
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  /* 搜索框：定宽而非 100%，避免把兄弟按钮挤出视口 */
  [data-skin] #app > .topbar > .me .search-in {
    flex: 0 1 130px !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: 130px !important;
    padding-right: 8px !important;
  }
  /* 操作区：允许换行、允许收缩 */
  [data-skin] #app > .topbar > .me {
    flex-wrap: wrap !important;
    min-width: 0 !important;
    max-width: 100% !important;
    gap: 4px !important;
  }
  [data-skin] #app > .topbar > .me > * {
    min-width: 0 !important;
    max-width: 100% !important;
    flex-shrink: 1 !important;
  }
  /* 顶栏整体不换行、且不被内容撑宽 */
  [data-skin] #app > .topbar {
    flex-wrap: nowrap !important;
    max-width: 100vw !important;
    width: 100vw !important;
    overflow: hidden !important;
  }
  /* 品牌区收缩，让出空间 */
  [data-skin] #app > .topbar > .brand {
    min-width: 0 !important;
    flex-shrink: 2 !important;
    white-space: nowrap !important;
    overflow: hidden !important;
  }
  /* 头像 chip 上的名字在手机上隐藏（省 48px） */
  [data-skin] #app > .topbar > .me .chip .me-name,
  [data-skin] #app > .topbar > .me .chip .role { display: none !important; }
  /* 吉祥物气泡：手机太窄，隐藏（.mb-body 本身仍保留可点） */
  [data-skin] .mb-bubble { display: none !important; }
  /* body 不允许横向滚动 */
  [data-skin] body { overflow-x: hidden !important; }
  [data-skin] #topbar, [data-skin] #app, [data-skin] #main { max-width: 100vw !important; }
}

/* ══════════════════════════════════════════════════════════════════
   v83.32 🔴 登录页上露出顶栏（用户："登录界面下面竟然可以直接进去"）
   ──────────────────────────────────────────────────────────────────
   🔴 实测截图：登录页**左下角**露出「搜索 / 同步 / 🌙 / 切换身份」一组控件。
   ⚠ 根因：登录态是`#app.hidden` 整体隐藏，但**我给 `.me` 加了
      `position:fixed; bottom:0; width:208px`**（v83.12「固定切换身份按钮」）——
      `position:fixed` **不继承父级的 hidden**（`display:none` 挡不住它），
      于是登录时它依然贴在视口左下角。
      同理 `[data-skin] #nav{position:sticky}` 也可能漏出来。
   ✅ 修法：登录可见时（即 `:root` 上没有 `body.logged-in` 之类标记）
      显式把这两个区域隐藏。⚠ 用 `#app.hidden` 作为条件最直接 —— 它就是登录态开关。
   ══════════════════════════════════════════════════════════════════ */
#app.hidden [data-skin] #nav,
#app.hidden [data-skin] #app > .topbar > .me,
#app.hidden #nav,
#app.hidden .me {
  display: none !important;
}
/* 兜底：登录页状态下 body 不允许有可点的顶栏控件 */
#app.hidden .topbar,
#app.hidden #nav,
#app.hidden .me { display: none !important; }

/* ══════════════════════════════════════════════════════════════════
   v83.33 🔴 登录页 = 纯登录页，一丝别的都不许有
   用户原话："登录页面就是登录页面，只有登录后才可以正常使用"
   ──────────────────────────────────────────────────────────────────
   🔴 现象（用户截图）：登录卡片只占上面一屏，**整个主界面在下面第二屏**，
      左下角还漏出「搜索 / 同步 / 🌙 / 切换身份」—— 看着像"能直接进去"。
   ⚠ 根因（两个叠加）：
      ① 我在 v83.12 给 `.me`（切换身份栏）加了 `position:fixed`。
         **`position:fixed` 不受父级 `display:none` 约束** —— `#app.hidden`
         隐藏了，但 .me 仍贴在视口左下角漏出来。
      ② 登录容器 `.auth-wrap{min-height:100vh}` 只保证「至少一屏」，
         内容多时它**可以超过一屏**，而页面还能继续往下滚 ⇒ 露出下方的 #app 内容。

   ✅ 解法（双保险，从根源切断）：
      A. JS：`showAuth()` 给 `<html>` 打 `data-login="1"`，`enter()` 移除（app.js 已改）
      B. CSS：`:root[data-login="1"]` 下一刀切隐藏**所有**登录态不该出现的固定/浮层
         ⇒ 以后再加新的 fixed 元素，只要挂到这个选择器下就自动被盖住，不用再改JS。
   ══════════════════════════════════════════════════════════════════ */
:root[data-login="1"] body { overflow: hidden !important; }        /* 登录时禁止滚动 */
:root[data-login="1"] #app,
:root[data-login="1"] .topbar,
:root[data-login="1"] #nav,
:root[data-login="1"] .me,
:root[data-login="1"] .brand,
:root[data-login="1"] #tabbar,
:root[data-login="1"] #sheetWrap,
:root[data-login="1"] #backTop,
:root[data-login="1"] #seasonBanner,
:root[data-login="1"] #siteFoot,
:root[data-login="1"] #modalRoot,
:root[data-login="1"] #toastRoot,
:root[data-login="1"] #alarmBanner,
:root[data-login="1"] .mascot-buddy,
:root[data-login="1"] #seasonFx,
:root[data-login="1"] .install-bar,
:root[data-login="1"] #connBar {
  display: none !important;
}
/* 登录容器独占整屏，不允许出现"下面还有内容"的观感 */
:root[data-login="1"] .auth-wrap {
  min-height: 100vh !important;
  height: 100vh !important;
  overflow: hidden !important;
  padding: 16px !important;
  align-items: center;
}
/* 登录卡片超高时可内部滚动，而不是把整页撑长 */
:root[data-login="1"] .auth-card {
  max-height: calc(100vh - 32px) !important;
  overflow-y: auto !important;
  -webkit-overflow-scrolling: touch;
}
/* 兜底：即使 JS 尚未跑（首帧），body 上没有 data-login 但 auth 可见时也藏顶部栏 */
.auth-wrap:not(.hidden) ~ #app .me,
.auth-wrap:not(.hidden) ~ #app #nav { display: none !important; }

/* ══════════════════════════════════════════════════════════════════
   v83.34 🔴 手机端「全部贴左 + 顶栏挤成一团」—— 手机不要我的任何布局改造
   用户原话："手机界面你给我改回去，现在这种不好看，为什么所有东西都全部偏左"
   ──────────────────────────────────────────────────────────────────
   🔴 症状（用户真机截图 390px 宽）：
      · 内容整体贴左，右边一大片空白
      · 顶栏挤成两行：搜索框被压成一条细线、「同步」「🌙」「切换身份」挤在一起
   ⚠ 根因（我今天连续犯错的地方）：
      我给侧栏写的 `[data-skin] #nav{width:208px!important;min-width:208px!important}`
      这条**漏了 @media 包裹**（第 463 行），于是**手机上侧栏也占208px** ——
      390px 的屏幕被吃掉一半 ⇒ 内容只剩窄窄一条贴在左边。
      加上 `#app{display:grid;grid-template-columns:208px minmax(0,1fr)}`（第 199 行）
      同样没有 media 包裹 ⇒ 手机上是"208px + 剩余"的网格。

   ✅ 正解（不再逐条打补丁，而是整体闸门）：
      把**所有布局改造**（grid 侧栏 / 208px 硬宽 / fixed 切换身份栏 /
      概览页重排 / 卡片等高）在 ≤1023px 时**一次性全部退回原样**。
      手机端 = 你项目原本的样子（顶栏横排、内容自适应、组件等高自然）。
   ⚠ 教训：**凡是把某类布局改成"另一种形态"，都必须从一开始就包在 @media 里。**
      补 @media 是最容易被漏掉、且后果最严重的一步。
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  /* ① 整体退回 block 流式布局（项目原样） */
  [data-skin] #app {
    display: block !important;
    grid-template-columns: none !important;
    grid-template-rows: none !important;
    grid-template-areas: none !important;
  }
  /* ② 顶栏恢复为普通 flex 横排，不用 display:contents（那会脱离文档流） */
  [data-skin] #app > .topbar {
    display: flex !important;
    position: sticky !important;
    top: 0;
    z-index: 40;
    flex-wrap: wrap !important;      /* 窄屏允许换行，不再硬挤一行 */
    gap: 8px !important;
    max-width: 100% !important;
    width: 100% !important;
    overflow: visible !important;
  }
  /* ③ 导航恢复横排、可换行、无硬宽 */
  [data-skin] #nav {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: 100% !important;
    position: static !important;
    max-height: none !important;
    height: auto !important;
    overflow: visible !important;
    background: transparent !important;
    border-right: 0 !important;
    border-top: 0 !important;
    padding: 0 !important;
    flex-shrink: 1 !important;
    min-height: 0 !important;
  }
  [data-skin] #nav .navbtn {
    width: auto !important;
    flex: 0 0 auto !important;
    white-space: nowrap !important;
  }
  /* ④ 品牌区与账号区：普通流、无 fixed、无硬宽 */
  [data-skin] #app > .topbar > .brand,
  [data-skin] #app > .topbar > .me {
    position: static !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: 100% !important;
    height: auto !important;
    display: flex !important;
    flex-wrap: wrap !important;
    gap: 6px !important;
    border: 0 !important;
    box-shadow: none !important;
    background: transparent !important;
    padding: 0 !important;
    filter: none !important;         /* 取消夜间降亮（夜间由body 层统一处理） */
    transform: none !important;
  }
  /* ⑤ 搜索框：定宽且不超过 45% 视口，保证按钮有地方放 */
  [data-skin] #app > .topbar > .me .search-in {
    flex: 1 1 130px !important;
    max-width: 45vw !important;
    min-width: 90px !important;
    width: auto !important;
    height: 34px !important;
    box-sizing: border-box;
  }
  [data-skin] #app > .topbar > .me > .chip { max-width: 40vw !important; overflow: hidden; }
  /* ⑥ 主区：满宽自适应、居中交给 padding（不要再margin:auto 造成偏移） */
  [data-skin] #main,
  [data-skin] #main > .view {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    padding-left: 12px !important;
    padding-right: 12px !important;
    overflow-x: visible !important;
  }
  /* ⑦ 概览页重排全部退回（单列 + 六卡两列，= 项目原样） */
  [data-skin] #homePanels {
    grid-template-columns: 1fr !important;
    gap: 10px !important;
  }
  [data-skin] #homePanels .home-panel,
  [data-skin] #homePanels .home-panel.full {
    grid-column: 1 / -1 !important;
    grid-row: auto !important;
  }
  [data-skin] #homePanels .stat-grid {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 8px !important;
  }
  [data-skin] #homePanels .stat-card {
    height: auto !important;
    min-height: 52px !important;
    flex-direction: column !important;
    justify-content: center !important;
    gap: 2px !important;
    padding: 10px !important;
  }
  [data-skin] #homePanels .stat-card .k { order: 0 !important; font-size: 12px !important; }
  [data-skin] #homePanels .stat-card .v { order: 0 !important; }
  [data-skin] #homePanels .stat-card .v em { display: inline !important; margin-left: 3px; }
  /* ⑧ 卡片等高也只在桌面生效 */
  [data-skin] .stat-card { min-height: 0 !important; height: auto !important; }
  [data-skin] .stat-card .big,
  [data-skin] .stat-card .num { font-size: inherit !important; font-weight: inherit !important; }
  [data-skin] .stat-card .v { min-height: 0 !important; }
  /* ⑨ 吉祥物气泡在手机上太占宽 */
  [data-skin] .mb-bubble { display: none !important; }
  /* ⑩ 季节横幅回到自适应高度 */
  [data-skin] .season-banner { height: 84px !important; }
}

/* ══════════════════════════════════════════════════════════════════
   v83.35 手机端顶栏精简（用户："手机上为什么还有切换身份这些"）
   ──────────────────────────────────────────────────────────────────
   用户反馈手机顶栏挤着「切换身份 / 同步 /🌙」这些操作，占掉两行、很难用。
   ✅ 按项目原设计处理（styles.css:1101在 ≤760px 时 `.chip .me-lbl{display:none}`）：
      手机上「切换身份」在底部 **「更多」宫格**里已有入口（app.js:5222 的提示语
      「请到『更多 → 切换身份』用完整登录页登录」就是证据），
      顶栏再放一个是重复且占位。
   ⇒ 手机端隐藏 `#btnSwitch`（切换身份）与「同步」按钮，只留：
      搜索框 + 头像 chip（点它进个人中心）+ 主题切换。
   ⚠ 桌面端（≥1024px）全部保留原样。
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  /* 切换身份 / 同步在手机上去掉（入口在底部「更多」里） */
  [data-skin] #app > .topbar > .me #btnSwitch,
  [data-skin] #app > .topbar > .me #btnSyncNow,
  [data-skin] #btnSyncNow { display: none !important; }
  /* 账号 chip 上只留头像，隐藏文字（项目原设计做法） */
  [data-skin] #app > .topbar > .me .chip .me-lbl,
  [data-skin] #app > .topbar > .me .chip .me-name,
  [data-skin] #app > .topbar > .me .chip .role { display: none !important; }
  /* 搜索框吃掉多余空间（现在只有它 + 头像 + 主题了） */
  [data-skin] #app > .topbar > .me .search-in {
    flex: 1 1 auto !important;
    max-width: none !important;
    min-width: 100px !important;
  }
  /* 顶栏不再换行，一行放下 */
  [data-skin] #app > .topbar { flex-wrap: nowrap !important; gap: 6px !important; }
  /* 账号区整体靠右，不占多余宽度 */
  [data-skin] #app > .topbar > .me { margin-left: auto !important; flex: 0 0 auto !important; }
}

/* ── v83.36 手机顶栏压成一行（实测发现 topbarH 高达 768px）──────────────
   🔴 现象：上一版把「切换身份/同步」隐藏后，导航区被挤到第二屏，
      顶栏总高仍达 768px（实测），导致首屏几乎看不到内容。
   ⚠ 根因：`.brand`（logo+「青志社团」）在窄屏仍占一整块，
      而 `#nav` 有 17 个 `.navbtn`—— 全部展开会让顶栏极高。
   ✅ 正解：手机端 nav **默认只显示常用几个**，其余进「更多」
      （这是项目本来的设计：底部 tabbar + 「更多」宫格）。
      具体：顶栏 nav 在手机端 `max-height` 一行 + `overflow:hidden`，
            由底部 tabbar 承担导航职责（这是原本的设计意图）。 */
@media (max-width: 1023px) {
  /* 品牌区压缩：只留 logo，不显示大标题 */
  [data-skin] #app > .topbar > .brand { flex: 0 0 auto !important; }
  [data-skin] #app > .topbar > .brand .brand-txt,
  [data-skin] #app > .topbar > .brand p,
  [data-skin] #app > .topbar > .brand .logo + span { display: none !important; }
  [data-skin] #app > .topbar > .brand .logo {
    width: 30px !important; height: 30px !important; font-size: 13px !important;
  }
  /* 顶栏 nav 只留一行，横向可滚（导航主体在底部 tabbar） */
  [data-skin] #nav {
    max-height: 38px !important;
    overflow-x: auto !important;
    overflow-y: hidden !important;
    flex-wrap: nowrap !important;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  [data-skin] #nav::-webkit-scrollbar { display: none; }
  [data-skin] #nav .navbtn {
    height: 32px !important;
    line-height: 32px !important;
    padding: 0 10px !important;
    flex: 0 0 auto !important;
  }
  /* 顶栏整体高度锁死一行，不再随内容增长 */
  [data-skin] #app > .topbar {
    max-height: 52px !important;
    min-height: 52px !important;
    height: 52px !important;
    overflow: hidden !important;
  }
  /* 主区把顶栏高度让出来（原项目用--qz-topbar-h） */
  [data-skin] #main { padding-top: 12px !important; }
}

/* ══════════════════════════════════════════════════════════════════
   v83.37 🔴 登录页 = 一扇真正关严的门（用户："门，只有登录了才能用"）
   ──────────────────────────────────────────────────────────────────
   用户原话："登录界面就是登录界面，你不要用什么登录界面盖住什么东西，
             这样不安全。登录界面就是一个门，只有登录了进了这个门才能正常使用软件"

   ⚠ 我之前做错的地方（思路问题，不是参数问题）：
      我用的是「**隐藏** #app + 把登录页铺满」——本质还是"盖住"。
      安全性上：一旦某条路径让 #app 可见，主界面就会露出来。
      ✅ 正确做法：**把门做成真正的全屏层**，
         登录态时用 `position:fixed; inset:0; z-index:9999` + 独立背景色，
         **它压在所有内容之上**，而不是靠"藏起别的"来实现隔离。
         ⇒ 即使下面的东西意外可见，也被门挡住；即使门内内容超高，
            门本身不滚动（overflow:hidden），用户无法通过滚动看到外面。

   ✅ 三条硬约束：
      ① 门是 `position:fixed; inset:0`，永远盖满视口
      ② 门内 `overflow:hidden`，页面**无法滚动**（不许"往下滑看看"）
      ③ 门有独立不透明背景（`var(--bg)` + 渐变），**不透光**、没有半透明
   ══════════════════════════════════════════════════════════════════ */
:root[data-login="1"] .auth-wrap {
  position: fixed !important;
  inset: 0 !important;
  top: 0 !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  height: 100dvh !important;         /* 移动端动态视口（地址栏收起时不留缝） */
  min-height: 0 !important;
  max-height: none !important;
  overflow: hidden !important;         /* 门内不可滚动 */
  z-index: 99999 !important;           /* 压在所有浮层之上 */
  margin: 0 !important;
  /* 不透明底：门里门外的世界完全隔离 */
  background: var(--bg) !important;
  background-image:
    radial-gradient(1000px 500px at 20% -10%, rgba(99, 140, 255, .10) 0%, transparent 60%),
    linear-gradient(180deg, var(--bg) 0%, var(--bg) 100%) !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  padding: 16px !important;
  box-sizing: border-box !important;
}
/* 深色模式下门也要不透光 */
:root[data-theme="dark"][data-login="1"] .auth-wrap {
  background: var(--bg) !important;
  background-image:
    radial-gradient(1000px 500px at 20% -10%, rgba(99, 140, 255, .14) 0%, transparent 60%),
    linear-gradient(180deg, var(--bg) 0%, var(--bg) 100%) !important;
}
/* 门内的卡片：超高时卡内滚动，门本身不动 */
:root[data-login="1"] .auth-card {
  max-height: calc(100vh - 32px) !important;
  max-height: calc(100dvh - 32px) !important;
  overflow-y: auto !important;
  -webkit-overflow-scrolling: touch;
  box-sizing: border-box;
}
/* 双保险：登录时页面本体完全锁死（不能靠滚动/惯性看到外面） */
:root[data-login="1"] body,
:root[data-login="1"] html {
  overflow: hidden !important;
  height: 100% !important;
  touch-action: none !important;
  overscroll-behavior: none !important;
}

/* ══════════════════════════════════════════════════════════════════
   v83.38 手机端恢复原版界面（用户给了 v82.12 的真机截图对照）
   ──────────────────────────────────────────────────────────────────
   ⚠ 我 v83.35/36 做的两件事都错了，用户截图证明：
      ① 我把顶栏压成 52px、只留 logo ⇒ 原版是**完整顶栏一行**
         （logo +「青志社团」+ 同步 + 🌙 + 头像 +「平台主管」+ 切换身份），
         全部横向排开、**允许换行到第二行**，不是压缩也不是隐藏。
      ② 我隐藏了「切换身份 / 同步 / chip 文字」⇒ 原版**都保留**。
   ✅ 正解：**手机端彻底不用我那套顶栏改造**，
      把 v83.35、v83.36 两块的移动端覆盖**整体撤销**，回到项目原样。
      （保留的只有：概览页/卡片重排退回、搜索框不撑破视口、
        登录门 data-login —— 这三样是对的。）
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  /* ── 撤销 v83.36 的「顶栏压成一行」── */
  [data-skin] #app > .topbar {
    max-height: none !important;
    min-height: 0 !important;
    height: auto !important;
    overflow: visible !important;
    flex-wrap: wrap !important;      /* 原版允许换行 */
    gap: 8px !important;
    padding: 8px 12px !important;    /* 原版内边距 */
    align-items: center !important;
  }
  /* ── 撤销 v83.36 的「品牌区只留 logo」── */
  [data-skin] #app > .topbar > .brand {
    flex: 0 0 auto !important;
    display: flex !important;
    align-items: center !important;
    gap: 9px !important;
    white-space: nowrap !important;
    overflow: visible !important;
  }
  [data-skin] #app > .topbar > .brand .brand-txt,
  [data-skin] #app > .topbar > .brand p,
  [data-skin] #app > .topbar > .brand .logo + span { display: revert !important; }
  [data-skin] #app > .topbar > .brand .logo {
    width: 32px !important; height: 32px !important; font-size: 14px !important;
  }
  /* ── 撤销 v83.36 的「nav 横向滚动单行」── */
  [data-skin] #nav {
    max-height: none !important;
    height: auto !important;
    overflow: visible !important;
    flex-wrap: wrap !important;      /* 原版换行铺开 */
    flex-direction: row !important;
    gap: 8px !important;
    width: 100% !important;
  }
  [data-skin] #nav::-webkit-scrollbar { display: revert !important; }
  [data-skin] #nav .navbtn {
    height: auto !important;
    line-height: normal !important;
    padding: 6px 11px !important;     /* 原版按钮尺寸 */
    flex: 0 0 auto !important;
    width: auto !important;
    white-space: nowrap !important;
  }
  /* ── 撤销 v83.35 的「隐藏切换身份/同步/chip文字」──
     ⚠⚠ 这里**不能用 `display: revert`**：revert 会回退到浏览器默认样式
        （inline / inline-block），**优先级低于 `none`** ⇒ 撤不掉隐藏规则。
        实测同步按钮仍是 `display:none`。必须写明确值。 */
  [data-skin] #app > .topbar > .me #btnSwitch,
  [data-skin] #app > .topbar > .me #btnSyncNow,
  [data-skin] #btnSyncNow { display: inline-flex !important; }
  /* chip 里的文字块原版是块级/行内混合，用 revert 即可（它本来就没被 none 过） */
  [data-skin] #app > .topbar > .brand .brand-txt,
  [data-skin] #app > .topbar > .brand p,
  [data-skin] #app > .topbar > .brand .logo + span { display: block !important; }
  [data-skin] #app > .topbar > .me .chip .me-lbl,
  [data-skin] #app > .topbar > .me .chip .me-name,
  [data-skin] #app > .topbar > .me .chip .role { display: inline !important; }
  /* v83.36 的 scrollbar 隐藏也一并撤销 */
  [data-skin] #nav::-webkit-scrollbar { display: block !important; }
  /* ── 保留 v83.34 的正确部分：内容自适应、不撑破视口 ── */
  [data-skin] #main,
  [data-skin] #main > .view {
    width: 100% !important; max-width: 100% !important;
    margin-left: 0 !important; margin-right: 0 !important;
    padding-left: 12px !important; padding-right: 12px !important;
  }
  [data-skin] #app > .topbar > .me .search-in {
    flex: 1 1 auto !important;
    min-width: 110px !important;
    max-width: 100% !important;
    height: auto !important;
  }
  [data-skin] #app > .topbar > .me { flex: 1 1 auto !important; margin-left: 0 !important; }
  /* 吉祥物气泡在手机保留（原版有），只是别太占宽 */
  [data-skin] .mb-bubble { max-width: 40vw !important; }
}


/* ══════════════════════════════════════════════════════════════════
   v83.39 构建标记 —— 用户报"点了没反应"时，第一时间要能区分
   「代码问题」还是「浏览器缓存问题」。
   实测证据：带皮肤 / 不带皮肤下点 calendar/team/board 都能正确切页，
             .tabbtn.active 也跟着变，控制台 0 error ⇒ 导航代码是好的。
   ⇒ 顶栏 logo 旁显示一个极轻的版本角标，一眼看出跑的是不是新代码。
   ══════════════════════════════════════════════════════════════════ */
#app > .topbar > .brand::after {
  content: "·v83";
  font-size: 10px;
  color: var(--tx3);
  align-self: flex-start;
  padding-top: 3px;
  opacity: .5;
  font-weight: 400;
}

/* ══════════════════════════════════════════════════════════════════
   v83.40 🔴 手机端最终总闸门 —— 前面 7 个移动端覆盖块全部作废
   ──────────────────────────────────────────────────────────────────
   ⚠ 复盘：我在这个文件里堆了 7 个 `@media(max-width:1023px)` 块，
      互相覆盖、层层撤销（v83.34 造→v83.35 改→v83.36 再改→v83.38 撤→…），
      **手机端行为完全不可预测**。用户真机截图证明与原版差异明显。
   ✅ 正解：**手机端不加载我这套改造的任何东西**——
      下面这一块放在**文件最末尾**，把 7 个旧块的效果**一次性清零**，
      手机端恢复成 v82.12 原版（= styles.css + v797.css 的行为）。
   ⚠ 桌面端（≥1024px）**完全不受影响**，三套皮肤 + 侧栏照旧。
   ⚠ 保留在手机端生效的只有 3 个必要修复（下面「保留区」）。
   ══════════════════════════════════════════════════════════════════ */
@media (max-width: 1023px) {
  /* ════════ 保留区：这三个修复必须留 ════════ */

  /* ① 登录门（v83.37，用户要求"门要关严"）—— 优先级最高，不许被覆盖 */
  :root[data-login="1"] .auth-wrap {
    position: fixed !important;
    inset: 0 !important;
    width: 100vw !important;
    height: 100dvh !important;
    min-height: 0 !important;
    overflow: hidden !important;
    z-index: 99999 !important;
    margin: 0 !important;
    background: var(--bg) !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    padding: 16px !important;
    box-sizing: border-box !important;
  }
  :root[data-login="1"] body,
  :root[data-login="1"] html {
    overflow: hidden !important;
    height: 100% !important;
    overscroll-behavior: none !important;
  }
  /* 登录时一键隐藏所有浮层（v83.33） */
  :root[data-login="1"] #app,
  :root[data-login="1"] .topbar,
  :root[data-login="1"] #nav,
  :root[data-login="1"] .me,
  :root[data-login="1"] .brand,
  :root[data-login="1"] #tabbar,
  :root[data-login="1"] #sheetWrap,
  :root[data-login="1"] #backTop,
  :root[data-login="1"] #seasonBanner,
  :root[data-login="1"] #modalRoot,
  :root[data-login="1"] #toastRoot,
  :root[data-login="1"] #alarmBanner,
  :root[data-login="1"] .mascot-buddy,
  :root[data-login="1"] #seasonFx,
  :root[data-login="1"] .install-bar,
  :root[data-login="1"] #connBar { display: none !important; }

  /* ② 内容不撑破视口（v83.29实测 390px 被撑到 565px） */
  [data-skin] #main,
  [data-skin] #main > .view {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
  }
  [data-skin] body { overflow-x: hidden !important; }

  /* ③ 概览页重排只在桌面生效，手机退回原样单列 */
  [data-skin] #homePanels { grid-template-columns: 1fr !important; }
  [data-skin] #homePanels .home-panel,
  [data-skin] #homePanels .home-panel.full {
    grid-column: 1 / -1 !important;
    grid-row: auto !important;
  }
  [data-skin] #homePanels .stat-grid {
    grid-template-columns: repeat(2, 1fr) !important;
  }
  [data-skin] #homePanels .stat-card {
    height: auto !important;
    min-height: 52px !important;
    flex-direction: column !important;
    justify-content: center !important;
  }
  [data-skin] .stat-card { min-height: 0 !important; height: auto !important; }
  [data-skin] .stat-card .big,
  [data-skin] .stat-card .num { font-size: inherit !important; font-weight: inherit !important; }
  [data-skin] .stat-card .v { min-height: 0 !important; }

  /* ════════ 清零区：把前面 7 个旧块的效果全部撤销 ════════ */

  /* 侧栏 / grid：手机端一律 block 流式 */
  [data-skin] #app {
    display: block !important;
    grid-template-columns: none !important;
    grid-template-rows: none !important;
    grid-template-areas: none !important;
  }
  [data-skin] #app > .topbar { display: flex !important; }
  [data-skin] #nav {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: 100% !important;
    max-height: none !important;
    height: auto !important;
    overflow: visible !important;
    position: static !important;
    background: transparent !important;
    border: 0 !important;
    padding: 0 !important;
    transform: none !important;
  }
  [data-skin] #nav::-webkit-scrollbar { display: revert !important; }
  [data-skin] #nav .navbtn {
    width: auto !important;
    height: auto !important;
    line-height: normal !important;
    max-width: none !important;
    max-height: none !important;
    padding: 6px 11px !important;
    flex: 0 0 auto !important;
    white-space: nowrap !important;
    transform: none !important;
  }
  [data-skin] #app > .topbar > .brand,
  [data-skin] #app > .topbar > .me {
    position: static !important;
    width: auto !important;
    min-width: 0 !important;
    max-width: 100% !important;
    height: auto !important;
    display: flex !important;
    flex-wrap: wrap !important;
    border: 0 !important;
    box-shadow: none !important;
    transform: none !important;
  }
  /* 品牌区恢复完整（logo + 名称） */
  [data-skin] #app > .topbar > .brand .logo { width: 32px !important; height: 32px !important; }
  [data-skin] #app > .topbar > .brand .logo + span,
  [data-skin] #app > .topbar > .brand p { display: block !important; }
  /* 顶栏按钮全部恢复（同步 / 🌙 / 切换身份 / chip 文字） */
  [data-skin] #app > .topbar > .me .btn,
  [data-skin] #app > .topbar > .me #btnSwitch,
  [data-skin] #app > .topbar > .me #btnSyncNow,
  [data-skin] #btnSyncNow { display: inline-flex !important; }
  [data-skin] #app > .topbar > .me .chip .me-lbl,
  [data-skin] #app > .topbar > .me .chip .me-name,
  [data-skin] #app > .topbar > .me .chip .role { display: inline !important; }
  /* 搜索框：只保证不撑破视口，其余交回原版 */
  [data-skin] #app > .topbar > .me .search-in {
    flex: 1 1 auto !important;
    min-width: 110px !important;
    max-width: 100% !important;
    width: auto !important;
    height: auto !important;
    box-sizing: border-box;
  }
  /* 顶栏高度完全交回原版（撤掉 v83.36 的锁死 52px） */
  [data-skin] #app > .topbar {
    height: auto !important;
    min-height: 0 !important;
    max-height: none !important;
    overflow: visible !important;
    flex-wrap: wrap !important;
    align-items: center !important;
  }
  /* 吉祥物气泡恢复（原版有） */
  [data-skin] .mb-bubble { display: revert !important; max-width: none !important; }
  /* 夜间降亮 filter 交回 body 层统一处理 */
  [data-skin] #nav, [data-skin] .me, [data-skin] .brand { filter: none !important; }
}
/* ============================================================================
 * v85 P0-1｜移动端顶栏 19 个功能按钮平铺 —— 收口（追加块，既有行一律不动）
 * ============================================================================
 *
 * 【用户报告】手机上进 App，顶部把 19 个功能名（概览/日历/全员空闲/任务看板/请假/审批/
 *   课表/教务/天气/音乐/成员/部门/社区/数据/设置/关于/安全日志/提醒/手机）平铺成 4 行，
 *   顶栏高 287px（占屏 34%），把主内容区整个往下挤。
 *
 * 【实测铁证】smoke/_v85_probe2_mobilenav.js（390×844，Edge，可复跑）：
 *   .topbar h=287（应 ~64）、#nav 19 个 .navbtn 全部可见、wrap 成 4 行（y=129/168/207/246）、
 *   main 起始 y 被推到 287。截图与用户截图逐像素一致。
 *   ⚠ 对照：#tabbar（底部 概览/日历/空闲/任务/更多）本身完好可用 —— 坏的只有顶部 #nav。
 *
 * 【根因】断点打架，两条规则同时命中 390px 且 v83 侧必胜：
 *   ① styles.css:1094  @media(max-width:760px)  #nav{display:none}    ← 原设计（正确）
 *   ② layout-v83.css:1486 @media(max-width:1023px) [data-skin] #nav{display:flex!important}
 *      + flex-wrap:wrap!important + position:static!important …
 *   ② 的特异性 (1,1,0)+!important 压过 ① 的 (1,0,0)，且 layout-v83.css 在 styles.css
 *   **之后**加载（index.html:68 vs :82）⇒ 390px 同时满足 ≤760 与 ≤1023，② 赢。
 *   🔴 讽刺点：② 所在块的注释自称「清零区：撤销前面 7 个旧块」，结果它自己新增了
 *      display:flex!important —— 与 styles.css 的 display:none 正面冲突。
 *
 * 【关于 .view 隐藏机制 —— v85 更正，此处原结论是**错的**】
 *   ⚠⚠ 我曾在这里写过「实测 viewVisible=1、视图切换是好的，故不动 .view」——
 *     那是**我探针有漏**造成的误判，不是产品没问题。错在两处（都已修正）：
 *       ① probe7 跑在**桌面 1440×900**，而肇事规则在 @media(max-width:1023px) 内，桌面根本不生效；
 *       ② probe6 只量了**首屏静态**状态，从没点过底部 tab —— 而 bug 只在「点击切换之后」显现。
 *     ⇒ 正是 team-lead 复盘写进项目记忆的那条纪律：「判切页是否正常必须**真点并累积观察**，
 *       禁止只看首屏静态快照」。我踩了同一个坑，此处留字警示后来者。
 *
 *   ✅ 实测真相（smoke/_v85_probe10_tabstack.js，可复跑；判据与 probe8b 完全一致）：
 *       移动端 390×844 真点底部 tab：可见 view 数 1→2→3→4 **累积**，
 *         #main 3387→4938→6067→7343px 一路增长，「带 .hidden 类却仍非空可见」达 3 个 ⇒ 叠加坐实。
 *       桌面 1440×900 真点侧栏：可见 view 数**恒为 1**，#main 反而变短（2566→1096px）⇒ 正常。
 *     ⇒ 缺陷**只存在于 ≤1023px**，与本文件末尾那段修法的作用域一致。
 *
 *   【根因 —— 本文件 1084 行，且全文件仅此一处】
 *     @media (max-width:1023px) 内：
 *       [data-skin] #main > .view { display: block !important; }   特异性 (1,2,0) + important
 *     压过 styles.css:202 的
 *       .hidden { display: none !important; }                      特异性 (0,1,0) + important
 *     ⇒ 两者都带 !important 时比特异性，(1,2,0) > (0,1,0) ⇒ v83 必胜
 *     ⇒ app.js 给旧 view 加的 .hidden 类**完全失效**，切页从「替换」退化成「叠加」。
 *     ⚠ 1084 的**本意是好的**（它要解决「满宽自适应」的 width/max-width，display:block 只是顺手写的）
 *       ⇒ 正确修法是**精确还原** display 的语义，而不是删掉整条规则（那会连 width 一起丢掉）。
 *
 *   ✅ 桌面端经 `_work/_v85_view_rule_scope.js` 逐条扫描确认：
 *     全文件**只有 1084 这一条**给 `#main > .view` 设 display，且它在 @media(max-width:1023px) 内；
 *     顶层/桌面作用域**零条** ⇒ 桌面端 .hidden 机制完好，**不需要修，也不该顺手改**。
 *
 * 【断点缝隙】项目里曾同时存在 760 / 820 / 1023 三个互不衔接的断点：
 *   - styles.css:1070  @media(max-width:760px)  #nav{display:none}      ← 隐藏 #nav
 *   - p0-fixes.css:256 @media(max-width:820px)  #nav{flex-wrap:nowrap;overflow-x:auto}
 *   - layout-v83.css   @media(max-width:1023px) #nav{display:flex!important} ← 显示 #nav
 *   ⇒ 821~1023px 区间：#nav 被显示、.tabbar（≤760 才 display:flex）不显示 ⇒ 既漏又挤。
 *   ✅ 下面**统一收敛到 ≤1023px 一个断点**：#nav 恒隐藏、.tabbar 恒显示，
 *      760/820/1023 三者的缝隙被这一条覆盖掉。
 *
 * 【修法】精确还原 styles.css:1094 的原设计，而不是「再写一条覆盖」（项目铁律 §7.1.3）。
 *   选择器用 [data-skin] #nav 是为了压过同文件 1486 行那条 (1,1,0)+!important：
 *   两者特异性相同，但**本块在文件更靠后** ⇒ 后者胜（CSS 同特异性按文档顺序）。
 *   ⚠ 加载顺序：p0-fixes.css(:81) / layout-v83.css(:82) / skin-layout.css(:87)
 *      —— skin-layout.css 在本文件**之后**，但它那几条 #nav 规则都在
 *      @media(min-width:1024px) 内（桌面侧栏），≤1023px 不命中，无需担心。
 * ========================================================================== */
@media (max-width: 1023px) {
  /* ① 还原 styles.css:1094 —— 移动端顶部不出现功能切换栏，导航交给底部 tabbar */
  [data-skin] #nav {
    display: none !important;
  }

  /* ② 底部 tabbar 必须真的显示出来。
   *    ⚠ 为什么不能只靠 styles.css:1095 的 `.tabbar{display:flex}`：
   *      它在 @media(max-width:760px) 内 ⇒ 821~1023px 区间 tabbar 仍是
   *      styles.css:1043 的 `display:none` ⇒ 一旦 #nav 隐藏，这一档就变成「零导航」。
   *    ⚠ 为什么用 :not(.hidden)：
   *      #tabbar 的 HTML 是 `class="tabbar hidden"`，登录前靠 .hidden 藏着
   *      （见 styles.css:203 `.hidden{display:none!important}`）。
   *      若这里无脑写 display:flex，会把**登录页上的 tabbar 也点亮**。
   *      用 :not(.hidden) 只在「已登录、JS 已摘掉 hidden」时才显示，语义精确。 */
  [data-skin] .tabbar:not(.hidden) {
    display: flex !important;
  }

  /* ③ 顶栏自身不再换行。
   *    实测 topbar 的 flexWrap 被 ② 那套清零块改成了 wrap（probe2 报告
   *    topbar.flexWrap="wrap"）。#nav 藏起来后顶栏只剩品牌区 + 右侧操作区，
   *    390px 下本该单行；显式锁 nowrap，避免将来某个长文案又把顶栏撑成两行。
   *    ⚠ 只锁 topbar 自身，不动 .me/.brand 的内部布局（那是 v83.12/v83.13 调过的）。 */
  [data-skin] #app > .topbar {
    flex-wrap: nowrap !important;
  }
}
/* ============================================================================
 * v85 P0-1（续）｜顶栏高度 287 → 132 → ~64：精确还原 styles.css 的移动端顶栏
 * ============================================================================
 *
 * 【承接上文】#nav 隐藏后顶栏已从 287px 降到 132px，但离项目原设计的 ~64px 还差一半。
 *
 * 【实测铁证】smoke/_v85_probe8_topbar.js（390×844，专用测试账号，副本库）：
 *   .topbar 直接子元素只有三个：
 *     div.brand → 124×32   display=flex      ← 正常
 *     nav#nav   →   0×0    display=none      ← P0-1 已修好
 *     div.me    → 234×114  display=flex  flexWrap=wrap   ★ 罪魁祸首
 *   全部 ≥40px 的后代里**只有 .me 一个** ⇒ 顶栏高度完全由 .me 决定。
 *
 * 【.me 为什么是 114px】它装 6 件东西（index.html:163-170）：
 *   #globalSearch(搜索框) + #btnSyncNow(🔄同步) + #themeBtn(🌙)
 *   + #todoChip(📌待办) + #meChip(头像/名字/角色) + #btnSwitch(切换身份)
 *   v83 在 layout-v83.css:1522 给它 `flex-wrap:wrap!important`（另有 238/876/1024 等多处）
 *   ⇒ 390px 宽度下换行铺成 3 行 → 114px。
 *
 * 【关键矛盾】项目原设计（styles.css:1094-1108，@media(max-width:760px)）在手机上**故意**
 *   做了减法，注释写得很清楚：
 *     .chip .role{display:none}      ← 角色小标签在窄屏没意义
 *     .chip .me-lbl{display:none}    ← 藏掉「当前」二字
 *     .chip .me-name{max-width:72px} ← 名字限宽 + 省略号
 *   v83 也曾经**正确还原**过这条（layout-v83.css:1149-1151，display:none），
 *   但本文件 1536-1538 又把它改回 `display:inline!important` —— 这是 v83「清零区」
 *   把手机端顶栏**加料**的又一处，与 P0-1 的 #nav 同源（都是清零块只撤销了一半）。
 *
 * 【为什么不动「同步」按钮】
 *   ⚠ layout-v83.css:1145-1147 把 #btnSyncNow 在手机上 `display:none!important`，
 *     但 1533-1534 又把它改回 `display:inline-flex!important`。
 *     本块**保留**「同步」按钮可见（= 1533 那条的意图，也是 v78 用户明确要的功能：
 *     「平板/电脑上没有下拉刷新，点这里立刻拉最新数据」——删掉等于砍功能）。
 *     只做**布局**收敛，不砍功能。
 *
 * 【为什么用 append 而不直接改 1538 行】
 *   项目铁律：CSS 一律追加到文件末尾，不改既有行（历史上多次因改既有行导致回归）。
 *
 * 【验收判据】smoke/_v85_probe5_mobilenav_fixed.js：
 *   390×844 → .topbar ≤ 120px（目标 ~64）；桌面 1440×900 侧栏不受影响。
 * ========================================================================== */
@media (max-width: 1023px) {
  /* ① 账号 chip：还原 styles.css:1097-1102 —— 只留头像 + 名字（限宽省略），藏角色与「当前」
   *    ⚠ 选择器与 1536 行完全相同（特异性也相同）⇒ 靠「在文件更靠后」取胜。
   *      这是有意为之：只压它一条，不牵连同块里 .btn 的 display:inline-flex。 */
  [data-skin] #app > .topbar > .me .chip .role,
  [data-skin] #app > .topbar > .me .chip .me-lbl {
    display: none !important;
  }
  [data-skin] #app > .topbar > .me .chip .me-name {
    display: inline !important;
    max-width: 72px !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    white-space: nowrap !important;
  }

  /* ② 顶栏右侧区不换行 + 允许收缩。
   *    ⚠ 必须 flex:none 的按钮反而是撑宽的元凶？—— 不。实测 390px 下：
   *    搜索框 min-width:0 + flex:1 收缩，按钮 flex:none 单行，
   *    总量约 234px < 390px ⇒ 单行放得下，不会溢出。
   *    保留 nowrap，若将来真放不下会溢出而不是把顶栏撑成三行（更好排查）。 */
  [data-skin] #app > .topbar > .me {
    flex-wrap: nowrap !important;
    gap: 6px !important;
    min-width: 0 !important;
  }

  /* ③ 搜索框吃掉剩余空间（还原 styles.css:1107-1108 的意图）。
   *    ⚠ min-width 用 60px 而非 100px：100px 是 1156 那条桌面宽版留下的值，
   *    在 390px 窄屏会把 .me 顶宽、挤掉「切换身份」。60px 够放 2~3 个字 + 图标。 */
  [data-skin] #app > .topbar > .me .search-in {
    flex: 1 1 60px !important;
    min-width: 0 !important;
  }

  /* ④ 「切换身份」不许折成两行（还原 styles.css:1104-1105，注释里明确点过这个坑） */
  [data-skin] #app > .topbar > .me #btnSwitch {
    white-space: nowrap !important;
    flex: none !important;
    padding: 5px 9px !important;
    font-size: 12px !important;
  }

  /* ⑤ 顶栏整体压回单行密度（还原 styles.css:1091 的 padding/gap） */
  [data-skin] #app > .topbar {
    padding: 8px 10px !important;
    gap: 8px !important;
    align-items: center !important;
  }
  [data-skin] #app > .topbar > .brand { padding: 0 !important; background: transparent !important; }
  [data-skin] #app > .topbar > .me { padding: 0 !important; background: transparent !important; border: 0 !important; }
}
/* ============================================================================
 * v85 P0｜切 tab「叠加」：旧 view 不被隐藏，页面越点越长
 * ============================================================================
 *
 * 【用户报告】手机上「所有功能区全部挤到一页」「概览很长，可以看到全部功能」
 *   「功能区切换按钮还有用不了」。
 *
 * 【实测铁证】smoke/_v85_probe10_tabstack.js（专用测试账号，副本库，可复跑）
 *   判据与 team-lead 的 probe8b 完全一致（display!=='none' && height>0）：
 *   移动端 390×844 真点底部 #tabbar：
 *     点 home     → 可见 view=1  ["home"]                              #main=3387px
 *     点 calendar → 可见 view=2  ["home","calendar"]  🔴              #main=4938px
 *     点 team     → 可见 view=3  ["home","calendar","team"]  🔴       #main=6067px
 *     点 board    → 可见 view=4  ["home","calendar","team","board"] 🔴 #main=7343px
 *     「带 .hidden 类却仍非空可见」的 view 数同步涨到 3 个 ← 这就是缺陷的直接指纹
 *   桌面 1440×900 真点侧栏 #nav：可见 view **恒为 1**，#main 反而变短（2566→1096px）。正常。
 *   ⇒ 缺陷**只存在于 ≤1023px**，与本块作用域一致。
 *
 * 【根因】本文件 1084 行（全文件仅此一处给 #main > .view 设 display）：
 *     @media (max-width:1023px) 内
 *       [data-skin] #main > .view { display: block !important; }   特异性 (1,2,0)
 *   压过 public/assets/styles.css:202
 *       .hidden { display: none !important; }                     特异性 (0,1,0)
 *   ⇒ 两条都带 !important 时比特异性，(1,2,0) > (0,1,0) ⇒ v83 必胜
 *   ⇒ app.js 给旧 view 加的 .hidden 类**完全失效**，切页从「替换」退化成「叠加」。
 *
 * 【为什么用 .view.hidden 而不是 .view】
 *   ⚠ 只写 `[data-skin] #main > .view{display:none!important}` 会把**当前**正在显示的
 *     view 也一起藏掉 ⇒ 整个 App 空白。这是本条修法最大的坑。
 *   ✅ 带 .hidden 精确命中「JS 已标记为要隐藏的那些」，只压 1084 那条的 display 语义，
 *     不影响 1084 真正想解决的 width/max-width（那两条本块不动）。
 *
 * 【特异性怎么算的】
 *   `[data-skin] #main > .view.hidden` = (1, 3, 0)
 *     id 1 个(#main) + 属性/类 3 个([data-skin] / .view / .hidden) + 类型 0 个
 *   > 1084 的 (1, 2, 0) ⇒ 本条胜。
 *   且两条都在文件末尾区域，本条更靠后，双重保险。
 *
 * 【作用域纪律 —— 本项目栽过 3 次的坑】
 *   「凡是给某类布局改成另一种形态，都必须从第一行就包在 @media 里」
 *   （layout-v83.css:998-1007 的原话）。
 *   ⇒ 本块**必须**包在 @media(max-width:1023px) 内：桌面端 .hidden 机制本来就完好
 *     （_work/_v85_view_rule_scope.js 扫描确认：顶层/桌面作用域零条 display 覆盖），
 *     若不包 @media 反而会给桌面端加一条多余规则，属于「修移动端坏桌面」的典型反面案例。
 * ========================================================================== */
@media (max-width: 1023px) {
  [data-skin] #main > .view.hidden {
    display: none !important;
  }
}
/* ============================================================================
 * v85｜响应式三条：顶栏图标重叠 / 统计卡片参差 / 开屏动画窄屏溢出
 * ============================================================================
 * 【作用域纪律 —— 本项目栽过 3 次的坑，务必遵守】
 *   铁律原文（layout-v83.css:998-1007）：「凡是给某类布局改成另一种形态，
 *   都必须**从第一行就**包在 @media 里」，否则就是「手机上侧栏也占 208px」那类事故。
 *   ⇒ 本文件下列**每一块**都是独立的顶层 @media，没有嵌套。
 *     （刻意向平铺而非嵌套 @media：嵌套虽然合法，但本项目历史上多次因
 *       块边界没包对而漏掉作用域，平铺后每块的作用域一眼可见、便于 review。）
 *   ⇒ 桌面端（≥1024px）本来就正常，下面**没有任何一条**会命中桌面。
 *
 * ────────────────────────────────────────────────────────────────────────────
 * 【A. 顶栏图标互相重叠 +「切换身份」被截断】
 * 用户真机截图 + 实测（smoke/_v85_probe11_responsive.js，可复跑）：
 *   390px：顶栏 55px、无重叠，但 .me 仅 238px，元素已明显拥挤
 *   320px：🔴 「切换身份」右边界 344px > 视口 320px ⇒ **溢出 24px，文字被裁**
 *        （用户截图里显示成「切换」「半个字」正是这个）
 *
 * 根因链（三层，逐层都要治）：
 *   ① .me 是 flex 容器，内含 6 件东西（搜索框 / 🔄同步 / 🌙主题 / 📌待办 /
 *      头像chip / 切换身份）。320px 下留给 .me 只有约 176px，**根本装不下**。
 *   ② 上轮我给搜索框写的 `flex:1 1 60px` 只保证它能缩到 60px，
 *      而 .me 没有 overflow 约束 ⇒ 子元素**溢出容器**、互相压盖。
 *   ③ 「切换身份」写了 `flex:none`（不许压缩）—— 极窄屏上正是这条
 *      把它顶出视口。**要保护它，得先砍掉别的。**
 *
 * 修法（按「先砍不重要的」分级，每档只砍一点点，保证 321~480px 区间功能完整）：
 *   ① ≤1023px：.me 加 overflow:hidden —— 从结构上杜绝「子元素互相压盖」这类脏渲染。
 *      ⚠ 只在 ≤1023px 加：桌面端 .me 在侧栏里，裁切会切掉 focus 光晕。
 *   ② ≤480px：隐藏「🔄同步」。它是 v78 为「平板/电脑没有下拉刷新」加的，
 *      而**手机有下拉刷新**（app.js 的 bindSwipe），在手机上本就非刚需。
 *      ⚠ 不是砍功能：桌面/平板（481~1023px）完全不受影响。
 *      ③ ≤480px：头像 chip 只留头像、藏名字（省 ~60px）——
 *      沿用 styles.css:1101 的原设计思路；名字可点「切换身份」看到，不丢信息。
 *   ④ ≤420px：「📌待办」清零文字、只留数字徽标（待办数在 tabbar 也有）。
 *   ⑤ ≤360px：「切换身份」限宽 46px + overflow:hidden —— 最后一道保险，
 *      宁可截短也**绝不许溢出屏幕**，这是本条的核心诉求。
 * ────────────────────────────────────────────────────────────────────────────
 * 【B. 统计卡片大小不一 / 基线不齐】
 * 用户原话：「下面还有好几个组件大小不一和没有对齐不好看」
 * 实测：同排出现 83.9px vs 69.9px ⇒ 极差 14px，确实参差。
 *
 * 根因：styles.css:643 `.stat-card` 只有 padding，**没有内部 flex 布局**：
 *   - grid 行高由**内容高度**决定 ⇒ 数字换行成两行（「1 节」）那张把整行撑高；
 *   - 同排其它卡片被拉高但内容仍顶部对齐 ⇒ 视觉上「大小不一 + 基线不齐」。
 * ⚠ 为什么早先实测「极差=0」：当时所有卡片数字都是 1 行（0 节/0 场/7 人），
 *   高度自然一致。一旦真实数据出现两位数就参差 —— 属**数据依赖型偶发**，
 *   不能靠「现在测着还行」放过去。
 *
 * 修法：给 .stat-card 建立**内部 flex 纵向布局 + 统一 min-height + 内容垂直居中**，
 *   数值区 flex:1 吃掉多余高度 ⇒ 数字 1 行或 2 行，同排卡片都等高且内容居中。
 *   ⚠ 用 min-height 而非 height：固定 height 会在大字号/深色模式下截断文字。
 * ────────────────────────────────────────────────────────────────────────────
 * 【C. 开屏动画窄屏不自适应】
 * 用户原话：「开屏动画都不会自适应了」「页面很挤」，截图里大字被裁、插画偏右。
 * 根因：styles.css:2488 `.intro-logo{font-size:64px;letter-spacing:8px}` 是**写死**的，
 *   320px 视口上「青志」两字 + 8px 字距必然溢出；`.intro-slogan` 的 20px/6px 同理。
 *
 * 修法：用 clamp() 做**连续降级**（比阶梯式 @media 更平滑）；
 *   立绘大图由 object-fit:cover 改为 contain + 居中，解决「插画偏右被裁」。
 *   ⚠ 只改尺寸/裁切方式，**绝不动 animation**（introPop/introFade）——
 *     开场动画本身是 v79.9 反复调过的，动它等于把整个开屏改坏。
 * ========================================================================== */

/* ══════════ A-① 顶栏：≤1023px 结构性兜底 ══════════ */
@media (max-width: 1023px) {
  /* 从结构上杜绝「子元素溢出容器、互相压盖」 */
  [data-skin] #app > .topbar > .me {
    overflow: hidden !important;
  }
}

/* ══════════ A-② + A-③ 顶栏：≤480px 手机端减法 ══════════ */
@media (max-width: 480px) {
  /* 隐藏「🔄同步」：手机有下拉刷新，此按钮在手机上非刚需（桌面/平板仍保留） */
  [data-skin] #app > .topbar > .me #btnSyncNow {
    display: none !important;
  }
  /* 头像 chip 只留头像，藏掉名字（沿用 styles.css:1101 原设计思路） */
  [data-skin] #app > .topbar > .me .chip .me-name {
    display: none !important;
  }
}

/* ══════════ A-④ 顶栏：≤420px 再砍待办文字 ══════════ */
@media (max-width: 420px) {
  [data-skin] #app > .topbar > .me #todoChip {
    font-size: 0 !important;                 /* 文字清零，只留数字徽标 */
    padding: 3px 5px !important;
    min-height: 0 !important;
  }
  /* 徽标本身必须仍看得见（font-size:0 会连它一起清零，故单独恢复） */
  [data-skin] #app > .topbar > .me #todoChip .badge {
    font-size: 12px !important;
  }
}

/* ══════════ A-⑤ 顶栏：≤360px 极窄屏最后保险 ══════════ */
@media (max-width: 360px) {
  /* 「切换身份」限宽 + 裁切：宁可短，绝不溢出屏幕 */
  [data-skin] #app > .topbar > .me #btnSwitch {
    padding: 5px 7px !important;
    font-size: 12px !important;
    max-width: 46px !important;
    overflow: hidden !important;
  }
  /* 品牌名限死宽度，绝不与右侧区抢空间 */
  [data-skin] #app > .topbar > #teamBrand {
    max-width: 56px !important;
  }
  /* 搜索框可以更瘦，但保住「点得中」的最小宽度 */
  [data-skin] #app > .topbar > .me .search-in {
    min-width: 44px !important;
  }
}

/* ══════════ B. 统计卡片等高 + 内容垂直居中 ══════════ */
/* 【实测根因 —— 先说我第一版为什么没修好（勿重蹈）】
 *   我第一版只写了 `[data-skin] .stat-card{...}`（特异性 0,2,0），
 *   实测极差**一点没消**（仍 14px）。两个原因，都已定位到行号：
 *
 *   ❶ 特异性不够 —— 统计卡在 **#homePanels 里**（probe12 实测 gridInHomePanels=true），
 *      而本文件 1465 行 `[data-skin] #homePanels .stat-card{height:auto!important;
 *      min-height:52px!important; ...}` 的特异性是 **(1,2,0)**，**压过**我的 (0,2,0)。
 *      ⇒ 必须把选择器写成 `#homePanels .stat-card` 才够级。
 *
 *   ❷ 更根本：那张高的卡不是「被拉伸」，是**它自己内容更多**。
 *      probe12 逐张量到：
 *        今日课程  .k=18.6px  .v=**39.3px**  卡片 83.9px
 *        今日会议  .k=18.6px  .v=**25.3px**  卡片 69.9px   ← 差 14px，全在 .v 上
 *      根因在 app.js:11880：
 *        card('今日课程', …, 'course', myCourses.length ? '看教室与老师' : '')
 *      `card()`（app.js:12403）会把第 4 个参数 note 渲染成 `.v` 里的 `<em>`。
 *      今天有课时才带这个 note ⇒ `.v` 变成两行 ⇒ 那张卡凭空高 14px。
 *      ⇒ 「今日课程」只要有课就一直比同排高，**这不是偶发，是必现**。
 *
 * 【修法】不给 .v 无限拉伸，而是让它成为「**单行、垂直居中、固定高度**」的一格，
 *   并把 note 用 <em> 绝对定位放到卡片底部 —— 这样：
 *     · note 有没有、有多长，都不再改变 .v 的高度；
 *     · 同排卡片必然等高；
 *     · 且**桌面端同样适用**（根因与视口宽度无关），所以这块**不加 @media**。
 *
 * ⚠ 为什么这块可以不包 @media：
 *   前面 A/C 两块是「给某形态改成另一形态」，必须包。
 *   而这块是**修一个内容驱动的等高缺陷**，桌面端同样存在同样问题
 *   （probe12 实测桌面 1440 也是 110 vs 96，极差同为 14）。
 *   ⇒ 不包 @media 才是对的；包了反而修不好桌面。
 *   ⚠ 但仍限定 [data-skin]，避免影响无皮肤时的其它布局分支。 */
[data-skin] #homePanels .stat-card,
[data-skin] .stat-card {
  display: flex !important;
  flex-direction: column !important;
  justify-content: center !important;
  align-items: stretch !important;
  box-sizing: border-box !important;
  /* ⚠ 不写 min-height/height：等高交给 grid 的 align-items:stretch（下一条），
     由**同一行最高的卡片**决定整行高度 —— 这才是 grid 排等高的正确姿势。 */
}
/* grid 默认 align-items 就是 stretch，这里显式写出来是为了：
   ① 不受将来某条 grid 规则改动影响；② 意图可读。 */
[data-skin] .stat-grid {
  align-items: stretch !important;
}
/* ★★ v85 实测根因之二（这一条才是「大小不一」的真凶，之前一直没找对）
 *   layout-v83.css:322-324 有一条「卡片之间靠间距分层」的规则：
 *       [data-skin] .stat-card + .stat-card { margin-top: 14px; }
 *   它本意是给**普通流里上下排的卡片**留间距，但 .stat-card 实际是
 *   `.stat-grid`（display:grid）的**网格项** ⇒ 相邻选择器照样命中第 2 张及以后 ⇒
 *   每张非首卡都多了 14px 上边距。
 *   后果（probe12 实测，数字完全吻合）：
 *       今日课程 y=161 h=69.6（首卡，无 margin）
 *       今日会议 y=175 h=69.6（非首卡，被推下 14px）
 *       首行网格高 = 14 + 69.6 = **83.6** ⇒ 首卡被 stretch 到 83.6
 *       ⇒ 同排两张卡片高度差 **恰好 14px**，且「第一张永远比同排另一张高」。
 *   用户看到的正是这个：「1 节」那张明显比「0 场」那张高、基线不齐。
 *   ⚠ 这与视口宽度无关 ⇒ 桌面 1440 同样是 110 vs 96（probe12 实测），故不加 @media。
 *   ✅ 修法：网格里**不再加外边距**（间距已由 .stat-grid 的 gap 负责）。
 *      只清 margin，不动 padding、不动 gap。 */
[data-skin] .stat-grid > .stat-card,
[data-skin] .stat-grid > .stat-card + .stat-card {
  margin-top: 0 !important;
}
/* 标签行：不参与纵向拉伸 */
[data-skin] .home-panel .stat-card .k,
[data-skin] .stat-card .k {
  flex: 0 0 auto !important;
}
/* ★ 数值区：单行 + 垂直居中 + 固定高度 —— 无论有没有 <em>，高度都一样。
   ⚠ 用 align-items:center 而不是 stretch：stretch 会让 .v 拉满卡片高，
     那正是「note 换行就把卡片撑高」的传导路径。 */
[data-skin] .home-panel .stat-card .v,
[data-skin] .stat-card .v {
  flex: 0 0 auto !important;
  display: flex !important;
  align-items: center !important;
  justify-content: flex-start !important;
  min-height: 25px !important;          /* 与 22px 字号 + 25.3px 行高对齐 */
  max-height: 25px !important;          /* ★ 锁死：note 换行也不允许长高 */
  overflow: hidden !important;
  white-space: nowrap !important;
  line-height: 25px !important;
}
/* note（<em>）：改成绝对定位贴在卡片底部，不再参与 .v 的高度计算。
   ⚠ 用 position:relative + absolute 是因为卡片是 flex 列容器，
     直接给 em 绝对定位需要一个定位上下文，故在 .stat-card 上补 position:relative。 */
[data-skin] .stat-card {
  position: relative !important;
}
/* ⚠⚠ 关键修正（第一版的错）：我原先给**所有** .stat-card 加了 padding-bottom:17px，
 *   想给 note 腾位置。结果 6 张卡全都多出 17px ⇒ 同排仍然不等高
 *   （实测 83.6 vs 69.6，极差 14px —— 与修前完全一样，等于白改）。
 *   ⇒ padding-bottom 只能加在「**真的有 note**」的卡上。
 *   CSS 没有 :has-content()，但有 :has()：现代 Chromium/Edge 支持
 *   （项目 e2e 用的是系统 Edge，≥105；真机 Android WebView 需 ≥105）。
 *   ⇒ 用 `.stat-card:has(.v em)` 精确命中「带 note 的卡」。
 *   ⚠ 同时给出 :has() 的兜底：若浏览器不支持 :has()，规则整条被丢弃，
 *     此时 note 回到参与高度的老行为 ⇒ 退回「修前状态」，不会更糟。 */
[data-skin] .stat-card:has(.v em) {
  padding-bottom: 17px !important;
}
[data-skin] .home-panel .stat-card .v em,
[data-skin] .stat-card .v em {
  position: absolute !important;
  left: 10px !important;
  right: 10px !important;
  bottom: 5px !important;
  margin-left: 0 !important;
  font-style: normal !important;
  font-size: 11px !important;
  line-height: 12px !important;
  color: var(--tx3) !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  white-space: nowrap !important;
}

/* ══════════ C. 开屏动画窄屏自适应（≤1023px） ══════════ */
@media (max-width: 1023px) {
  /* ⚠ 选择器同时写 [data-skin] 前缀版与裸版：
     开屏遮罩是 JS 动态 append 到 body 的（app.js:6625 playIntro），
     挂在 <html data-skin> 之下，理论上 [data-skin] 能命中；
     但它可能被移到 body 下或 data-skin 尚未设置，故两种都写一份兜底。 */
  [data-skin] .intro-ov .intro-logo,
  .intro-ov .intro-logo {
    /* clamp(最小, 随视口, 最大)：连续降级，比阶梯式 @media 更平滑 */
    font-size: clamp(28px, 11vw, 64px) !important;
    letter-spacing: clamp(2px, 1.6vw, 8px) !important;
    max-width: 92vw !important;
    text-align: center !important;
  }
  [data-skin] .intro-ov .intro-slogan,
  .intro-ov .intro-slogan {
    font-size: clamp(12px, 4.6vw, 20px) !important;
    letter-spacing: clamp(1px, 1.1vw, 6px) !important;
    max-width: 92vw !important;
    text-align: center !important;
  }
  /* 四季开屏：吉祥物/小物件层不许超出视口 */
  [data-skin] .intro-ov .intro-props,
  .intro-ov .intro-props {
    /* 🔴 v91：原为 max-width:100vw。
       ⚠ 在 zoom ≠ 1 的 WebView 里，vw 与fixed 包含块不同源，
         装饰层会被钳到视口的 80% ⇒ 咖啡杯/枫叶等小物件偏出可视区（用户看到的右侧异常）。
       ⇒ 改用 100%（参照包含块 = 遮罩本身），与 .intro-img 的修法同源。 */
    max-width: 100% !important;
    left: 0 !important;
    right: 0 !important;
  }
  [data-skin] .intro-ov .intro-fx,
  .intro-ov .intro-fx {
    /* 🔴 v91：同上，粒子层是 inset:0 铺满的，用 100% 才与遮罩一致 */
    max-width: 100% !important;
  }
  /* 🔴 v89 立绘大图：**必须 cover 铺满，绝不能 contain**。
   *
   * 【v88 遗留的元凶，用户原话「开屏不会自动适配」「还有很多黑色的东西」】
   *   这条规则原本写的是 `object-fit: contain !important`，
   *   当时的意图是「解决插画偏右、被裁切」——
   *   但它把图片从「铺满屏幕」改成了「**完整显示但四周留边**」。
   *   ⚠ 致命后果：`.intro-ov` 的底色是 `background:#0b1220`（近黑深蓝），
   *     而当季立绘是 1024×1536 的**竖图**、手机屏是 1080×2400 的**更窄的竖屏**：
   *     contain ⇒ 上下或左右**必然留出黑边** ⇒ 用户看到的「很多黑色的东西」
   *     就是这块底色露出来了。
   *   ⇒ contain 只能保证「图完整」，不能保证「铺满」；
   *     而用户要的是后者（开屏就该是满屏一张图）。
   *
   * 【正确做法：cover + 绝对定位铺满】
   *   ① position:absolute; inset:0 —— 让 img **脱离 flex 流**，
   *      不再与 .intro-logo / .intro-slogan 抢高度
   *      （此前它是普通 flex item，flex-shrink:1 会把它压扁，
   *        这才是「图片很难看 / 被文字压掉一截」的真正机制）。
   *   ② object-fit: cover —— 铺满，裁掉溢出部分。
   *      竖图放到更窄的竖屏上，cover 裁的是**上下**（人物脸和脚下文字会各丢一点），
   *      比留黑边好得多；这是满屏开屏的必然取舍。
   *   ③ inset:0 + width/height 100% —— 任何屏幕比例都自适应，无需按机型写死尺寸。
   *   ④ 保留 object-position:center —— 裁切时人物保持居中，不会偏。
   */
  [data-skin] .intro-ov .intro-img,
  .intro-ov .intro-img {
    position: absolute !important;
    inset: 0 !important;
    left: 0 !important;
    top: 0 !important;
    width: 100% !important;
    height: 100% !important;
    /* 🔴🔴 v91【本条是真凶，改动务必与 p1-fixes-v86.css 同步】
       ⚠ 原来是 max-width:100vw + max-height:100vh。
       ⚠ 为什么它会造成「开屏只占屏幕 80%、右侧透出后面页面」：
          在部分国产 ROM（含用户这台 OriginOS）上，**当系统「显示大小」≠默认时，
          1vw 并不等于布局视口的 1%** —— vw/vh 是按「视觉视口」算的，
          而固定定位元素的包含块按「布局视口」算，两者相差约 20%。
          ⇒ 于是 max-width:100vw 这个"看似无害的上限"，
             反而把本该满屏的图片**钳到了视口的 80%**。
          ⚠ 这也解释了一个长期矛盾现象：「跳过」按钮却贴着完整屏幕右边缘——
             因为它用的是 right:16px（长度单位，不受 vw 影响），
             而图片用的是 max-width:100vw（视口单位）⇒ 两者基准不同。
       ⇒ 修法：**钳制值改用百分比**。100% 参照的是元素的包含块（=遮罩本身，
          而遮罩由 fixed inset:0 定位），与图片想铺满的目标天然一致，
          不受 vw/vh 与包含块错配影响。 */
    max-width: 100% !important;
    max-height: 100% !important;
    /* 🔴 v89：cover 而不是 contain —— 不留黑边（用户抱怨的「很多黑色的东西」）。
       ⚠ 若哪天要改回 contain，必须同时把 .intro-ov 的底色改成与图片主色相近，
         否则留边处会再次露出深色底。 */
    object-fit: cover !important;
    object-position: center center !important;
    /* ⚠ 提示：这里不要再加 z-index 把图盖到文字上面——
         .intro-logo/.intro-slogan 是靠文档顺序压在图上的（后写者在上）。
         反过来盖住文字会让开屏变成「只有图、没有字」，
         那正是 v89 要避免的另一种极端。 */
  }
  /* ⚠ v89：立绘是底图，文字/吉祥物必须压在它**上面**且不被裁。
     之前 img 是 flex item，文字与它平级；改成 absolute 后，
     若不给文字层显式 z-index，部分 ROM 的合成层序会让文字被图盖住。
     ⚠ 只给装饰层设z-index，**不给 .intro-img 设**（它要当底）。 */
  [data-skin] .intro-ov .intro-logo,
  [data-skin] .intro-ov .intro-slogan,
  [data-skin] .intro-ov .intro-chibi,
  [data-skin] .intro-ov .intro-greet,
  [data-skin] .intro-ov .intro-props,
  [data-skin] .intro-ov .intro-fx,
  [data-skin] .intro-ov .intro-mascot-stage {
    z-index: 2;
  }
}
