/* ============================================================
   国旗护卫队成员管理系统 · 手机端适配（v1.86）
   全站 12 个页面共用。所有规则都收在媒体查询里，
   电脑/平板宽屏一像素都不受影响。
   断点：768px 以下视为手机（外加 480px 的小屏微调）。
   配套体检脚本：jstest/mobile_audit.mjs（无头 Chrome 实测）。
   ============================================================ */

/* ---------- ① 全局兜底 ---------- */
@media (max-width: 768px) {
    html, body { max-width: 100%; }
    img, video, svg { max-width: 100%; height: auto; }

    /* 表格一律横向可滑动，不再撑破页面（index 成员表、internal 课表等） */
    table {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        max-width: 100%;
    }

    /* 固定宽度的网格（forge 热力表、internal 校正/热力网格）也放进滑动容器。
       注意要压掉 min-width——否则 min/max 冲突时 min 赢，还是 640px 伸出去 */
    .heat-grid, .calib-grid, .duty-grid {
        min-width: 0;
        max-width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    /* 装饰性光斑/跑马灯别把页面撑出横向滚动 */
    body { overflow-x: hidden; }

    /* 主要按钮：触摸目标 ≥40px，手指点得中 */
    .p-btn, .g-btn, .btn,
    .pc-trigger, .theme-btn,
    .pc-menu button,
    .sc-sites button, .sched-actions button,
    .pv-head button {
        min-height: 40px;
    }
    .nav a { min-height: 44px; display: flex; align-items: center; }
}

/* ---------- ② 子页面头部（education/exchange/forge/glory/join/legacy/moments/showcase/youth/internal 共用 p-top） ---------- */
@media (max-width: 768px) {
    .p-top {
        padding: 8px 12px;
        gap: 8px;
        flex-wrap: nowrap;
    }
    .p-brand {
        flex: 1 1 auto;
        min-width: 0;
    }
    .p-brand b {
        font-size: 14.5px;
        display: block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .p-brand small { display: none; }
    .p-brand .badge { width: 30px; height: 30px; }
    /* 四个主题色块加大到 30px，好点 */
    .p-theme button, .g-theme button { width: 30px; height: 30px; }
    .p-btn { padding: 7px 12px; font-size: 13px; white-space: nowrap; }
    .p-hero { padding: 36px 16px 30px; }
    .p-hero h1 { font-size: 24px; letter-spacing: 6px; }
    .p-main { padding: 18px 12px 44px; }
}

/* ---------- ③ gallery（g-top 头部 + 网格） ---------- */
@media (max-width: 768px) {
    .g-top {
        padding: 8px 12px;
        gap: 8px;
        flex-wrap: nowrap;
    }
    .g-brand { flex: 1 1 auto; min-width: 0; gap: 8px; }
    .g-brand b {
        font-size: 14px;
        display: block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .g-brand small { display: none; }
    .g-brand .badge { width: 30px; height: 30px; }
    .g-btn { padding: 7px 12px; font-size: 13px; white-space: nowrap; }
    /* 通知铃铛菜单别超出屏幕 */
    .g-bell-menu {
        right: 0;
        left: auto;
        max-width: calc(100vw - 24px);
    }
}

/* ---------- ④ index 头部（首页导航） ---------- */
@media (max-width: 768px) {
    /* 一排装不下：第一行 队名 + 汉堡，第二行 个人中心 + 主题 */
    .header-inner {
        flex-wrap: wrap;
        height: auto;
        padding: 8px 0;
        gap: 6px 10px;
    }
    .brand {
        order: 1;
        flex: 1 1 auto;
        min-width: 0;
        gap: 8px;
    }
    .brand-badge { width: 30px; height: 37px; }
    .brand-text { min-width: 0; }
    .brand-text strong {
        font-size: 14.5px;
        display: block;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .brand-text small { display: none; }
    .nav-toggle { order: 2; }
    /* 汉堡菜单从头部正下方弹出（头部变成两行后 72px 就不准了） */
    .nav { top: 100%; }
    .pc-drop { order: 3; margin-left: auto; }
    .pc-trigger { font-size: 13px; padding: 8px 10px; min-height: 38px; }
    .theme-switch { order: 4; }
    .theme-btn { padding: 8px 10px; font-size: 13px; }
    .theme-menu { right: 0; left: auto; }
}

/* ---------- ⑤ index 个人中心（pc-window 在小屏上再收紧） ---------- */
@media (max-width: 480px) {
    .pc-window { width: 100vw; height: 100dvh; border-radius: 0; }
    /* v1.87 修：这里原来是 flex:1 1 48%（一行两个）→ 行高 67px、菜单整体 297px，
       侧栏被撑到 870px 而 .pc-side 是 flex:none 不肯缩，右侧内容区直接被压成 0px。
       结果就是「菜单能点、点了也切了，但内容区是一条缝，看着像没反应」。
       改回一行三个 + 紧凑高度。 */
    .pc-menu button { flex: 1 1 30%; min-height: 36px; padding: 6px 4px; font-size: 11.5px; }
    .pc-main { padding: 16px 12px; }
    .pc-head { flex-direction: column; align-items: flex-start; gap: 8px; }
    .pc-stats { grid-template-columns: 1fr 1fr; gap: 8px; }
    .pc-form .field.full { grid-column: 1 / -1; }
    /* 登录框铺满 */
    .pc-login-box { padding: 20px 16px; }
    .pc-login-aside { padding: 18px 16px; }
    /* 首页 hero 按钮整行 */
    .hero-actions .btn { flex: 1 1 100%; justify-content: center; }
}

/* ---------- ⑤b 首页 hero：手机端——旗子当**背景**，文字压在旗面上 ----------
   v2.26 改（兄长："想让红旗动图在文字后面，而不是这样断层的上下设计"）。

   以前手机端把视频/动图放进**顶部一条横幅**（高 68vw），文字排在横幅下面 ——
   视觉上就是"上面一块旗、下面一块字"，中间一条明显的分界 → 断层感。

   现在改成**和桌面同一套层叠**：
     · .hero-flag 铺满整个 hero（不再是一条），当背景层
     · 文字层照旧靠下（align-items:flex-end），于是「以青春之我／护国旗之威」
       连同说明与按钮**直接压在旗面上**
     · 取景按竖屏重新算：960×540 的动图，cover 到 390 宽时缩放比是**由高度决定**的
       （658/540≈1.22，缩放后宽约 1172）——纵向整幅都在画面里（天空到旗面下沿全能看见），
       只需要挑**横向窗口**。object-position: 12% 让窗口落在 x≈8%~43%：
       旗杆 + 大五角星 + 旗面左半都在，正是最像"国旗"的那一段。
     · 压暗罩比桌面更重（文字整片骑在旗上）：上轻（还看得清旗）→ 下重（白字稳稳压住）。
   桌面端这套完全不动（下面的规则全在 max-width:768px 里）。 */
@media (max-width: 768px) {
    /* v2.27：**整面旗完整可见 + 居中 + 自然比例**
       ------------------------------------------------------------
       兄长看过 v2.26 的真机截图后说："分辨率有问题，整个旗帜也没有露出来，
       进行适当的尺寸修改，贴合实际大小居中。"
       —— 对：v2.26 用的是 `object-fit: cover`（铺满 = 必然裁切），
       390 宽的竖屏上要填满 658 高，横向只截到画面的 33%，
       于是只剩旗面中间一大块（大星被放得极大、旗杆和另几颗星都出画了）。
       "铺满"和"整面旗都在"在竖屏上**天生冲突**（16:9 的旗满宽只有 219 高）。

       现在改成：**contain（整面旗，满宽 390×219，自然比例、水平居中）**，
       然后把两个问题分别解掉 ——
         · 图片下沿用**与旗面同色的深红**渐隐 + 压暗罩接着化开
           （不是纯黑：纯黑会看出边界；旗面下沿本来就是深红布，接缝几乎看不出来）
         · 上沿贴着头图，不留天空以外的空档
       hero 高度顺势收到 490px 左右 —— 一屏能多露出下面的内容，
       而文字仍然**压在旗面上**（标题正好落在旗面下半、金标题贴着旗子）。 */
    .hero {
        height: clamp(470px, 58vh, 540px);
        min-height: 0;
        background: linear-gradient(180deg, #7A0A1B 0%, #4A0611 46%, #2E040B 100%);
    }
    /* 文字沉到底部，留 58px 给底部圆点 */
    .hero-slide { align-items: flex-end; padding-bottom: 58px; }

    .hero-flag { display: block; inset: 0; height: auto; }
    .hero-flag .hero-flag-img {
        object-fit: contain;             /* ⭐ 整面旗完整可见（不再裁切） */
        object-position: 50% 0%;         /* ⭐ 水平居中、贴着顶部 */
        width: 100%;
        height: auto;                    /* 高度按 16:9 自己算 → 贴合实际比例 */
        /* 下沿自己先化开一半，剩下的交给下面的压暗罩 —— 两层一起才看不出边界 */
        -webkit-mask-image: linear-gradient(180deg, #000 58%, rgba(0, 0, 0, .45) 80%, transparent 100%);
                mask-image: linear-gradient(180deg, #000 58%, rgba(0, 0, 0, .45) 80%, transparent 100%);
    }
    /* 压暗罩：上轻（旗面亮得起来）→ 中下重（文字稳稳压住），
       而且最后几档用的是**旗面那种深红**，接缝才融得进去 */
    .hero-flag::after {
        background: linear-gradient(180deg,
            rgba(22, 3, 8, .12) 0%,
            rgba(22, 3, 8, .06) 28%,
            rgba(74, 6, 17, .52) 50%,
            rgba(64, 5, 15, .90) 70%,
            rgba(46, 4, 11, .98) 100%);
    }

    /* 排版收一档 */
    .hero-tag {
        font-size: 11.5px; letter-spacing: 1px;
        padding: 5px 13px; margin-bottom: 12px;
    }
    .hero h1 { font-size: 26px; line-height: 1.24; letter-spacing: 1px; margin-bottom: 12px; }
    .hero p { font-size: 12.5px; line-height: 1.7; margin-bottom: 18px; }
    .hero-actions { gap: 9px; }
    .hero-actions .btn { padding: 11px 18px; font-size: 14px; }
    /* ⚠️ 必须 > 30px：快捷卡片压进 hero 48px（`.quick{margin-top:-48px}`），
       而手机上「活动页文字结束」到「卡片行开始」只有约 44px 空地，
       指示点占 32px —— 16px 时正好被卡片顶端擦到（中心点只差 2px 就点不到了）。
       36px 落在这 44px 空地的中间，桌面那边同样是 64px + z-index:7。 */
    .hero-dots { bottom: 36px; }
    .hero-dots button { width: 24px; }
}

/* 小屏手机（320~360）再收一档。 */
@media (max-width: 360px) {
    .hero { height: 470px; }
    .hero h1 { font-size: 23px; }
    .hero p { font-size: 12px; }
    .hero-tag { font-size: 11px; }
    .hero-actions .btn { padding: 10px 14px; font-size: 13.5px; }
    /* ⚠️ 别在这里再改 .hero-flag 的高度：v2.27 起它是**整屏背景**，
       写死高度会把它变回"顶部一条横幅"，断层感就又回来了。 */
}

/* ---------- ⑥ internal 的弹窗：手机全屏 ---------- */
@media (max-width: 768px) {
    .pv-overlay, .sc-overlay {
        padding: 0;
        align-items: stretch;
    }
    .pv-box, .sc-box {
        max-width: 100%;
        width: 100%;
        height: 100%;
        max-height: 100%;
        border-radius: 0;
        padding: 14px 12px;
        box-sizing: border-box;
    }
    /* 弹窗里的行内小按钮也加大 */
    .sc-list .row button,
    .sched-actions button, .cmp-pick button,
    .sched-stack-toggle {
        min-height: 38px;
    }
    /* 上传区的输入框堆叠 */
    .sched-upload, .sc-media-upload { flex-direction: column; align-items: stretch; }
    .sched-upload select, .sched-upload input[type=text] { width: 100%; }
    /* 多行工具条允许换行 */
    .sc-sites { flex-wrap: wrap; }
}

@media (max-width: 768px) {
/* ---------- ⑥b 各页面的小控件补丁（体检实测点名出来的） ---------- */
    /* 主题色块 34px（够点，且不挤） */
    .p-theme button, .g-theme button { width: 34px; height: 34px; }
    .p-brand, .g-brand { min-height: 40px; align-items: center; }
    /* gallery 顶部「登录」链接：别被挤成 27px 宽 */
    .g-tip a { min-width: 44px; text-align: center; }
    /* gallery 搜索框：手机端占满可用宽度 */
    .g-search input { width: auto; max-width: 100%; flex: 1; min-width: 0; }
    /* index 动态速递跑马灯：纵向加高好点，横向不动（保无缝循环） */
    .ticker-group a {
        min-height: 40px;
        display: inline-flex;
        align-items: center;
    }
    .ticker-inner { min-height: 40px; }
    .ticker-label { align-self: stretch; display: inline-flex; align-items: center; }
    /* gallery 视图切换 tab / 登录弹窗 tab */
    .g-view button { min-height: 40px; }
    .g-tabs button { min-height: 38px; min-width: 64px; }
    /* gallery 顶部的「登录」小链接（JS 注入的 #gLoginTip） */
    .g-tip a { display: inline-block; min-height: 34px; line-height: 34px; padding: 0 4px; }
    /* internal 登录区的「点此注册」小链接 */
    .reg-line a {
        display: inline-block;
        min-height: 36px;
        line-height: 36px;
        padding: 0 8px;
    }
    .reg-line { min-height: 40px; display: flex; align-items: center; justify-content: center; gap: 4px; }
    /* glory 的赛事筛选 chip */
    .p-chip { min-height: 36px; }

/* ---------- ⑥c 最后一轮小控件（体检点名） ---------- */
    /* index 页脚链接 */
    .site-footer a { min-height: 32px; display: inline-flex; align-items: center; }
    /* youth 名人名言轮播圆点：视觉 10px，点击区 22px */
    .q-dots button { width: 10px; height: 10px; padding: 6px; background-clip: content-box; border-radius: 999px; }
    /* showcase 本月最热小链接 */
    #hotBoard a { display: inline-block; min-height: 32px; line-height: 32px; padding: 0 6px; }
    /* showcase 卡片装饰光斑手机端直接关掉（纯装饰） */
    .p-glow { display: none; }

/* ---------- ⑥d 最后两处（体检点名） ---------- */
    /* youth 名言轮播圆点：跟页面自己的选择器同级才能压过它 */
    .quote .q-dots button {
        width: 32px; height: 32px; padding: 11px;
        background-clip: content-box; border-radius: 999px;
    }
    /* index 首页 hero 轮播条：纵向加出点击区，横向不动 */
    .hero-dots button {
        min-width: 32px;
        height: 32px;
        padding: 0;
        background-clip: content-box;
    }
    /* index 登录弹窗里的小链接 */
    #pcGoReg, #pcQuickLogin {
        display: inline-block;
        min-height: 34px;
        line-height: 34px;
        padding: 0 6px;
    }
}

/* ---------- ⑥e 超窄屏（≤340px）：头部换行 ---------- */
@media (max-width: 340px) {
    .p-top, .g-top { flex-wrap: wrap; }
    .p-brand, .g-brand { flex: 1 1 100%; }
    .p-theme, .g-theme { margin-left: auto; }
    .p-brand b, .g-brand b { font-size: 12.5px; }
    .p-btn, .g-btn { font-size: 12px; padding: 6px 10px; }
}

/* ---------- ⑥f v2.17：超窄屏（≤380px）头部再把 gap 收一档 ----------
   实测：gallery 在 360px 下**整页能左右拖着走**（多出 6px）。
   根源是头部那几个「0 宽占位元素」（`.g-brand` / `.spacer` 实测宽度都是 0）
   照样各吃掉一个 8px 的 gap —— 那几个 gap 是净损耗。
   与其现在去动队名排版（那属于子站改版要处理的事），先把 gap 收紧更安全。
   ⚠️ 只作用于 ≤380px 的手机：电脑 / 平板 / 大屏手机都不受影响。 */
@media (max-width: 380px) {
    html[data-mnav="on"] .g-top,
    html[data-mnav="on"] .p-top { gap: 4px; }
}

/* ---------- ⑦ 小屏微调 ---------- */
@media (max-width: 480px) {
    .p-hero h1 { font-size: 21px; }
    .internal-grid, .news-grid, .quick-grid,
    .dept-grid, .video-grid, .edu-grid, .rule-list {
        grid-template-columns: 1fr;
    }
    .footer-grid { grid-template-columns: 1fr; }
}

/* ---------- ⑧ index 个人中心：侧栏不许吃掉整个弹窗（v1.87 修）---------- */
@media (max-width: 768px) {
    /* 手机上 .pc-window 变成竖排（≤900px 断点），侧栏在上、内容区在下。
       侧栏里最多有 20 个菜单按钮（队员 9 + 管理 11 + 退出），
       一旦它的高度涨到弹窗高度，下面的 .pc-main 就会被 flex 压成 0px ——
       菜单点得动、面板也切了，但内容区只剩一条缝，看起来就是「点了没反应」。
       所以：侧栏可缩 + 封顶 + 自己滚；内容区给一个保底高度。 */
    .pc-side {
        flex: 0 1 auto;              /* 允许被压缩（原来 flex:none，一步不让） */
        max-height: 52vh;            /* 封顶：够放 20 个菜单按钮，又不至于把内容区挤没 */
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        padding: 12px 12px 10px;
    }
    .pc-menu {
        flex: none;                  /* 别再跟着侧栏一起拉伸（桌面是 flex:1 撑满侧栏） */
        margin-top: 10px;
    }
    .pc-main {
        flex: 1 1 auto;
        min-height: 140px;           /* 保底：宁可让侧栏滚，也不许内容区消失 */
    }
    /* 用户卡片收紧，把纵向空间让给内容区 */
    .pc-user { padding-bottom: 8px; }
    .pc-avatar { width: 44px; height: 44px; font-size: 18px; margin-bottom: 8px; }
    .pc-avatar-wrap { width: 44px; }
    .pc-user h4 { font-size: 15px; margin: 0 0 2px; }
    .pc-user p { margin: 2px 0; }
    .pc-logout { min-height: 36px; }
    /* 管理功能折叠（v1.87）：手机上默认收起，点标题展开。
       类名由 JS 加，万一 JS 没跑就没有这个类 —— 菜单照常全展开，不会卡死。 */
    #adminMenu .pc-menu-title {
        min-height: 36px;
        display: flex;
        align-items: center;
        margin: 0 0 4px;
        cursor: pointer;
        user-select: none;
    }
    #adminMenu.is-collapsed .pc-menu-title { margin-bottom: 0; }
    #adminMenu.is-collapsed button { display: none; }
}

/* ============================================================
   ⑨ 手机端全站导航（v1.88）
   ------------------------------------------------------------
   背景：子站之间原本没有任何互链，从「国防教育」想去「赛场荣光」
   要回主页再点风采展示再点进去，至少 3 次跳转。
   现在每个子页面头部多一个汉堡按钮 → 全屏导航；原来占 35% 屏宽的
   4 个主题色块收进一个下拉；长页面多了回顶按钮。

   铁律：**桌面端一像素不动**。下面所有注入的元素在宽屏一律 display:none，
   手机端也要等 JS 给 <html> 加上 data-mnav="on" 才显示 ——
   JS 挂了就没有这个属性，头部跟以前一模一样。
   ============================================================ */

/* 宽屏（>768px）：这些元素只服务手机，一律不出现 */
@media (min-width: 769px) {
    .mnav-btn, .mnav-theme, .mnav-sheet, .mnav-mask, .mnav-top { display: none !important; }
}

@media (max-width: 768px) {
    /* 手机端默认也先藏起来，由 data-mnav 打开 */
    .mnav-btn, .mnav-theme, .mnav-sheet, .mnav-mask, .mnav-top { display: none; }

    /* ---- 头部：队名 + 主题 + 汉堡 ---- */
    html[data-mnav="on"] .mnav-theme { display: block; }
    html[data-mnav="on"] .mnav-btn { display: inline-flex; }
    /* 4 个主题色块（占 136px＝35% 屏宽）和「返回主站」都收进菜单，
       腾出来的宽度全给队名 —— 以前队名基本是被挤没的。
       队名徽标本身就是回首页的链接，所以去掉「返回主站」不丢功能。 */
    html[data-mnav="on"] .p-theme,
    html[data-mnav="on"] .g-theme,
    html[data-mnav="on"] .p-btn { display: none; }

    /* 头部按钮跟随主题的玻璃质感，跟 .p-btn 同一套变量 */
    html[data-mnav="on"] .mnav-btn,
    html[data-mnav="on"] .mnav-theme-btn {
        align-items: center; justify-content: center; gap: 6px;
        flex: none; min-height: 40px; padding: 0;
        /* 顶栏是红底时用 --hdr-* 这组反白变量；没设的页面自动退回原样 */
        border: 1px solid var(--hdr-line, var(--line)); border-radius: 10px;
        background: var(--hdr-btn-bg, rgba(var(--glass-rgb), .6));
        color: var(--hdr-ink, var(--ink)); font-family: inherit; font-size: 13px;
        cursor: pointer; -webkit-appearance: none; appearance: none;
    }
    html[data-mnav="on"] .mnav-btn { width: 40px; }
    html[data-mnav="on"] .mnav-theme-btn { padding: 0 11px; }
    html[data-mnav="on"] .mnav-btn:active,
    html[data-mnav="on"] .mnav-theme-btn:active { background: var(--hdr-btn-bg-hover, rgba(var(--glass-rgb), .95)); }

    /* 汉堡三道杠 */
    .mnav-bars, .mnav-bars::before, .mnav-bars::after {
        display: block; width: 18px; height: 2px; border-radius: 2px;
        background: currentColor;
    }
    .mnav-bars { position: relative; }
    .mnav-bars::before, .mnav-bars::after { content: ''; position: absolute; left: 0; }
    .mnav-bars::before { top: -6px; }
    .mnav-bars::after { top: 6px; }

    /* 主题按钮上的小圆点：底色由页面自己的 .t-* 给，这里只管尺寸 */
    .mnav-dot { width: 16px; height: 16px; border-radius: 50%; flex: none;
                box-shadow: 0 0 0 1px var(--hdr-line, var(--line)); }
    .mnav-theme-txt { white-space: nowrap; }

    /* 主题下拉 */
    .mnav-theme { position: relative; }
    .mnav-theme-menu {
        position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
        min-width: 148px; padding: 6px;
        background: var(--surface); border: 1px solid var(--line);
        border-radius: 12px; box-shadow: var(--shadow-lg);
        display: none;
    }
    html[data-mnav="on"] .mnav-theme.is-open .mnav-theme-menu { display: block; }
    .mnav-theme-item {
        display: flex; align-items: center; gap: 9px; width: 100%;
        min-height: 42px; padding: 0 10px;
        border: 0; border-radius: 8px; background: transparent;
        color: var(--ink); font-family: inherit; font-size: 13.5px;
        text-align: left; cursor: pointer;
    }
    .mnav-theme-item:active { background: var(--surface-2); }
    .mnav-theme-item.is-active { color: var(--red-ink); font-weight: 700; }
    .mnav-sw { width: 16px; height: 16px; border-radius: 50%; flex: none;
               box-shadow: 0 0 0 1px var(--line); }

    /* ---- 全屏导航 ---- */
    html[data-mnav="on"].mnav-open .mnav-mask {
        display: block; position: fixed; inset: 0; z-index: 9997;
        background: rgba(8, 14, 28, .45);
    }
    html[data-mnav="on"].mnav-open .mnav-sheet {
        display: flex; flex-direction: column;
        position: fixed; inset: 0; z-index: 9998;
        background: var(--bg); color: var(--ink);
        animation: mnav-in .22s ease;
    }
    @keyframes mnav-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }

    .mnav-sheet-top {
        flex: none; display: flex; align-items: center; gap: 10px;
        padding: 10px 14px; min-height: 56px;
        border-bottom: 1px solid var(--line);
        background: var(--surface);
    }
    .mnav-sheet-brand {
        flex: 1 1 auto; min-width: 0; font-size: 14.5px; font-weight: 700;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .mnav-close {
        flex: none; width: 40px; height: 40px;
        border: 1px solid var(--line); border-radius: 10px;
        background: var(--surface-2); color: var(--ink);
        font-size: 16px; line-height: 1; cursor: pointer;
    }
    .mnav-sheet-body {
        flex: 1 1 auto; overflow-y: auto; -webkit-overflow-scrolling: touch;
        padding: 6px 14px 26px;
    }
    .mnav-group { margin-top: 14px; }
    .mnav-group-title {
        font-size: 11.5px; letter-spacing: 1px; color: var(--gray);
        margin: 0 0 6px; font-weight: 700;
    }
    .mnav-item {
        display: flex; align-items: center; gap: 12px;
        min-height: 50px; padding: 0 12px; margin-bottom: 4px;
        border-radius: 11px; text-decoration: none; color: var(--ink);
        background: var(--surface); border: 1px solid var(--line);
        font-size: 14.5px;
    }
    .mnav-item:active { background: var(--surface-2); }
    .mnav-item.is-here { border-color: var(--red); color: var(--red-ink); font-weight: 700; }
    .mnav-ico { font-size: 17px; width: 22px; text-align: center; flex: none; }
    .mnav-txt { flex: 1 1 auto; min-width: 0; }
    .mnav-here { flex: none; font-size: 11px; color: var(--gray); font-weight: 400; }

    /* ---- 回顶（长页面才出现） ---- */
    html[data-mnav="on"] .mnav-top.is-show {
        display: flex; align-items: center; justify-content: center;
        position: fixed; right: 14px; bottom: 18px; z-index: 60;
        width: 46px; height: 46px; border-radius: 50%;
        border: 1px solid var(--line); background: var(--surface);
        color: var(--ink); font-size: 19px; cursor: pointer;
        box-shadow: var(--shadow-lg);
    }

    /* 点按高亮改成跟主题协调的红，替掉浏览器默认的蓝色 */
    html[data-mnav="on"] a,
    html[data-mnav="on"] button { -webkit-tap-highlight-color: rgba(200, 16, 46, .16); }
}

/* ⚠️ 这一条**故意放在媒体查询外面**（桌面端要它生效）：
   `.wk-peek` 是手机端"收起时的概览行"，电脑端**一个字都不该多出来** ——
   桌面端打开某一天时，那一行如果跟着显示，就是"桌面被改动了"。
   手机端由下面 ≤768px 那条把它打开。 */
.wk-peek { display: none; }

/* ============================================================
   v2.18 · 移动端版式（第一阶段：首页 + 课表）
   ------------------------------------------------------------
   兄长 2026-10-09：「彻底改变移动端布局……提升简洁与直观性」。
   v2.17 铺好了地基层（底栏 / 设计令牌 / 安全区），这一版开始按页改版。

   这一节两件事：
     ⑨ 个人中心（手机上是个整屏弹窗）：**侧栏菜单改成顶部横向标签条**
        —— 手机屏宽只够 224px 的侧栏 + 内容挤在一起，10 个面板要滚半天，
        还看不出自己在哪一栏。
     ⑩ 课表：**一周概览 + 点开看详情**（他明确选的那种）
        —— 原来手机上 7 天全展开，一屏只塞得下两天，翻半天找不到今天。
   ⚠️ 全部收在媒体查询里，桌面端一像素不动。
   ============================================================ */

/* ---------- ⑨ 个人中心：手机整屏 + 面板菜单横滑 ---------- */
@media (max-width: 768px) {
    .pc-overlay { padding: 0; align-items: stretch; }
    .pc-window {
        width: 100%; max-width: 100%;
        height: 100% !important; max-height: 100%;
        border-radius: 0;
        flex-direction: column;
    }
    .pc-side {
        width: 100%; flex: none;
        padding: 12px 12px 0;
        /* 原来那条 168° 的深色渐变保留（辨识度靠它），只是压扁成一条 */
        background: linear-gradient(160deg, #1E0A0E 0%, #A81228 78%, #4B5320 145%);
    }
    /* 用户区：头像 + 名字 + 身份压成一行，别占半屏 */
    .pc-user {
        display: flex; align-items: center; gap: 10px;
        text-align: left; padding: 2px 0 10px; border-bottom: 0;
    }
    .pc-avatar { width: 44px; height: 44px; margin: 0; font-size: 20px; }
    .pc-user h4 { margin: 0; font-size: 15px; }
    .pc-user p { margin: 2px 0 0; font-size: 12px; opacity: .8; }
    /* 面板菜单：横向可滑的胶囊条（图标+文字，点按 ≥44px） */
    .pc-menu {
        display: flex; flex-wrap: nowrap; gap: 8px;
        overflow-x: auto; overflow-y: hidden;
        margin: 0 -12px; padding: 6px 12px 12px;
        scrollbar-width: none; -webkit-overflow-scrolling: touch;
        overscroll-behavior-x: contain;      /* 滑到头别触发"返回上一页" */
    }
    .pc-menu::-webkit-scrollbar { display: none; }
    .pc-menu button {
        flex: 0 0 auto;
        min-height: 44px;                     /* 手指够得着（WCAG/Apple/Google 都过） */
        padding: 0 14px;
        border-radius: 999px;
        white-space: nowrap;
        font-size: 13.5px;
        background: rgba(255, 255, 255, .14);
        color: #fff;
        border: 1px solid rgba(255, 255, 255, .18);
    }
    .pc-menu button.is-active {
        background: #fff; color: #A81228; font-weight: 700;
        border-color: #fff;
    }
    /* 「管理功能」这种分组小标题在横向条里纯占地方 */
    .pc-menu-title { display: none; }
    /* 内容区：自己滚，底部给标签栏留出位置 */
    .pc-main {
        padding: 14px 12px calc(var(--m-tab-h, 56px) + 24px);
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }
    /* 弹窗右上角的 × ：手机上必须够大够好点（最常被骂的元素） */
    .pc-close { width: 44px; height: 44px; top: 6px; right: 6px; font-size: 22px; }
}

/* ---------- ⑩ 课表：一周概览 + 点开看详情（他选的那种） ----------
   原来的手机规则（在 index.html 的 820px 媒体查询里）是「7 天全展开」，
   一屏只放得下两天。现在改成：**每天一张卡，默认只露标题与概览，点开才看详情**；
   今天那一张默认是打开的（一进来就看到今天上什么）。
   ⚠️ 只作用于 ≤768px；769~820px 仍然走"全展开"的老行为，互不干扰。 */
@media (max-width: 768px) {
    #wkDetail { padding: 0 2px 8px; }
    #wkDetail .wk-day {
        display: block;                        /* 覆盖 index 里 820px 那条"全展开" */
        background: var(--m-card, var(--surface, #fff));
        border: 1px solid var(--m-line-c, var(--line, rgba(17, 24, 39, .08)));
        border-radius: var(--m-r, 14px);
        margin: 0 0 10px;
        padding: 0 12px;
        overflow: hidden;
    }
    /* 标题行 = 可点的概览：周几 + 几节课 + 前两门课名 */
    #wkDetail .wk-day > h5 {
        display: flex; align-items: center; gap: 8px;
        min-height: 52px;                      /* 整行可点，手指够得着 */
        margin: 0; padding: 0;
        cursor: pointer;
        font-size: 15px;
        touch-action: manipulation;
    }
    #wkDetail .wk-day > h5 span {
        margin-left: auto; flex: none;
        font-size: 12px; color: var(--m-ink-2, var(--gray, #6b7280)); font-weight: 400;
    }
    /* 折叠箭头：只用 transform 转，不做高度动画（高度动画在中低端安卓必掉帧） */
    #wkDetail .wk-day > h5::after {
        content: '›';
        flex: none; margin-left: 6px;
        font-size: 20px; line-height: 1; color: var(--m-ink-2, var(--gray, #6b7280));
        transition: transform .18s ease;
    }
    #wkDetail .wk-day.is-open > h5::after { transform: rotate(90deg); }
    /* 概览预览：收起时显示（第一行课名），展开后让位给完整列表 */
    #wkDetail .wk-day > .wk-peek {
        display: block;
        margin: -6px 0 12px;
        font-size: 12.5px; color: var(--m-ink-2, var(--gray, #6b7280));
        white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    #wkDetail .wk-day.is-open > .wk-peek { display: none; }
    /* 详情：收起时不渲染（display:none 而不是高度动画） */
    #wkDetail .wk-day:not(.is-open) > .wk-ev,
    #wkDetail .wk-day:not(.is-open) > .wk-free { display: none; }
    #wkDetail .wk-day.is-open { padding-bottom: 10px; }
    /* 详情行：时间在上、课名在下（手机竖着读），别硬挤成一行 */
    #wkDetail .wk-ev {
        display: block;
        padding: 8px 0;
        border-top: 1px solid var(--m-line-c, rgba(17, 24, 39, .08));
        font-size: 14px;
    }
    #wkDetail .wk-ev .t {
        display: block; width: auto;
        font-size: 12px; color: var(--m-ink-2, var(--gray, #6b7280));
    }
    #wkDetail .wk-ev .n { font-weight: 600; }
    #wkDetail .wk-ev .m { margin-left: 6px; font-size: 12px; color: var(--m-ink-2, var(--gray, #6b7280)); }
    /* 今天那一张给个左边框，一眼看出是哪天 */
    #wkDetail .wk-day.is-today { border-left: 3px solid var(--m-accent, var(--red, #c8102e)); }
    /* 翻周的按钮排一行别挤成一团 */
    .wk-bar { flex-wrap: wrap; gap: 8px; }
    .wk-nav, .wk-btn { min-height: 44px; }
    .wk-title { min-width: 0; font-size: 14px; }
}

/* ============================================================
   v2.19 · 移动端版式（第二阶段：内部协同）
   ------------------------------------------------------------
   内部协同是**队部用的后台**，手机上最难受的是三张宽表：
     · 课表校正 `.calib-grid`（每格一个输入框，一格 108px 宽）
     · 值班排班 `.duty-grid`
     · 考勤热力 `.heat-grid`
   这三张表在 390px 的屏上必然横向超出，而"横着滑"本身**发现性很差** ——
   用户看到半张表，往往以为就这么多。

   所以这一版做三件事（都只作用于手机）：
     ① **左侧「节次」那一列粘住**（sticky）—— 横滑的时候始终知道自己在看第几节
     ② 滑动容器顶部加一行**明确提示**「← 左右滑动看全表 →」，且它自己也粘住
     ③ 表里的输入框/按钮放大到能点（≥44px），校正输入框放宽一点，别挤成一条
   ⚠️ sticky 只用「不透明底色 + 定位」，**不加圆角/阴影/overflow:clip** ——
      iOS WebKit 上那两个属性跟 sticky 一起用会触发滚动冻结（研究员查到的真 bug）。
   ============================================================ */
@media (max-width: 768px) {
    /* ⓪ 先解决"谁来滚"的问题（这一条是量出来才发现的）：
       mobile.css 第 ① 段给**所有** table 设了 `display:block; overflow-x:auto; max-width:100%`，
       于是这三张宽表变成"**表格自己**是滚动容器" —— 后果是：
         · 外面那层 `.calib-wrap` 永远不溢出 → 我加在它上面的"滑动提示"永远不出现；
         · 左列 sticky 是相对表格自己的滚动盒，行为没错但和提示/量宽对不上。
       所以这里把这三张表改回**正常表格**、宽度由内容决定，**让外面的 wrap 来滚**：
       这样"提示 + 粘列 + 量宽"三者才是同一件事。
       ⚠️ 只对这三张表这么做，别的表（成员表、考勤明细）保持原样。 */
    .calib-wrap, .duty-wrap {
        overflow-x: auto;
        overflow-y: visible;          /* 别同时设 y:auto，否则 sticky 会失效 */
        overscroll-behavior-x: contain;   /* 横滑到头别触发"返回上一页" */
        max-width: 100%;
    }
    table.calib-grid, table.heat-grid, table.duty-grid {
        display: table;               /* 覆盖第 ① 段的 table{display:block} */
        max-width: none;
        min-width: max-content;       /* 宽度由内容决定 → 外面的 wrap 溢出 → 由 wrap 滚 */
    }

    /* ① + ② 三张宽表：粘住左列 + 滑动提示 */
    .calib-wrap, .duty-wrap { position: relative; }
    .calib-wrap::before,
    .duty-wrap::before {
        content: '← 左右滑动看全表 →';
        position: sticky;         /* 跟着一起横滑时它自己不动，始终看得见 */
        left: 0;
        display: block;
        padding: 2px 0 6px;
        font-size: 11.5px;
        color: var(--m-ink-2, var(--gray, #6b7280));
        background: var(--m-bg, var(--bg, transparent));
        z-index: 3;
    }
    /* 只在"真的需要横滑"时才提示 —— 用 max-width 判断不了，交给 JS 加类（见 mobile-shell.js）：
       `.m-wide` 是 JS 量出来 scrollWidth > clientWidth 之后加的 */
    .calib-wrap:not(.m-wide)::before,
    .duty-wrap:not(.m-wide)::before { content: none; }

    /* 左列（节次/时间）粘住 */
    table.calib-grid td.slot-h,
    table.heat-grid td.slot-h,
    .duty-grid td.duty-slot,
    .duty-grid th:first-child {
        position: sticky;
        left: 0;
        z-index: 2;
        /* ⚠️ 必须不透明，否则横滑时下面的格子会透上来 */
        background: var(--m-card, var(--surface, #fff));
    }
    /* 表头第一格（左上角）盖住左列，层级最高 */
    table.calib-grid th:first-child,
    table.heat-grid th:first-child {
        position: sticky; left: 0; z-index: 3;
        background: var(--m-card, var(--surface, #fff));
    }

    /* ③ 表格里的控件放大到能点 */
    table.calib-grid td input {
        width: 132px;              /* 原来 108px，中文课名放不下 */
        min-height: 46px;          /* 实测：写 44 量出来是 42（边框/取整），抬到 46 才稳过 44 */
        box-sizing: border-box;
        font-size: 13px;           /* 原来 11px，手机上太小 */
    }

    /* 后台里的按钮：工具条 / 翻页 / 保存这类**一律 ≥44px**。
       ⚠️ 为什么用这么宽的 `:not()` 选择器而不是逐个点名：
          实测点名点漏过两次（「🧹 全部清空」42px、「← 上一周」24px 都是漏网的，
          而且它们在**课表中心那个弹窗**里，不在 `.portal` 里 —— 第一版白名单写窄了），
          后台按钮还在持续增加 —— 与其追着补，不如按"容器"一刀切。 */
    .portal button:not([class*="close"]),
    .portal .btn-red,
    .portal [role="button"],
    .sc-box button:not([class*="close"]),
    .pv-box button:not([class*="close"]),
    .admin-editor button:not([class*="close"]) { min-height: 44px; box-sizing: border-box; }
    /* 手机端：一键审核按钮整行、≥48px（它是这一屏里最容易误点的"重操作"，
       做得大好点、也好读清楚它影响多少人） */
    #reviewApproveAll {
        flex: 1 1 100%;
        min-height: 48px;
        justify-content: center;
        font-size: 15px;
    }
    /* 报名审核那一条工具条在手机上换行排（chips 一行、搜索一行、按钮一行） */
    #apane-review .toolbar { flex-wrap: wrap; gap: 8px; }
    #apane-review .adm-search { flex: 1 1 100%; min-height: 44px; }

    /* 报名/成员两张宽表：手机上横向可滑，别把弹窗撑破 */
    #apane-review .table-wrap, #apane-members .table-wrap {
        overflow-x: auto;
        overscroll-behavior-x: contain;
    }

    .calib-actions button,
    .sc-list .row button,
    .sched-actions button,
    .sched-stack-toggle { min-height: 44px; }

    /* 欢迎区的动作按钮：手机上一列放一个，别两个挤在一起 */
    .w-actions { grid-template-columns: 1fr; max-width: none; }
    .w-action { min-height: 56px; }
    .w-logout { min-height: 44px; }

    /* 登录 / 注册那种表单：按钮整行、输入框够高 */
    .portal .btn-red, .portal button[type="submit"] { min-height: 48px; width: 100%; }
    .portal .login-tabs button { min-height: 44px; }
    /* 玻璃拟态在手机上很费（逐帧模糊背景）：静态卡片留着，
       但把**整块 portal 的大面积毛玻璃**换成不透明底色，滚动立刻顺一截 */
    .portal {
        -webkit-backdrop-filter: none; backdrop-filter: none;
        background: var(--m-card, var(--surface, #fff));
    }
    .internal-card {
        -webkit-backdrop-filter: none; backdrop-filter: none;
        background: var(--m-card, var(--surface, #fff));
        padding: 16px;
    }
}

/* ============================================================
   v2.20 · 移动端版式（第三阶段：我们的时间（照片墙）+ 招新报名（表单））
   ------------------------------------------------------------
   这两页在手机上各有各的毛病：
     · 照片墙：卡片最小 210px → 390px 的屏上只能排 1 列，一屏看一张照片，
       翻半天；而且每张卡片都带毛玻璃，几十张卡片滚起来很费。
     · 招新报名：输入框 13.5px —— **iOS 聚焦时会自动放大整页**（页面突然能横拖，
       用户得手动缩回去）；提交按钮也不是整行的。
   下面 ⑫ 管照片墙、⑬ 管表单。依旧全部收在媒体查询里，桌面一像素不动。
   ============================================================ */

/* ---------- ⑫ 我们的时间（照片墙） ---------- */
@media (max-width: 768px) {
    /* 顶部是 sticky 的，还带 16px 毛玻璃 —— 滚动时每帧都要重绘它后面的照片，
       是这一页最贵的一处。**只关毛玻璃，绝不动它的背景色**。
       ⚠️⚠️ 这里踩过一个很隐蔽的坑（v2.20 埋的，v2.22 的浅色截图才露出来）：
       我当时顺手把背景写成了 `background: var(--m-card, …)`（想让它不透明），
       结果**把页头原来那条红旗红渐变顶掉了**，而页头文字色仍是 `--hdr-ink`（白）——
       于是**浅色主题下变成白字白底，整个页头的按钮全看不见了**。
       深色主题下 `--surface` 恰好是深色，所以一直没露馅（断言也全绿）。
       结论：页头的背景归**页面自己**管，手机端只允许"关掉毛玻璃"。 */
    .g-top {
        -webkit-backdrop-filter: none; backdrop-filter: none;
        padding: 10px 12px;
        gap: 8px;
        border-bottom: 1px solid var(--m-line-c, var(--line, transparent));
    }

    /* 两列瀑布（原来 210px 最小宽 → 手机上只有 1 列） */
    .g-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }

    /* ⚠️ 每张卡片都带 18px 毛玻璃 + 阴影：几十张一起滚，中低端安卓必掉帧。
       手机端去掉毛玻璃（换不透明底色），并让**屏幕外的卡片先不渲染**。 */
    .g-card {
        -webkit-backdrop-filter: none; backdrop-filter: none;
        background: var(--m-card, var(--surface, #fff));
        border-radius: 12px;
        /* content-visibility 是研究简报里收益最大的一条；
           ⚠️ 必须配 contain-intrinsic-size，否则滚动条长度会乱跳。 */
        content-visibility: auto;
        contain-intrinsic-size: 0 180px;
    }

    /* 上传入口：整行一个大按钮，别缩成小格子 */
    .g-upload {
        grid-column: 1 / -1;
        min-height: 64px;
        justify-content: center;
        -webkit-backdrop-filter: none; backdrop-filter: none;
        background: var(--m-card, var(--surface, #fff));
    }

    /* 工具条 / 铃铛 / 分类下拉：手机上换行 + 够大 */
    .g-tools { flex-wrap: wrap; gap: 8px; }
    .g-tools button, .g-tools select, .g-tools a,
    .g-bell, .g-btn, .g-chip { min-height: 44px; }

    /* 灯箱（点开看大图）：手机上整屏、**去掉毛玻璃** ——
       整屏模糊是全站最贵的一处渲染，而且这里还是"边看边滑"的场景。 */
    .g-lb {
        padding: 0;
        -webkit-backdrop-filter: none; backdrop-filter: none;
        background: rgba(8, 12, 24, .94);
    }
    .g-lb .g-lb-box, .g-lb img { max-width: 100%; max-height: 100%; }
    /* 灯箱里的操作按钮（点赞/收藏/评论/关闭）≥44px */
    .g-lb button, .g-lb .g-act { min-height: 44px; }

    /* 批量管理的操作条换行 */
    .g-batchbar, .g-batch { display: flex; flex-wrap: wrap; gap: 8px; }
}

/* ---------- ⑬ 招新报名（表单） ---------- */
@media (max-width: 768px) {    /* ⚠️ 这一条是**必须**的：`.field input { font-size: 13.5px }` 的权重比全局
       `input { font-size: 16px }` 高，所以要在手机媒体查询里点名压过去。
       字号 <16px 时 iOS Safari 会在聚焦瞬间**自动放大整页** ——
       新生填表时页面突然能横向拖，非常难受。 */
    .field input, .field select, .field textarea,
    input[type="text"], input[type="tel"], input[type="number"],
    input[type="password"], input[type="email"], textarea, select {
        font-size: 16px;
    }

    /* 字段间距和标签：手机上放松一点、标签 14px */
    .field { margin-bottom: 16px; }
    .field label { font-size: 14px; margin-bottom: 6px; }
    /* ⚠️ 别给文字容器写死高度（微信字体放大 8 档会把字撑出框）；
       textarea 给个最小高度就够，让它随内容长。 */
    .field textarea { min-height: 104px; }
    /* 输入框本身 ≥48px 高，手指点得准 */
    .field input, .field select { min-height: 48px; }

    /* 提交按钮：整行、48px、字大一点 */
    .form-actions { flex-direction: column; align-items: stretch; gap: 8px; }
    .form-actions button[type="submit"], .form-actions .btn-red {
        width: 100%; min-height: 48px; font-size: 16px;
    }
    /* 提示文字在按钮下面居中，别挤在右边 */
    .form-actions .form-tip { text-align: center; }
    /* 错误/成功提示跟着表单走（原来在表单底部，长表单要滚到底才看见） */
    .form-msg { font-size: 14px; }

    /* 列表首个字段上边留点空（跳转锚点落下来时标题才不会被顶栏压住） */
    #joinForm { scroll-margin-top: 70px; }
}

/* ---------- ⑭ 移动端专属小部件 ---------- */
/* `.m-only`：桌面**必须**看不见的东西（跳转入口这类）。
   ⚠️ 基础层写 display:none 是故意的 —— 反过来的话，桌面会突然多出一个蓝链接
   （v2.17 底栏就踩过这个坑：桌面出现过一排没样式的蓝链接）。 */
.m-only { display: none; }

@media (max-width: 768px) {
    /* 招新页的"↓ 直接去填报名表"：手机上公告很长，得给个直达入口 */
    .m-jump {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-height: 46px;                 /* 手指够得着 */
        margin-top: 16px;
        padding: 0 20px;
        border-radius: 999px;
        background: var(--m-card, var(--surface, #fff));
        color: var(--m-accent, var(--red, #c8102e));
        border: 1px solid currentColor;
        font-size: 15px;
        font-weight: 700;
        text-decoration: none;
    }
    .m-jump:active { opacity: .75; }
}

/* ============================================================
   v2.21 · 移动端版式（第四阶段：六个子站 + 国防教育 + 风采展示 + 下载 App）
   ------------------------------------------------------------
   这些页面（education / exchange / forge / glory / legacy / moments /
   showcase / youth / app）**共用同一套骨架**（.p-top / .p-hero / .p-main /
   .sub-title / .sync-grid），各自只有一小块独有的模块。

   所以这一版不逐个页面重写，而是：先把"共用骨架"的手机体验一次修好（⑮），
   再单独处理下载页（⑯，它是唯一有二维码和下载按钮的页面）。

   ⚠️ 先量后改：写这一节之前先在 390×844 上把九个页面都量了一遍
   （`jstest/_diag_phase4.mjs`），结论是：
     · 横向溢出 **0**、图片变形 **0** —— 这九个页面"没有坏"
     · 真正的问题只有两类：**控件太小**（36~40px）和**字太小**（11~11.5px）
   所以这一节就是照这两条改，不做花活。
   ============================================================ */

/* ---------- ⑮ 子站共用骨架：控件够大、小字看得清 ---------- */
@media (max-width: 768px) {
    /* 页头：品牌链接 / 返回按钮 / 主题按钮 / 汉堡 —— 一律 ≥44px 高。
       这几个是**每个页面都有**的入口，之前量出来是 40×40。
       （40×40 只比 44 差一点，但它是"每页第一个要点的地方"，值得较真。） */
    .p-brand, .g-brand { min-height: 44px; }
    .p-btn, .g-btn, .p-go, .p-glow { min-height: 44px; }
    html[data-mnav="on"] .mnav-btn,
    html[data-mnav="on"] .mnav-theme-btn { min-width: 44px; min-height: 44px; }

    /* 筛选胶囊（"全部赛事 / 省级 / 市级…"、"全部年份 / 2025 年…"）——
       手机上这排是最常点的东西，之前 36px 高。加高 + 给点左右内边距，
       顺便让它们横向能滑（年份多的时候不要挤成两行把页面顶下去）。 */
    .p-chip {
        min-height: 44px;
        padding: 0 16px;
        font-size: 13.5px;
    }
    .p-chips {
        display: flex; flex-wrap: nowrap;
        gap: 8px; overflow-x: auto;
        scrollbar-width: none; -webkit-overflow-scrolling: touch;
        overscroll-behavior-x: contain;
    }
    .p-chips::-webkit-scrollbar { display: none; }

    /* 次要小字：11~11.5px 在手机上真的看不清（研究员给的正文下限是 13px，
       次要信息给到 12px 是折中 —— 既看得清，又不至于抢正文的位置）。
       ⚠️ 选择器**必须带 `html[data-mnav="on"]` 前缀**：这些页面自己写的是
       `.p-hero .p-tag { font-size: 11.5px }` 这种「两个类」的规则（权重 0,2,0），
       光写 `.p-tag` 根本压不住 —— 实测就是它漏网（`_diag_phase4` 抓到的）。
       加一个属性选择器把权重提到 0,2,1 才能稳赢，而且不必动 `!important`。
       （`data-mnav="on"` 是手机端才有的标记，桌面不受影响。） */
    html[data-mnav="on"] small,
    html[data-mnav="on"] .p-tag,
    html[data-mnav="on"] .news-meta,
    html[data-mnav="on"] .meta,
    html[data-mnav="on"] .hint,
    html[data-mnav="on"] .tip,
    html[data-mnav="on"] .tl-year { font-size: 12px; }

    /* 轮播圆点（youth 的引语轮播）：它是**次要控件**，
       按 WCAG 2.5.8 的 24px 底线给到 40px 就够 —— 硬凑 44 会让一排点占掉半行。 */
    .q-dots button, .dots button, .tl-dot { min-width: 40px; min-height: 40px; }

    /* 卡片类区块（荣誉/历史/时间线）左右内边距收一点，手机屏窄 */
    .his-card, .honor-item, .tl-item, .act-card, .org-box { padding-left: 14px; padding-right: 14px; }

    /* 时间线（moments / youth）在手机上：年份标签别跟内容并排挤，
       竖排下来更好读（原来的两栏在 390px 上只剩 70px 给内容） */
    .tl-item, .tl-wrap { display: block; }
    .tl-year { display: block; margin-bottom: 6px; }
    .tl-line { display: none; }     /* 竖线在单列里没有意义，还占宽度 */
}

/* ---------- ⑯ 下载 App（app.html）：二维码 + 下载按钮 ---------- */
@media (max-width: 768px) {
    /* 图标与说明在手机上竖排居中（原来左右并排，文字被挤成一条） */
    .intro { flex-direction: column; text-align: center; gap: 12px; }
    .appicon { width: 72px; height: 72px; }

    /* 二维码：手机上看自己屏幕上的二维码其实没意义（另一台设备才扫），
       缩小到 180px 省出空间给下载按钮 —— 但**不隐藏**（有人会用平板扫） */
    .qr img, #qrImg { max-width: 180px; height: auto; }

    /* 主按钮：整行、够大、字够大（这是这一页唯一想让人点的东西） */
    .big {
        width: 100%;
        justify-content: center;
        min-height: 52px;
        font-size: 16px;
        border-radius: 14px;
    }

    /* 「复制」按钮：原来 46×27 —— 手机上点不准 */
    .copy { min-height: 44px; min-width: 64px; font-size: 13px; margin-left: 8px; }

    /* 下载地址那一行：字号抬到 13px，允许换行（地址很长） */
    .url { font-size: 13px; line-height: 1.7; }
    .url code { word-break: break-all; }

    .card { padding: 16px; }
    .warn { font-size: 13.5px; }
}

/* ============================================================
   v2.22 · 全站收尾（总检扫出来的四件事）
   ------------------------------------------------------------
   前四个阶段是"按页面改"，这一节是**按总检结果改**：
   写 `jstest/check_mobile_all.mjs`（13 页 × 手机/平板/电脑）一扫，扫出四类真问题，
   这一节就是挨个补上的。**全部只作用于手机（≤768px）**。
   ============================================================ */

/* ---------- ⑰-1 手机上所有"粘住/固定"的容器，一律不要毛玻璃 ---------- */
/* 总检扫出来：`.site-header`（首页，fixed blur 10px）、`.p-top`（九个页面，sticky blur 16px）、
   `.pc-overlay` / `.sc-overlay` / `.g-modal` / `.lb`（各种弹窗遮罩）都还挂着毛玻璃。
   毛玻璃要**逐帧**模糊它背后的内容，而这些元素又是"滚动时一直在屏幕上"的 ——
   这是手机上掉帧的头号原因（研究员也点了这一条）。
   ⚠️ 这里用 `!important` 是**有理由的**：这些毛玻璃分别写在各自页面的样式块里，
   权重从 0,1,0 到带 data-mnav 的 0,2,0 不等，而且以后新页面还会加；
   而"手机上不给固定容器加毛玻璃"是**全局策略**，不存在"某个元素该例外"的情况。
   （去掉模糊后背景色仍是各页面自己定的不透明/半透明色，文字对比度另有测试盯着。） */
@media (max-width: 768px) {
    .site-header, .p-top, .g-top, .m-tabbar, .mnav-sheet, .mnav-mask,
    [class*="overlay"], [class*="modal"], [class*="lightbox"], .lb, .lb-box {
        -webkit-backdrop-filter: none !important;
        backdrop-filter: none !important;
    }

    /* ---------- ⑰-2 几个漏网的小字（11.5px）抬到 12px ---------- */
    /* 总检扫出来的：`hero-tag`（首页轮播上那行小标签）、`p-year`（交流互鉴年份）、
       `.act-meta span`（交流互鉴的活动标签）、`.partner .p-tag`、`.sync-ph span`。
       ⚠️ 前缀用 `html.m-mobile`（由 mobile-shell.js 在手机上打上的标记类），
       **不要用 `html[data-mnav="on"]`** —— 那是老导航脚本加的属性，**首页没有**，
       于是首页上的小字规则一直没生效（这一条也是总检抓出来的）。
       `html.m-mobile`（0,1,1）能压过页面自己的 `.act-meta span`（0,1,1，但元素数 1<2）等写法。 */
    html.m-mobile .hero-tag,
    html.m-mobile .p-year,
    html.m-mobile .p-tag,
    html.m-mobile .act-meta span,
    html.m-mobile .sync-ph span,
    html.m-mobile .g-brand small,
    html.m-mobile .p-brand small,
    html.m-mobile small { font-size: 12px; }

    /* ---------- ⑰-3 搜索框字号 13px → 16px（治 iOS 聚焦放大整页） ---------- */
    /* 招新表单那一版已经处理过 `.field input`；总检发现**照片墙的搜索框**（`.g-search input`
       13px）和**时光长廊的搜索框**（`.p-search input`）漏了。
       带上 `html.m-mobile` 前缀把权重提上去，稳过页面的 0,1,1。 */
    html.m-mobile .g-search input,
    html.m-mobile .p-search input,
    html.m-mobile input[type="search"],
    html.m-mobile input[type="text"]:not([class*="calib"]),
    html.m-mobile input[type="tel"],
    html.m-mobile input[type="number"],
    /* `<select>` 也一样：iOS 对下拉框同样会在聚焦时放大整页。
       总检最后一条就是它：照片墙上传框里的「分类」下拉（`#gCatPick`）只有 13px。 */
    html.m-mobile select { font-size: 16px; }

    /* 复选框/单选框：13×13 在手机上点不准（WCAG 2.5.8 的 AA 底线就是 24px，给到 24） */
    html.m-mobile input[type="checkbox"],
    html.m-mobile input[type="radio"] { width: 24px; height: 24px; }

    /* 上传表单里那几个输入（拍摄时间之类）也抬到 44px 高 */
    .g-taken, .g-sel, .g-modal input[type="text"], .g-modal input[type="date"] { min-height: 44px; }

    /* ---------- ⑰-4 照片墙的页头在手机上会"叠字"（总检 + 截图抓到的真 bug） ---------- */
    /* 现象（390×844 实测）：`.g-top` 里挤了 8 个东西（队徽+队名、spacer、铃铛、
       四个主题圆点、返回主站、身份块、手机导航的两个按钮），
       队徽那一块被压成 **2px 宽**，而里面 154px 宽的队名**溢出压到旁边的"身份"文字上**，
       整个页头变成 144px 高的一团。
       修法：让页头换行排、队名在手机上不显示（只留队徽）、主题圆点交给"汉堡"菜单里那一套。 */
    .g-top, .p-top {
        flex-wrap: wrap;
        gap: 8px;
        padding: 10px 12px;
    }
    .g-top .spacer, .p-top .spacer { display: none; }   /* 换行布局里 spacer 只会把控件顶到下一行 */
    .g-brand, .p-brand { flex: 0 0 auto; min-width: 0; }
    .g-brand b, .p-brand b,
    .g-brand small, .p-brand small { display: none; }   /* 手机上只留队徽，不再和按钮抢宽度 */
    .g-brand .badge, .p-brand .badge { flex: none; }
    .g-theme, .p-theme { display: none; }               /* 主题切换在"汉堡"里已有一套 */
    /* 身份/退出：**不要**写成 `flex: 1 1 100%` —— 那会强制独占一行，
       页头变成 3 行、185px 高（手机上吃掉两成屏）。
       让它按内容宽度走、自然换行，实测刚好 2 行。 */
    #gRole, #pRole { flex: 0 1 auto; min-width: 0; }
    #gRole, #pRole { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
}

/* ============================================================
   v2.32 · 手机端「个人中心」改版
   ------------------------------------------------------------
   背景（为什么要改）：
   个人中心原来在手机上就是"左侧竖排导航压成一条顶端菜单"，
   队员 9 个入口 + 管理 11 个入口一共 20 个，横着滑要滑好几屏，
   而且进任何一个面板之后**找不到"我是谁"**（头像/队号/状态被压成一行小字）。
   现在手机上先进一个「个人中心首页」：身份名片 + 常用宫格 + 管理宫格，
   点格子 = 点原来那个按钮（零新增切换逻辑）。

   ⚠️ 三条纪律（和 mobile-ui.css 一致）：
     ① **桌面端（≥769px）一个像素都不动**：本文件最后这一段全部收在
        `@media (max-width: 768px)` 里，并且关键规则再加一层 `html.m-mobile`
        （由 mobile-shell.js 只在手机上打上）把权重顶到 0,3,1 以上 ——
        既压得过 index.html 里自带的 `@media(max-width:900px)`，
        又**完全不参与**桌面端的层叠。
     ② **不新增毛玻璃 / 大阴影**：新增卡片只用 1px 描边 + 一层很浅的投影，
        粘住/固定容器一律不挂 backdrop-filter（那是手机上掉帧的头号原因）。
     ③ **新增元素在宽屏一律不存在**：`#mpTop / #mpHome / #mpSheet` 在
        媒体查询**外面**就写死 display:none（见下面第一条），所以哪怕断点判断
        出了岔子，桌面上也只是多几个不显示的空盒子，挤不动任何现有布局。
   ============================================================ */

/* ---------- 新增元素的宽屏基线：一律不显示（故意写在媒体查询外面） ---------- */
.mp-top, .mp-home, .mp-sheet, .mp-back2 { display: none; }

/* `.pc-menu-scroll` 是 v2.32 为了"手机端单行 chip 条"加的一层包壳，
   里面就是原来那两个菜单（#pcMenu / #adminMenu）。
   ⚠️ 桌面端必须**完全透明**：`display: contents` 会让这个盒子根本不生成，
   两个菜单仍旧是 .pc-side 的直接 flex 子项 —— 和加壳之前一模一样（已用逐像素比对验证）。
   手机端才把它变成"那个横向滚动容器"。 */
.pc-menu-scroll { display: contents; }

@media (max-width: 768px) {

    /* ========== ① 手机端个人中心：顶部小标题栏（只在「首页」出现） ========== */
    html.m-mobile .pc-window.mp-home-on > .mp-top {
        display: flex;
        align-items: center;
        gap: 10px;
        flex: none;
        /* 顶部也要让出刘海/状态栏安全区（viewport-fit=cover 时贴边会被切） */
        padding: calc(8px + env(safe-area-inset-top, 0px)) 12px 8px;
        background: var(--surface);
        border-bottom: 1px solid var(--line);
    }
    html.m-mobile .mp-top .mp-title {
        flex: 1 1 auto;
        min-width: 0;
        font-size: 17px;
        font-weight: 700;
        color: var(--ink);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    /* 返回箭头 / 铃铛：44×44 —— Apple/Google/WCAG 都认这个最小触摸目标 */
    html.m-mobile .mp-top .mp-back,
    html.m-mobile .mp-top .mp-bell {
        flex: none;
        position: relative;
        width: 44px;
        height: 44px;
        display: grid;
        place-items: center;
        padding: 0;
        border: 1px solid var(--line);
        border-radius: 12px;
        background: var(--surface-2);
        color: var(--red-ink);
        font-size: 18px;
        line-height: 1;
        font-family: inherit;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
    /* 触摸反馈用 :active —— 手机上没有"悬停"，:hover 会**粘住**不散 */
    html.m-mobile .mp-top .mp-back:active,
    html.m-mobile .mp-top .mp-bell:active { background: var(--line); }
    html.m-mobile .mp-top .mp-dot {
        position: absolute;
        top: 5px;
        right: 5px;
        min-width: 18px;
        height: 18px;
        padding: 0 4px;
        border-radius: 999px;
        background: var(--red);
        color: #fff;
        font-size: 12px;          /* 手机端正文/次要字一律 ≥12px（体检卡这条） */
        font-style: normal;
        font-weight: 700;
        line-height: 18px;
        text-align: center;
    }
    html.m-mobile .mp-top .mp-dot[hidden] { display: none; }

    /* ========== ② 首页主体：自己滚，底部留安全区 ========== */
    html.m-mobile .pc-window.mp-home-on > .mp-home {
        display: block;
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-y: contain;
        background: var(--bg);
        padding: 0 0 calc(16px + env(safe-area-inset-bottom, 0px));
    }

    /* ---- 身份名片卡：红金渐变，一眼看清"我是谁" ---- */
    html.m-mobile .mp-namecard {
        margin: 14px;
        padding: 16px;
        border-radius: 20px;
        color: #fff;
        /* 渐变是写死的（跟左侧栏那条深红同一套色），三个主题下都是"白字压深红"，
           所以对比度永远够 —— 不跟着主题变量走反而更稳。 */
        background: linear-gradient(150deg, #B4102A, #8E0B22);
        box-shadow: 0 6px 16px rgba(140, 10, 30, .18);
    }
    html.m-mobile .mp-namecard .mp-nc-row { display: flex; align-items: center; gap: 12px; }
    html.m-mobile .mp-namecard .mp-avatar {
        flex: none;
        width: 58px;
        height: 58px;
        border-radius: 16px;
        display: grid;
        place-items: center;
        overflow: hidden;
        font-size: 26px;
        font-weight: 800;
        color: #fff;
        background: rgba(255, 255, 255, .18);
        border: 1px solid rgba(255, 255, 255, .3);
    }
    html.m-mobile .mp-namecard .mp-avatar img { width: 100%; height: 100%; object-fit: cover; }
    html.m-mobile .mp-namecard .mp-nm { font-size: 19px; font-weight: 700; line-height: 1.25; }
    html.m-mobile .mp-namecard .mp-sid { margin-top: 3px; font-size: 12px; opacity: .88; }
    html.m-mobile .mp-chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 14px; }
    html.m-mobile .mp-chip {
        max-width: 100%;
        padding: 5px 11px;
        border-radius: 999px;
        font-size: 12px;
        color: #fff;
        background: rgba(255, 255, 255, .16);
        border: 1px solid rgba(255, 255, 255, .26);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    html.m-mobile .mp-chip.is-gold {
        font-weight: 700;
        color: #4A3600;
        background: linear-gradient(145deg, var(--gold-light), var(--gold));
        border-color: transparent;
    }

    /* ---- 分组 + 宫格 ---- */
    html.m-mobile .mp-sec { margin: 18px 14px 0; }
    html.m-mobile .mp-sec > h4 {
        margin: 0 0 10px;
        font-size: 13px;
        font-weight: 600;
        letter-spacing: .4px;
        color: var(--gray);
    }
    html.m-mobile .mp-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    html.m-mobile .mp-grid.g3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    /* 格子本体是 <button>：既能被键盘/读屏正常识别，又天然满足 ≥44px */
    html.m-mobile .mp-cell {
        position: relative;
        display: flex;
        flex-direction: column;
        gap: 8px;
        min-height: 86px;
        padding: 14px 12px;
        text-align: left;
        font-family: inherit;
        font-size: 14px;
        color: var(--ink);
        background: var(--surface);
        border: 1px solid var(--line);
        border-radius: 16px;
        box-shadow: 0 2px 8px rgba(160, 20, 40, .05);
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
    html.m-mobile .mp-cell .mp-ic {
        width: 38px;
        height: 38px;
        border-radius: 11px;
        display: grid;
        place-items: center;
        font-size: 18px;
        background: var(--surface-2);
        color: var(--red-ink);
    }
    html.m-mobile .mp-cell .mp-lb { font-size: 14px; font-weight: 600; }
    html.m-mobile .mp-cell .mp-sb {
        font-size: 12px;           /* 12px：手机端不许出现 <12px 的字 */
        color: var(--gray);
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    html.m-mobile .mp-cell .mp-dot {
        position: absolute;
        top: 10px;
        right: 10px;
        min-width: 20px;
        height: 20px;
        padding: 0 6px;
        border-radius: 999px;
        background: var(--red);
        color: #fff;
        font-size: 12px;
        font-style: normal;
        font-weight: 700;
        line-height: 20px;
        text-align: center;
    }
    html.m-mobile .mp-cell .mp-dot[hidden] { display: none; }
    /* 三列那一组格子窄：图标和内边距都收一点，文字降到 13px 免得换行 */
    html.m-mobile .mp-grid.g3 .mp-cell { min-height: 84px; padding: 12px 8px; gap: 7px; }
    html.m-mobile .mp-grid.g3 .mp-cell .mp-ic { width: 36px; height: 36px; font-size: 17px; }
    html.m-mobile .mp-grid.g3 .mp-cell .mp-lb { font-size: 13px; }
    /* 管理功能那一组：金色区分（用金色**叠加**而不是写死米色底 ——
       写死浅底在暗色主题下就变成"浅底浅字"，这也是 v2.22 页头踩过的坑） */
    html.m-mobile .mp-cell.is-admin {
        background: linear-gradient(180deg, rgba(201, 162, 39, .10), rgba(201, 162, 39, .03));
        border-color: rgba(201, 162, 39, .42);
    }
    html.m-mobile .mp-cell.is-admin .mp-ic {
        color: #4A3600;
        background: linear-gradient(145deg, var(--gold-light), var(--gold));
    }
    /* 触摸反馈（替代 hover） */
    html.m-mobile .mp-cell:active { background: var(--surface-2); transform: translateY(1px); }
    html.m-mobile .mp-cell.is-admin:active { background: rgba(201, 162, 39, .18); }

    /* ---- 全部功能：底部抽屉 ---- */
    /* 用 absolute 而不是 fixed：它住在 .pc-window 里（那个盒子本来就是 position:relative），
       这样抽屉永远不跑出个人中心，也不会和页面底部标签栏打架。 */
    html.m-mobile .mp-sheet.is-open {
        display: block;
        position: absolute;
        inset: 0;
        z-index: 40;
    }
    html.m-mobile .mp-sheet .mp-mask {
        position: absolute;
        inset: 0;
        background: rgba(20, 4, 8, .45);
        border: 0;
        padding: 0;
        cursor: pointer;
    }
    html.m-mobile .mp-sheet .mp-sheet-box {
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        max-height: 74%;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        padding: 10px 14px calc(16px + env(safe-area-inset-bottom, 0px));
        background: var(--surface);
        border-top: 1px solid var(--line);
        border-radius: 18px 18px 0 0;
    }
    html.m-mobile .mp-sheet .mp-handle {
        width: 44px;
        height: 5px;
        margin: 0 auto 12px;
        border-radius: 999px;
        background: var(--line);
    }
    html.m-mobile .mp-sheet .mp-sheet-box > h4 {
        margin: 0 0 12px;
        font-size: 14px;
        font-weight: 600;
        color: var(--gray);
    }

    /* ========== ③ 进入面板：侧栏 → 顶部吸顶 chip 条 + 「‹ 返回」 ==========
       ⚠️ v2.32 修：第一版写成了 `flex-wrap: wrap`，队员组一行、管理组第二行 ——
          390 宽的屏上整整占掉 ~100px（近一成二的可视高度），而那正是内容区。
          现在整条**只有一行、由 `.pc-menu-scroll` 这一个滚动口横滑**：
          `.pc-side` 自己不再是滚动容器（返回键要能被它"排除在外"）。 */
    html.m-mobile .pc-window.mp-pane-on > .pc-side {
        display: flex;
        flex-direction: row;
        flex-wrap: nowrap;                 /* 单行：不许折行 */
        align-items: center;
        gap: 8px;
        /* 侧栏那条深红渐变保留（辨识度靠它），只把它压扁成一条 */
        background: linear-gradient(160deg, #1E0A0E 0%, #A81228 78%, #4B5320 145%);
        padding: 8px 12px 10px;
        max-height: none;
        overflow: hidden;                  /* 滚动交给下面的 .pc-menu-scroll */
        /* 右侧给 ✕（.pc-close，44×44）留出位置，chips 不会滑到它底下 */
        padding-right: 60px;
    }
    /* 手机端用户区（头像/名字/状态）与「退出登录」都收起来：
       身份信息首页名片上已经有一份，退出登录挪进「全部功能」抽屉。
       —— 这样顶端只剩一条 chip 条，内容区能多出 70px。 */
    html.m-mobile .pc-window.mp-pane-on > .pc-side > .pc-user,
    html.m-mobile .pc-window.mp-pane-on > .pc-side > .pc-logout { display: none; }
    /* 「‹ 返回」：固定的第一格，**不在滚动容器里**，所以永远不会被滚出去、
       也不会盖住任何 chip（用 sticky 浮在上面会盖住第一个 chip，实测被
       check_clickable 抓成 20 个"看得见但点不到"）。 */
    html.m-mobile .pc-window.mp-pane-on .mp-back2 {
        flex: 0 0 auto;
        display: inline-flex;
        align-items: center;
        gap: 4px;
        min-height: 44px;
        padding: 0 14px;
        border-radius: 999px;
        font-family: inherit;
        font-size: 13.5px;
        white-space: nowrap;
        cursor: pointer;
        color: #fff;
        background: rgba(255, 255, 255, .14);
        border: 1px solid rgba(255, 255, 255, .18);
        -webkit-tap-highlight-color: transparent;
    }
    html.m-mobile .pc-window.mp-pane-on .mp-back2:active { background: rgba(255, 255, 255, .3); }
    /* 唯一的横向滚动口：两个菜单并排铺在里面，一起滚 */
    html.m-mobile .pc-window.mp-pane-on > .pc-side > .pc-menu-scroll {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;
        gap: 8px;
        flex: 1 1 auto;
        min-width: 0;
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-x: contain;    /* 滑到头别触发"返回上一页" */
        scrollbar-width: none;
        /* 焦点/scrollIntoView 滚进来时首尾各留 12px，别贴着边 */
        scroll-padding-inline: 12px;
    }
    html.m-mobile .pc-window.mp-pane-on > .pc-side > .pc-menu-scroll::-webkit-scrollbar { display: none; }
    /* 两个菜单容器：**不再是各自的滚动容器**，按内容宽度平铺，由上面那个口统一横滑。 */
    html.m-mobile .pc-window.mp-pane-on .pc-menu-scroll > .pc-menu {
        flex: 0 0 auto;
        width: max-content;
        margin: 0;
        padding: 0;
        overflow: visible;
    }
    /* 管理那一组：紧接在队员组后面，用一条竖细线分隔（只有管理员才有内容）。
       ⚠️ 这里要**顶掉两条已有规则**，都是为了让"当前项高亮"在管理面板上也成立：
         · `#adminMenu.is-collapsed button { display:none }`（v1.87 的折叠）
           —— 折叠后管理组一个 chip 都不画，当前面板没有高亮；
              而手机端首页宫格已经给了全部管理入口，chip 条里就该直接铺开。
         · `#adminMenu .pc-menu-title { display:flex }`（id 选择器，压得过 `.pc-menu-title`）
           —— chip 条里再挂一段"管理功能"标题纯属占地方。 */
    html.m-mobile .pc-window.mp-pane-on .pc-menu-scroll > .pc-menu-admin {
        margin: 0 0 0 2px;
        padding: 0 0 0 10px;
        border-top: 0;
        border-left: 1px solid rgba(255, 255, 255, .22);
    }
    html.m-mobile .pc-window.mp-pane-on #adminMenu .pc-menu-title { display: none; }
    html.m-mobile .pc-window.mp-pane-on #adminMenu.is-collapsed button { display: flex; }
    /* chip 条是横滑的：✕ 会一直悬在右边，chips 从它底下滑过去。
       原来的 `rgba(255,255,255,.12)` 几乎透明，看起来像"数据中心"那个 chip 后面
       粘了个 ✕（还抢它的点按）。这里给它不透明的底色（色值同样从右段渐变上量来的），
       让它明确是"浮在条上面的一颗按钮"。 */
    html.m-mobile .pc-window.mp-pane-on > .pc-close {
        background-image: linear-gradient(rgba(255, 255, 255, .14), rgba(255, 255, 255, .14)),
                          linear-gradient(180deg, #8E1023, #A61328);
        box-shadow: 0 2px 8px rgba(0, 0, 0, .28);
    }
    /* 粘住的 chip 条上不许有毛玻璃（沿用 v2.19 的减负约定） */
    html.m-mobile .pc-window.mp-pane-on > .pc-side,
    html.m-mobile .pc-window.mp-pane-on .pc-menu {
        -webkit-backdrop-filter: none;
        backdrop-filter: none;
    }
    /* 首页态：侧栏与内容区都让位给首页；用 !important 是因为
       JS 是直接写 el.style.display（内联样式压得过普通类规则） */
    html.m-mobile .pc-window.mp-home-on > .pc-side,
    html.m-mobile .pc-window.mp-home-on > .pc-main,
    html.m-mobile .pc-window.mp-home-on > .pc-admin-main { display: none !important; }
    /* 首页态不要那个 ✕：右上角已经被标题栏的铃铛占了 */
    html.m-mobile .pc-window.mp-home-on > .pc-close { display: none !important; }

    /* 去掉 hover-only 的交互（触摸屏上 :hover 会点完粘住不散） */
    html.m-mobile .pc-window .pc-close:hover { transform: none; background: rgba(255, 255, 255, .12); }
    html.m-mobile .pc-window.mp-pane-on .pc-menu button:hover {
        background: rgba(255, 255, 255, .14);
        color: #fff;
    }
    html.m-mobile .pc-window.mp-pane-on .pc-menu button.is-active:hover { background: #fff; color: #A81228; }

    /* 内容区底部：让出安全区（Home 指示条） */
    html.m-mobile .pc-window.mp-pane-on > .pc-main,
    html.m-mobile .pc-window.mp-pane-on > .pc-admin-main {
        padding-bottom: calc(var(--m-tab-h, 56px) + 24px + env(safe-area-inset-bottom, 0px));
    }
    /* 手机端把滚动条藏掉：这几条容器本来就有"能滚"的暗示（内容被切一半），
       而常驻的滚动条会吃掉 8~10px 宽度、还在卡片右边缘画一条竖线。
       （`.pc-menu` 的横滑条早就这么处理了，见上面 ⑨ 那一段。） */
    html.m-mobile .pc-window > .mp-home,
    html.m-mobile .pc-window > .pc-main,
    html.m-mobile .pc-window > .pc-admin-main,
    html.m-mobile .pc-window .mp-sheet .mp-sheet-box {
        scrollbar-width: none;
    }
    html.m-mobile .pc-window > .mp-home::-webkit-scrollbar,
    html.m-mobile .pc-window > .pc-main::-webkit-scrollbar,
    html.m-mobile .pc-window > .pc-admin-main::-webkit-scrollbar,
    html.m-mobile .pc-window .mp-sheet .mp-sheet-box::-webkit-scrollbar { display: none; }

    /* ========== ④ 管理面板：宽表 → 卡片列表 ========== */
    /* 报名审核 / 成员管理 / 考勤管理 这三张表在手机上原来只能"横向拖"
       （min-width:880px），一屏看得见两三列，姓名和操作永远不在同一屏。
       现在改成**一档一卡**：主标题=姓名+盾徽，右上角=状态，中间=队号/部门/学号…，
       底部=操作按钮横排（≥44px）。做法是经典的 `data-label` 卡片化：
       HTML 结构一个字没动（只给 <td> 加了 data-label / class 属性），
       桌面端照旧渲染成表格。 */
    html.m-mobile #apane-review .table-wrap,
    html.m-mobile #apane-members .table-wrap,
    html.m-mobile #apane-attendance .table-wrap {
        overflow: visible;
        border: 0;
        border-radius: 0;
        background: transparent;
        box-shadow: none;
    }
    html.m-mobile #apane-review .adm-table,
    html.m-mobile #apane-members .adm-table,
    html.m-mobile #apane-attendance .adm-table { display: block; min-width: 0; }
    html.m-mobile #apane-review .adm-table > thead,
    html.m-mobile #apane-members .adm-table > thead,
    html.m-mobile #apane-attendance .adm-table > thead { display: none; }
    html.m-mobile #apane-review .adm-table > tbody,
    html.m-mobile #apane-members .adm-table > tbody,
    html.m-mobile #apane-attendance .adm-table > tbody { display: block; }
    html.m-mobile #apane-review .adm-table > tbody > tr,
    html.m-mobile #apane-members .adm-table > tbody > tr,
    html.m-mobile #apane-attendance .adm-table > tbody > tr {
        position: relative;
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 8px 10px;
        margin: 0 0 10px;
        padding: 12px;
        background: var(--surface);
        border: 1px solid var(--line);
        border-radius: 14px;
    }
    /* 卡片上不要 hover 底色（触摸屏上没有"悬停"，而且原来的 hover 会粘住） */
    html.m-mobile #apane-review .adm-table > tbody > tr:hover,
    html.m-mobile #apane-members .adm-table > tbody > tr:hover,
    html.m-mobile #apane-attendance .adm-table > tbody > tr:hover { background: var(--surface); }
    html.m-mobile #apane-review .adm-table > tbody > tr > td,
    html.m-mobile #apane-members .adm-table > tbody > tr > td,
    html.m-mobile #apane-attendance .adm-table > tbody > tr > td {
        display: block;
        min-width: 0;
        padding: 0;
        border: 0;
        white-space: normal;
        word-break: break-word;
        font-size: 13px;
        /* 覆盖 .adm-table-sticky 给"最后一列"加的右侧粘住（卡片模式下会错位） */
        position: static !important;
        background: transparent !important;
    }
    /* 每一格自己带标签（桌面端是表头，卡片模式没有表头了） */
    html.m-mobile #apane-review .adm-table > tbody > tr > td::before,
    html.m-mobile #apane-members .adm-table > tbody > tr > td::before,
    html.m-mobile #apane-attendance .adm-table > tbody > tr > td::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 2px;
        font-size: 12px;
        color: var(--gray);
    }
    html.m-mobile #apane-review .adm-table > tbody > tr > td[data-label=""],
    html.m-mobile #apane-members .adm-table > tbody > tr > td[data-label=""],
    html.m-mobile #apane-attendance .adm-table > tbody > tr > td[data-label=""] { font-size: 13px; }
    html.m-mobile #apane-review .adm-table > tbody > tr > td[data-label=""]::before,
    html.m-mobile #apane-members .adm-table > tbody > tr > td[data-label=""]::before,
    html.m-mobile #apane-attendance .adm-table > tbody > tr > td[data-label=""]::before { display: none; }
    /* 姓名 = 卡片主标题：占满一行、排到最前（order:-1），右侧留出状态标签的位置 */
    html.m-mobile #apane-review .adm-table > tbody > tr > td.mp-td-title,
    html.m-mobile #apane-members .adm-table > tbody > tr > td.mp-td-title,
    html.m-mobile #apane-attendance .adm-table > tbody > tr > td.mp-td-title {
        grid-column: 1 / -1;
        order: -1;
        padding-right: 76px;
        font-size: 15px;
        font-weight: 600;
    }
    /* 状态 = 卡片右上角（绝对定位，不占网格格） */
    html.m-mobile #apane-review .adm-table > tbody > tr > td.mp-td-status,
    html.m-mobile #apane-members .adm-table > tbody > tr > td.mp-td-status {
        position: absolute !important;
        top: 13px;
        right: 12px;
        font-size: 12px;
    }
    /* 操作 = 卡片底部横排，每个按钮 ≥44px */
    html.m-mobile #apane-review .adm-table > tbody > tr > td.mp-td-acts,
    html.m-mobile #apane-members .adm-table > tbody > tr > td.mp-td-acts,
    html.m-mobile #apane-attendance .adm-table > tbody > tr > td.mp-td-acts {
        grid-column: 1 / -1;
        margin-top: 2px;
        /* 操作那一格自己就是一行 flex（考勤表里那个"保存"没有 .row-actions 包着） */
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
    }
    html.m-mobile #apane-review .row-actions,
    html.m-mobile #apane-members .row-actions,
    html.m-mobile #apane-attendance .row-actions {
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
        white-space: normal;
    }
    html.m-mobile #apane-review .adm-table .adm-btn,
    html.m-mobile #apane-members .adm-table .adm-btn,
    html.m-mobile #apane-attendance .adm-table .adm-btn {
        flex: 1 1 auto;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 0 14px;
        font-size: 13px;
    }
    /* 空状态那一行（colspan=10）要占满整张卡。
       ⚠️ 不用 `:has()` —— 老安卓 WebView 不认，一条不认的选择器会把**整组规则**
          一起作废（CSS 选择器列表不是"逐条容错"的）。这里只靠 colspan 撑满即可。 */
    html.m-mobile #apane-review .adm-table > tbody > tr > td[colspan],
    html.m-mobile #apane-members .adm-table > tbody > tr > td[colspan],
    html.m-mobile #apane-attendance .adm-table > tbody > tr > td[colspan] { grid-column: 1 / -1; }
    /* 需要整行宽的格子（考勤那张表里的下拉与备注输入框所在的 <td>） */
    html.m-mobile #apane-attendance .adm-table > tbody > tr > td.mp-td-full { grid-column: 1 / -1; }
    /* 考勤管理那张表里有 <select> / <input>：给满宽度、够高好点 */
    html.m-mobile #apane-attendance .adm-table .att-sel,
    html.m-mobile #apane-attendance .adm-table .att-note {
        width: 100%;
        min-height: 44px;
        box-sizing: border-box;
    }
    /* 报名/成员库里那两枚小盾徽在卡片上稍微放大一点，看得清 */
    html.m-mobile #apane-review .cap-mark,
    html.m-mobile #apane-members .cap-mark,
    html.m-mobile #apane-review .adm-mark,
    html.m-mobile #apane-members .adm-mark { font-size: 15px; }

    /* ========== ⑤ 工作台 / 数据中心 / 考勤：统计 2 列小卡 + 按钮整行 ========== */
    html.m-mobile .pc-admin-main .pc-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
    html.m-mobile .pc-admin-main .pc-stat { padding: 12px; border-radius: 12px; }
    html.m-mobile .pc-admin-main .pc-stat strong { font-size: 22px; }
    html.m-mobile .pc-admin-main .pc-head { margin-bottom: 14px; }
    /* 数据中心那一堆"操作组"：手机上一行一个（原来三个挤一行，中文标签被压成两行） */
    html.m-mobile .pc-admin-main .adm-actions { display: flex; flex-wrap: wrap; gap: 8px; }
    html.m-mobile .pc-admin-main .adm-actions .adm-btn {
        flex: 1 1 100%;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        font-size: 13.5px;
    }
    /* 工具条（筛选 chips / 下拉 / 搜索）在手机上换行排，控件一律 ≥44px */
    html.m-mobile .pc-admin-main .toolbar { flex-wrap: wrap; gap: 8px; }
    html.m-mobile .pc-admin-main .toolbar .adm-select,
    html.m-mobile .pc-admin-main .toolbar .adm-btn,
    html.m-mobile .pc-admin-main .att-head-tools .adm-select,
    html.m-mobile .pc-admin-main .att-head-tools .adm-btn { min-height: 44px; }
    html.m-mobile .pc-admin-main .att-head-tools { display: flex; flex-wrap: wrap; gap: 8px; }
    html.m-mobile .pc-admin-main .att-head-tools .adm-select { width: 100% !important; }
    /* 工作台下半部分（部门分布 + 待审核）在手机上竖排 */
    html.m-mobile .pc-admin-main .admin-cols { grid-template-columns: 1fr; }
    /* 工作台「最新待审核」那一列：按钮 ≥44px */
    html.m-mobile .pc-admin-main .dash-item .adm-btn { min-height: 44px; padding: 0 14px; }
}

/* ============================================================
   v2.33 · 手机端「个人中心」**面板本体**改版
   ------------------------------------------------------------
   兄长这次的原话：「点进『个人主页』等面板后，面板本体还是老的桌面版式 ——
   为什么会变成在保留原版 UI 的情况下又把新版 UI 叠加了上去呐喂」。
   根因：v2.32 只把「个人中心首页」（身份名片 + 宫格 + 顶部 chip 条）做成了手机版，
   **面板本体一个像素没动** —— 所以手机上进任何一个面板，看到的仍是桌面那套
   21px 大标题、20px/22px 内边距的卡片、880px 宽的表格（要横着拖才看得全）。
   这一版把面板本体也按同一套语言重做，并把「个人主页」里与名片重复的信息去掉。

   视觉语言（与 v2.32 的 .mp-cell **完全同一套值**，不另造）：
     卡片 = 白底 + 1px var(--line) 描边 + 16px 圆角 + 0 2px 8px 柔和投影
     标题 15~17px 粗体 / 说明 12~13px var(--gray)
     触摸目标 ≥44px；分组间距 14~18px

   ⚠️ 三条纪律（沿用 v2.32，一字不改）：
     ① 桌面端（≥769px）**一个像素都不动**：本段全部收在 @media (max-width:768px)
        里、且关键规则再加一层 html.m-mobile；新增元素在媒体查询**外面**就写死
        display:none（见下面「宽屏基线」）。
     ② 不新增毛玻璃 / 大阴影。
     ③ 不改任何接口、字段、接口调用；面板 DOM 只**加属性/加类**
        （data-label、mp-cards / mp-kv / mp-mini / mp-save 这些名字桌面端全不认识），
        结构一个字没动 —— 点宫格仍走 mpTap() → 原按钮 .click()。

   ⚠️ 为什么用 `.mp-cards` 这个类而不是逐个面板写选择器：
      这些表格**本来就是静态 HTML**（只有 <tbody> 是 JS 填的），给 <table> 挂一个类
      就能一条规则管住 8 张表；逐面板写选择器要靠 :is() 之类合并，
      而老安卓 WebView 不认那些选择器，**一条不认会把整组规则一起作废**
      （v2.32 注释里已经踩过这个坑），所以宁可多加一个类名。
   ============================================================ */

/* ---------- 宽屏基线（故意写在媒体查询外面）：v2.33 新增元素一律不存在 ---------- */
/* #mpPaneQuick = 个人主页里的「快捷入口」；#mpReadAll = 我的通知里的「全部标为已读」。
   桌面端这两个盒子根本不显示 —— 连"多一个空盒子"都挤不到桌面布局。 */
#mpPaneQuick, #mpReadAll { display: none; }

@media (max-width: 768px) {

    /* ============================================================
       ① 共用：把面板本体统一成同一套卡片语言
       ============================================================ */
    /* 卡片：padding 从 20/22 收到 14（桌面的大留白在手机上纯浪费屏），圆角 14→16，
       投影换成和 .mp-cell 完全一样的那一层。 */
    html.m-mobile .pc-main .pc-card,
    html.m-mobile .pc-admin-main .pc-card {
        padding: 14px;
        border-radius: 16px;
        box-shadow: 0 2px 8px rgba(160, 20, 40, .05);
        margin-bottom: 14px;
    }
    html.m-mobile .pc-main .pc-card > h5,
    html.m-mobile .pc-admin-main .pc-card > h5 {
        margin: 0 0 10px;
        font-size: 15px;
        font-weight: 700;
        line-height: 1.35;
    }
    /* 卡片标题里那两段小字（`.set-tip` 说明 / `.pc-tag` 计数）**自己占一行**：
       它们跟在标题后面时会跟标题抢宽度，把标题挤成两行（截图里亲眼看到
       「📤 上传我的 / 课表」「教员列 / 表」），读起来很别扭。
       ⚠️ 光写 `display:block` 没用 —— `.pc-card h5` 本身是 `display:flex`，
          里面的 span 是**弹性项目**（弹性项目会被"块化"，块化不等于换行），
          必须给 `flex: 1 1 100%` 才会真的折到下一行。第一版就是这么白改的。 */
    html.m-mobile #pcOverlay .pc-card > h5 { flex-wrap: wrap; align-items: flex-start; }
    html.m-mobile #pcOverlay .pc-card > h5 > .set-tip,
    html.m-mobile #pcOverlay .pc-card > h5 > .pc-tag {
        flex: 1 1 100%;
        min-width: 0;
        margin-top: 2px;
        line-height: 1.5;
    }
    /* 标题区：「面包屑」这一角色由顶部那条 chip 条 + 「‹ 返回」承担（v2.32 已做），
       这里只做标题本身 —— 竖排（标题一行、右上角那颗按钮/工具条各自整行）。 */
    html.m-mobile .pc-main .pc-head,
    html.m-mobile .pc-admin-main .pc-head {
        display: block;
        margin: 0 0 12px;
        padding: 0;
    }
    html.m-mobile .pc-main .pc-head h3,
    html.m-mobile .pc-admin-main .pc-head h3 {
        font-size: 17px;
        font-weight: 700;
        line-height: 1.3;
    }
    html.m-mobile .pc-main .pc-head p,
    html.m-mobile .pc-admin-main .pc-head p { margin: 3px 0 0; font-size: 12.5px; line-height: 1.55; }
    /* 标题右边那一颗按钮 / 工具条：整行、≥44px（原来它们和标题挤在一行） */
    html.m-mobile .pc-head > .adm-btn,
    html.m-mobile .pc-head > .adm-select { margin-top: 10px; width: 100% !important; min-height: 44px; }
    html.m-mobile .pc-head > .att-head-tools { margin-top: 10px; width: 100%; display: flex; flex-wrap: wrap; gap: 8px; }
    html.m-mobile .pc-head > .att-head-tools > #attDate { flex: 1 1 auto; width: auto !important; min-height: 44px; font-size: 16px; }
    html.m-mobile .pc-head > .att-head-tools > .adm-btn { flex: 0 0 auto; min-height: 44px; }

    /* 手机上「面板里的按钮一律 ≥44px」。
       ⚠️ 为什么按容器一刀切而不是逐个点名：v2.19 点名点漏过两次，
          而面板里的按钮还在持续增加 —— 与其追着补，不如按容器兜底。
       `:not([class*="close"])` 放过弹窗右上角那个 ✕（它是 .pc-close，另有 44px 规则）。 */
    html.m-mobile .pc-main button:not([class*="close"]),
    html.m-mobile .pc-admin-main button:not([class*="close"]) { min-height: 44px; box-sizing: border-box; }
    /* 主按钮（保存 / 提交 / 确认这类"重操作"）整行、≥48px */
    html.m-mobile .pc-main .pc-form .btn,
    html.m-mobile .pc-main .pc-card > .btn,
    html.m-mobile .pc-admin-main .pc-form .btn { width: 100%; min-height: 48px; font-size: 14.5px; }

    /* 筛选区 / 工具条：一张卡里，搜索框与下拉各自整行 */
    html.m-mobile .pc-admin-main .toolbar {
        display: block;
        margin: 0 0 12px;
        padding: 12px;
        background: var(--surface);
        border: 1px solid var(--line);
        border-radius: 16px;
        box-shadow: 0 2px 8px rgba(160, 20, 40, .05);
    }
    html.m-mobile .pc-admin-main .toolbar .chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
    html.m-mobile .pc-admin-main .toolbar .chips .chip { flex: 1 1 auto; min-height: 44px; font-size: 13px; }
    html.m-mobile .pc-admin-main .toolbar > .adm-search,
    html.m-mobile .pc-admin-main .toolbar > .adm-select,
    html.m-mobile .pc-admin-main .toolbar > .adm-btn { width: 100%; min-height: 44px; margin-bottom: 8px; font-size: 14px; }
    html.m-mobile .pc-admin-main .toolbar > :last-child { margin-bottom: 0; }

    /* 统计块：一律 2 列小卡（原来 4 列在 390px 上每格只有 80px，数字挤成两行） */
    html.m-mobile .pc-main .pc-stats,
    html.m-mobile .pc-admin-main .pc-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-bottom: 14px; }
    html.m-mobile .pc-main .pc-stat,
    html.m-mobile .pc-admin-main .pc-stat { padding: 12px; border-radius: 14px; box-shadow: 0 2px 8px rgba(160, 20, 40, .05); }
    html.m-mobile .pc-main .pc-stat strong,
    html.m-mobile .pc-admin-main .pc-stat strong { font-size: 20px; }
    html.m-mobile .pc-main .pc-stat span,
    html.m-mobile .pc-admin-main .pc-stat span { font-size: 12px; }

    /* 手机端不许出现 <12px 的字（体检卡这一条，桌面端不受影响） */
    html.m-mobile #pcOverlay .set-tip,
    html.m-mobile #pcOverlay .pc-tag,
    html.m-mobile #pcOverlay .dash-item small,
    html.m-mobile #pcOverlay .pc-msg time,
    html.m-mobile #pcOverlay .tc-sec > h4 .num,
    html.m-mobile #pcOverlay .pc-step .st,
    html.m-mobile #pcOverlay .adm-desc,
    html.m-mobile #pcOverlay .empty { font-size: 12px; }

    /* ============================================================
       ② 宽表 → 「一档一卡」（手机端通用）
       ------------------------------------------------------------
       下面这些表在 390px 上只能看到两三列（.adm-table 有 min-width:880px），
       姓名和操作永远不在同一屏。做法与 v2.32 的三张表**完全一样**：
       只给 <td> 加 data-label / 语义类，CSS 靠 `td::before{content:attr(data-label)}`
       把每一行变成一张卡 —— 主标题占满一行、状态贴右上角、操作按钮整行横排。
       挂 .mp-cards 的表：近期安排 / 我的考勤 / 我的请假 / 荣誉档案 /
       请假审批 / 出勤统计明细 / 操作日志 / 教员账号。
       ============================================================ */
    /* 这些表原来住在 .table-wrap（带描边+阴影+横向滚动）里，卡片化后那层壳必须消失，
       否则"卡里还有一层卡"。所有 wrap 里装的都是 .mp-cards 表，所以一起清掉。 */
    html.m-mobile #pcOverlay .table-wrap {
        overflow: visible;
        border: 0;
        border-radius: 0;
        background: transparent;
        box-shadow: none;
    }
    html.m-mobile #pcOverlay .mp-cards { display: block; width: 100%; min-width: 0; }
    html.m-mobile #pcOverlay .mp-cards > thead { display: none; }
    html.m-mobile #pcOverlay .mp-cards > tbody { display: block; }
    html.m-mobile #pcOverlay .mp-cards > tbody > tr {
        position: relative;
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 8px 10px;
        margin: 0 0 10px;
        padding: 12px;
        background: var(--surface);
        border: 1px solid var(--line);
        border-radius: 14px;
        box-shadow: 0 2px 8px rgba(160, 20, 40, .05);
    }
    html.m-mobile #pcOverlay .mp-cards > tbody > tr:last-child { margin-bottom: 0; }
    /* 卡片上不要 hover 底色（触摸屏上没有"悬停"，而且原来的 hover 会粘住不散） */
    html.m-mobile #pcOverlay .mp-cards > tbody > tr:hover { background: var(--surface); }
    html.m-mobile #pcOverlay .mp-cards > tbody > tr > td {
        display: block;
        min-width: 0;
        padding: 0;
        border: 0;
        font-size: 13px;
        text-align: left;
        white-space: normal;
        word-break: break-word;
        /* 覆盖 .adm-table-sticky 给"最后一列"加的右侧粘住（卡片模式下会错位） */
        position: static !important;
        background: transparent !important;
    }
    /* 每一格自己带标签（卡片模式没有表头了） */
    html.m-mobile #pcOverlay .mp-cards > tbody > tr > td::before {
        content: attr(data-label);
        display: block;
        margin-bottom: 2px;
        font-size: 12px;
        color: var(--gray);
    }
    html.m-mobile #pcOverlay .mp-cards > tbody > tr > td[data-label=""]::before { display: none; }
    html.m-mobile #pcOverlay .mp-cards > tbody > tr > td[data-label=""] { font-size: 13px; }
    /* 主标题（姓名 / 事项 / 请假日期 / 荣誉名称 / 对象说明）：整行、排到最前、
       右边留出状态标签的位置 */
    html.m-mobile #pcOverlay .mp-cards > tbody > tr > td.mp-td-title {
        grid-column: 1 / -1;
        order: -1;
        padding-right: 74px;
        font-size: 15px;
        font-weight: 700;
        line-height: 1.4;
    }
    /* 状态 / 徽标 = 卡片右上角（绝对定位，不占网格格） */
    html.m-mobile #pcOverlay .mp-cards > tbody > tr > td.mp-td-status {
        position: absolute !important;
        top: 12px;
        right: 12px;
        font-size: 12px;
        text-align: right;
    }
    /* 需要整行宽的格（事由 / 备注 / 审批意见 / 操作日志的"对象说明"） */
    html.m-mobile #pcOverlay .mp-cards > tbody > tr > td.mp-td-full { grid-column: 1 / -1; }
    /* 操作 = 卡片底部横排 */
    html.m-mobile #pcOverlay .mp-cards > tbody > tr > td.mp-td-acts {
        grid-column: 1 / -1;
        margin-top: 2px;
        display: flex;
        flex-wrap: wrap;
        gap: 8px;
    }
    html.m-mobile #pcOverlay .mp-cards .row-actions { display: flex; flex-wrap: wrap; gap: 8px; white-space: normal; }
    /* 空状态那一行（colspan=7/4）要占满整张卡 */
    html.m-mobile #pcOverlay .mp-cards > tbody > tr > td[colspan] { grid-column: 1 / -1; }
    /* 卡片里的按钮：≥44px，均分整行 */
    html.m-mobile #pcOverlay .mp-cards .adm-btn {
        flex: 1 1 auto;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        padding: 0 14px;
        font-size: 13px;
    }
    /* ⚠️ 从截图里发现并修掉的问题（v2.32 就有，只是没人细看）：
       `.adm-table-sticky td:last-child` 为了"操作列横向粘住"带了一条
       `box-shadow: -9px 0 12px -9px rgba(0,0,0,.28)`；卡片模式下一行只有一张卡，
       于是这条**本该在滚动时遮住内容的投影**变成卡片里一条莫名其妙的竖线
       （空状态那行尤其明显：整张卡左侧 9px 处一条灰线）。
       卡片模式下不需要它 —— 桌面端的表格滚动照旧有。 */
    html.m-mobile #pcOverlay #apane-review .adm-table > tbody > tr > td,
    html.m-mobile #pcOverlay #apane-members .adm-table > tbody > tr > td,
    html.m-mobile #pcOverlay #apane-attendance .adm-table > tbody > tr > td,
    html.m-mobile #pcOverlay .mp-cards > tbody > tr > td { box-shadow: none !important; }
    /* 卡片里的下拉/输入（考勤那张表的出勤状态与备注）满宽好点 */
    html.m-mobile #pcOverlay .mp-cards .att-sel,
    html.m-mobile #pcOverlay .mp-cards .att-note { width: 100%; min-height: 44px; box-sizing: border-box; }

    /* ---- 小表（部门分布 / 部门出勤率）：2~4 列、360px 放得下 ----
       这种表卡片化反而更啰嗦，所以只把它从"横向滚动的块"还原成真表格：
       不溢出、不换行、行距收紧，视觉仍与卡片一致。 */
    html.m-mobile #pcOverlay .mp-mini { display: table; width: 100%; min-width: 0; overflow: visible; table-layout: auto; }
    html.m-mobile #pcOverlay .mp-mini td { padding: 8px 6px; border-bottom: 1px solid var(--line); font-size: 13px; white-space: normal; }
    html.m-mobile #pcOverlay .mp-mini tr:last-child td { border-bottom: 0; }
    html.m-mobile #pcOverlay .mp-mini td:first-child { color: var(--gray); }

    /* ---- 键值表（我的报名 / 审核与分配结果 / 账号绑定）：标签在上、值在下 ----
       原来是两列（标签列写死 120~140px），手机上剩给值的宽度太窄，长学院名会折成柱状。 */
    html.m-mobile #pcOverlay .mp-kv { display: block; width: 100%; min-width: 0; overflow: visible; }
    html.m-mobile #pcOverlay .mp-kv > tbody { display: block; }
    html.m-mobile #pcOverlay .mp-kv > tbody > tr { display: block; padding: 9px 0; border-bottom: 1px solid var(--line); }
    html.m-mobile #pcOverlay .mp-kv > tbody > tr:last-child { border-bottom: 0; }
    html.m-mobile #pcOverlay .mp-kv > tbody > tr > td {
        display: block;
        width: auto !important;
        padding: 0;
        border: 0;
        font-size: 13.5px;
        line-height: 1.6;
        text-align: left;
    }
    html.m-mobile #pcOverlay .mp-kv > tbody > tr > td:first-child { font-size: 12px; color: var(--gray); }
    html.m-mobile #pcOverlay .mp-kv > tbody > tr > td:nth-child(2) { font-weight: 600; }
    html.m-mobile #pcOverlay .mp-kv > tbody > tr > td:nth-child(3):not(:empty) { margin-top: 4px; }

    /* ============================================================
       ③ 个人主页（#pane-home）⭐ 重点
       ------------------------------------------------------------
       兄长指出：名片上刚说完队号/状态/部门/身份，「个人主页」里又说了一遍。
       那四个块就是这面板上的 .pc-stats（考勤功能关掉、或状态不是 active/training 时，
       JS 会把四格换成"当前状态 / 所属部门 / 队号 / 身份"当作兜底）。
       纯 CSS 分不出这四格是在说身份还是在说统计，所以 renderMember() 里按
       "到底取到了哪一组"给它打了个 .mp-ident 标记 —— 手机端只藏带标记的那种。
       于是个人主页上只剩：欢迎语 → 一句状态提示 → 近期安排 → 快捷入口，
       全是名片上没有的新信息。
       ============================================================ */
    html.m-mobile #pane-home .pc-head { margin-bottom: 10px; }
    /* 右上那颗状态胶囊与名片上的"状态"重复，手机上藏掉（下面那句提示里已经有状态了） */
    html.m-mobile #pane-home #pcRoleTag { display: none; }
    /* 欢迎语卡：一句欢迎 + 一行说明 */
    html.m-mobile #pane-home .pc-head h3 { font-size: 17px; }
    html.m-mobile #pane-home .pc-head p { font-size: 13px; color: var(--gray); }
    /* 状态提示条（#mStatusBanner 里的 .m-banner）：压成卡片，字体收到 13px */
    html.m-mobile #pane-home .m-banner {
        margin-bottom: 14px;
        padding: 13px 14px;
        border-radius: 16px;
        font-size: 13px;
        line-height: 1.6;
        box-shadow: 0 2px 8px rgba(160, 20, 40, .05);
    }
    html.m-mobile #pane-home .m-banner b { font-size: 14px; }
    /* ⭐ 与名片重复的那一组（.mp-ident）：手机端整块不显示 */
    html.m-mobile #pane-home .pc-stats.mp-ident { display: none; }
    /* 「近期安排」那张表：手机端一档一卡（data-label 已在 HTML 里挂好） */
    html.m-mobile #pane-home .mp-sched-table > tbody > tr > td.mp-td-title { padding-right: 68px; }
    /* 「最新通知」两块：条目卡片化。
       ⚠️ 用 flex 而不是 grid：这里三个孩子的宽度都是"内容决定"的，
          用 grid 把 time 钉在第 3 列会和"第 2 列起、跨到最后一列"的正文**重叠**。 */
    html.m-mobile #pane-home .pc-msg {
        display: flex;
        align-items: flex-start;
        gap: 10px;
        padding: 12px;
        margin-bottom: 8px;
        border: 1px solid var(--line);
        border-bottom: 1px solid var(--line);
        border-radius: 14px;
        background: var(--surface);
    }
    html.m-mobile #pane-home .pc-msg:last-child { margin-bottom: 0; }
    html.m-mobile #pane-home .pc-msg .mi { flex: none; width: 38px; height: 38px; }
    html.m-mobile #pane-home .pc-msg > div:not(.mi) { flex: 1 1 auto; min-width: 0; }
    html.m-mobile #pane-home .pc-msg b { font-size: 14px; }
    html.m-mobile #pane-home .pc-msg p { font-size: 12.5px; }
    html.m-mobile #pane-home .pc-msg time { flex: none; font-size: 12px; }
    /* 「入队进度提示」那种锁定卡：说明文字 13px，别再顶到 30px 的留白 */
    html.m-mobile #pane-home .pc-card.member-locked { padding: 14px; }
    html.m-mobile #pane-home .locked-text { font-size: 13px; line-height: 1.6; margin: 0; }

    /* ---- 「快捷入口」：手机端才显示（宽屏基线已写死 display:none） ----
       它是个人主页上唯一"新增的东西"，所以必须是真的新信息 ——
       里面 6 格全是**手机端侧栏(已被压成顶部 chip 条)里不好找**的入口，
       点一下 = 点原来那个菜单按钮（data-mp-src 指的正是那个选择器）。 */
    html.m-mobile #mpPaneQuick {
        display: block;
        /* .mp-sec 自带的 14px 左右外边距是给"整屏首页"用的；
           面板本体已经有 12px 内边距，这里不能再加一遍 */
        margin: 16px 0 0;
    }
    html.m-mobile #mpPaneQuick > h4 {
        margin: 0 0 10px;
        font-size: 13px;
        font-weight: 600;
        letter-spacing: .4px;
        color: var(--gray);
    }

    /* ============================================================
       ④ 今日课程 / 我的课表
       ============================================================ */
    /* 日期 / 周次 / 时段 / 「回到今天」原本挤在一行（一行放不下就折成两三行，看着很乱），
       现在按 order 重排成：日期整行 →(周次 | 回到今天)→ 时段整行 → 图例整行。 */
    html.m-mobile #pcOverlay .tc-bar {
        gap: 8px;
        margin-bottom: 14px;
        padding: 12px;
        border-radius: 16px;
        background: var(--surface);
        border: 1px solid var(--line);
        box-shadow: 0 2px 8px rgba(160, 20, 40, .05);
    }
    /* ⚠️ 字体必须 ≥16px：iOS 上聚焦 <16px 的输入框会把**整页**放大 */
    html.m-mobile #pcOverlay .tc-bar input[type="date"] { order: 1; flex: 1 1 100%; min-height: 44px; font-size: 16px; }
    html.m-mobile #pcOverlay .tc-bar .tc-week { order: 2; flex: 1 1 auto; min-width: 0; font-size: 13.5px; }
    html.m-mobile #pcOverlay .tc-bar .tc-now {
        order: 3;
        flex: 0 0 auto;
        min-height: 44px;
        padding: 0 16px;
        border-radius: 12px;
        border: 1px solid var(--line);
        background: var(--surface-2);
        color: var(--red-ink);
        font-family: inherit;
        font-size: 13.5px;
        font-weight: 600;
        cursor: pointer;
    }
    html.m-mobile #pcOverlay .tc-bar .tc-now:active { background: var(--line); }
    html.m-mobile #pcOverlay .tc-bar select.tc-slot { order: 4; flex: 1 1 100%; min-height: 44px; font-size: 16px; }
    html.m-mobile #pcOverlay .tc-bar .tc-legend { order: 5; flex: 1 1 100%; margin-left: 0; font-size: 12px; line-height: 1.5; }
    html.m-mobile #pcOverlay .tc-sec { margin-bottom: 16px; }
    html.m-mobile #pcOverlay .tc-sec > h4 { margin-bottom: 10px; font-size: 13px; }
    /* 课程条目 → 卡片行：①课程名（粗） ②右上"第几节 + 时间"小标签 ③地点/教师 */
    html.m-mobile #pcOverlay .tc-item {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: start;
        gap: 4px 10px;
        margin: 0 0 8px;
        padding: 12px;
        border-radius: 14px;
        background: var(--surface);
        border: 1px solid var(--line);
        box-shadow: 0 2px 8px rgba(160, 20, 40, .05);
        font-size: 13px;
    }
    html.m-mobile #pcOverlay .tc-item .nm {
        grid-column: 1;
        grid-row: 1;
        order: -1;
        min-width: 0;
        font-size: 15px;
        font-weight: 700;
        line-height: 1.35;
    }
    html.m-mobile #pcOverlay .tc-item .tm {
        grid-column: 2;
        grid-row: 1;
        justify-self: end;
        padding: 3px 9px;
        border-radius: 999px;
        white-space: nowrap;
        font-size: 12px;
        font-weight: 700;
        color: var(--red-ink);
        background: rgba(200, 16, 46, .08);
    }
    html.m-mobile #pcOverlay .tc-item .mt { grid-column: 1 / -1; font-size: 12.5px; color: var(--gray); line-height: 1.5; }
    /* 「没课的队员」那一串名单：做成小胶囊，好点也不挤 */
    html.m-mobile #pcOverlay .tc-free { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px; border-radius: 14px; }
    html.m-mobile #pcOverlay .tc-free span { min-height: 30px; display: inline-flex; align-items: center; font-size: 12.5px; }
    html.m-mobile #pcOverlay .tc-empty { padding: 22px 10px; font-size: 13px; }

    /* 我的课表：翻周工具条卡片化；上传课表的两个按钮整行 ≥48px */
    html.m-mobile #pcOverlay .wk-bar {
        padding: 10px 12px;
        border-radius: 16px;
        background: var(--surface);
        border: 1px solid var(--line);
        box-shadow: 0 2px 8px rgba(160, 20, 40, .05);
    }
    html.m-mobile #pcOverlay .wk-bar .wk-title { flex: 1 1 auto; text-align: left; }
    /* ⚠️ 另一个从截图里揪出来的老 bug：index.html 里 **--accent 这个变量压根没定义**
       （`--accent: …` 只写在 internal.html / showcase.html 里）。CSS 变量取不到值属于
       "computed-value 阶段无效"，于是 `.wk-btn.primary { background: var(--accent); color:#fff }`
       变成「**透明底 + 白字**」—— 手机上看就是"📷 导出图片"整颗按钮凭空消失，
       只剩一个 12px 的相机图标浮在那儿（桌面端其实也是坏的，但这一段是手机专用样式，
       桌面的渲染结果一个字都不能动，所以这里只修手机端）。 */
    html.m-mobile #pcOverlay .wk-bar .wk-title { color: var(--red-ink); }
    html.m-mobile #pcOverlay .wk-btn.primary {
        background: var(--red);
        border-color: var(--red);
        color: #fff;
    }
    /* 上传课表的两个按钮：它挂在 `.set-row` 下，而手机端 `.set-row` 已改成 block，
       所以这里得用 width:100%（写 flex:1 1 100% 是不生效的 —— 一开始就写错了）。 */
    html.m-mobile #pcOverlay #wkPick,
    html.m-mobile #pcOverlay #wkSubmit { width: 100%; min-height: 48px; font-size: 14.5px; }
    html.m-mobile #pcOverlay #wkUploadCard .set-row { display: block; }
    html.m-mobile #pcOverlay #wkUploadCard .set-tip { display: block; margin-top: 6px; }
    html.m-mobile #pcOverlay #wkUploadCard input[type="text"] { width: 100%; min-height: 44px; font-size: 16px; }

    /* ============================================================
       ⑤ 个人信息（#pane-info）
       ============================================================ */
    /* 表单：一行一个字段（label 在上、input 整行） */
    html.m-mobile #pane-info .pc-form { grid-template-columns: 1fr; gap: 12px; }
    html.m-mobile #pane-info .pc-form .field label { font-size: 13px; }
    html.m-mobile #pane-info .pc-form input,
    html.m-mobile #pane-info .pc-form select,
    html.m-mobile #pane-info .pc-form textarea { min-height: 44px; font-size: 16px; }
    html.m-mobile #pane-info .pc-form textarea { min-height: 84px; }
    /* 头像：字符头像 40→44px（触摸目标），两个按钮整行 */
    html.m-mobile #pane-info .pc-avatars { flex-wrap: wrap; gap: 10px; }
    html.m-mobile #pane-info .pc-avatars span { width: 44px; height: 44px; font-size: 20px; }
    html.m-mobile #pane-info .pc-card > .set-row { display: block; }
    html.m-mobile #pane-info .pc-card > .set-row > .adm-btn { width: 100%; margin-bottom: 8px; }
    html.m-mobile #pane-info .pc-card > .set-row > .set-tip { display: block; }

    /* 保存按钮整行吸底：字段一多，滚到底才看得见「保存修改」；
       吸住之后随时能点。整块往外撑满卡片内边距，边上不留一条缝。 */
    html.m-mobile #pcOverlay .pc-form > .field.mp-save {
        position: sticky;
        bottom: 0;
        z-index: 6;
        margin: 0 -14px -14px;
        padding: 12px 14px calc(12px + env(safe-area-inset-bottom, 0px));
        background: var(--surface);
        border-top: 1px solid var(--line);
        border-radius: 0 0 16px 16px;
    }
    /* 同一套样式也用在「我的请假 → 提交申请」「账号设置 → 改密码 / 激活 / 绑定邮箱」上 */

    /* ============================================================
       ⑥ 我的通知（#pane-msg）
       ============================================================ */
    /* 列表项卡片化：图标 + 内容 + 时间，未读左侧一条红杠（同上：用 flex，别用 grid） */
    html.m-mobile #pcMsgList { padding: 12px; }
    html.m-mobile #pcMsgList .pc-msg {
        display: flex;
        align-items: flex-start;
        gap: 10px;
        min-height: 56px;
        padding: 12px;
        margin-bottom: 8px;
        border: 1px solid var(--line);
        border-bottom: 1px solid var(--line);
        border-radius: 14px;
        background: var(--surface);
    }
    html.m-mobile #pcMsgList .pc-msg:last-child { margin-bottom: 0; }
    html.m-mobile #pcMsgList .pc-msg .mi { flex: none; }
    html.m-mobile #pcMsgList .pc-msg > div:not(.mi) { flex: 1 1 auto; min-width: 0; }
    html.m-mobile #pcMsgList .pc-msg b { font-size: 14px; }
    html.m-mobile #pcMsgList .pc-msg p { font-size: 12.5px; }
    html.m-mobile #pcMsgList .pc-msg time { flex: none; font-size: 12px; }
    html.m-mobile #pcMsgList .pc-msg[style] {
        border-left: 3px solid var(--red);
        background: rgba(200, 16, 46, .05) !important;
    }
    /* 「全部标为已读」：整行、≥48px（宽屏基线里它是 display:none，桌面端看不见它） */
    html.m-mobile .pc-main.is-inteam #mpReadAll {
        display: block;
        width: 100%;
        min-height: 48px;
        margin: 12px 0 0;
        border-radius: 14px;
        border: 1px solid var(--line);
        background: var(--surface);
        color: var(--red-ink);
        font-family: inherit;
        font-size: 14px;
        font-weight: 700;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }
    html.m-mobile .pc-main.is-inteam #mpReadAll:active { background: var(--surface-2); }
    html.m-mobile .pc-main.is-inteam #mpReadAll[disabled] { opacity: .6; }

    /* ============================================================
       ⑦ 我的考勤 / 我的请假 / 我的报名 / 荣誉档案 / 账号设置（队员侧其余面板）
       ============================================================ */
    /* 签到卡 */
    html.m-mobile #pane-att .sign-card .btn { width: 100%; min-height: 48px; }
    html.m-mobile #pane-att .sign-card .sign-tip { font-size: 12.5px; }
    /* 进队进度条：原来是横排 5 段（手机上每段只有 60px，字全折），改竖排一行一段 */
    html.m-mobile #pane-join .pc-progress { display: block; }
    html.m-mobile #pane-join .pc-step {
        display: flex;
        align-items: center;
        gap: 10px;
        flex: none;
        min-width: 0;
        margin: 0 0 10px;
        text-align: left;
    }
    html.m-mobile #pane-join .pc-step::before { display: none; }
    html.m-mobile #pane-join .pc-step .dot { flex: none; margin: 0; }
    html.m-mobile #pane-join .pc-step .st { margin: 0 0 0 auto; }
    /* 表单（请假 / 账号设置）与个人信息同一套：一行一个字段、按钮整行吸底 */
    html.m-mobile #pane-leave .pc-form,
    html.m-mobile #pane-setting .pc-form { grid-template-columns: 1fr; gap: 12px; }
    html.m-mobile #pane-leave .pc-form input,
    html.m-mobile #pane-leave .pc-form textarea,
    html.m-mobile #pane-setting .pc-form input,
    html.m-mobile #pane-setting .pc-form select,
    html.m-mobile #pane-setting .pc-form textarea { min-height: 44px; font-size: 16px; }
    /* 「邮箱验证码」那一行是"输入框 + 获取验证码"并排：手机上让按钮整行，别把输入框挤短 */
    html.m-mobile #pane-setting .pc-form .field.full > div[style] { flex-wrap: wrap; }
    html.m-mobile #pane-setting #mailBindSendBtn { flex: 1 1 100%; min-height: 44px; }
    html.m-mobile #pane-setting #mailBindCode { flex: 1 1 100%; }
    /* 账号说明 / 未绑定提醒：正文 13px，按钮整行 */
    html.m-mobile #pane-setting .pc-callout .btn { flex: 1 1 100%; margin-left: 0; }
    html.m-mobile #pane-setting .pc-callout p { flex: 1 1 100%; font-size: 13px; }

    /* ============================================================
       ⑧ 教员侧：工作台 / 数据中心 / 教员账号 / 账号安全 / 系统设置
       （报名审核 / 成员管理 / 考勤管理 / 出勤统计表 的卡片化见上面 ②）
       ============================================================ */
    /* --- 工作台 --- */
    html.m-mobile #apane-dash .dash-item,
    html.m-mobile #apane-stats .dash-item {
        display: block;
        padding: 12px;
        margin-bottom: 8px;
        border-bottom: 1px solid var(--line);
        border: 1px solid var(--line);
        border-radius: 14px;
        background: var(--surface);
    }
    html.m-mobile #apane-dash .dash-item:last-child,
    html.m-mobile #apane-stats .dash-item:last-child { margin-bottom: 0; }
    html.m-mobile #apane-dash .dash-item b,
    html.m-mobile #apane-stats .dash-item b { font-size: 14.5px; }
    html.m-mobile #apane-dash .dash-item span,
    html.m-mobile #apane-stats .dash-item span,
    html.m-mobile #apane-dash .dash-item small,
    html.m-mobile #apane-stats .dash-item small { font-size: 12.5px; }
    /* 待审核条目上的按钮：整行、≥44px（原来跟文字挤在一行） */
    html.m-mobile #apane-dash .dash-item .adm-btn,
    html.m-mobile #apane-stats .dash-item .adm-btn { width: 100%; min-height: 44px; margin-top: 8px; }

    /* --- 出勤统计：月份选择整行、部门出勤率的条形图别撑破 --- */
    html.m-mobile #apane-stats #statsMonth { width: 100% !important; min-height: 44px; font-size: 16px; }
    html.m-mobile #apane-stats .dept-bar { max-width: 100%; }

    /* --- 数据中心：说明文字 13px、操作按钮已经整行（v2.32），日志表见 ② --- */
    html.m-mobile #apane-data .adm-desc { font-size: 13px; line-height: 1.65; }
    html.m-mobile #apane-data .pc-card > .adm-actions .adm-btn { width: 100%; min-height: 44px; }

    /* --- 教员账号：说明文字与列表 --- */
    html.m-mobile #apane-admins .adm-desc { font-size: 13px; line-height: 1.65; }
    html.m-mobile #apane-admins .pc-card { max-width: none !important; }

    /* --- 账号安全：头像两个按钮整行、密码表单一行一个字段 --- */
    html.m-mobile #apane-security .pc-card { max-width: none !important; }
    html.m-mobile #apane-security .set-row { display: block; }
    html.m-mobile #apane-security .set-row > .adm-btn { width: 100%; margin-bottom: 8px; }
    html.m-mobile #apane-security .set-row > .set-tip { display: block; }
    html.m-mobile #apane-security .lfield { margin-bottom: 12px; }
    html.m-mobile #apane-security .lfield label { display: block; margin-bottom: 5px; font-size: 13px; color: var(--gray); }
    html.m-mobile #apane-security .lfield input { width: 100%; min-height: 44px; font-size: 16px; box-sizing: border-box; }
    /* 「确认修改」不在 `.pc-form` 里（它是独立的 #adminPwdForm），
       所以上面那条整行规则没盖到它 —— 截图里它还是个小方块。这里补一条。 */
    html.m-mobile #apane-security #adminPwdForm .btn { width: 100%; min-height: 48px; font-size: 14.5px; }

    /* --- 系统设置：一整块一块的 set-sec 变成卡片；行内控件放大到能点 --- */
    html.m-mobile #apane-settings .set-sec {
        padding: 14px;
        margin-bottom: 14px;
        border-radius: 16px;
        background: var(--surface);
        border: 1px solid var(--line);
        box-shadow: 0 2px 8px rgba(160, 20, 40, .05);
    }
    html.m-mobile #apane-settings .set-sec > h4 { font-size: 14px; line-height: 1.5; }
    html.m-mobile #apane-settings .set-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 8px 0; }
    html.m-mobile #apane-settings .set-row > label { flex: 0 0 auto; font-size: 12.5px; }
    /* ⚠️ 输入框必须 16px：iOS 上聚焦 <16px 的输入框会把整页放大。
       ⚠️ `min-width: 116px` 不能省：只写 `flex: 1 1 118px` 的话，一行放不下时
          浏览器会**先把它压扁**再换行 —— 截图里「值班时段」那一行的
          「06:30-07:30」被压成了「06:30-07:」，时间直接看不全。给个下限，
          放不下就老老实实换行。 */
    html.m-mobile #apane-settings .set-row > input,
    html.m-mobile #apane-settings .set-row > select {
        flex: 1 1 118px;
        min-width: 116px;
        width: auto !important;
        min-height: 44px;
        font-size: 16px;
    }
    html.m-mobile #apane-settings .set-row > button { flex: 0 0 auto; min-height: 44px; }
    /* 「值班时段」那一行的时段名里**连时间一起写**（值长这样：「早训 06:30-07:30」），
       「停课日」那一行的日期同理。它们原来靠内联 `width:170px / 140px` 撑开，
       而手机端把宽度统一成 `auto` 后就按 118px 分了 → 截图里被切成
       「早训 06:30-07:」「上午 08:30-12:」。这两个字段本身就该独占一行，
       别的（节次 / 名称 / 删除）排到下一行去。 */
    html.m-mobile #apane-settings .set-duty > .d-label,
    html.m-mobile #apane-settings .set-hol > .h-d { flex: 1 1 100%; min-width: 0; }
    html.m-mobile #apane-settings .set-sw { min-height: 44px; padding: 10px 14px; font-size: 13px; flex: 1 1 auto; }
    /* 真实的点击目标是外面那个 `.set-sw` 胶囊（min-height:44px），
       这里面只是把原生复选框放大一点、好认（原生在 Chrome 上只有 13px）。 */
    html.m-mobile #apane-settings .set-sw input { width: 22px; height: 22px; }
    html.m-mobile #apane-settings .set-logo-box { flex: 0 0 auto; }
    /* 组织架构里那些"身份"编辑行：取色器 + 名称输入 + 删除按钮排一行 */
    html.m-mobile #apane-settings .pos-row { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
    html.m-mobile #apane-settings .pos-row input[type="text"] { flex: 1 1 118px; min-width: 116px; width: auto; min-height: 44px; font-size: 16px; }
    html.m-mobile #apane-settings .pos-row input[type="color"] { width: 48px; height: 44px; }
    html.m-mobile #apane-settings .pos-row .set-del { min-height: 44px; padding: 0 12px; }
    /* 页面最下面的「保存全部设置 / 放弃修改」：整行 ≥48px，吸底好点 */
    html.m-mobile #apane-settings .set-actions {
        position: sticky;
        bottom: 0;
        z-index: 6;
        display: block;
        padding: 12px 0 calc(12px + env(safe-area-inset-bottom, 0px));
        background: var(--bg);
        border-top: 1px solid var(--line);
    }
    html.m-mobile #apane-settings .set-actions > button { width: 100%; min-height: 48px; margin-bottom: 8px; font-size: 14.5px; }
    html.m-mobile #apane-settings .set-actions > .set-msg { display: block; }
}

