/* ============================================================
   高级动效（？？？模式 v2）—— 苹果风格弹性动效
   ------------------------------------------------------------
   为什么重写：
   旧版「？？？模式」给 body 挂了无限循环的渐变位移 + hue-rotate 滤镜，
   给每个头像挂了无限旋转、每个气泡挂了无限扫光、每个 hover 项挂了无限脉冲。
   结果是：
     · 常驻动画一直在触发合成层重绘 → 低端机直接卡死（手机尤其明显）；
     · hue-rotate 让整页颜色发青发紫，配上半透明磨砂非常「脏」，观感很丑。
   本文件改为「一次性、只动 transform / opacity」的物理动效：
     · 弹窗从触发按钮的位置被「拽出来」（transform-origin + clip-path 展开）；
     · 标签页指示块用弹性曲线滑动；
     · 新消息单条入场（不做整表重绘动画）；
     · 按钮 / 列表项按压回弹。
   没有任何无限循环动画，静止时不占用 GPU。
   ============================================================ */

:root {
    --mo-spring: cubic-bezier(.16, 1.08, .24, 1);
    --mo-apple: cubic-bezier(.22, .9, .18, 1);
    --mo-exit: cubic-bezier(.55, .05, .22, 1);
    --mo-d1: .2s;
    --mo-d2: .36s;
    --mo-d3: .58s;
}

/* ------------------------------------------------------------
   1. 主题底色：静态、单层，不再有动画与滤镜
   ------------------------------------------------------------ */
body.mystery-mode {
    background:
        radial-gradient(120% 90% at 12% 0%, rgba(96, 128, 255, .16), transparent 60%),
        radial-gradient(100% 80% at 92% 8%, rgba(255, 128, 200, .12), transparent 58%),
        linear-gradient(168deg, #0a0c16 0%, #11131d 52%, #0a0e18 100%);
    background-attachment: fixed;
}

body.mystery-mode .app-container {
    border: 1px solid rgba(150, 170, 255, .16);
    box-shadow: 0 24px 70px rgba(0, 0, 0, .58), 0 0 0 1px rgba(255, 255, 255, .02) inset;
}

/* 磨砂只保留一层，且半径收敛到 10px：半径越大越吃 GPU，视觉收益却很小 */
body.mystery-mode .sidebar,
body.mystery-mode .chat-header,
body.mystery-mode .chat-input-area,
body.mystery-mode .modal-content {
    backdrop-filter: blur(10px) saturate(1.08);
    -webkit-backdrop-filter: blur(10px) saturate(1.08);
}

/* ------------------------------------------------------------
   2. 弹窗：从触发按钮里「拽出来」
   ------------------------------------------------------------
   --mo-ox / --mo-oy : transform-origin，由 mystery-motion.js 按「点击的位置」写入
   --mo-dx / --mo-dy : 起始位移，与按钮同方向，做出「被抽出来」的物理感
   ------------------------------------------------------------ */
body.mystery-mode .modal-overlay .modal-content {
    transform-origin: var(--mo-ox, 50%) var(--mo-oy, 110%);
    transition: none;
    transform: none;
}

/* will-change 只在动画真正播放的那几百毫秒里挂上：常驻的 will-change
   会一直占着一块合成层，那正是旧版卡顿的来源之一。
   .mo-animating 由 mystery-motion.js 在动画开始时加上、animationend 时摘掉。 */
body.mystery-mode .modal-overlay.mo-animating .modal-content {
    will-change: transform, opacity, clip-path;
}

/* style.css 里有 .modal-overlay.show .modal-content{transform:translateY(0)}，
   特异性与本规则相同但顺序在前，这里显式再压一次，避免关闭动画结束后
   弹窗残留一个 translateY 造成的位置偏差。 */
body.mystery-mode .modal-overlay.show .modal-content {
    transform: none;
}

body.mystery-mode .modal-overlay.mo-opened .modal-content {
    animation: moDetach var(--mo-d3) var(--mo-spring) both;
}

body.mystery-mode .modal-overlay.mo-closing .modal-content {
    animation: moReturn .42s var(--mo-exit) both;
}

body.mystery-mode .modal-overlay.mo-opened .mo-stagger {
    animation: moChildIn .42s var(--mo-apple) both;
    animation-delay: calc(70ms + var(--mo-i, 0) * 38ms);
}

/* 不再动画 filter: blur()：整块弹窗做高斯模糊会让浏览器每帧重新光栅化
   一整张大图层，是弹窗展开时掉帧的主要来源。改用 transform + opacity +
   clip-path（都能走合成器），观感几乎一致。 */
@keyframes moDetach {
    0% {
        opacity: 0;
        transform: translate3d(var(--mo-dx, 0px), var(--mo-dy, 26px), 0) scale(.72);
        clip-path: inset(46% 46% 46% 46% round 30px);
    }
    58% {
        opacity: 1;
        transform: translate3d(0, -2px, 0) scale(1.012);
    }
    100% {
        opacity: 1;
        transform: translate3d(0, 0, 0) scale(1);
        clip-path: inset(0 0 0 0 round var(--mo-radius, 12px));
    }
}

@keyframes moReturn {
    0% {
        opacity: 1;
        transform: translate3d(0, 0, 0) scale(1);
        clip-path: inset(0 0 0 0 round var(--mo-radius, 12px));
    }
    100% {
        opacity: 0;
        transform: translate3d(var(--mo-dx, 0px), var(--mo-dy, 26px), 0) scale(var(--mo-shrink, .18));
        clip-path: inset(47% 47% 47% 47% round 40px);
    }
}

@keyframes moChildIn {
    from { opacity: 0; transform: translate3d(0, 10px, 0); }
    to { opacity: 1; transform: none; }
}

/* 弹窗出现时遮罩只做一次淡入，不做模糊动效（大面积模糊最伤帧率） */
body.mystery-mode .modal-overlay.show {
    transition: opacity var(--mo-d2) var(--mo-apple), visibility 0s linear 0s;
}

/* ------------------------------------------------------------
   3. 设置标签页：弹性滑动的指示块
   ------------------------------------------------------------ */
body.mystery-mode .settings-tabs {
    position: relative;
}

body.mystery-mode .settings-tabs .mo-tab-pill {
    position: absolute;
    top: 5px;
    bottom: 5px;
    left: 0;
    width: var(--mo-pill-w, 0px);
    border-radius: 999px;
    background: linear-gradient(180deg, rgba(255, 255, 255, .16), rgba(255, 255, 255, .05));
    border: 1px solid rgba(230, 199, 138, .5);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .38), 0 0 0 1px rgba(255, 255, 255, .04) inset;
    transform: translate3d(var(--mo-pill-x, 0px), 0, 0);
    transition: transform var(--mo-d3) var(--mo-spring), width var(--mo-d3) var(--mo-spring);
    pointer-events: none;
    z-index: 0;
}