/* ============================================================
   v2.34 · 校区维度：两个**新增的下拉**在手机端也要够 44px
   ------------------------------------------------------------
   为什么只写这两条：其余校控件（成员管理筛选 #memberCampus、
   个人中心的 #pfCampus）落在 v2.32/v2.33 已经铺好的手机版式里
   ——`.toolbar .adm-select` 和 `#pane-info .pc-form select` 都已经是
   min-height:44px，直接沿用就行，不必再写。
   这两个是**新开的坑位**：
     · #pcRegCampus  注册弹层里，「性别」那一行的控件没有手机端尺寸规则；
     · #aeCampus     成员档案编辑抽屉（ae-grid）在手机端也没有尺寸规则。
   只给它们加高度、不动同排既有控件（3~4px 差肉眼看不出来），
   桌面端一个像素都不变。 */
html.m-mobile #pcRegCampus,
html.m-mobile #aeCampus { min-height: 44px; }

/* ============================================================
   v2.35 · 通知发布中心 / 队伍通知（手机端）
   ------------------------------------------------------------
   为什么整段都收在 @media (max-width: 768px) 里：
   桌面版这一版要求**逐像素不变**，所以桌面端一个新规则都不加；
   面板本身在 index.html 里只用既有类（.pc-card / .chips / .chip /
   .adm-btn / .adm-select / .adm-table-compact / .data-msg），
   这里只补"手机上点得到、不溢出"的部分。
   为什么还要叠 html.m-mobile：和本文件其它段一致 —— 既压得过
   index.html 自带的 @media(max-width:900px)，也不会在桌面误伤。
   ============================================================ */
@media (max-width: 768px) {
    /* 输入框：≥44px 好点，16px 字号防 iOS 聚焦时自动放大页面 */
    html.m-mobile #apane-notice #ntTitle,
    html.m-mobile #apane-notice #ntExpire,
    html.m-mobile #apane-notice #ntBody,
    html.m-mobile #apane-notice #ntMemberKw {
        min-height: 44px;
        font-size: 16px;
        width: 100%;
        max-width: none;
        box-sizing: border-box;
    }
    html.m-mobile #apane-notice #ntBody { min-height: 116px; line-height: 1.7; }
    /* 「置顶 / 有效期」这两个 label 在窄屏上各占一行，别和标题挤成一条 */
    html.m-mobile #apane-notice #ntFormCard > div:first-of-type > label {
        flex: 1 1 100%;
        min-height: 40px;
        font-size: 13px;
    }
    html.m-mobile #apane-notice #ntExpire { flex: 1 1 auto; width: auto; }
    /* 目标四组：标签一行、chip 一整行 */
    html.m-mobile #apane-notice #ntFormCard > div > span:first-child { flex: 1 1 100%; }
    /* 规格要求「目标 chip 横向滚动不换行」。为什么不 wrap：
       四组 chip（校区 2 / 部门 4 / 状态 7）在 390px 上换行会把表单撑长两三屏，
       手指要划半天才够得到「发送」；改成单行横向滚动，一组一眼看全，左右滑即可。
       滚动条也藏掉 —— 手机上本来就不显示，PC 的 Chrome 模拟手机时别多一条灰条。 */
    html.m-mobile #apane-notice #ntAllChips,
    html.m-mobile #apane-notice #ntCampusChips,
    html.m-mobile #apane-notice #ntDeptChips,
    html.m-mobile #apane-notice #ntStatusChips {
        flex-wrap: nowrap;
        overflow-x: auto;
        overflow-y: hidden;
        padding-bottom: 4px;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }
    html.m-mobile #apane-notice #ntAllChips::-webkit-scrollbar,
    html.m-mobile #apane-notice #ntCampusChips::-webkit-scrollbar,
    html.m-mobile #apane-notice #ntDeptChips::-webkit-scrollbar,
    html.m-mobile #apane-notice #ntStatusChips::-webkit-scrollbar { display: none; }
    html.m-mobile #apane-notice #ntAllChips > .chip,
    html.m-mobile #apane-notice #ntCampusChips > .chip,
    html.m-mobile #apane-notice #ntDeptChips > .chip,
    html.m-mobile #apane-notice #ntStatusChips > .chip { flex: 0 0 auto; white-space: nowrap; }
    html.m-mobile #apane-notice .chip { min-height: 38px; padding: 7px 14px; }
    html.m-mobile #apane-notice #ntMemberList { max-height: 240px; }
    html.m-mobile #apane-notice #ntMemberList label { min-height: 40px; padding: 6px 8px; font-size: 13px; }
    html.m-mobile #apane-notice #ntMemberKw { margin-bottom: 4px; }
    /* 发送行：整行竖排，按钮占满一整行（手指点在正文下面很自然） */
    html.m-mobile #apane-notice #ntFormCard > .toolbar:last-child {
        display: block;
        padding-top: 4px;
    }
    html.m-mobile #apane-notice #ntPreview { display: block; font-size: 13px; line-height: 1.7; }
    html.m-mobile #apane-notice #ntSend {
        display: block;
        width: 100%;
        min-height: 48px;
        margin: 10px 0 0;
        font-size: 15px;
    }
    html.m-mobile #apane-notice #ntMsg { display: block; margin-top: 8px; }
    html.m-mobile #apane-notice #ntRefresh { min-height: 40px; }
    /* 「我发出的通知」表：手机上把「发送时间」列藏掉（时间在回执里还能看到），
       6 列挤进 390px 会变成每格两三个字一行，反而看不出谁读了多少。 */
    html.m-mobile #apane-notice #ntManageBody td,
    html.m-mobile #apane-notice #ntManageBody th { font-size: 12px; }
    html.m-mobile #apane-notice #ntManageBody th:nth-child(3),
    html.m-mobile #apane-notice #ntManageBody td:nth-child(3) { display: none; }
    html.m-mobile #apane-notice #ntManageBody .adm-btn {
        min-height: 32px;
        padding: 4px 9px;
        font-size: 12px;
    }
    /* 回执里的名字 chip：允许换行、别把长名字截掉 */
    html.m-mobile #apane-notice #ntReceiptBody .chip { height: auto; min-height: 30px; white-space: normal; text-align: left; }

    /* 队伍通知列表（在「我的通知」面板里）：正文长段落要能断行，右侧时间不挤标题 */
    html.m-mobile #pane-msg .nt-item { padding-left: 10px !important; }
    html.m-mobile #pane-msg .nt-item > div:last-of-type { flex: 1 1 auto; min-width: 0; }
    html.m-mobile #pane-msg .nt-item b { display: flex; flex-wrap: wrap; align-items: center; gap: 2px; }
    html.m-mobile #pane-msg .nt-body { font-size: 13.5px; word-break: break-word; }
    html.m-mobile #pane-msg .nt-item time { display: none; }

    /* —— v2.36 新增：收件箱 / 「我发出的通知」的分页条，以及编辑态提示条 ——
       分页按钮在 390px 上被左右推到边，中间那行「第 x / y 页」要能换行不溢出。 */
    html.m-mobile #pcNoticePager,
    html.m-mobile #ntManagePager {
        flex-wrap: wrap;
        justify-content: space-between;
        gap: 6px;
        margin-top: 8px;
    }
    html.m-mobile #pcNoticePager .adm-btn,
    html.m-mobile #ntManagePager .adm-btn { min-height: 38px; padding: 6px 12px; font-size: 12.5px; }
    html.m-mobile #pcNoticePager > span,
    html.m-mobile #ntManagePager > span { font-size: 12px; }
    /* 操作列现在最多四个按钮（回执 / 编辑 / 撤回 / 删除）：手机上允许换行，
       否则四个按钮挤成一条会把整张表撑出横向滚动。 */
    html.m-mobile #apane-notice #ntManageBody td { white-space: normal; }
    html.m-mobile #apane-notice #ntManageBody td:last-child .adm-btn { margin: 2px 3px 2px 0; }
    /* 编辑态提示条：窄屏上「取消编辑」单独占一行，文字不被挤成三行 */
    html.m-mobile #apane-notice #ntEditBar { align-items: flex-start; line-height: 1.6; }
    html.m-mobile #apane-notice #ntEditBar #ntEditCancel {
        flex: 1 1 100%;
        min-height: 40px;
        margin-left: 0;
    }
}