body.mystery-mode .settings-tabs .tab-button {
    position: relative;
    z-index: 1;
}

body.mystery-mode .settings-tabs .tab-button.active {
    background: transparent;
}

/* ------------------------------------------------------------
   4. 按压回弹：只在交互瞬间动，静止不耗电
   ------------------------------------------------------------ */
body.mystery-mode .icon-btn,
body.mystery-mode .btn,
body.mystery-mode .tab-button,
body.mystery-mode .friend-item,
body.mystery-mode .avatar-menu-item,
body.mystery-mode .friend-menu-item,
body.mystery-mode .bubble-style-option {
    transition: transform var(--mo-d1) var(--mo-spring),
                border-color var(--mo-d1) ease,
                background-color var(--mo-d1) ease,
                color var(--mo-d1) ease;
}

body.mystery-mode .icon-btn:active,
body.mystery-mode .btn:active,
body.mystery-mode .friend-menu-item:active,
body.mystery-mode .avatar-menu-item:active {
    transform: scale(.94);
}

body.mystery-mode .btn-main,
body.mystery-mode .btn-primary {
    transition: transform var(--mo-d1) var(--mo-spring), box-shadow var(--mo-d1) ease;
}

body.mystery-mode .btn-primary:hover {
    box-shadow: 0 8px 22px rgba(230, 199, 138, .22);
}

/* 侧边栏角色项：悬停时轻微抬起，带一点方向性 */
body.mystery-mode .friend-item {
    border-radius: 10px;
}

body.mystery-mode .friend-item:hover {
    transform: translate3d(3px, 0, 0);
    background: linear-gradient(90deg, rgba(230, 199, 138, .12), rgba(230, 199, 138, 0));
}

body.mystery-mode .friend-item.active {
    background: linear-gradient(90deg, rgba(230, 199, 138, .18), rgba(230, 199, 138, .02));
}

/* 排序蓄力反馈：计时过半开始「吸气」，让用户知道长按快生效了 */
body.mystery-mode .friend-item.reorder-arming {
    transform: scale(.985);
}

/* ------------------------------------------------------------
   5. 新消息入场：只给「刚追加的那一条」加一次性动画
   ------------------------------------------------------------ */
body.mystery-mode .message.mo-enter {
    animation: moRise var(--mo-d3) var(--mo-spring) both;
}

body.mystery-mode .message.mo-enter.mo-from-right {
    animation-name: moSlideRight;
}

@keyframes moRise {
    0% {
        opacity: 0;
        transform: translate3d(-10px, 16px, 0) scale(.96);
    }
    70% { opacity: 1; transform: translate3d(0, -1px, 0) scale(1.004); }
    100% {
        opacity: 1;
        transform: translate3d(0, 0, 0) scale(1);
    }
}

@keyframes moSlideRight {
    0% { opacity: 0; transform: translate3d(18px, 12px, 0) scale(.96); }
    100% { opacity: 1; transform: none; }
}