/* ===== v2.37 场次考勤（手机端）：6 格统计压成 3 列 2 行，别把点名表挤到首屏之外 ===== */
@media (max-width: 768px) {
  html.m-mobile #apane-attendance .pc-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin-bottom: 10px; }
  html.m-mobile #apane-attendance .pc-stats .pc-stat { padding: 8px 6px; border-radius: 10px; }
  html.m-mobile #apane-attendance .pc-stats .pc-stat strong { font-size: 18px; }
  html.m-mobile #apane-attendance .pc-stats .pc-stat span { font-size: 11px; }
  html.m-mobile #apane-attendance #att2Body td, html.m-mobile #apane-attendance #att2Body th { font-size: 12px; }
  html.m-mobile #apane-attendance #attwBody td, html.m-mobile #apane-attendance #attwHead th { font-size: 12px; padding: 6px 4px; }
  html.m-mobile #apane-attendance #mkBody td { font-size: 12px; }
  html.m-mobile #apane-attendance .att2-mark, html.m-mobile #apane-attendance .att2-clear { min-height: 34px; padding: 4px 9px; font-size: 12px; }
}

/* ---------------- v2.39：我的考勤「当前场次」提示 + 签到规则说明 ---------------- */
#mAttSignBox .sign-now {
  display: inline-block;
  margin: 0 0 8px;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(240, 140, 0, .12);
  border: 1px solid rgba(240, 140, 0, .32);
  color: #8A5300;
  font-size: 12.5px;
  line-height: 1.5;
}
[data-theme="dark"] #mAttSignBox .sign-now {
  color: #FFC46B;
  background: rgba(255, 196, 107, .14);
  border-color: rgba(255, 196, 107, .34);
}
html.m-mobile #mAttSignBox .sign-now {
  display: block;
  text-align: center;
  font-size: 12px;
}