/* 丰富档：一次追加多条时按 --mo-i 交错入场（最多 6 条，避免长队列拖动画帧） */
body.motion-rich .message.mo-enter {
    animation-delay: calc(var(--mo-i, 0) * 42ms);
}

/* 丰富档：新气泡上掠过一道高光。
   只在**这一批里的最后一条**消息上播（JS 里挑出来的 sheenNode），
   而且把光带尺寸钉死在 120px 的窄条上：
   旧实现给 .bubble 加 inset:0 的整块渐变层，长回复的气泡有上千像素高，
   扫光要整块重绘，多条一起来就是明显卡顿。 */
body.motion-rich .bubble.mo-sheen {
    position: relative;
    overflow: hidden;             /* 把扫光条裁剪在气泡内；条宽固定，裁剪开销很小 */
}

body.motion-rich .bubble.mo-sheen::after {
    content: '';
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 120px;                 /* 固定窄条：重绘面积与气泡大小无关 */
    max-width: 40%;
    background: linear-gradient(112deg, transparent 20%, rgba(255, 255, 255, .16) 50%, transparent 80%);
    transform: translate3d(-140%, 0, 0);
    animation: moSheen .72s var(--mo-apple) .04s 1 both;
    pointer-events: none;
    border-radius: inherit;
    will-change: transform;
}

@keyframes moSheen {
    from { transform: translate3d(-140%, 0, 0); }
    to { transform: translate3d(760%, 0, 0); }
}

/* ------------------------------------------------------------
   6. 视图切换：从角色列表「聚焦」到聊天区
   ------------------------------------------------------------ */
body.mystery-mode .sidebar,
body.mystery-mode .chat-header,
body.mystery-mode .chat-input-area {
    animation: moShellIn .46s var(--mo-apple) both;
}

body.mystery-mode .sidebar { animation-delay: 20ms; }
body.mystery-mode .chat-header { animation-delay: 70ms; }
body.mystery-mode .chat-input-area { animation-delay: 110ms; }

/* ------------------------------------------------------------
   【关键修复】手机视图 + ？？？模式：侧边栏打开了就关不掉
   ------------------------------------------------------------
   moShellIn 用的是 animation-fill-mode: both，动画播完后
   100% 关键帧的 `transform: none` 会**一直**留在元素上。
   而 CSS 层叠里「动画声明」的优先级高于普通作者声明，
   于是 style.css 的 `.sidebar.hidden { transform: translateX(-100%) }`
   被这条残留的 transform:none 直接压掉 —— 手机上点遮罩、点聊天区
   都加了 .hidden，侧边栏却纹丝不动，看起来就是「关不掉」。
   这里在 .hidden 状态下彻底取消动画，让原本的 transform 过渡接管；
   重新打开（移除 .hidden）时 animation-name 由 none 变回 moShellIn，
   入场动画会自然地再播一次。
   特异性：body.mystery-mode .sidebar.hidden（3 类 1 元素）>
           body.mystery-mode .sidebar（2 类 1 元素），无需 !important。
   ------------------------------------------------------------ */
body.mystery-mode .sidebar.hidden {
    animation: none;
}

body.mystery-mode #chat-area.mo-view-in {
    animation: moFocusIn var(--mo-d2) var(--mo-apple) both;
}

@keyframes moShellIn {
    from { opacity: 0; transform: translate3d(0, 8px, 0); }
    to { opacity: 1; transform: none; }
}

@keyframes moFocusIn {
    from {
        opacity: .35;
        transform: translate3d(0, 6px, 0) scale(.995);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

/* ------------------------------------------------------------
   7. 轻量档：只保留弹窗与按压反馈，其余全部关闭
   ------------------------------------------------------------ */
body.motion-lite .message.mo-enter,
body.motion-lite #chat-area.mo-view-in,
body.motion-lite .sidebar,
body.motion-lite .chat-header,
body.motion-lite .chat-input-area,
body.motion-lite .mo-stagger,
body.motion-lite .settings-tabs .mo-tab-pill {
    animation: none !important;
    transition: none !important;
}

body.motion-lite .settings-tabs .mo-tab-pill {
    opacity: 0;
}

/* ------------------------------------------------------------
   8. 系统级「减少动效」优先：一律关闭
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
    body.mystery-mode .modal-overlay.mo-opened .modal-content,
    body.mystery-mode .modal-overlay.mo-closing .modal-content,
    body.mystery-mode .message.mo-enter,
    body.mystery-mode #chat-area.mo-view-in,
    body.mystery-mode .sidebar,
    body.mystery-mode .chat-header,
    body.mystery-mode .chat-input-area,
    body.mystery-mode .mo-stagger,
    body.motion-rich .bubble.mo-sheen::after {
        animation: none !important;
    }

    body.mystery-mode .settings-tabs .mo-tab-pill {
        transition: none !important;
    }
}
