/* ====== style.css ====== */
/* ========================================
           CSS 变量定义区域
           定义全局颜色、间距、圆角、过渡效果等设计系统变量
           ======================================== */
        :root {
            --bg-primary: #1a1c23;
            --bg-secondary: #262933;
            --bg-tertiary: #2d303a;
            --bg-sidebar: #1f222b;
            --text-primary: #e0e0e0;
            --text-secondary: #aaa;
            --text-muted: #888;
            --accent-gold: #e6c78a;
            --accent-gold-rgb: 230, 199, 138;
            --border-color: #333;
            --border-light: rgba(255, 255, 255, 0.1);
            --shadow-lg: 0 10px 30px rgba(0, 0, 0, 0.5);
            --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
            --radius-sm: 6px;
            --radius-md: 8px;
            --radius-lg: 12px;
            --radius-xl: 20px;
            --transition-fast: 0.2s;
            /* 悬浮按钮（左上汉堡 / 右上视图切换）：它俩浮在 app-container 里，
               过去背景、描边、图标色全是写死的深灰，切浅色 / 星铁 / 绝区零都不变色。
               现在统一走这三个变量，各主题自己覆盖。 */
            --float-btn-bg: rgba(31, 34, 43, 0.9);
            --float-btn-bg-hover: rgba(31, 34, 43, 1);
            --float-btn-border: #555;
            --float-btn-text: #aaa;
            --float-btn-text-hover: #fff;
            --transition-normal: 0.3s;
            --spacing-xs: 5px;
            --spacing-sm: 8px;
            --spacing-md: 12px;
            --spacing-lg: 15px;
            --spacing-xl: 20px;
            --spacing-2xl: 25px;
            --font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            --z-index-overlay: 100;
            --z-index-modal: 1000;
            --sidebar-width: 280px;
            --avatar-size-sm: 40px;
            --avatar-size-md: 45px;
            --bubble-max-width-desktop: 85%;
            --bubble-max-width-mobile: 90%;
        }

        /* ========================================
           全局重置样式
           移除所有元素的默认外边距和内边距，统一盒模型
           ======================================== */
        * { margin: 0; padding: 0; box-sizing: border-box; }

        /* ========================================
           主体容器样式
           设置页面背景、字体、高度，使用 Flexbox 居中布局
           ======================================== */
        html {
            height: 100%;
        }

        body {
            font-family: var(--font-family);
            background-color: var(--bg-primary);
            color: var(--text-primary);
            min-height: 100vh;
            min-height: 100dvh;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
        }

        /* ========================================
           应用主容器
           包含侧边栏和聊天区域的响应式容器
           ======================================== */
        .app-container {
            width: 95vw;
            height: 90vh;
            max-width: 1400px;
            background-color: var(--bg-secondary);
            border-radius: var(--radius-lg);
            box-shadow: var(--shadow-lg);
            display: flex;
            overflow: hidden;
            position: relative;
        }

        /* ========================================
           聊天区域样式
           占据剩余空间，包含头部、消息区和输入区
           支持背景图片自定义，带有半透明遮罩层
           ======================================== */
        .chat-area {
            flex: 1 1 0;
            min-width: 0;
            /* 必须有确定高度，才能让中间消息列表独立滚动而不挤掉输入框。 */
            min-height: 0;
            height: 100%;
            overflow: hidden;
            display: flex;
            flex-direction: column;
            background-color: var(--bg-tertiary);
            background-size: cover;
            background-position: center;
            background-repeat: no-repeat;
            position: relative;
            transition: background-image 0.5s ease;
        }

        /* 聊天区域背景遮罩层，确保文字可读性
           注意：--chat-bg-overlay-opacity 默认 1（无背景图时等同纯色底）；
           设置了聊天背景图后由 JS 调低，否则遮罩会把背景图完全盖住。 */
        .chat-area::before {
            content: '';
            position: absolute;
            top: 0; left: 0; right: 0; bottom: 0;
            background-color: #2d303a;
            opacity: var(--chat-bg-overlay-opacity, 1);
            transition: opacity 0.3s ease;
            z-index: 0;
            pointer-events: none;
        }

        /* 确保头部、消息区和输入区在遮罩层之上 */
        .chat-header, .chat-messages, .chat-input-area {
            position: relative;
            z-index: 1;
        }

        /* 头部、搜索栏和输入区不可被消息内容压缩；仅消息区允许收缩并滚动。 */
        .chat-header,
        .chat-search-bar,
        .chat-input-area {
            flex: 0 0 auto;
            flex-shrink: 0;
        }

        /* 3D 实验室 */
        .laboratory-panel h3 { margin-bottom: 15px; color: #e6c78a; }
        .laboratory-switch { display:flex; align-items:flex-start; gap:10px; cursor:pointer; padding:12px; border:1px solid var(--border-color); border-radius:var(--radius-md); background:rgba(255,255,255,.03); }
        .laboratory-switch input { width:18px; height:18px; margin-top:2px; flex:none; }
        .laboratory-switch span { display:flex; flex-direction:column; gap:4px; }
        .laboratory-switch small, .laboratory-hint { color:var(--text-secondary); font-size:.82em; line-height:1.5; }
        .laboratory-options { margin-top:15px; padding:15px; border-left:2px solid var(--accent-gold); background:rgba(0,0,0,.12); }
        #laboratory-3d-viewer { position:absolute; z-index:4; right:18px; bottom:105px; width:210px; height:276px; border:1px solid rgba(var(--accent-gold-rgb),.55); border-radius:12px; overflow:hidden; background:rgba(20,22,30,.78); box-shadow:var(--shadow-lg); touch-action:none; }
        #laboratory-3d-viewer canvas { display:block; cursor:grab; }
        #laboratory-3d-viewer canvas:active { cursor:grabbing; }
        .laboratory-3d-title { height:26px; display:flex; align-items:center; gap:6px; padding:0 9px; color:var(--accent-gold); font-size:.78em; background:rgba(0,0,0,.4); cursor:move; user-select:none; }
        @media (max-width: 600px) { #laboratory-3d-viewer { transform:scale(.78); transform-origin:bottom right; right:-5px; bottom:84px; } }

        /* ========================================
           侧边栏样式
           显示联系人列表、搜索框和功能按钮
           ======================================== */
        .sidebar {
            width: var(--sidebar-width);
            background-color: var(--bg-sidebar);
            display: flex;
            flex-direction: column;
            padding: var(--spacing-xl);
            border-right: 1px solid var(--border-color);
            z-index: 2;
            transition: transform var(--transition-normal) ease;
            flex-shrink: 0;
            position: relative;
        }


        .sidebar.hidden {
            transform: translateX(-100%);
            position: absolute;
            height: 100%;
            box-shadow: 2px 0 10px rgba(0,0,0,0.5);
        }

        .sidebar-header { font-size: 1.2em; font-weight: bold; margin-bottom: 15px; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; row-gap: 8px; }
        /* 【为什么要有这一层】flex 项的 min-width 默认是 auto，但中文可以逐字断行，
           于是「短信」这种两字标题在窄侧边栏里会被压成一列一个字（看起来像竖排）。
           现在标题自己 nowrap 且不允许收缩；右侧那组入口整体换行兜底。 */
        .sidebar-header > i { flex: none; }
        .sidebar-title { flex: none; white-space: nowrap; }
        .sidebar-header-actions {
            display: flex; align-items: center; gap: 6px;
            margin-left: auto; flex: 0 0 auto;
        }
        /* 侧边栏只有 240~280px 宽，两个入口按钮各让出 2px 就能让整行放得下，
           省得为了 6px 的差额被迫折行。 */
        .sidebar-header-actions .forum-entry { padding: 3px 7px; }
        /* 这组按钮原先各自带 margin-left（8px / auto），叠上父级 gap 会白占十几像素，
           正是它把标题挤成竖排的最后一根稻草，进组后统一交给 gap 管。 */
        .sidebar-header-actions .forum-entry,
        .sidebar-header-actions .small-icon-btn { margin-left: 0; }

        /* ------------------------------------------------------------
           侧边栏内的「收起」按钮。
           桌面端侧边栏是常驻栏，不需要它（隐藏）；
           手机 / 平板竖屏下侧边栏变成盖在内容上的浮层，此时汉堡按钮
           被侧边栏自己的层叠上下文盖住（.sidebar z-index:100 >
           .mobile-menu-btn z-index:10），用户点不到，表现就是
           「侧边栏打开了关不掉」。所以在侧边栏**内部**放一个关闭按钮，
           它跟着侧边栏一起移动，任何情况下都点得到。
           ------------------------------------------------------------ */
        /* 必须写成两个类：.icon-btn 的基础样式里有 display:flex，而且它在
           本文件中排在后面，同特异性下后者胜出，单写 .sidebar-close-btn
           的 display:none 会被压掉，桌面端也会冒出这个按钮。 */
        .sidebar-header .sidebar-close-btn {
            display: none;
            flex-shrink: 0;
            /* .small-icon-btn 自带 margin-left:auto，主题按钮已经用它顶到右边了。
               这里必须归零，否则两个 auto 会平分剩余空间，两个按钮被撑开分家。 */
            margin-left: 0;
        }


        .search-box-container {
            margin-bottom: 15px;
            position: relative;
        }
        .search-box {
            width: 100%;
            padding: 8px 12px 8px 35px;
            background-color: var(--bg-tertiary);
            border: 1px solid var(--border-color);
            border-radius: var(--radius-md);
            color: var(--text-primary);
            font-size: 0.9em;
            outline: none;
            transition: all var(--transition-fast);
        }
        .search-box:focus {
            border-color: var(--accent-gold);
            box-shadow: 0 0 8px rgba(230, 199, 138, 0.3);
        }
        .search-box::placeholder {
            color: var(--text-muted);
        }
        .search-icon {
            position: absolute;
            left: 10px;
            top: 50%;
            transform: translateY(-50%);
            color: var(--text-muted);
            font-size: 1em;
            pointer-events: none;
        }

        .friend-list { flex-grow: 1; overflow-y: auto; margin-bottom: 20px; }
        .friend-list::-webkit-scrollbar { width: 6px; }
        .friend-list::-webkit-scrollbar-track { background: rgba(0,0,0,0.2); border-radius: 3px; }
        .friend-list::-webkit-scrollbar-thumb { background-color: rgba(255,255,255,0.3); border-radius: 3px; transition: background-color 0.2s; }
        .friend-list::-webkit-scrollbar-thumb:hover { background-color: rgba(255,255,255,0.5); }
        .friend-item {
            display: flex; align-items: center; padding: var(--spacing-md) var(--spacing-sm);
            border-radius: var(--radius-md); cursor: pointer; transition: background-color var(--transition-fast);
            margin-bottom: var(--spacing-sm); position: relative;
        }
        .friend-item:hover { background-color: var(--bg-tertiary); }
        .friend-item.active { background-color: #3a3d47; border-left: 3px solid var(--accent-gold); }
        .friend-avatar { width: var(--avatar-size-sm); height: var(--avatar-size-sm); border-radius: 50%; object-fit: cover; margin-right: 12px; border: 2px solid transparent; background-color: #3a3d47; position: relative; z-index: 1; }
        .friend-avatar.lazy-avatar { background: linear-gradient(90deg, #3a3d47 25%, #4a4d57 50%, #3a3d47 75%); background-size: 200% 100%; animation: lazyShimmer 1.5s infinite; }
        @keyframes lazyShimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
        /* 超出「同时在跑的占位动画」上限的头像（多半在屏幕外）改用静态底色：
           视觉效果几乎一致，但不再有 infinite 动画常驻，见 main.js 的 initLazyAvatars。 */
        .friend-avatar.lazy-avatar.lazy-avatar--static { animation: none; background: #3a3d47; }
        /* 系统级「减少动效」：占位流光一并关掉，只留静态底色 */
        @media (prefers-reduced-motion: reduce) {
            .friend-avatar.lazy-avatar { animation: none; background: #3a3d47; }
        }
        .friend-item.active .friend-avatar { border-color: var(--accent-gold); }
        .friend-name { font-size: 1em; font-weight: 500; }
        .friend-status { font-size: 0.75em; color: var(--text-muted); margin-left: auto; }
        .friend-pin {
            position: absolute;
            top: 5px;
            right: 5px;
            color: var(--accent-gold);
            font-size: 0.8em;
            display: none;
        }
        .friend-item.pinned .friend-pin { display: block; }
        /* 长按/拖动角色排序时的反馈；排序不影响置顶和分组规则。 */
        .friend-item.reordering { opacity: .55; outline: 1px dashed var(--accent-gold); cursor: grabbing; user-select: none; }
        /* 排序启动前仍允许页面/列表正常滚动；启动后由 JS 阻止默认移动行为。 */
        .friend-item { -webkit-user-drag: none; user-select: none; }
        .friend-item img { -webkit-user-drag: none; }
        @media (pointer: coarse) { .friend-item { touch-action: pan-y; } }

        .sidebar-footer { margin-top: auto; display: flex; justify-content: space-between; align-items: center; }

        /* ========================================
           扩展功能入口行（分支管理 / 对话分析 / 对话回放 …）
           ----------------------------------------
           这些按钮由 advanced-features.js 按设置开关动态插入。
           过去它们被塞进 .sidebar-footer，与「批量编辑 / 建群 / 加好友 / 设置」
           共用一条不可换行的行，开关一多就互相挤压、图标叠在一起。
           现在独立成行：可换行、按钮统一收成小号，并且整行只在
           确实有内容时才显示（hidden 由 JS 控制）。
           ======================================== */
        .sidebar-tools {
            margin-top: auto;
            display: flex;
            flex-wrap: wrap;
            align-items: center;
            gap: 8px;
            padding-top: 10px;
            margin-bottom: 10px;
            border-top: 1px dashed var(--border-color);
        }
        .sidebar-tools[hidden] { display: none; }
        .sidebar-tools .icon-btn {
            width: 34px;
            height: 34px;
            font-size: .95em;
            flex: 0 0 auto;
        }
        /* 给这一行加个小标题：按钮多起来之后，光看图标很难一眼认出
           「分支管理 / 对话分析 / 对话回放」分别是什么。 */
        .sidebar-tools::before {
            content: '扩展功能';
            flex: 1 0 100%;
            font-size: .68em;
            letter-spacing: .06em;
            color: var(--text-muted);
            text-transform: none;
        }
        .sidebar-tools .icon-btn:hover { transform: scale(1.06); }
        .sidebar-tools .icon-btn[style*="display: none"],
        .sidebar-tools .icon-btn[hidden] { display: none; }
        /* 有扩展按钮时，底部那行不再需要靠 margin-top:auto 顶到底部 */
        .sidebar-tools:not([hidden]) + .sidebar-footer { margin-top: 0; }
        .forum-entry { display: inline-flex; align-items: center; gap: 4px; margin-left: 8px; padding: 3px 8px; border: 1px solid rgba(230,199,138,.45); border-radius: 999px; color: var(--accent-gold); font-size: .72em; font-weight: 500; text-decoration: none; }
        .forum-entry:hover { background: rgba(230,199,138,.14); }
        .icon-btn {
            background: none; border: 1px solid #555; color: var(--text-secondary);
            border-radius: 50%; width: 40px; height: 40px;
            display: flex; justify-content: center; align-items: center;
            cursor: pointer; transition: all var(--transition-fast);
        }
        .icon-btn:hover { border-color: var(--accent-gold); color: #fff; transform: scale(1.1); }


        /* 悬浮方形按钮（汉堡菜单 / 视图切换）共用几何与居中规则。
           修复：过去 .mobile-menu-btn 基础样式只写 display:none，媒体查询改成 display:flex 后
           没有 justify-content / align-items，加上 <button> 自带 padding，
           导致三条杠图标被挤到按钮左上角。这里统一强制居中。 */
        .mobile-menu-btn,
        .view-toggle-btn {
            position: absolute;
            /* 定位基准是 .app-container，而顶栏那排 icon-btn 在 .chat-header 的
               flex 流里 —— 两套坐标系，写死 15px 必然错位（换主题就会偏，
               实测 -12px ~ +3.5px）。改成由 JS 把 header 的垂直中心换算成
               这个变量，见 syncFloatBtnPosition()。 */
            top: var(--float-btn-top, 15px);
            z-index: 10;
            box-sizing: border-box;
            /* 尺寸与圆角跟随顶栏那排 .icon-btn（由 JS 把实测值写进 --float-btn-size）：
               原来写死 40px + 8px 圆角，而那排按钮在窄屏是 30px 的正圆，
               即使中心对齐，大小和形状也不一样，看着仍然「不是一行」。 */
            width: var(--float-btn-size, 40px);
            height: var(--float-btn-size, 40px);
            padding: 0;          /* 清掉按钮默认内边距，否则图标偏移 */
            margin: 0;
            background-color: var(--float-btn-bg);
            border: 1px solid var(--float-btn-border);
            color: var(--float-btn-text);
            border-radius: 50%;
            font-size: 1.2em;
            line-height: 1;      /* 避免行高把图标顶偏 */
            cursor: pointer;
            transition: all 0.2s;
            /* 关键：flex 居中，图标始终位于按钮正中 */
            align-items: center;
            justify-content: center;
            text-align: center;
            -webkit-appearance: none;
            appearance: none;
        }

        /* 图标本身也归零，防止 remixicon 的伪元素带来额外偏移。
           translateZ(0) 是给字体图标开一个独立合成层：深色 / 彩色底上
           浏览器默认走次像素抗锯齿，放大看会有橙边蓝边，提层后改灰度抗锯齿。
           （只有这两颗悬浮按钮加，全局加会多建一堆合成层） */
        .mobile-menu-btn > i,
        .view-toggle-btn > i {
            display: block;
            line-height: 1;
            margin: 0;
            pointer-events: none;
            transform: translateZ(0);
        }

        .mobile-menu-btn {
            display: none;       /* 桌面隐藏；移动端媒体查询会改为 flex */
            left: 15px;
        }

        .view-toggle-btn {
            display: flex;
            right: 15px;
        }

        .mobile-menu-btn:hover,
        .view-toggle-btn:hover {
            border-color: var(--accent-gold);
            color: var(--float-btn-text-hover);
            background-color: var(--float-btn-bg-hover);
        }


        .sidebar-overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            z-index: 1;
            opacity: 0;
            visibility: hidden;
            transition: opacity 0.3s, visibility 0.3s;
        }
        .sidebar-overlay.show {
            opacity: 1;
            visibility: visible;
        }


        .friend-context-menu {
            position: fixed;
            background-color: #2d303a;
            border: 1px solid #444;
            border-radius: 8px;
            padding: 8px;
            display: none;
            flex-direction: column;
            gap: 5px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.5);
            z-index: 1000;
            min-width: 140px;
        }
        .friend-context-menu.show { display: flex; }


        .friend-group-list {
            display: flex;
            flex-direction: column;
            gap: 8px;
        }
        .friend-group-option {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 12px 16px;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.2s;
            background-color: #383b45;
            border: 1px solid transparent;
        }
        .friend-group-option:hover {
            background-color: #4a4d57;
        }
        .friend-group-option.active {
            background-color: #e3f2fd;
            color: #1976d2;
            border-color: #1976d2;
        }
        .friend-group-option i {
            font-size: 1.2em;
        }


        .friend-group-header {
            display: flex;
            align-items: center;
            padding: 10px 8px 6px;
            margin-top: 12px;
            margin-bottom: 4px;
            color: #888;
            font-size: 0.85em;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            border-bottom: 1px solid #3a3d47;
            cursor: pointer;
            user-select: none;
            transition: all 0.2s;
        }
        .friend-group-header:hover {
            color: var(--accent-gold);
            background-color: rgba(230, 199, 138, 0.1);
        }
        .friend-group-header:first-child {
            margin-top: 0;
        }
        .friend-group-header i {
            margin-right: 6px;
            font-size: 1em;
            transition: transform 0.3s;
        }
        .friend-group-header.collapsed i {
            transform: rotate(-90deg);
        }
        .friend-group-header .group-count {
            margin-left: auto;
            font-size: 0.9em;
            opacity: 0.7;
        }
        .friend-group-content {
            overflow: hidden;
            transition: max-height 0.3s ease-out;
        }
        .friend-group-content.collapsed {
            max-height: 0 !important;
        }
        .friend-menu-item {
            display: flex;
            align-items: center;
            padding: 8px 12px;
            border-radius: 6px;
            cursor: pointer;
            color: #ddd;
            font-size: 0.9em;
            transition: background-color 0.2s;
        }
        .friend-menu-item:hover { background-color: #3a3d47; color: var(--accent-gold); }
        .friend-menu-item i { margin-right: 10px; font-size: 1.1em; }
        .friend-menu-item.danger:hover { color: #f44336; }


        /* 桌面视图下右上角同样悬浮着「切换视图」按钮（right:15px + 40px 宽 = 55px），
           且其 z-index:10 高于 chat-header 的 z-index:1，
           若右内边距仍是 25px，清空聊天记录的垃圾桶按钮会被盖住且无法点击。
           因此右侧统一预留 62px。 */
        .chat-header {
            padding: 15px 62px 15px 25px;
            border-bottom: 1px solid rgba(255,255,255,0.1);
            font-size: 1.1em; font-weight: bold; display: flex;
            justify-content: space-between; align-items: center;
            gap: 10px;
        }

        /* 长角色名可省略号收缩，右侧按钮组不被挤压 */
        .chat-header > #current-friend-name {
            min-width: 0;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .chat-header > div {
            flex-shrink: 0;
        }

        .editable-name {
            cursor: pointer; padding: 4px 8px; border-radius: 4px;
            transition: background-color 0.2s; display: inline-block;
        }
        .editable-name:hover { background-color: rgba(255,255,255,0.1); color: var(--accent-gold); }
        .name-input {
            background: transparent; border: 1px solid var(--accent-gold);
            color: var(--accent-gold); font-size: 1.1em; font-weight: bold;
            padding: 4px 8px; border-radius: 4px; outline: none; width: 150px;
        }

        .chat-messages {
            /* 只让消息区域占用并滚动剩余高度，不能因长记录挤压底部输入框。 */
            flex: 1 1 0;
            min-height: 0;
            padding: 25px;
            overflow-y: auto;
            display: flex;
            flex-direction: column;
            gap: 20px;
            overscroll-behavior: contain;
            -webkit-overflow-scrolling: touch;
        }
        .chat-messages::-webkit-scrollbar { width: 8px; }
        .chat-messages::-webkit-scrollbar-track { background: rgba(0,0,0,0.2); }
        .chat-messages::-webkit-scrollbar-thumb { background-color: rgba(255,255,255,0.2); border-radius: 4px; }

        /* ========================================
           「回到最新消息」悬浮按钮
           未滑到底部时出现，点击平滑滑到聊天记录最后
           ======================================== */
        .scroll-to-bottom-btn {
            position: absolute;
            right: 22px;
            /* 距聊天区底部的距离由 JS 写进 --stb-bottom：
               输入区高度会随输入行数、待发送附件与手机键盘变化，
               写死数值会让按钮压在输入框上面。 */
            bottom: var(--stb-bottom, 96px);
            width: 40px;
            height: 40px;
            padding: 0;
            border-radius: 50%;
            border: 1px solid rgba(var(--accent-gold-rgb, 230, 199, 138), 0.5);
            background-color: rgba(28, 30, 38, 0.92);
            color: var(--accent-gold);
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.2em;
            cursor: pointer;
            z-index: 4;
            box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
            opacity: 0;
            transform: translateY(10px) scale(0.9);
            pointer-events: none;
            transition: opacity 0.22s ease, transform 0.22s ease, background-color 0.2s ease;
        }
        /* hidden 属性必须真的不显示：.scroll-to-bottom-btn 自带 display:flex，
           作者样式会盖掉浏览器默认的 [hidden]{display:none}，所以显式补一条。 */
        .scroll-to-bottom-btn[hidden] { display: none; }
        .scroll-to-bottom-btn.show {
            opacity: 1;
            transform: translateY(0) scale(1);
            pointer-events: auto;
        }
        .scroll-to-bottom-btn:hover {
            background-color: rgba(230, 199, 138, 0.2);
            border-color: var(--accent-gold);
        }
        .scroll-to-bottom-btn:active { transform: translateY(1px) scale(0.96); }
        .scroll-to-bottom-btn .stb-badge {
            position: absolute;
            top: -5px;
            right: -5px;
            min-width: 18px;
            height: 18px;
            padding: 0 5px;
            border-radius: 9px;
            background: #e05a5a;
            color: #fff;
            font-size: 0.62em;
            line-height: 18px;
            text-align: center;
            font-weight: 700;
        }
        .scroll-to-bottom-btn .stb-badge[hidden] { display: none; }

        /* ========================================
           全屏模式：界面铺满整个视口
           由 body.fullscreen-mode 驱动（见 main.js 的 applyFullscreenMode）
           ======================================== */
        body.fullscreen-mode {
            padding: 0;
            align-items: stretch;
            justify-content: stretch;
        }
        body.fullscreen-mode .app-container {
            width: 100vw;
            height: 100vh;
            height: 100dvh;
            max-width: none;
            border-radius: 0;
            box-shadow: none;
        }
        /* 全屏模式下纵向位置同样交给 --stb-bottom 计算（输入区永远是动态高度），
           这里只把横向内收一点，避免贴到窗口边缘。 */
        body.fullscreen-mode .scroll-to-bottom-btn { right: 20px; }

        /* 手机上「全屏模式」和「手机视图」效果一致，都铺满屏幕，无需重复规则 */
        @media (max-width: 768px) {
            body.fullscreen-mode .app-container { border-radius: 0; }
        }

        .message { display: flex; align-items: flex-start; max-width: 60%; animation: fadeIn 0.3s ease; }
        @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }

        .avatar {
            width: 45px; height: 45px; border-radius: 50%;
            object-fit: cover; flex-shrink: 0; cursor: pointer;
            transition: transform 0.2s; border: 2px solid transparent;
            /* 头像框（avatar-frame.css）是绝对定位的覆盖层，需要一个定位参照。
               头像在 flex 行里，relative 不会改变它原来的排版。 */
            position: relative;
        }
        .avatar:hover { transform: scale(1.05); border-color: var(--accent-gold); }

        .message-content { display: flex; flex-direction: column; min-width: 0; max-width: 100%; }
        .nickname { font-size: 0.85em; color: #ccc; margin-bottom: 5px; text-shadow: 0 1px 2px rgba(0,0,0,0.8); }

        /* border-radius 由 JS 写入的 --bubble-radius 变量驱动，
           使「气泡样式」切换后已渲染的气泡也能立即生效 */
        .bubble {
            padding: 12px 16px;
            border-radius: var(--bubble-radius, 12px);
            line-height: 1.5;
            word-wrap: break-word; overflow-wrap: break-word;
            max-width: 100%; position: relative;
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
            background-size: cover !important;
            background-position: center !important;
            background-repeat: no-repeat !important;
            transition: all 0.3s;
        }


        .bubble p { margin: 0 0 8px 0; }
        .bubble p:last-child { margin-bottom: 0; }
        .bubble h1, .bubble h2, .bubble h3, .bubble h4, .bubble h5, .bubble h6 {
            margin: 12px 0 8px 0;
            font-weight: bold;
            line-height: 1.4;
        }
        .bubble h1 { font-size: 1.5em; }
        .bubble h2 { font-size: 1.3em; }
        .bubble h3 { font-size: 1.2em; }
        .bubble ul, .bubble ol { margin: 8px 0; padding-left: 20px; }
        .bubble li { margin: 4px 0; }
        .bubble blockquote {
            border-left: 3px solid var(--accent-gold);
            padding-left: 12px;
            margin: 8px 0;
            color: var(--text-secondary);
            font-style: italic;
        }
        .bubble code {
            background-color: rgba(0,0,0,0.3);
            padding: 2px 6px;
            border-radius: 4px;
            font-family: 'Consolas', 'Monaco', monospace;
            font-size: 0.9em;
        }
        .bubble pre {
            background-color: rgba(0,0,0,0.4);
            padding: 12px;
            border-radius: 6px;
            overflow-x: auto;
            max-width: 100%;
            margin: 8px 0;
            -webkit-overflow-scrolling: touch;
        }
        .bubble pre code {
            background-color: transparent;
            padding: 0;
        }
        .bubble table {
            border-collapse: collapse;
            width: 100%;
            margin: 8px 0;
        }
        .bubble th, .bubble td {
            border: 1px solid rgba(255,255,255,0.2);
            padding: 8px;
            text-align: left;
        }
        .bubble th { background-color: rgba(230, 199, 138, 0.2); }
        .bubble hr {
            border: none;
            border-top: 1px solid rgba(255,255,255,0.2);
            margin: 12px 0;
        }
        .bubble a {
            color: var(--accent-gold);
            text-decoration: underline;
        }


        /* ========================================
           平板竖屏适配 (Portrait Tablet)
           针对 769px-1024px 且高度大于宽度的设备
           使用类似手机的布局体验
           ======================================== */
        @media (min-width: 769px) and (max-width: 1024px) and (orientation: portrait) {
            .app-container {
                width: 100vw;
                height: 100vh;
                height: 100dvh;
                max-width: none;
                border-radius: 0;
                box-shadow: none;
            }

            .sidebar {
                position: absolute;
                width: min(82vw, 340px);
                max-width: calc(100vw - 56px);
                height: 100%;
                z-index: 100;
                box-shadow: 2px 0 10px rgba(0,0,0,0.5);
            }

            .sidebar.hidden {
                transform: translateX(-105%);
            }

            .mobile-menu-btn {
                display: flex;
            }

            /* 平板竖屏同样是浮层侧边栏，也需要栏内关闭按钮 */
            .sidebar-header .sidebar-close-btn { display: flex; }

            /* 右侧需为悬浮的「切换视图」按钮（right:15px + 40px 宽）让位，
               否则会盖住清空聊天记录的垃圾桶按钮 */
            .chat-header {
                min-height: 56px;
                padding: 12px max(62px, calc(env(safe-area-inset-right) + 62px)) 12px max(50px, env(safe-area-inset-left));
                font-size: 1em;
                gap: 8px;
            }

            #current-friend-name,
            #my-display-name {
                min-width: 0;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }

            .chat-header > div {
                flex-shrink: 0;
            }

            .chat-messages {
                padding: 15px;
            }

            .chat-input-area {
                padding: 12px 15px;
                gap: 12px;
            }

            .input-wrapper input, .input-wrapper textarea {
                padding: 12px 14px;
                font-size: 1em;
            }

            .input-icons i {
                font-size: 1.2em;
            }

            #send-btn {
                font-size: 1.4em;
            }

            .message {
                max-width: 88%;
            }

            .avatar {
                width: 42px;
                height: 42px;
            }

            .bubble {
                padding: 11px 15px;
                font-size: 1em;
            }

            .modal-content {
                width: 90%;
                max-height: 85vh;
            }

            /* 与手机端同样的问题：fixed 定位的角色/联系人菜单不能被塞 bottom，
               否则 top 与 bottom 同时生效会把菜单拉伸成长条。 */
            .avatar-context-menu {
                left: 15px !important;
                bottom: 70px !important;
                min-width: 150px;
            }

            .ai-avatar-context-menu,
            .friend-context-menu {
                left: 15px !important;
                min-width: 150px;
                max-height: min(62vh, 380px);
                overflow-y: auto;
            }

            .message-actions, .quick-replies {
                margin-left: 50px;
            }

            .view-toggle-btn {
                display: none;
            }
        }

        /* 平板横屏适配 (Landscape Tablet) - 保持桌面布局但优化间距 */
        @media (min-width: 769px) and (max-width: 1024px) and (orientation: landscape) {
            .app-container {
                width: 98vw;
                height: 95vh;
            }

            .sidebar {
                width: 240px;
                padding: var(--spacing-lg);
            }

            .bubble {
                max-width: 80% !important;
            }

            .message-actions, .quick-replies {
                margin-left: 50px;
            }
        }

        @media (min-width: 769px) {
            .bubble {
                max-width: var(--bubble-max-width, 85%) !important;
                width: fit-content;
            }
        }


        @media (max-width: 768px) {
            .bubble {
                max-width: 90% !important;
            }
        }


        .bubble.has-custom-bg {
            color: #fff;
            text-shadow: 0 1px 3px rgba(0,0,0,0.9);
            background-color: rgba(0,0,0,0.4) !important;
            border: 1px solid rgba(255,255,255,0.1);
        }

        .bubble.proactive {
            border: 1px solid var(--accent-gold);
            background: linear-gradient(135deg, rgba(230, 199, 138, 0.1), rgba(45, 48, 58, 0.4));
            box-shadow: 0 0 10px rgba(230, 199, 138, 0.2);
        }
        .proactive-tag {
            font-size: 0.7em;
            color: var(--accent-gold);
            margin-bottom: 4px;
            display: block;
            font-style: italic;
        }


        .message-actions {
            display: flex;
            gap: 8px;
            margin-top: 8px;
            margin-left: 0;
        }
        .regenerate-btn {
            display: flex;
            align-items: center;
            gap: 4px;
            padding: 6px 12px;
            background: rgba(230, 199, 138, 0.15);
            border: 1px solid rgba(230, 199, 138, 0.3);
            border-radius: 6px;
            color: var(--accent-gold);
            font-size: 0.85em;
            cursor: pointer;
            transition: all 0.2s;
        }
        .regenerate-btn:hover {
            background: rgba(230, 199, 138, 0.25);
            transform: translateY(-1px);
        }
        .regenerate-btn:active { transform: translateY(0); }
        .regenerate-btn i { font-size: 0.9em; }


        /* 消息滑动：同一条 AI 回复的多个版本（‹ 2/3 ›） */
        .swipe-bar {
            display: flex;
            align-items: center;
            gap: 2px;
            margin-top: 0;
            align-self: center;
            width: fit-content;
            padding: 1px 4px;
            border-radius: 12px;
            background: rgba(255, 255, 255, 0.04);
            border: 1px solid rgba(255, 255, 255, 0.07);
        }
        .swipe-arrow {
            display: flex;
            align-items: center;
            justify-content: center;
            width: 20px;
            height: 20px;
            padding: 0;
            border: none;
            border-radius: 50%;
            background: transparent;
            color: var(--text-secondary, #a9afbd);
            font-size: 15px;
            line-height: 1;
            cursor: pointer;
            transition: background 0.15s, color 0.15s;
        }
        .swipe-arrow:hover:not(:disabled) {
            background: rgba(230, 199, 138, 0.18);
            color: var(--accent-gold, #e6c78a);
        }
        .swipe-arrow:disabled { opacity: 0.25; cursor: default; }
        .swipe-count {
            font-size: 0.7em;
            color: var(--text-secondary, #8b90a0);
            min-width: 34px;
            text-align: center;
            user-select: none;
            letter-spacing: 0.3px;
        }

        .quick-replies {
            display: flex;
            gap: 10px;
            margin-top: 10px;
            margin-left: 0;
            flex-wrap: wrap;
        }
        .quick-reply-btn {
            padding: 8px 16px;
            background: rgba(100, 150, 200, 0.2);
            border: 1px solid rgba(100, 150, 200, 0.4);
            border-radius: 20px;
            color: #a8d8ff;
            font-size: 0.9em;
            cursor: pointer;
            transition: all 0.2s;
            max-width: 70%;
            word-break: break-word;
        }
        .quick-reply-btn:hover {
            background: rgba(100, 150, 200, 0.35);
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
        }

        .system-bubble {
            background-color: rgba(0,0,0,0.4);
            border: 1px dashed rgba(255,255,255,0.3);
            color: #ddd;
            font-size: 0.9em;
            text-align: center;
            width: 100%;
            max-width: 100% !important;
            align-self: center;
            margin: 10px 0;
        }

        .message-image {
            /* 宽图必须按容器缩放，不能只限制高度，否则移动端会横向溢出而被裁掉。 */
            display: block;
            width: auto;
            height: auto;
            max-width: min(100%, 420px);
            max-height: 300px;
            object-fit: contain;
            border-radius: 8px;
            box-shadow: 0 4px 8px rgba(0,0,0,0.3);
            cursor: zoom-in;
        }
        @media (max-width: 560px) {
            .message-image { max-width: 100%; max-height: 52vh; }
            .message-content { min-width: 0; }
        }
        .message-image:hover { transform: scale(1.02); }

        .message-video {
            max-width: 100%;
            max-height: 300px;
            border-radius: 8px;
            display: block;
            box-shadow: 0 4px 8px rgba(0,0,0,0.3);
        }

        .message.other { align-self: flex-start; }
        .message.other .bubble { background-color: var(--accent-gold); color: #333; border-top-left-radius: var(--bubble-radius, 12px); }
        .message.other .message-content { margin-left: 12px; }

        .message.mine { align-self: flex-end; flex-direction: row-reverse; }
        .message.mine .bubble { background-color: var(--accent-gold); color: #333; border-top-right-radius: var(--bubble-radius, 12px); }
        .message.mine .message-content { margin-right: 12px; align-items: flex-end; }

        .chat-input-area {
            padding: 15px 25px; border-top: 1px solid rgba(255,255,255,0.1);
            display: flex; align-items: center; gap: 15px;
            background-color: #2d303a; position: relative;
            flex-direction: column;
            flex: 0 0 auto;
            flex-shrink: 0;
        }
        /* min-width: 0 是关键：flex 子项默认 min-width:auto，
           内容（引用预览条里 nowrap 的长文本）会把 min-content 撑到超宽，
           整条 input-stack 连带溢出 .chat-input-area，把右侧的取消按钮顶出屏幕。
           见 .pending-reply-preview 处的说明。 */
        .input-stack { flex-grow: 1; width: 100%; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
        .pending-attachments { display: flex; flex-wrap: wrap; gap: 8px; padding: 8px; border: 1px solid rgba(255,255,255,0.12); border-radius: 14px; background: rgba(0,0,0,0.18); }
        .pending-attachments[hidden] { display: none; }
        .pending-attachment-item { position: relative; width: 74px; height: 74px; border-radius: 10px; background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.16); display: flex; flex-direction: column; align-items: center; justify-content: center; color: #ddd; overflow: visible; }
        .pending-attachment-item img, .pending-attachment-item video { width: 100%; height: 100%; object-fit: cover; border-radius: 9px; }
        .pending-attachment-icon { font-size: 1.8em; color: var(--accent-gold); }
        .pending-attachment-name { width: 100%; padding: 0 5px; margin-top: 3px; font-size: 0.68em; color: #ccc; text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .pending-attachment-remove { position: absolute; top: -7px; right: -7px; width: 22px; height: 22px; border-radius: 50%; border: 1px solid rgba(255,255,255,0.35); background: #2d303a; color: #fff; display: grid; place-items: center; cursor: pointer; z-index: 2; }
        .pending-attachment-remove:hover { background: #ff5757; }

        /* 待发送引用：以单行预览展示，不将完整被引用内容写入输入框。
           【溢出修复】被引用内容可能长达 300 字，.pending-reply-content 用
           white-space: nowrap 单行显示。nowrap 文本的 min-content 就是整行宽度，
           而 flex 子项默认 min-width:auto 不允许缩到比 min-content 更窄 ——
           于是宽度一路向上顶：.pending-reply-preview → .input-stack →
           头像那一行的行内 div → .chat-input-area，整条预览被撑出屏幕，
           最右侧的取消按钮（✕）跑到可视区外，用户「点不到叉」。
           修法：给这条 flex 链上的每一环都补 min-width: 0（行内 div 与
           .input-stack 见各自规则），并在这里加 max-width/overflow 双保险，
           让 nowrap 文本在本条内被 ellipsis 截断，而不是把容器撑开。 */
        .pending-reply-preview { display: flex; align-items: center; gap: 8px; min-width: 0; max-width: 100%; overflow: hidden; padding: 7px 9px; border: 1px solid rgba(230,199,138,0.42); border-radius: 10px; background: rgba(230,199,138,0.09); color: #ddd; }
        .pending-reply-preview[hidden] { display: none; }
        .pending-reply-preview > .ri-double-quotes-l { flex: 0 0 auto; color: var(--accent-gold); font-size: 1.05em; }
        .pending-reply-content { flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 0.82em; }
        .pending-reply-content strong { color: var(--accent-gold); font-weight: 500; }
        .pending-reply-cancel { flex: 0 0 auto; width: 24px; height: 24px; padding: 0; border: 0; border-radius: 50%; background: transparent; color: #aaa; display: grid; place-items: center; cursor: pointer; }
        .pending-reply-cancel:hover { background: rgba(255,87,87,0.18); color: #ff7777; }
        /* 触屏下 24px 的叉偏小，取消引用又是高频操作，放大命中区 */
        @media (pointer: coarse) {
            .pending-reply-cancel { width: 32px; height: 32px; }
        }
        .input-wrapper { flex-grow: 1; position: relative; display: flex; align-items: center; width: 100%; }
        .input-wrapper input, .input-wrapper textarea {
            width: 100%; padding: 12px 15px; border-radius: 20px;
            border: 1px solid rgba(255,255,255,0.2); background-color: rgba(0,0,0,0.3);
            color: #eee; outline: none;
        }
        .input-wrapper input::placeholder, .input-wrapper textarea::placeholder { color: #aaa; }
        .input-icons { display: flex; gap: 15px; color: #aaa; font-size: 1.2em; }
        .input-icons i { cursor: pointer; transition: color 0.2s; }
        .input-icons i:hover { color: #fff; }

        #image-upload, #avatar-upload, #bg-upload, #import-upload, #char-import-upload, #char-avatar-upload, #bubble-bg-upload { display: none; }

        .emoji-picker {
            position: absolute; bottom: 70px; left: 25px;
            background-color: #383b45; border: 1px solid #555;
            border-radius: 8px; padding: 10px;
            display: grid; grid-template-columns: repeat(8, 1fr); gap: 8px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.3); z-index: 100;
            display: none; max-height: 250px; overflow-y: auto;
        }
        .emoji-picker.show { display: grid; }
        .emoji-item { font-size: 1.5em; cursor: pointer; text-align: center; padding: 5px; border-radius: 4px; }
        .emoji-item:hover { background-color: #4a4d58; }


        .avatar-context-menu {
            position: absolute;
            bottom: 80px;
            left: 25px;
            background-color: #2d303a;
            border: 1px solid #444;
            border-radius: 8px;
            padding: 8px;
            display: none;
            flex-direction: column;
            gap: 5px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.5);
            z-index: 101;
            min-width: 160px;
        }
        .avatar-context-menu.show { display: flex; }
        .avatar-menu-item {
            display: flex;
            align-items: center;
            padding: 8px 12px;
            border-radius: 6px;
            cursor: pointer;
            color: #ddd;
            font-size: 0.9em;
            transition: background-color 0.2s;
        }
        .avatar-menu-item:hover { background-color: #3a3d47; color: var(--accent-gold); }
        .avatar-menu-item i { margin-right: 10px; font-size: 1.1em; }


        .ai-avatar-context-menu {
            position: fixed;
            background-color: #2d303a;
            border: 1px solid #444;
            border-radius: 8px;
            padding: 8px;
            display: none;
            flex-direction: column;
            gap: 5px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.5);
            z-index: 1001;
            min-width: 160px;
        }
        .ai-avatar-context-menu.show { display: flex; }


        .modal-overlay {
            position: fixed; top: 0; left: 0; width: 100%; height: 100%;
            background-color: rgba(0, 0, 0, 0.6);
            display: flex; justify-content: center; align-items: center;
            z-index: 1000; opacity: 0; visibility: hidden;
            transition: opacity 0.3s, visibility 0.3s;
        }
        .modal-overlay.show { opacity: 1; visibility: visible; }

        .modal-content {
            background-color: #2d303a;
            width: 500px;
            max-width: 90%;
            max-height: 85vh;
            border-radius: 12px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
            display: flex;
            flex-direction: column;
            transform: translateY(-20px);
            transition: transform 0.3s;
            border: 1px solid #444;
        }
        .modal-overlay.show .modal-content { transform: translateY(0); }

        .modal-header {
            padding: 20px;
            border-bottom: 1px solid #3a3d47;
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-shrink: 0;
        }
        .modal-header h2 { font-size: 1.5em; }
        .settings-search-wrap {
            flex: 1;
            max-width: 420px;
            margin: 0 18px;
            position: relative;
        }
        .settings-search-wrap i {
            position: absolute;
            left: 12px;
            top: 50%;
            transform: translateY(-50%);
            color: #aaa;
            pointer-events: none;
        }
        .settings-search-wrap input {
            width: 100%;
            padding: 10px 12px 10px 38px;
            border-radius: 999px;
            border: 1px solid #444;
            background: #383b45;
            color: #eee;
            outline: none;
        }
        .settings-search-wrap input:focus { border-color: var(--accent-gold); }
        .settings-no-results {
            padding: 28px;
            text-align: center;
            color: #aaa;
            border: 1px dashed #555;
            border-radius: 10px;
            margin-top: 12px;
        }
        .close-modal { background: none; border: none; color: #aaa; font-size: 1.5em; cursor: pointer; }
        .close-modal:hover { color: #fff; }

        .modal-body {
            padding: 25px;
            flex-grow: 1;
            overflow-y: auto;
            scrollbar-width: thin;
            scrollbar-color: #555 #2d303a;
        }

        .modal-body::-webkit-scrollbar { width: 6px; }
        .modal-body::-webkit-scrollbar-track { background: #2d303a; border-radius: 3px; }
        .modal-body::-webkit-scrollbar-thumb { background-color: #555; border-radius: 3px; }
        .modal-body::-webkit-scrollbar-thumb:hover { background-color: #777; }

        .settings-tabs { display: flex; gap: 15px; margin-bottom: 25px; border-bottom: 1px solid #3a3d47; overflow-x: auto; }
        .tab-button {
            background: none; border: none; color: #aaa; font-size: 1em;
            padding-bottom: 10px; cursor: pointer; position: relative;
            white-space: nowrap;
        }
        .tab-button.active { color: var(--accent-gold); font-weight: bold; }
        .tab-button.active::after {
            content: ''; position: absolute; bottom: -1px; left: 0;
            width: 100%; height: 2px; background-color: var(--accent-gold);
        }
        .tab-content { display: none; }
        .tab-content.active { display: block; }

        .form-group { margin-bottom: 20px; }
        .form-group label { display: block; margin-bottom: 8px; color: #aaa; font-size: 0.9em; }
        /* 设置面板控件基线：原先只有一条 padding 加「focus 换个边框色」，
           没有过渡、没有 placeholder 配色、focus 也无可见反馈，
           这是「其他功能的输入框也丑」最主要的来源。
           层叠纪律：主选择器保持与原文件完全相同的特异性 (0,1,1)，
           不新增 :not() 链 —— 一旦特异性涨过 `body.light-theme .form-group input`
           (0,2,2)，这套暗色值就会反向覆盖浅色主题。 */
        .form-group input, .form-group select, .form-group textarea {
            width: 100%; padding: 10px 12px; border-radius: 9px;
            border: 1px solid var(--ui-field-border, #454a57);
            background-color: var(--ui-field-bg, #383b45);
            color: var(--ui-field-text, #eee); outline: none;
            font-family: inherit; font-size: 0.92em; line-height: 1.5;
            box-sizing: border-box;
            transition: border-color .18s, box-shadow .18s, background-color .18s;
        }
        .form-group textarea { resize: vertical; min-height: 80px; }
        .form-group input::placeholder, .form-group textarea::placeholder {
            color: var(--ui-field-placeholder, #8b90a0); opacity: 1;
        }
        /* 复选框不能被 width:100% 拉成一条；带内联 style 的那些仍由内联决定 */
        .form-group input[type="checkbox"], .form-group input[type="radio"] { width: auto; height: auto; }
        .form-group input, .form-group select, .form-group textarea { accent-color: var(--accent-gold); }
        /* hover / focus 用 .form-group input:focus 形式（特异性 0,2,1）：
           必须高于上面基础规则 (0,1,1) 才能真正改到边框色；
           又必须低于 `body.light-theme .form-group input` (0,2,2)，
           才不会被这套暗色值反向压住浅色主题。 */
        .form-group input:hover, .form-group select:hover, .form-group textarea:hover {
            background-color: var(--ui-field-bg-hover, #383b45);
            border-color: #565c6b;
        }
        .form-group input:focus, .form-group select:focus, .form-group textarea:focus {
            border-color: var(--accent-gold);
            box-shadow: var(--ui-focus-ring, 0 0 0 3px rgba(230, 199, 138, .18));
        }


        .message.system {
            justify-content: center;
            opacity: 0.92;
        }
        .message.system .avatar,
        .message.system .message-actions,
        .message.system .message-time {
            display: none;
        }
        .message.system .message-content {
            max-width: 82%;
            align-items: center;
        }
        .message.system .message-sender {
            color: var(--accent-gold);
            text-align: center;
        }
        .message.system .bubble {
            background: rgba(230, 199, 138, 0.14);
            border: 1px solid rgba(230, 199, 138, 0.35);
            color: #f0e6c8;
            border-radius: 999px;
        }

        .group-error-continue-modal { z-index: 1300; }
        .group-error-continue-modal .modal-content { max-width: 460px; }
        .group-error-continue-modal .modal-header h2 { color: #f0b27a; }
        .group-error-continue-tip { margin-top: 10px; color: #aaa; font-size: 0.88em; line-height: 1.55; }
        .group-error-continue-check {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-top: 18px;
            color: #e6c78a;
            cursor: pointer;
            user-select: none;
        }
        .group-error-continue-check input { width: auto; accent-color: var(--accent-gold); }
        .group-error-continue-actions { gap: 12px; justify-content: flex-end; }
        .group-error-continue-actions .btn { flex: 1; justify-content: center; }

        .modal-footer {
            padding: 20px;
            border-top: 1px solid #3a3d47;
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-shrink: 0;
        }
        .btn {
            padding: 10px 20px; border-radius: 6px; border: none;
            font-size: 1em; cursor: pointer; display: flex; align-items: center; gap: 8px;
        }
        .btn-secondary { background-color: #555; color: #eee; }
        .btn-secondary:hover { background-color: #666; }
        /* 主色 / 危险色压暗：原来的纯绿 #4CAF50 与纯红 #f44336 在深色界面里
           太跳，和站内的金色 + 深灰不在一个调子上，改成低饱和的墨绿与砖红。 */
        .btn-primary { background-color: #2f5a45; color: #e8f2ec; }
        .btn-primary:hover { background-color: #3a6d54; }
        .btn-test { background-color: #2196F3; color: white; }
        .btn-test:hover { background-color: #1e88e5; }
        .btn-danger { background-color: #7a3232; color: #f6e7e7; }
        .btn-danger:hover { background-color: #8d3a3a; }
        .btn-outline { background: transparent; border: 1px solid #666; color: #ddd; }
        .btn-outline:hover { border-color: var(--accent-gold); color: var(--accent-gold); }
        .btn-success { background-color: #2f5a45; color: #e8f2ec; }
        .btn-success:hover { background-color: #3a6d54; }
        .btn-sm { padding: 5px 10px; font-size: 0.85em; }

        /* ==========================================================
           多站点 API 配置面板（设置 → AI 配置）
           ========================================================== */
        .ep-block { border-bottom: 1px dashed #3a3d47; padding-bottom: 16px; }
        .ep-current-row { display: flex; gap: 10px; align-items: center; }
        .ep-current-row select { flex: 1 1 auto; min-width: 0; }
        .ep-current-row .btn { flex: 0 0 auto; }
        .ep-check-row {
            display: flex; align-items: flex-start; gap: 9px;
            margin-top: 12px; cursor: pointer; font-size: .84em; color: #c6cad6;
        }
        .ep-check-row input { width: 16px; height: 16px; flex: 0 0 auto; margin-top: 1px; }
        .ep-check-row span { flex: 1 1 auto; line-height: 1.55; }
        .ep-check-inline { margin: 0; }
        .ep-quick-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 12px; }
        .ep-hint { font-size: .76em; color: #8b93a5; flex: 1 1 100%; line-height: 1.6; }
        .ep-hint i { color: var(--accent-gold, #e6c78a); margin-right: 3px; }
        #endpoint-list-empty.ep-hint { flex: 0 0 100%; padding: 10px 0 0; }

        .ep-list { display: flex; flex-direction: column; gap: 8px; }
        .ep-site {
            border: 1px solid #3d414c; border-radius: 10px;
            background: rgba(255,255,255,.025); padding: 10px 12px;
        }
        .ep-site.is-active { border-color: rgba(230,199,138,.55); background: rgba(230,199,138,.07); }
        .ep-site.is-off { opacity: .55; }
        .ep-site-head { display: flex; gap: 10px; align-items: flex-start; flex-wrap: wrap; }
        .ep-order {
            flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
            display: inline-flex; align-items: center; justify-content: center;
            background: rgba(230,199,138,.18); color: #e6c78a;
            font-size: .74em; font-weight: 700; margin-top: 2px;
        }
        .ep-site-main { flex: 1 1 220px; min-width: 0; }
        .ep-site-name { font-size: .92em; color: #eee; font-weight: 600; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
        .ep-site-meta { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 4px; font-size: .76em; color: #98a0b0; }
        .ep-meta-item { display: inline-flex; align-items: center; gap: 4px; min-width: 0; overflow-wrap: anywhere; }
        .ep-meta-item i { color: #7d8496; }
        .ep-meta-item.ep-warn { color: #f0b27a; }
        .ep-site-actions { display: flex; flex-wrap: wrap; gap: 5px; flex: 0 0 auto; }
        .ep-site-actions .btn { height: 26px; padding: 0 8px; font-size: .76em; }
        .ep-badge {
            font-size: .68em; font-weight: 600; padding: 1px 7px; border-radius: 999px;
            border: 1px solid rgba(255,255,255,.16); color: #aeb6c6; background: rgba(255,255,255,.05);
        }
        .ep-badge--active { border-color: rgba(230,199,138,.6); color: #e6c78a; background: rgba(230,199,138,.14); }
        .ep-badge--off { border-color: rgba(244,67,54,.5); color: #f4837a; }
        .ep-badge--backup { border-color: rgba(120,180,255,.4); color: #8fbaff; }
        .ep-badge--models { border-style: dashed; color: #8fd18f; border-color: rgba(143,209,143,.45); }
        .ep-site-test { margin-top: 6px; font-size: .76em; line-height: 1.5; overflow-wrap: anywhere; }
        .ep-site-test.ep-tone-ok { color: #8fd18f; }
        .ep-site-test.ep-tone-err { color: #f4837a; }
        .ep-site-test.ep-tone-info { color: #8ab6e8; }

        .ep-editor { margin-top: 10px; padding-top: 10px; border-top: 1px dashed #3d414c; }
        .ep-editor-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; }
        .ep-editor-grid label { display: block; font-size: .76em; color: #9aa1b2; }
        .ep-editor-grid input, .ep-editor-grid textarea {
            width: 100%; margin-top: 4px; padding: 7px 9px; border-radius: 7px;
            border: 1px solid #444; background: #383b45; color: #eee; outline: none; font-family: inherit;
        }
        .ep-editor-grid textarea { resize: vertical; min-height: 54px; }
        .ep-editor-grid input:focus, .ep-editor-grid textarea:focus { border-color: var(--accent-gold, #e6c78a); }
        .ep-editor-wide { grid-column: 1 / -1; }
        .ep-editor-actions { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin-top: 10px; }
        .ep-editor-actions .btn { height: 28px; font-size: .78em; }
        .ep-editor-current { display: flex; gap: 6px; margin-left: auto; flex-wrap: wrap; }

        /* 「测试对话模型」现在会逐条列出主模型 / 备用模型的结果，需要竖排 */
        .test-result:has(.ep-test-line) { display: block; flex-direction: column; align-items: flex-start; }
        .ep-test-line { padding: 1px 0; line-height: 1.65; }
        .ep-test-note { margin-top: 4px; opacity: .78; font-size: .92em; }

        body.light-theme .ep-site { border-color: #d5d8e0; background: rgba(0,0,0,.02); }
        body.light-theme .ep-site-name { color: #2b2f3a; }
        body.light-theme .ep-site-meta { color: #6b7180; }
        body.light-theme .ep-editor-grid input,
        body.light-theme .ep-editor-grid textarea { background: #fff; border-color: #c9ccd6; color: #22262e; }

        /* 长期记忆档案操作按钮：button 与 label 统一尺寸、颜色和基线。 */
        .memory-archive-actions .memory-archive-action {
            box-sizing: border-box;
            min-height: 32px;
            margin: 0;
            padding: 5px 10px;
            border: 1px solid #666;
            border-radius: 6px;
            background: transparent;
            color: #ddd;
            font-size: 0.85em;
            line-height: normal;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
            cursor: pointer;
        }
        .memory-archive-actions .memory-archive-action:hover {
            border-color: var(--accent-gold);
            color: var(--accent-gold);
        }

        .test-result { font-size: 0.9em; margin-top: 5px; min-height: 1.2em; word-break: break-word; display: flex; align-items: center; gap: 8px; }
        .test-result.success { color: #4CAF50; }
        .test-result.error { color: #f44336; }
        .test-result.info { color: #2196F3; }
        .test-result.warning { color: #ff9800; }

        @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
        .loading-spinner {
            display: inline-block;
            width: 14px;
            height: 14px;
            border: 2px solid rgba(255,255,255,0.3);
            border-radius: 50%;
            border-top-color: #fff;
            animation: spin 0.8s linear infinite;
            vertical-align: middle;
            margin-right: 6px;
        }


        @keyframes thinking-dot {
            0%, 100% { transform: translateY(0); opacity: 0.4; }
            50% { transform: translateY(-4px); opacity: 1; }
        }
        .thinking-dots {
            display: inline-flex;
            gap: 4px;
            align-items: center;
            justify-content: center;
            height: 20px;
        }
        .thinking-dots span {
            display: inline-block;
            width: 6px;
            height: 6px;
            background-color: #aaa;
            border-radius: 50%;
            animation: thinking-dot 1.4s ease-in-out infinite;
        }
        .thinking-dots span:nth-child(2) { animation-delay: 0.2s; }
        .thinking-dots span:nth-child(3) { animation-delay: 0.4s; }


        .config-export-btn, .config-import-label {
            background: #2d303a;
            color: var(--accent-gold);
            border: 1px solid #444;
            padding: 8px 16px;
            border-radius: 8px;
            cursor: pointer;
            font-size: 0.9em;
            display: inline-flex;
            align-items: center;
            gap: 6px;
            transition: all 0.2s;
            margin-right: 10px;
        }
        .config-export-btn:hover, .config-import-label:hover {
            background: #3a3d4a;
            border-color: var(--accent-gold);
            transform: translateY(-2px);
            box-shadow: 0 4px 12px rgba(230, 199, 138, 0.2);
        }
        #config-import-input {
            display: none;
        }


        .shortcut-hint {
            font-size: 0.75em;
            color: #888;
            margin-left: 8px;
            padding: 2px 6px;
            background: rgba(255,255,255,0.1);
            border-radius: 4px;
        }

        .import-section {
            border: 1px dashed #555;
            border-radius: 8px;
            padding: 20px;
            text-align: center;
            margin-bottom: 20px;
            transition: all 0.2s;
        }
        .import-section:hover {
            border-color: var(--accent-gold);
            background-color: rgba(230, 199, 138, 0.05);
        }
        .import-section p { color: #888; font-size: 0.85em; margin-bottom: 15px; }
        .import-hint { font-size: 0.8em; color: #666; margin-top: 10px; }

        .memory-list, .context-edit-list {
            max-height: 200px;
            overflow-y: auto;
            border: 1px solid #444;
            border-radius: 6px;
            padding: 10px;
            background: #262933;
            margin-top: 10px;
        }
        .memory-item, .context-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 8px;
            border-bottom: 1px solid #333;
            font-size: 0.9em;
        }
        .memory-item:last-child, .context-item:last-child { border-bottom: none; }
        .memory-key { color: var(--accent-gold); font-weight: bold; margin-right: 10px; }
        .memory-val { color: #ccc; flex: 1; }
        .del-memory, .del-context, .edit-context {
            cursor: pointer; font-size: 1.2em; padding: 0 5px;
        }
        /* 上下文列表里的编辑/删除已经按钮化（见下方 .context-actions），
           这里的规则只对「长期记忆」列表的裸图标继续生效。 */
        .del-memory { padding: 6px; }
        .del-memory, .del-context { color: #c05a5a; }
        .del-memory:hover, .del-context:hover { color: #d97a7a; }
        .edit-context { color: #6fa87e; }
        .edit-context:hover { color: #85bd93; }

        .context-text {
            flex: 1;
            margin-right: 10px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            color: #ddd;
        }
        .context-role {
            font-weight: bold;
            margin-right: 5px;
            font-size: 0.8em;
            padding: 2px 4px;
            border-radius: 3px;
        }
        .role-mine { background-color: #3a3d47; color: var(--accent-gold); }
        .role-other { background-color: #3a3d47; color: #aaa; }


        .add-friend-modal .modal-content {
            width: 400px;
            max-height: 80vh;
            display: flex;
            flex-direction: column;
        }
        .add-friend-modal .modal-body {
            flex: 1;
            overflow-y: auto;
            padding: 20px;
            position: relative;
        }

        .add-friend-footer {
            padding: 15px 20px;
            border-top: 1px solid #444;
            background-color: #262933;
            flex-shrink: 0;
            display: flex;
            flex-direction: column;
            gap: 10px;
        }

        #friend-options-list {
            display: flex;
            flex-direction: column;
            gap: 10px;
            min-height: 100px;
        }

        .friend-option {
            display: flex;
            align-items: center;
            padding: 15px;
            border: 1px solid #444;
            border-radius: 8px;
            margin-bottom: 10px;
            cursor: pointer;
            transition: background-color 0.2s;
            flex-shrink: 0;
            position: relative;
        }
        .friend-option:hover {
            background-color: #383b45;
            border-color: var(--accent-gold);
        }
        .friend-option img {
            width: 50px;
            height: 50px;
            border-radius: 50%;
            margin-right: 15px;
            object-fit: cover;
            flex-shrink: 0;
        }
        .friend-option-info {
            flex: 1;
            overflow: hidden;
            margin-right: 10px;
        }

        .group-member-select-content {
            width: 640px;
        }

        .group-member-select-toolbar {
            display: flex;
            align-items: center;
            gap: 10px;
            flex-wrap: wrap;
            margin-bottom: 12px;
            color: #cfd3df;
        }

        .group-member-select-toolbar span {
            margin-right: auto;
            color: var(--accent-gold);
            font-weight: 600;
        }

        .group-member-select-search {
            width: 100%;
            padding: 12px 14px;
            border-radius: 8px;
            border: 1px solid #444;
            background: #232631;
            color: #eee;
            margin-bottom: 14px;
            outline: none;
        }

        .group-member-select-search:focus {
            border-color: var(--accent-gold);
            box-shadow: 0 0 0 2px rgba(230, 199, 138, 0.15);
        }

        .group-member-select-list {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
            gap: 10px;
            max-height: 48vh;
            overflow-y: auto;
            padding-right: 4px;
        }

        .group-member-option {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 12px;
            border: 1px solid #444;
            border-radius: 10px;
            background: #262933;
            cursor: pointer;
            transition: border-color 0.2s, background-color 0.2s, transform 0.2s;
        }

        .group-member-option:hover {
            border-color: var(--accent-gold);
            background: #303440;
            transform: translateY(-1px);
        }

        .group-member-option.selected {
            border-color: var(--accent-gold);
            background: rgba(230, 199, 138, 0.12);
        }

        .group-member-option.disabled {
            opacity: 0.55;
            cursor: not-allowed;
        }

        .group-member-option input {
            width: 18px;
            height: 18px;
            accent-color: var(--accent-gold);
        }

        .group-member-option img {
            width: 42px;
            height: 42px;
            border-radius: 50%;
            object-fit: cover;
            flex-shrink: 0;
        }

        .group-member-option-info {
            min-width: 0;
            flex: 1;
            display: flex;
            flex-direction: column;
            gap: 4px;
        }

        .group-member-option-info strong,
        .group-member-option-info small {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .group-member-option-info small {
            color: #999;
        }

        .group-member-option-check {
            color: var(--accent-gold);
            opacity: 0;
            transition: opacity 0.2s;
        }

        .group-member-option.selected .group-member-option-check {
            opacity: 1;
        }

        .friend-option-info h3 {
            font-size: 1.1em;
            margin-bottom: 5px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .friend-option-info p {
            font-size: 0.85em;
            color: #aaa;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        .custom-badge {
            position: absolute;
            top: 5px;
            right: 5px;
            background-color: var(--accent-gold);
            color: #333;
            font-size: 0.7em;
            padding: 2px 6px;
            border-radius: 4px;
            font-weight: bold;
        }

        .export-char-btn {
            background: none;
            border: 1px solid #555;
            color: #aaa;
            border-radius: 50%;
            width: 32px;
            height: 32px;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
            transition: all 0.2s;
            flex-shrink: 0;
            font-size: 1.1em;
        }
        .export-char-btn:hover {
            border-color: var(--accent-gold);
            color: var(--accent-gold);
            background-color: rgba(230, 199, 138, 0.1);
        }

       /* 创建/编辑角色弹窗样式 */
        .character-edit-modal .modal-content {
            width: 500px;
            max-height: 85vh;
        }

        .create-character-section {
            margin-top: 20px;
            padding-top: 20px;
            border-top: 1px dashed #444;
        }
        .create-character-section h3 {
            color: var(--accent-gold);
            margin-bottom: 15px;
            font-size: 1.1em;
        }
        .import-char-section {
            margin-top: 15px;
            padding: 15px;
            border: 1px dashed #666;
            border-radius: 8px;
            text-align: center;
            background-color: rgba(0,0,0,0.1);
        }
        .import-char-section p {
            font-size: 0.85em;
            color: #aaa;
            margin-bottom: 10px;
        }


        .avatar-select-group {
            display: flex;
            gap: 10px;
            align-items: center;
        }
        .avatar-select-group input {
            flex: 1;
            min-width: 0;
        }
        .avatar-select-btn {
            padding: 10px 15px;
            border-radius: 6px;
            border: 1px solid #555;
            background-color: #383b45;
            color: #ddd;
            cursor: pointer;
            display: flex;
            align-items: center;
            gap: 5px;
            font-size: 0.9em;
            transition: all 0.2s;
        }
        .avatar-select-btn:hover {
            border-color: var(--accent-gold);
            color: var(--accent-gold);
            background-color: rgba(230, 199, 138, 0.1);
        }

        /* 头像行在窄屏有三个控件（地址框 + 选择文件 + 裁切），
           一行摆不下就把按钮换到第二行并等宽铺开，避免地址框被压成一条缝。 */
        @media (max-width: 560px) {
            .avatar-select-group {
                flex-wrap: wrap;
            }
            .avatar-select-group input {
                flex: 1 1 100%;
            }
            .avatar-select-group .avatar-select-btn {
                flex: 1 1 auto;
                justify-content: center;
            }
        }


        @media (max-width: 768px) {
            body {
                padding: 0;
            }

            .app-container,
            .app-container.mobile-view {
                /* 不用 100vw：手机上 100vw 含滚动条宽度，会比屏幕宽出一截，
                   整页被挤出横向滚动，看起来就是界面错位。 */
                width: 100%;
                max-width: 100%;
                height: 100vh;
                height: 100dvh;
                border-radius: 0;
                box-shadow: none;
            }

            .sidebar,
            .app-container.mobile-view .sidebar {
                position: absolute;
                width: min(86vw, 320px);
                max-width: calc(100vw - 52px);
                height: 100%;
                z-index: 100;
                box-shadow: 2px 0 10px rgba(0,0,0,0.5);
            }

            .mobile-menu-btn {
                display: flex;
            }

            /* 手机视图：侧边栏是浮层，显示栏内关闭按钮 */
            .sidebar-header .sidebar-close-btn { display: flex; }

            /* 同上：为右上角悬浮的切换视图按钮预留 62px，避免遮挡垃圾桶按钮 */
            .chat-header {
                min-height: 56px;
                padding: 12px max(62px, calc(env(safe-area-inset-right) + 62px)) 12px max(50px, env(safe-area-inset-left));
                font-size: 1em;
                gap: 8px;
            }

            #current-friend-name,
            #my-display-name {
                min-width: 0;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
            }

            .chat-header > div {
                flex-shrink: 0;
            }

            /* 手机上聊天头部按钮较多（全屏/摘要/统计/清空），横排会互相挤压；
               允许换行并让名字区优先收缩，避免出现按钮被挤出屏幕或「错位」观感。 */
            .chat-header {
                flex-wrap: wrap;
                row-gap: 6px;
            }
            .chat-header > div {
                display: flex;
                flex-wrap: wrap;
                justify-content: flex-end;
                gap: 6px !important;
                max-width: 100%;
            }
            .chat-header .icon-btn {
                width: 32px !important;
                height: 32px !important;
                font-size: 0.85em !important;
            }

            .chat-messages {
                padding: 14px max(12px, env(safe-area-inset-right)) 14px max(12px, env(safe-area-inset-left));
                gap: 14px;
            }

            /* 悬浮按钮在手机上略微内收，避免贴到屏幕边缘
               （纵向位置仍由 JS 写进 --stb-bottom，不能在这里写死 bottom） */
            .scroll-to-bottom-btn {
                right: 12px;
                width: 38px;
                height: 38px;
            }

            .chat-input-area {
                padding: 10px max(12px, env(safe-area-inset-right)) calc(10px + env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left));
                gap: 10px;
            }

            .input-wrapper input, .input-wrapper textarea {
                padding: 10px 12px;
                font-size: 0.9em;
            }

            .input-icons i {
                font-size: 1.1em;
            }

            #send-btn {
                font-size: 1.3em;
            }

            .message {
                max-width: 94%;
            }

            .avatar {
                width: 38px;
                height: 38px;
            }

            .bubble {
                padding: 9px 12px;
                font-size: 0.9em;
            }

            /* 【手机端修复】以前这里给 .modal-content 加了 padding:15px，
               而 .modal-header / .modal-body / .modal-footer 各自还有自己的内边距，
               叠加后底部按钮区被挤得只剩一点点宽度：`margin-left:auto` 的「保存设置」
               被顶到换行，和「恢复默认」错位成两行、还可能被屏幕裁掉。
               这里去掉重复的外层 padding，并让底部按钮区在窄屏改成上下堆叠的整行按钮。 */
            .modal-content {
                width: 96%;
                max-width: none;
                max-height: 90vh;
                padding: 0;
                overflow: hidden;
            }

            .modal-header {
                padding: 12px 14px;
                flex-wrap: wrap;
                gap: 8px;
            }

            /* 设置弹窗的搜索框在手机上会挤压标题与关闭按钮，改成整行 */
            .settings-search-wrap {
                order: 3;
                flex: 1 1 100%;
                max-width: none;
                margin: 0;
            }

            /* 标签栏在手机上必须能横向滑动且不换行、不被压扁：
               以前 10 个标签挤在一行会被压缩到看不清，甚至把关闭按钮顶走。
               这里改成横向滚动 + 惯性滑动，并用 scroll-snap 让选中项落在中间。 */
            .settings-tabs {
                gap: 8px;
                margin-bottom: 16px;
                padding-bottom: 4px;
                overflow-x: auto;
                overflow-y: hidden;
                flex-wrap: nowrap;
                -webkit-overflow-scrolling: touch;
                overscroll-behavior-x: contain;
                scrollbar-width: none;
            }
            .settings-tabs::-webkit-scrollbar { display: none; }
            .settings-tabs .tab-button {
                flex: 0 0 auto;
                font-size: 0.92em;
                padding: 8px 4px 10px;
            }

            .modal-footer {
                padding: 12px 14px calc(12px + env(safe-area-inset-bottom));
                flex-wrap: wrap;
                gap: 10px;
                /* 关键：从 space-between 换成纵向堆叠，彻底消灭错位 */
                flex-direction: column;
                align-items: stretch;
            }
            .modal-footer > div {
                margin-left: 0 !important;
                width: 100%;
                flex-wrap: wrap;
                gap: 10px !important;
            }
            .modal-footer .btn {
                flex: 1 1 auto;
                justify-content: center;
                min-width: 120px;
                padding: 11px 14px;
            }
            /* 「恢复默认 / 保存设置」在手机上都是整行按钮，点按区域更大 */
            #reset-settings-btn,
            #save-settings-btn,
            #test-connection-btn {
                width: 100%;
                flex: 1 1 100%;
            }

            /* 设置页里的多列开关网格在窄屏改单列，避免文字被压在按钮下面 */
            .feature-toggle-grid {
                grid-template-columns: 1fr !important;
            }

            .modal-header h2 {
                font-size: 1.3em;
            }

            .modal-body {
                padding: 15px;
                font-size: 0.9em;
                line-height: 1.6;
            }

            .modal-body h3 {
                font-size: 1.1em;
                margin-top: 15px;
            }

            .modal-body p {
                font-size: 0.9em;
            }

        .modal-footer {
                /* 与上面同一媒体查询里的规则保持一致：这里只续航内边距，
                   布局（纵向堆叠 / 整行按钮）由上面的规则决定，不要再改回 space-between。 */
                padding: 12px 14px calc(12px + env(safe-area-inset-bottom));
            }

            .avatar-context-menu {
                /* 「我的头像」菜单是 position:absolute，锚定在输入区上方，
                   窄屏直接钉在左下更省事，纵向往上交给这条 bottom。 */
                left: 15px !important;
                bottom: 70px !important;
                min-width: 140px;
            }

            /* 【手机端修复】角色头像菜单与联系人右键菜单是 position:fixed，
               且由 JS 按点击位置写入 top/left。旧规则对它们也加了 bottom:70px !important，
               于是同一个元素同时存在 top 与 bottom、又没有固定高度 ——
               盒子会被拉伸成「从点击处一直连到屏幕底部」的长条，
               手机上看起来就是「菜单错位/变形、点不中」。
               现在这两个菜单纵向只由 JS 的 top 决定，这里只收窄左右边距并限制最大高度。 */
            .ai-avatar-context-menu,
            .friend-context-menu {
                left: 12px !important;
                max-width: calc(100vw - 24px);
                min-width: 0;
                max-height: min(62vh, 340px);
                overflow-y: auto;
                -webkit-overflow-scrolling: touch;
            }

            .message-actions, .quick-replies {
                margin-left: 52px;
            }

            .disclaimer-text {
                font-size: 0.7em !important;
                padding: 0 10px;
            }
        }


        .app-container.mobile-view {
            width: min(100vw, 430px);
            height: min(100vh, 844px);
            height: min(100dvh, 844px);
            max-width: none;
        }

        .app-container.mobile-view .sidebar {
            position: absolute;
            height: 100%;
            z-index: 100;
            box-shadow: 2px 0 10px rgba(0,0,0,0.5);
        }

        .app-container.mobile-view .mobile-menu-btn {
            display: flex;
        }

        /* 修复：右侧 padding 原为 50px，而 .view-toggle-btn 占据右侧 15+40=55px，
           导致「清空聊天记录」垃圾桶按钮被切换视图按钮盖住无法点击。
           这里按「按钮右偏移 + 按钮宽度 + 间隙」预留 62px。 */
        .app-container.mobile-view .chat-header {
            min-height: 56px;
            padding: 12px 62px 12px 50px;
            font-size: 1em;
            gap: 8px;
        }

        /* 移动视图下头部空间紧张：名字可省略号收缩，右侧按钮组不许被压缩 */
        .app-container.mobile-view .chat-header > #current-friend-name {
            min-width: 0;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .app-container.mobile-view .chat-header > div {
            flex-shrink: 0;
            gap: 6px !important;
        }

        @media (max-width: 768px), (min-width: 769px) and (max-width: 1024px) and (orientation: portrait) {
            body {
                padding: 0;
            }

            .app-container.mobile-view {
                width: 100%;
                max-width: 100%;
                height: 100vh;
                height: 100dvh;
                border-radius: 0;
                box-shadow: none;
            }
        }


        /* ========================================
           移动端软键盘避让（body.kb-shrink 由 main.js 在键盘弹出时加上）
           Chrome/Edge 安卓由 <meta viewport interactive-widget=resizes-content>
           直接压缩布局视口；iOS Safari 等不支持该属性的内核走这里：
           JS 把容器高度压成 visualViewport.height，因此必须让容器顶对齐，
           否则 body 的居中 flex 会把这块「变矮的容器」垂直居中，
           结果输入框的下半截仍然躲在键盘后面。
           ======================================== */
        body.kb-shrink {
            align-items: flex-start;
            justify-content: center;
            min-height: 0;
            height: 100%;
            overflow: hidden;
        }

        /* html 也要一起钉住：iOS/Safari 弹出键盘时会自动把整篇文档向上滚，
           若 html 高度仍是「键盘遮挡前的全高」，被压扁的容器会被一起推出可视区，
           表现就是「输入框还是被键盘挡住」。--kb-h 由 main.js 写入可见高度。 */
        html.kb-active {
            height: var(--kb-h, 100%);
            overflow: hidden;
        }

        html.kb-active body {
            height: var(--kb-h, 100%);
            overflow: hidden;
        }

        /* 键盘弹出时，全屏遮罩类弹窗（.modal-overlay / 应用内对话框）也必须改用
           「可见高度」：fixed 元素不受容器压扁影响，iOS 下 vh 也不随键盘变化，
           不显式约束的话弹窗里的输入框会永远躲在键盘后面。
           顶部对齐 + 允许滚动，保证内容再高也够得着。 */
        html.kb-active .modal-overlay {
            align-items: flex-start;
            overflow-y: auto;
            padding-top: 10px;
        }

        html.kb-active .modal-overlay .modal-content {
            max-height: calc(var(--kb-h, 100vh) - 24px);
            overflow-y: auto;
        }

        html.kb-active .ad-overlay {
            align-items: flex-start;
            padding-top: 10px;
            height: var(--kb-h, 100%);
        }

        html.kb-active .ad-card {
            max-height: calc(var(--kb-h, 100vh) - 24px);
        }

        body.kb-shrink .app-container,
        body.kb-shrink .app-container.mobile-view {
            border-radius: 0;
            box-shadow: none;
        }

        /* 键盘已经占掉这块空间：免责条与 safe-area 底部留白都该让位给输入框 */
        body.kb-shrink .disclaimer-text { display: none !important; }
        body.kb-shrink .chat-input-area { padding-bottom: 8px !important; }
        body.kb-shrink .toast-container { bottom: 12px; }

        .toast-container {
            position: fixed;
            bottom: 30px;
            left: 50%;
            transform: translateX(-50%) translateY(100px);
            background-color: #2d303a;
            border: 1px solid var(--accent-gold);
            border-radius: var(--radius-md);
            padding: 12px 24px;
            color: var(--text-primary);
            font-size: 0.95em;
            box-shadow: 0 5px 20px rgba(0, 0, 0, 0.6);
            z-index: 10000;
            opacity: 0;
            visibility: hidden;
            transition: all 0.3s ease;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        .toast-container.show {
            opacity: 1;
            visibility: visible;
            transform: translateX(-50%) translateY(0);
        }
        .toast-container i {
            font-size: 1.2em;
            color: var(--accent-gold);
        }

/* 拆分后的增强功能样式 */
.small-icon-btn {
    width: 28px;
    height: 28px;
    font-size: 0.85em;
    margin-left: auto;
}

body.light-theme {
    --bg-primary: #f4f6fb;
    --bg-secondary: #ffffff;
    --bg-tertiary: #eef1f7;
    --bg-sidebar: #f9fafc;
    --text-primary: #20242c;
    --text-secondary: #4f5b6b;
    --text-muted: #6f7c8d;
    --border-color: #d9deea;
    --border-light: rgba(0, 0, 0, 0.1);
    --shadow-lg: 0 10px 30px rgba(20, 30, 50, 0.15);
    --shadow-md: 0 4px 12px rgba(20, 30, 50, 0.12);
}

body.light-theme .chat-area::before {
    background-color: #eef1f7;
}

.global-search-results {
    max-height: 220px;
    overflow-y: auto;
    margin: -5px 0 12px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-tertiary);
    padding: 8px;
}

.search-result-group-title {
    color: var(--accent-gold);
    font-size: 0.82em;
    margin: 6px 0 4px;
    font-weight: 600;
}

.search-result-item {
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    padding: 7px;
    margin-bottom: 5px;
    cursor: pointer;
    color: var(--text-secondary);
    font-size: 0.84em;
    line-height: 1.35;
}

.search-result-item:hover {
    border-color: var(--accent-gold);
    color: var(--text-primary);
}

.message.search-highlight .bubble {
    outline: 2px solid var(--accent-gold);
    box-shadow: 0 0 14px rgba(230, 199, 138, 0.55);
}

.code-block-wrapper {
    position: relative;
}

.copy-code-btn {
    position: absolute;
    top: 6px;
    right: 6px;
    border: 1px solid rgba(255,255,255,0.2);
    background: rgba(0,0,0,0.55);
    color: #fff;
    border-radius: 5px;
    padding: 4px 8px;
    cursor: pointer;
    font-size: 0.75em;
    z-index: 2;
}

.command-panel {
    position: absolute;
    right: 18px;
    bottom: 86px;
    width: min(360px, calc(100vw - 40px));
    max-height: 320px;
    overflow-y: auto;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    padding: 12px;
    z-index: 5;
}

.command-panel.show { display: block; }
.command-card {
    padding: 10px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-color);
    margin-bottom: 8px;
    cursor: pointer;
}
.command-card:hover { border-color: var(--accent-gold); }
.command-card code { color: var(--accent-gold); }

@media print {
    body * { visibility: hidden; }
    #chat-messages, #chat-messages * { visibility: visible; }
    #chat-messages {
        position: absolute;
        inset: 0;
        overflow: visible !important;
        color: #111;
        background: white;
    }
    .message-actions, .chat-input-area, .sidebar, .chat-header { display: none !important; }
}
.friend-batch-checkbox {
    width: 18px;
    height: 18px;
    accent-color: var(--accent-gold);
    flex-shrink: 0;
}
.input-icons .recording,
/* 图片预览：缩放、旋转与下载 */
.image-preview-modal{position:fixed;inset:0;z-index:10000;background:rgba(0,0,0,.9);display:flex;align-items:center;justify-content:center;overflow:hidden}.image-preview-modal[hidden]{display:none!important}.image-preview-stage{width:100%;height:100%;padding:76px 24px 28px;display:flex;align-items:center;justify-content:center;overflow:auto;touch-action:none}.image-preview-stage img{max-width:92vw;max-height:82vh;object-fit:contain;transform-origin:center;transition:transform .18s ease;user-select:none;-webkit-user-drag:none;box-shadow:0 8px 35px rgba(0,0,0,.55)}.image-preview-toolbar{position:absolute;z-index:1;top:16px;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:7px;padding:7px;border:1px solid rgba(255,255,255,.2);border-radius:12px;background:rgba(32,32,32,.82);backdrop-filter:blur(8px)}.image-preview-toolbar button,.image-preview-toolbar a{width:38px;height:38px;display:grid;place-items:center;border:0;border-radius:8px;background:transparent;color:#fff;font-size:1.25rem;cursor:pointer;text-decoration:none}.image-preview-toolbar button:hover,.image-preview-toolbar a:hover{background:rgba(255,255,255,.17);color:var(--accent-gold)}.message-image{display:block;cursor:zoom-in;max-width:min(100%,420px)!important;width:auto!important;height:auto!important;object-fit:contain;box-sizing:border-box}.message .message-content{min-width:0;max-width:calc(100% - 50px)}@media(max-width:560px){.message-image{max-width:100%!important;max-height:52vh!important}.message .message-content{max-width:calc(100vw - 70px)}.image-preview-stage{padding:72px 10px 16px}.image-preview-stage img{max-width:96vw;max-height:80vh}.image-preview-toolbar{top:10px;gap:2px;padding:5px}.image-preview-toolbar button,.image-preview-toolbar a{width:34px;height:34px;font-size:1.1rem}}

#voice-input-btn.recording {
    color: #ff6b6b !important;
    animation: pulseMic 1s infinite;
}
@keyframes pulseMic {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.15); }
}
.emoji-category-title {
    grid-column: 1 / -1;
    color: var(--accent-gold);
    font-size: 0.82em;
    padding: 6px 4px 2px;
}
.feature-toggle-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 10px;
}
.feature-toggle-grid label {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: rgba(255,255,255,0.03);
}

/* 离线提示与多行输入框 */
.offline-banner {
    padding: 8px 16px;
    background: rgba(255, 176, 32, 0.16);
    border-bottom: 1px solid rgba(255, 176, 32, 0.35);
    color: #ffd28a;
    font-size: 0.88em;
    text-align: center;
}

.input-wrapper textarea {
    width: 100%;
    min-height: 44px;
    max-height: 140px;
    padding: 12px 15px;
    border-radius: 20px;
    border: 1px solid rgba(255,255,255,0.2);
    background-color: rgba(0,0,0,0.3);
    color: #eee;
    outline: none;
    resize: none;
    line-height: 1.45;
    font-family: inherit;
}

.input-wrapper textarea::placeholder { color: #aaa; }

#send-btn.disabled {
    opacity: 0.55;
}

.chat-search-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    background: rgba(38, 41, 51, 0.96);
    border-bottom: 1px solid rgba(255,255,255,0.08);
}
.chat-search-bar input {
    flex: 1;
    min-width: 0;
    padding: 8px 10px;
    border-radius: 14px;
    border: 1px solid rgba(255,255,255,0.18);
    background: rgba(0,0,0,0.25);
    color: #eee;
    outline: none;
}
.chat-search-bar .icon-btn { width: 28px; height: 28px; font-size: 0.9em; }
.message.search-match .bubble { box-shadow: 0 0 0 2px rgba(255, 211, 105, 0.75); }
.message.search-active .bubble { box-shadow: 0 0 0 3px var(--accent-gold), 0 0 18px rgba(230, 199, 138, 0.45); }
.audio-bubble audio { max-width: 260px; width: 100%; }
.message-meta { font-size: 0.72em; color: #888; margin-top: 4px; text-align: right; }
.message.mine .message-meta { text-align: right; }
.shortcut-list { list-style: none; display: flex; flex-direction: column; gap: 12px; }
.shortcut-list li { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
kbd { background: #1f222b; border: 1px solid #555; border-bottom-width: 2px; border-radius: 5px; padding: 2px 6px; color: var(--accent-gold); font-family: inherit; }


.reply-preview {
    margin: 2px 0 6px;
    padding: 6px 10px;
    border-left: 3px solid var(--accent-gold);
    background: rgba(230, 199, 138, 0.12);
    color: #cfc6b0;
    border-radius: 6px;
    font-size: 0.82em;
    max-width: var(--bubble-max-width);
    word-break: break-word;
}
.markdown-preview-popover {
    position: absolute;
    left: 0;
    right: 42px;
    bottom: calc(100% + 8px);
    max-height: 220px;
    overflow: auto;
    padding: 12px;
    border: 1px solid rgba(230, 199, 138, 0.35);
    border-radius: 10px;
    background: rgba(26, 28, 35, 0.96);
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
    color: #eee;
    z-index: 20;
}
.markdown-preview-popover[hidden] { display: none; }

/* 群聊 @ 成员菜单：挂到 body 上，避免被聊天区 overflow 裁掉。
   具体的 left / top / width 由 JS 按输入框实时测量。 */
.mention-menu {
    position: fixed;
    z-index: 1200;
    max-height: min(260px, 46vh);
    overflow-y: auto;
    padding: 6px;
    border: 1px solid rgba(230, 199, 138, 0.38);
    border-radius: 12px;
    background: rgba(32, 35, 44, 0.98);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.42);
}
.mention-menu[hidden] { display: none; }
.mention-menu-item {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 8px;
    border: 0;
    border-radius: 9px;
    background: transparent;
    color: #eee;
    text-align: left;
    cursor: pointer;
    font: inherit;
}
.mention-menu-item:hover,
.mention-menu-item.active {
    background: rgba(230, 199, 138, 0.16);
    color: var(--accent-gold);
}
.mention-menu-item img {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    object-fit: cover;
    flex: 0 0 auto;
    background: rgba(255, 255, 255, 0.08);
}
.mention-menu-text {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.mention-menu-text strong {
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.mention-menu-text small {
    color: #9a9a9a;
    font-size: 0.78em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.mention-menu-item.active .mention-menu-text small,
.mention-menu-item:hover .mention-menu-text small { color: #cbb892; }
.mention-menu-empty {
    padding: 10px 12px;
    color: #999;
    font-size: 0.86em;
}
body.light-theme .mention-menu {
    background: rgba(255, 250, 242, 0.98);
    color: var(--text-primary);
    border-color: #cdbb9f;
    box-shadow: 0 12px 28px rgba(92, 78, 58, 0.2);
}
body.light-theme .mention-menu-item { color: var(--text-primary); }
body.light-theme .mention-menu-item:hover,
body.light-theme .mention-menu-item.active {
    background: rgba(var(--accent-gold-rgb), 0.18);
    color: #7a5a24;
}
body.light-theme .mention-menu-text small { color: #8a7760; }
.memory-tag { display: inline-block; margin-right: 4px; color: var(--accent-gold); }

/* 修复：操作按钮现在在 message-content 内部，不需要左边距 */
.message-actions {
    margin-left: 0 !important;
}

        .group-name-content {
            width: 420px;
        }

        .group-manage-content {
            width: min(920px, 94vw);
        }

        .group-manage-grid {
            display: grid;
            grid-template-columns: repeat(2, minmax(0, 1fr));
            gap: 14px;
        }

        .group-manage-panel {
            background: #232631;
            border: 1px solid #3f4350;
            border-radius: 12px;
            padding: 16px;
        }

        .group-manage-panel h3 {
            display: flex;
            align-items: center;
            gap: 8px;
            color: var(--accent-gold);
            margin-bottom: 12px;
            font-size: 1em;
        }

        .group-manage-wide {
            grid-column: 1 / -1;
        }

        .group-manage-hint {
            color: #999;
            font-size: 0.85em;
            line-height: 1.5;
            margin-bottom: 12px;
        }

        .group-manage-list {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
            gap: 10px;
            max-height: 32vh;
            overflow-y: auto;
            padding-right: 4px;
        }

        .group-manage-row,
        .group-activity-row {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 10px;
            border: 1px solid #444;
            border-radius: 10px;
            background: #2b2f3a;
        }

        .group-manage-row input[type="checkbox"] {
            width: 18px;
            height: 18px;
            accent-color: var(--accent-gold);
        }

        .group-manage-row img,
        .group-activity-row img {
            width: 34px;
            height: 34px;
            border-radius: 50%;
            object-fit: cover;
            flex-shrink: 0;
        }

        .group-manage-row span,
        .group-activity-row span {
            min-width: 0;
            flex: 1;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .group-manage-row em {
            color: var(--accent-gold);
            font-size: 0.8em;
            font-style: normal;
        }

        .group-admin-actions {
            display: grid;
            grid-template-columns: 1fr 110px auto auto;
            gap: 10px;
            align-items: center;
        }

        .group-member-select-modal { z-index: 1200; }

        .group-admin-actions select,
        .group-admin-actions input,
        .group-activity-row input[type="number"] {
            padding: 9px 10px;
            border-radius: 8px;
            border: 1px solid #444;
            background: #1f222b;
            color: #eee;
        }

        .group-title-row {
            display: grid;
            grid-template-columns: 34px minmax(80px, 1fr) minmax(120px, 1.4fr);
            align-items: center;
            gap: 10px;
            padding: 10px;
            border: 1px solid #444;
            border-radius: 10px;
            background: #2b2f3a;
        }
        .group-title-row img { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; }
        .group-title-row span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .group-title-row input,
        .group-manage-panel textarea,
        .group-manage-panel > input {
            width: 100%; box-sizing: border-box; padding: 9px 10px; border-radius: 8px;
            border: 1px solid #444; background: #1f222b; color: #eee;
        }
        .group-manage-panel textarea { min-height: 72px; resize: vertical; margin: 0 0 9px; }
        .group-manage-panel > input { margin: 0 0 9px; }
        .group-feature-list { display: grid; gap: 8px; max-height: 190px; overflow-y: auto; margin-top: 12px; }
        .group-feature-item { padding: 10px; border-left: 3px solid var(--accent-gold); background: #2b2f3a; border-radius: 6px; }
        .group-feature-item strong, .group-feature-item small { display: block; }
        .group-feature-item small { color: #999; margin-top: 6px; font-size: .78em; }
        .poll-result-row { display: flex; justify-content: space-between; gap: 10px; margin-top: 6px; color: #ddd; font-size: .9em; }

        .group-activity-row input[type="range"] {
            flex: 1.4;
            accent-color: var(--accent-gold);
        }

        .group-activity-row input[type="number"] {
            width: 76px;
        }

        @media (max-width: 768px) {
            .group-manage-grid,
            .group-manage-list,
            .group-admin-actions {
                grid-template-columns: 1fr;
            }
        }

/* 重做浅色主题：降低纯白面积，改为暖灰卡片层级与清晰边界 */
body.light-theme {
    --bg-primary: #e9edf5;
    --bg-secondary: #f7f3ea;
    --bg-tertiary: #ece4d6;
    --bg-sidebar: #efe7d9;
    --text-primary: #242833;
    --text-secondary: #566174;
    --text-muted: #7a8494;
    --border-color: #d6c9b5;
    --border-light: rgba(82, 62, 35, 0.14);
    --shadow-lg: 0 18px 45px rgba(92, 78, 58, 0.18);
    --shadow-md: 0 8px 22px rgba(92, 78, 58, 0.12);
    background:
        radial-gradient(circle at top left, rgba(var(--accent-gold-rgb), 0.22), transparent 34%),
        linear-gradient(135deg, #e3e8f2 0%, #f3eee4 54%, #e8ddcc 100%);
}

body.light-theme .app-container {
    background: rgba(247, 243, 234, 0.96);
    border: 1px solid rgba(151, 124, 82, 0.22);
    box-shadow: var(--shadow-lg);
}

body.light-theme .sidebar,
body.light-theme .chat-header,
body.light-theme .chat-input-area,
body.light-theme .modal-content,
body.light-theme .command-panel {
    background: rgba(239, 231, 217, 0.96);
    color: var(--text-primary);
    border-color: var(--border-color);
}

body.light-theme .chat-area::before {
    background:
        linear-gradient(rgba(247, 243, 234, 0.84), rgba(247, 243, 234, 0.84)),
        radial-gradient(circle at 20% 10%, rgba(var(--accent-gold-rgb), 0.2), transparent 28%);
}

body.light-theme .friend-item,
body.light-theme .friend-option,
body.light-theme .command-card,
body.light-theme .import-char-section,
body.light-theme .settings-nav,
body.light-theme .settings-content {
    background: rgba(255, 251, 242, 0.72);
    border-color: rgba(151, 124, 82, 0.18);
}

body.light-theme .friend-item:hover,
body.light-theme .friend-option:hover,
body.light-theme .command-card:hover {
    background: rgba(var(--accent-gold-rgb), 0.16);
}

body.light-theme .search-box,
body.light-theme .input-wrapper input,
body.light-theme .input-wrapper textarea,
body.light-theme .form-group input,
body.light-theme .form-group select,
body.light-theme .form-group textarea,
body.light-theme .chat-search-bar input,
body.light-theme .settings-search-wrap input {
    background: #fffaf2;
    color: var(--text-primary);
    border-color: #cdbb9f;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.75);
}

body.light-theme .search-box::placeholder,
body.light-theme .input-wrapper textarea::placeholder {
    color: #8a7760;
}

/* 浅色主题「系统设置」文本可读性修复：
   基础样式是按暗底写的（label/tab-button/close-modal 都是 #aaa，
   tabs 分隔线 #3a3d47），在奶油底上几乎看不清 —— 所有浅色主题
   （默认浅色 / 星铁·浅 / 绝区零等）通用的发灰发白都源于此。
   这里统一压成深棕灰；zzz 主题自己有更高特异性的覆盖，不受影响。 */
body.light-theme .form-group label { color: #6d6156; }
body.light-theme .settings-tabs { border-bottom-color: #d8ccb8; }
body.light-theme .tab-button { color: #8a7760; }
body.light-theme .tab-button:hover { color: #5a4f42; }
body.light-theme .tab-button.active { color: #8c6b2f; }
body.light-theme .tab-button.active::after { background-color: #b08a3e; }
body.light-theme .close-modal { color: #8a7760; }
body.light-theme .close-modal:hover { color: #4a4036; }
body.light-theme .settings-search-wrap i { color: #8a7760; }
body.light-theme .settings-no-results { color: #8a7760; border-color: #cdbb9f; }
body.light-theme .plugin-permissions-hint { color: #8a7760; border-color: #cdbb9f; }
body.light-theme .plugin-permissions-desc { color: #7a6f60; }
/* 浅色主题下按钮/提示文本同理：#ddd 文字、#c6cad6 提示在奶油底上等于隐形 */
body.light-theme .btn-outline { border-color: #a5967f; color: #5a4f42; }
body.light-theme .btn-outline:hover { border-color: #b08a3e; color: #8c6b2f; }
body.light-theme .btn-secondary { background-color: #6b6156; color: #f6f1e8; }
body.light-theme .ep-check-row { color: #5a4f42; }
body.light-theme .ep-hint { color: #7a6f60; }

body.light-theme .message.other .bubble {
    background: #fffaf2;
    color: var(--text-primary);
    border: 1px solid rgba(151, 124, 82, 0.18);
}

body.light-theme .message.mine .bubble {
    background: linear-gradient(135deg, #e6c78a, #d6a95e);
    color: #221a10;
}

.global-search-results {
    position: relative;
    z-index: 8;
    background: #252934;
    box-shadow: var(--shadow-md);
}

body.light-theme .global-search-results {
    background: #fffaf2;
    color: var(--text-primary);
    border-color: #cdbb9f;
    box-shadow: 0 10px 24px rgba(92, 78, 58, 0.18);
}

body.light-theme .search-result-item {
    color: var(--text-secondary);
    background: rgba(239, 231, 217, 0.62);
}

body.light-theme .search-result-item:hover {
    background: rgba(var(--accent-gold-rgb), 0.18);
    color: var(--text-primary);
}

        /* 插件权限面板 */
        .plugin-permissions {
            border: 1px solid rgba(230,199,138,0.35);
            border-radius: 12px;
            padding: 14px;
            margin-bottom: 16px;
            background: rgba(230,199,138,0.06);
        }
        .plugin-permissions-title {
            display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
            color: var(--accent-gold); font-weight: bold; margin-bottom: 12px;
        }
        .plugin-permissions-hint {
            font-weight: normal; font-size: 0.78em; color: #999;
            border: 1px solid #555; border-radius: 999px; padding: 2px 8px;
        }
        .plugin-permissions-desc {
            font-size: 0.8em; color: #9a9a9a; line-height: 1.6;
            margin: -4px 0 10px; padding-left: 2px;
        }
        .plugin-permissions-desc b { color: var(--accent-gold); }
        .plugin-permission-item {
            display: flex; align-items: flex-start; gap: 10px;
            padding: 10px; border-radius: 8px; cursor: pointer;
            transition: background-color 0.2s;
        }
        .plugin-permission-item:hover { background: rgba(255,255,255,0.04); }
        .plugin-permission-item > input[type="checkbox"] {
            margin-top: 3px; flex-shrink: 0; width: 16px; height: 16px;
            accent-color: var(--accent-gold); cursor: pointer;
        }
        .plugin-permission-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
        .plugin-permission-body strong { color: #f0e6c8; font-size: 0.95em; }
        .plugin-permission-body small { color: #9a9a9a; font-size: 0.8em; line-height: 1.5; }
        .plugin-permission-body small b { color: #e6a8a8; font-weight: bold; }

        /* 插件卡片上的「单个插件独立授权」勾选区 */
        .plugin-grants {
            display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
            margin-top: 10px; padding: 8px 10px;
            background: rgba(255,255,255,0.03);
            border: 1px dashed #4a4d57; border-radius: 8px;
        }
        .plugin-grants-title { font-size: 0.8em; color: #999; white-space: nowrap; }
        .plugin-grant {
            display: inline-flex; align-items: center; gap: 5px;
            font-size: 0.82em; color: #ddd; cursor: pointer;
            padding: 2px 6px; border-radius: 6px;
        }
        .plugin-grant:hover { background: rgba(255,255,255,0.05); }
        .plugin-grant input[type="checkbox"] {
            width: 14px; height: 14px; cursor: pointer;
            accent-color: var(--accent-gold);
        }
        .plugin-grant-disabled { opacity: 0.5; cursor: not-allowed; }
        .plugin-grant-disabled input { cursor: not-allowed; }
        .plugin-grant-note { font-style: normal; font-size: 0.88em; color: #f0b27a; }
        .plugin-blocked-tip {
            margin-top: 10px; font-size: 0.8em; color: #f0b27a;
            background: rgba(240,178,122,0.1); border-left: 3px solid #f0b27a;
            padding: 8px 10px; border-radius: 4px; line-height: 1.5;
        }
        .plugin-card.plugin-blocked { opacity: 0.72; }

        .plugin-ai-writer {
            border: 1px solid rgba(230,199,138,0.35);
            border-radius: 12px;
            margin-bottom: 14px;
            background: rgba(230,199,138,0.05);
        }
        .plugin-ai-writer > summary {
            cursor: pointer;
            list-style: none;
            display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
            padding: 12px 14px;
            color: var(--accent-gold); font-weight: bold;
        }
        .plugin-ai-writer > summary::-webkit-details-marker { display: none; }
        .plugin-ai-writer > summary em {
            font-style: normal; font-weight: normal; font-size: 0.75em; color: #999;
            border: 1px solid #555; border-radius: 999px; padding: 2px 8px;
        }
        .plugin-ai-writer-body { padding: 0 14px 14px; display: flex; flex-direction: column; gap: 10px; }
        .plugin-ai-hint { margin: 0; font-size: 0.8em; color: #9a9a9a; line-height: 1.6; }
        .plugin-ai-field { display: flex; flex-direction: column; gap: 6px; color: #bbb; font-size: 0.85em; flex: 1; min-width: 0; }
        .plugin-ai-field textarea,
        .plugin-ai-field input {
            width: 100%; box-sizing: border-box;
            background: #1c1e25; color: #eee;
            border: 1px solid #3a3d47; border-radius: 8px;
            padding: 8px 10px; font-family: inherit; font-size: 0.95em; resize: vertical;
        }
        .plugin-ai-field textarea#plugin-ai-code { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.82em; line-height: 1.5; }
        .plugin-ai-row, .plugin-ai-actions { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
        .plugin-ai-status { margin: 0; min-height: 1.2em; font-size: 0.8em; color: #f0b27a; line-height: 1.5; }
        .plugin-ai-status.is-ok { color: #9dca8c; }

        .more-links { display: flex; flex-direction: column; gap: 10px; }
        .more-link {
            display: flex; align-items: center; gap: 12px;
            padding: 12px 14px; border-radius: 12px; text-decoration: none;
            border: 1px solid rgba(230,199,138,0.32);
            background: rgba(230,199,138,0.06); color: inherit;
            transition: background-color 0.2s, border-color 0.2s;
        }
        .more-link:hover { background: rgba(230,199,138,0.14); border-color: rgba(230,199,138,0.6); }
        .more-link > i { font-size: 1.4em; color: var(--accent-gold); flex-shrink: 0; }
        .more-link span { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
        .more-link strong { color: #f0e6c8; font-size: 0.98em; }
        .more-link small { color: #9a9a9a; font-size: 0.8em; word-break: break-all; }
        .more-link em { font-style: normal; color: var(--accent-gold); font-size: 0.82em; white-space: nowrap; }

        .more-refresh { margin-bottom: 18px; padding-bottom: 16px; border-bottom: 1px solid rgba(255,255,255,.08); }
        .more-refresh h4 { margin: 0 0 8px; color: #e6c78a; font-size: 1em; display: flex; align-items: center; gap: 6px; }
        .more-refresh > p { margin: 0 0 12px; color: #9a9a9a; font-size: .82em; line-height: 1.65; }
        .more-refresh > p strong { color: #d7dbe6; font-weight: 600; }
        .more-refresh-btn {
            width: 100%; display: flex; align-items: center; gap: 12px; text-align: left;
            padding: 12px 14px; margin-bottom: 8px; border-radius: 12px; cursor: pointer;
            border: 1px solid rgba(255,255,255,.12); background: rgba(255,255,255,.03); color: inherit;
            font: inherit;
        }
        .more-refresh-btn:hover { background: rgba(230,199,138,.1); border-color: rgba(230,199,138,.45); }
        .more-refresh-btn > i { font-size: 1.35em; color: var(--accent-gold); flex-shrink: 0; }
        .more-refresh-btn span { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
        .more-refresh-btn strong { color: #f0e6c8; font-size: .95em; }
        .more-refresh-btn small { color: #9a9a9a; font-size: .78em; line-height: 1.55; }
        .more-refresh-btn em { font-style: normal; color: #8fe0a8; font-size: .75em; white-space: nowrap; }
        .more-refresh-btn.is-danger { border-color: rgba(255,120,120,.35); }
        .more-refresh-btn.is-danger > i, .more-refresh-btn.is-danger em { color: #ff9a9a; }
        .more-refresh-btn:disabled { opacity: .6; cursor: progress; }

        .plugin-settings-list { display: flex; flex-direction: column; gap: 14px; }

        /* ------------------------------------------------------------
           设置 → 插件 → 搜索与筛选
           ------------------------------------------------------------ */
        .plugin-search-bar {
            display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
            margin: 0 0 12px;
        }
        .plugin-search {
            position: relative; flex: 1 1 220px; min-width: 160px;
            display: flex; align-items: center;
        }
        .plugin-search > i.ri-search-line {
            position: absolute; left: 11px; color: #8b8b8b;
            pointer-events: none; font-size: 1em;
        }
        .plugin-search input {
            width: 100%; box-sizing: border-box;
            padding: 9px 32px 9px 32px;
            background: #1c1e25; border: 1px solid #3a3d47; border-radius: 999px;
            color: #eee; font: inherit; font-size: 0.88em; outline: none;
            -webkit-appearance: none; appearance: none;
        }
        .plugin-search input:focus { border-color: var(--accent-gold, #e6c78a); }
        /* 隐藏 Safari/Chrome 自带的清除按钮，统一用自己的（样式与命中区都可控） */
        .plugin-search input::-webkit-search-cancel-button,
        .plugin-search input::-webkit-search-decoration { -webkit-appearance: none; display: none; }
        .plugin-search-clear {
            position: absolute; right: 5px; top: 50%; transform: translateY(-50%);
            width: 26px; height: 26px; display: flex; align-items: center; justify-content: center;
            padding: 0; border: 0; border-radius: 50%; background: transparent;
            color: #8b8b8b; font-size: 1.05em; cursor: pointer;
        }
        .plugin-search-clear:hover { color: var(--accent-gold, #e6c78a); }
        .plugin-search-bar select {
            flex: 0 0 auto; padding: 9px 10px;
            background: #1c1e25; border: 1px solid #3a3d47; border-radius: 9px;
            color: #eee; font: inherit; font-size: 0.85em; outline: none; cursor: pointer;
        }
        .plugin-search-bar select:focus { border-color: var(--accent-gold, #e6c78a); }
        .plugin-search-count {
            flex: 0 0 auto; font-size: 0.78em; color: #9a9a9a; white-space: nowrap;
        }
        .plugin-search-count.is-empty { color: #f0b27a; }
        .plugin-no-match {
            padding: 22px 14px; text-align: center; color: #9a9a9a;
            border: 1px dashed #4a4d57; border-radius: 10px; font-size: 0.88em; line-height: 1.7;
        }
        .plugin-no-match button {
            margin-top: 8px; padding: 5px 12px; border-radius: 8px; cursor: pointer;
            border: 1px solid rgba(230,199,138,.45); background: transparent;
            color: var(--accent-gold, #e6c78a); font: inherit; font-size: 0.92em;
        }
        /* 搜索命中的关键字高亮 */
        .plugin-card mark.plugin-hit {
            background: rgba(230,199,138,.32); color: inherit;
            border-radius: 3px; padding: 0 1px;
        }
        body.light-theme .plugin-search input,
        body.light-theme .plugin-search-bar select { background: #fff; border-color: rgba(0,0,0,.18); color: #2b2f3a; }
        body.light-theme .plugin-search > i.ri-search-line,
        body.light-theme .plugin-search-clear { color: #9b917f; }
        /* 手机端：搜索框占满一行，筛选下拉与计数另起一行 */
        @media (max-width: 560px) {
            .plugin-search-bar { gap: 6px; }
            .plugin-search { flex: 1 1 100%; }
            .plugin-search-bar select { flex: 1 1 auto; min-width: 0; }
            .plugin-search-count { flex: 0 0 auto; }
        }

        /* 实验室 · 五子棋 / 围棋 */
        body.board-game-on .chat-header,
        body.board-game-on .chat-messages,
        body.board-game-on .chat-input-area,
        body.board-game-on .chat-search-bar,
        body.board-game-on #offline-banner { display: none !important; }
        #board-game {
            position: absolute; inset: 0; z-index: 30;
            display: grid; grid-template-columns: minmax(180px, 250px) 1fr minmax(150px, 210px);
            /* ------------------------------------------------------------
               行高必须是 minmax(0, 1fr) 而不是默认的 auto。
               auto 行会被内容撑开：左栏聊天记录一多，整行就变高，
               于是 .bg-chat 的 flex:1 + min-height:0 拿不到确定高度，
               overflow-y:auto 形同虚设 —— 这就是「聊天区没有滚动条」的根因；
               同时面板被顶出 #chat-area（inset:0 + overflow 未裁剪），
               每次 render 重建棋盘时滚动位置被重置，看上去就是
               「按提示 → 棋盘自己往上跑」。行锁死为 1fr 后两者一起消失。
               ------------------------------------------------------------ */
            grid-template-rows: minmax(0, 1fr);
            height: 100%;
            overflow: hidden;
            background: #1a1c23; color: #e8e4da;
        }
        #board-game[hidden] { display: none !important; }
        /* min-height:0 —— 作为 grid 项时同样默认 min-height:auto，
           不加这一句，栏内内容仍会把整列撑高、把棋盘挤走。 */
        .bg-chat-pane, .bg-side { display: flex; flex-direction: column; gap: 10px; padding: 14px; min-width: 0; min-height: 0; overflow: hidden; }
        .bg-chat-pane { border-right: 1px solid rgba(230,199,138,.25); }
        .bg-side { border-left: 1px solid rgba(230,199,138,.25); }
        .bg-chat-pane header, .bg-side h3 { color: #e6c78a; margin: 0; font-size: 1em; flex-shrink: 0; }
        #bg-chat-form { flex-shrink: 0; }
        /* ------------------------------------------------------------
           棋桌边的聊天栏。三个要点：
             1) min-height:0 —— flex 子项默认 min-height:auto，内容一多
                就会被撑开而不是滚动，于是 overflow-y:auto 形同虚设，
                滚动条根本不出现（就是「聊天区加个滚动条」这条需求）。
             2) overscroll-behavior:contain —— 在栏内滚到底不再把滚动
                传给整页，手机上不会连带把棋盘顶走。
             3) 自带一条细滚动条样式，暗色面板上默认滚动条又粗又白很刺眼。
           ------------------------------------------------------------ */
        .bg-chat {
            flex: 1 1 auto;
            min-height: 0;
            overflow-y: auto;
            overflow-x: hidden;
            overscroll-behavior: contain;
            display: flex;
            flex-direction: column;
            gap: 8px;
            padding-right: 6px;
            margin-right: -6px;
            scrollbar-width: thin;
            scrollbar-color: rgba(230,199,138,.45) rgba(255,255,255,.06);
        }
        .bg-chat::-webkit-scrollbar { width: 8px; }
        .bg-chat::-webkit-scrollbar-track { background: rgba(255,255,255,.05); border-radius: 8px; }
        .bg-chat::-webkit-scrollbar-thumb {
            background: rgba(230,199,138,.4);
            border-radius: 8px;
            border: 2px solid transparent;
            background-clip: padding-box;
        }
        .bg-chat::-webkit-scrollbar-thumb:hover { background-color: rgba(230,199,138,.7); }
        /* 右栏按钮多起来（提示/悔棋/再开/弃权/结束数子/退出）时也要能滚 */
        .bg-side { overflow-y: auto; min-height: 0; scrollbar-width: thin; scrollbar-color: rgba(230,199,138,.35) transparent; }
        .bg-side::-webkit-scrollbar { width: 6px; }
        .bg-side::-webkit-scrollbar-thumb { background: rgba(230,199,138,.3); border-radius: 6px; }
        #board-game button:disabled { opacity: .38; cursor: not-allowed; }
        .bg-side .bg-size-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
        .bg-side .bg-size-row > span { flex: 1 1 100%; color: #9a9a9a; font-size: .76em; }
        .bg-side .bg-size-row button { padding: 5px 9px; font-size: .8em; border-radius: 7px; }
        .bg-side .bg-size-row button.on { background: rgba(230,199,138,.22); border-color: #e6c78a; color: #f3dcae; }
        #bg-finish { border-color: #4caf7d; color: #8fe0a8; }
        /* 棋盘在窄容器里可以横竖滚动，19 路也不至于挤成一团 */
        .bg-board-scroll {
            width: 100%; height: 100%; overflow: auto;
            display: flex; align-items: center; justify-content: center;
            overscroll-behavior: contain;
            -webkit-overflow-scrolling: touch;
        }
        #bg-board { flex-shrink: 0; }
        /* 19 路按 100% 宽度铺，手机上每格只剩 18px 左右，根本点不准。
           给它一个下限，让 .bg-board-scroll 横向滚动来兜底。 */
        #bg-board[data-size="19"] { width: max(min(100%, 72vh), 560px); }
        #bg-board[data-size="13"] { width: max(min(100%, 72vh), 340px); }
        .bg-line { margin: 0; padding: 7px 9px; border-radius: 10px; background: rgba(255,255,255,.05); font-size: .84em; line-height: 1.5; word-break: break-word; }
        .bg-line b { display: block; color: #e6c78a; font-size: .78em; }
        .bg-line.user { background: rgba(230,199,138,.13); }
        .bg-line.system { color: #9aa0ad; background: transparent; padding-left: 0; }
        #bg-chat-form { display: flex; gap: 6px; }
        #bg-chat-input { flex: 1; min-width: 0; border-radius: 9px; border: 1px solid rgba(230,199,138,.35); background: #11131a; color: inherit; padding: 8px; }
        #bg-chat-form button, .bg-side button {
            border: 1px solid rgba(230,199,138,.45); background: transparent; color: #e6c78a;
            border-radius: 9px; padding: 8px 10px; cursor: pointer;
        }
        .bg-side p { margin: 0; color: #b8b3a7; font-size: .82em; line-height: 1.55; }
        .bg-board-pane { display: flex; align-items: center; justify-content: center; padding: 12px; min-width: 0; min-height: 0; overflow: hidden; }

        /* ------------------------------------------------------------
           设置 → 「编辑当前对话上下文」
           ------------------------------------------------------------ */
        /* 列表项可选中：点一下选中（供「插在选中那条之前/之后」定位），
           再点一下取消。不给 cursor:pointer 用户根本不知道能点。 */
        .context-edit-list .context-item { cursor: pointer; transition: border-color .15s ease, background-color .15s ease; }
        .context-edit-list .context-item:hover { border-color: rgba(230, 199, 138, .45); }
        .context-edit-list .context-item.context-selected {
            border-color: var(--accent-gold, #e6c78a);
            background-color: rgba(230, 199, 138, .12);
            box-shadow: inset 2px 0 0 var(--accent-gold, #e6c78a);
        }
        .context-edit-list .context-item .edit-context:hover,
        .context-edit-list .context-item .del-context:hover { cursor: pointer; }

        /* 列表上方的计数行：渲染失败时它能立刻看出「条数不对」，
           不至于和「真的没消息」混为一谈。 */
        .context-count-hint {
            margin: 0 0 6px;
            font-size: 0.78em;
            color: #8f929c;
            line-height: 1.5;
        }
        .context-empty-tip {
            text-align: center;
            color: #777;
            padding: 14px 10px;
            font-size: 0.86em;
            line-height: 1.7;
        }
        /* 编辑/删除从 <i> 图标改成 <button>：
           旧写法是裸图标（font-size 1.2em + padding 0 5px），实际命中区只有
           大约 19×19px，手机上基本点不准 —— 而这两个按钮一个改消息、一个删消息，
           误触代价很高。改成 34×34 的按钮，触屏下再放到 40×40。 */
        .context-actions { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
        .context-edit-list .edit-context,
        .context-edit-list .del-context {
            display: inline-flex; align-items: center; justify-content: center;
            width: 34px; height: 34px; padding: 0;
            border: 1px solid transparent; border-radius: 8px;
            background: transparent; cursor: pointer;
            font-size: 1.05em; line-height: 1;
            transition: background-color .15s ease, border-color .15s ease, color .15s ease;
        }
        .context-edit-list .edit-context { color: #6fcf7f; }
        .context-edit-list .del-context { color: #f06b78; }
        .context-edit-list .edit-context:hover { background: rgba(111,207,127,.12); border-color: rgba(111,207,127,.35); }
        .context-edit-list .del-context:hover { background: rgba(240,107,120,.12); border-color: rgba(240,107,120,.35); }
        .context-edit-list .edit-context:active,
        .context-edit-list .del-context:active { transform: scale(.94); }
        /* 触屏设备（手机/平板）：命中区再大一圈，并取消 hover 残留 */
        @media (pointer: coarse) {
            .context-edit-list .edit-context,
            .context-edit-list .del-context { width: 40px; height: 40px; }
            .context-edit-list .context-item { padding: 6px 4px; }
        }
        /* 小屏：角色名太长会把正文挤没，给它一个上限并允许换行 */
        @media (max-width: 560px) {
            .memory-list, .context-edit-list { max-height: 46vh; padding: 6px; }
            .context-edit-list .context-item {
                align-items: flex-start;
                gap: 6px;
                font-size: 0.86em;
            }
            .context-edit-list .context-role {
                max-width: 84px;
                overflow: hidden;
                text-overflow: ellipsis;
                white-space: nowrap;
                flex-shrink: 0;
            }
            .context-edit-list .context-text { min-width: 0; }
        }
        /* 「显示更多」：分批渲染的入口。样式要和列表项区分开，
           别让用户把它当成一条消息；同时给足高度，手机上好点。 */
        .context-load-more {
            display: flex; align-items: center; justify-content: center; gap: 6px;
            width: 100%; margin-top: 8px; padding: 10px;
            border: 1px dashed rgba(230,199,138,.4); border-radius: 8px;
            background: rgba(230,199,138,.05); color: var(--accent-gold, #e6c78a);
            font: inherit; font-size: 0.84em; cursor: pointer;
            transition: background-color .15s ease, border-color .15s ease;
        }
        .context-load-more:hover { background: rgba(230,199,138,.12); border-color: rgba(230,199,138,.65); }
        .context-load-more:active { transform: scale(.99); }
        body.light-theme .context-load-more { background: rgba(230,199,138,.08); color: #8a6d2f; }
        /* 插入区里的表单元素在深色/浅色主题下都要可读 */
        .context-add-box select, .context-add-box textarea {
            background: var(--bg-tertiary, #2d303a);
            border: 1px solid var(--border-color, #333);
            color: var(--text-primary, #e0e0e0);
            border-radius: var(--radius-sm, 6px);
            padding: 7px 9px;
            font-family: inherit;
            font-size: .86em;
        }
        .context-add-box textarea:focus, .context-add-box select:focus {
            outline: none; border-color: var(--accent-gold, #e6c78a);
        }
        body.light-theme .context-add-box { border-color: rgba(0, 0, 0, .18); }
        body.light-theme .context-add-box select,
        body.light-theme .context-add-box textarea { background: #fff; color: #2b2f3a; }
        /* 存档条：显示「本局已保存」，并提供继续/放弃入口 */
        .bg-save-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
        .bg-save-row > span { flex: 1 1 100%; color: #9a9a9a; font-size: .74em; line-height: 1.5; }
        .bg-save-row button { flex: 1 1 auto; padding: 6px 8px; font-size: .8em; border-radius: 8px; }
        #bg-save.on { border-color: #4caf7d; color: #8fe0a8; }
        #bg-board { width: min(100%, 72vh); aspect-ratio: 1; }
        .bg-grid {
            display: grid;
            grid-template-columns: repeat(var(--bg-n), minmax(0, 1fr));
            grid-template-rows: repeat(var(--bg-n), minmax(0, 1fr));
            width: 100%; height: 100%;
            padding: 0;
            background: #e0ac67;
            border: 10px solid #c8924a;
            border-radius: 6px;
            overflow: visible;
        }
        .bg-cell {
            position: relative; min-width: 0; min-height: 0;
            margin: 0; padding: 0; border: 0; border-radius: 0;
            background: transparent; color: transparent;
            cursor: pointer; touch-action: manipulation;
        }
        /* 横线、竖线分开画，并且都锚定在格子正中心，再只向棋盘内侧延伸。
           这样边缘也不会把交点拉偏，棋子的中心就是线的交叉点。 */
        .bg-cell .bg-hline,
        .bg-cell .bg-vline {
            position: absolute; z-index: 0; pointer-events: none; background: #3b2717;
        }
        .bg-cell .bg-hline { top: 50%; height: 1.5px; margin-top: -.75px; }
        .bg-cell .bg-vline { left: 50%; width: 1.5px; margin-left: -.75px; }
        .bg-cell.edge-left .bg-hline { left: 50%; right: 0; }
        .bg-cell.edge-right .bg-hline { left: 0; right: 50%; }
        .bg-cell:not(.edge-left):not(.edge-right) .bg-hline { left: 0; right: 0; }
        .bg-cell.edge-top .bg-vline { top: 50%; bottom: 0; }
        .bg-cell.edge-bottom .bg-vline { top: 0; bottom: 50%; }
        .bg-cell:not(.edge-top):not(.edge-bottom) .bg-vline { top: 0; bottom: 0; }
        .bg-cell i, .bg-cell em { pointer-events: none; }
        .bg-cell em { display: none; }
        .bg-cell.star::before { content: ''; position: absolute; z-index: 1; left: 50%; top: 50%; width: 6px; height: 6px; transform: translate(-50%, -50%); border-radius: 50%; background: #3b2717; }
        .bg-cell.black, .bg-cell.white { color: transparent; }
        .bg-cell.black i, .bg-cell.white i {
            position: absolute; left: 50%; top: 50%; width: 74%; height: 74%;
            transform: translate(-50%, -50%); border-radius: 50%;
        }
        .bg-cell.black i { background: radial-gradient(circle at 35% 32%, #6d6d6d, #111 72%); }
        .bg-cell.white i { background: radial-gradient(circle at 35% 32%, #fff, #cfcfcf 74%); box-shadow: inset 0 0 0 1px rgba(0,0,0,.3); }
        .bg-cell.last i { box-shadow: inset 0 0 0 2px #d4534e; }
        .bg-cell.hint i {
            display: block; width: 46%; height: 46%;
            background: transparent; box-shadow: inset 0 0 0 3px #2f9e44;
        }
        .bg-cell.black em, .bg-cell.white em, .bg-cell.last em { display: none; }

        /* 非法落子的反馈：旧版点了非法点毫无反应，像是按钮坏了 */
        .bg-cell.illegal { animation: bgShake .42s ease; }
        .bg-cell.illegal::after {
            content: ''; position: absolute; inset: 18%; z-index: 2;
            border-radius: 50%; background: rgba(224,84,78,.55);
            box-shadow: 0 0 0 2px rgba(224,84,78,.85);
            pointer-events: none;
        }
        @keyframes bgShake {
            0%, 100% { transform: translateX(0); }
            20% { transform: translateX(-3px); }
            45% { transform: translateX(3px); }
            70% { transform: translateX(-2px); }
        }

        /* 劫争禁着点：画个小叉，让人知道这里为什么下不了 */
        .bg-cell.ko::after {
            content: '\u2716'; position: absolute; inset: 0; z-index: 2;
            display: flex; align-items: center; justify-content: center;
            color: rgba(59,39,23,.62); font-size: .7em; line-height: 1;
            font-style: normal; pointer-events: none;
        }

        /* 终局标记死子：金色叉 + 棋子压暗 */
        .bg-cell.dead i { opacity: .38; }
        .bg-cell.dead em {
            display: flex !important; position: absolute; inset: 0; z-index: 3;
            align-items: center; justify-content: center;
            color: #f3dcae; font-size: .95em; font-style: normal; font-weight: 700;
            text-shadow: 0 1px 3px rgba(0,0,0,.85); pointer-events: none;
        }
        body.board-game-on #board-game.dead-mode .bg-cell { cursor: crosshair; }

        @media (max-width: 760px) {
            /* 手机上原来是「150px 聊天 + 棋盘 + 按钮行」，棋盘被压得很小，
               19 路几乎没法点。改成棋盘优先占满，聊天栏收成可折叠的窄条。
               三行全部锁死上限：聊天行 132px、棋盘行 1fr、按钮行 auto，
               任何一行都不允许被内容撑高，否则整块面板会溢出并「往上跑」。 */
            #board-game { grid-template-columns: 1fr; grid-template-rows: minmax(96px, 132px) minmax(0, 1fr) auto; height: 100%; overflow: hidden; }
            .bg-chat-pane, .bg-side { border: 0; }
            .bg-chat-pane { padding: 8px 10px; gap: 6px; }
            .bg-board-pane { padding: 6px; }
            #bg-board { width: min(100%, 62vh); }
            .bg-side { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px 10px; max-height: 34vh; }
            .bg-side h3 { flex: 1 1 100%; font-size: .92em; }
            .bg-side p { flex: 1 1 100%; font-size: .76em; }
            .bg-side button { flex: 1 1 auto; padding: 7px 9px; font-size: .82em; white-space: nowrap; }
            .bg-side .bg-size-row > span { display: none; }
            .bg-side .bg-size-row button { flex: 0 0 auto; }
        }

        /* ============================================================
           实验室 · 森林冰火人（forest-icefire.js，默认不加载）
           ------------------------------------------------------------
           布局直接复用棋局的三栏骨架（.bg-chat-pane / .bg-board-pane /
           .bg-side / .bg-chat），只补游戏自己需要的部分：
           画布滚动容器、隐藏主聊天区、移动端三行布局。
           ============================================================ */
        body.fif-on .chat-header,
        body.fif-on .chat-messages,
        body.fif-on .chat-input-area,
        body.fif-on .chat-search-bar,
        body.fif-on #offline-banner { display: none !important; }
        #forest-icefire {
            position: absolute; inset: 0; z-index: 30;
            display: grid;
            grid-template-columns: minmax(180px, 250px) 1fr minmax(150px, 210px);
            /* 与 #board-game 同款：行高锁 minmax(0,1fr)，
               否则左栏聊天一多就把整行撑高、面板溢出。 */
            grid-template-rows: minmax(0, 1fr);
            height: 100%;
            overflow: hidden;
            background: #14161c; color: #e8e4da;
        }
        /* 画布比棋盤宽（最宽 28 格 × 34px ≈ 952px），小屏必须能横向滚，
           否则右侧的门和出口永远在屏幕外。纵向同理。 */
        .fif-canvas-scroll {
            width: 100%; height: 100%;
            overflow: auto;
            overscroll-behavior: contain;
            -webkit-overflow-scrolling: touch;
            display: flex; align-items: center; justify-content: center;
            scrollbar-width: thin;
            scrollbar-color: rgba(230,199,138,.35) transparent;
        }
        .fif-canvas-scroll::-webkit-scrollbar { width: 8px; height: 8px; }
        .fif-canvas-scroll::-webkit-scrollbar-thumb { background: rgba(230,199,138,.35); border-radius: 8px; }
        #fif-canvas {
            /* 不拉伸：保持像素比例，宽屏居中、窄屏滚动 */
            flex: 0 0 auto;
            image-rendering: pixelated;
            border-radius: 8px;
            background: #171a21;
            touch-action: pan-x pan-y;
        }
        .fif-board-pane { position: relative; }
        /* 触控：屏幕上只有一套键。左下角切换正在控谁（整块变色），
           右下角是走和跳。桌面端整块隐藏（见 JS）。 */
        .fif-touch {
            position: absolute; left: 0; right: 0; bottom: 8px;
            display: flex; justify-content: space-between; align-items: flex-end; gap: 8px;
            padding: 0 8px 0 max(8px, env(safe-area-inset-left));
            padding-right: max(8px, env(safe-area-inset-right));
            pointer-events: none; z-index: 2;
        }
        .fif-touch[hidden] { display: none; }
        .fif-who {
            pointer-events: auto; min-width: 96px; min-height: 52px; padding: 0 14px;
            border-radius: 16px; border: 2px solid transparent; color: #1a120c;
            font: inherit; font-size: .95rem; font-weight: 800; letter-spacing: .04em;
            touch-action: manipulation;
        }
        .fif-who[data-who="fire"] { background: #ff7a3c; }
        .fif-who[data-who="water"] { background: #4fb7ff; color: #062033; }
        .fif-pad { display: flex; align-items: center; gap: 8px; pointer-events: auto; }
        .fif-pad[hidden], .fif-who[hidden] { display: none; }
        .fif-pad button {
            min-width: 64px; min-height: 64px; width: 68px; height: 68px; border-radius: 18px;
            border: 2px solid transparent; color: #1a120c;
            font-size: 1.25rem; font-weight: 800;
            touch-action: none; user-select: none; -webkit-user-select: none;
        }
        .fif-pad[data-who="fire"] button { background: rgba(255,122,60,.92); }
        .fif-pad[data-who="water"] button { background: rgba(79,183,255,.92); color: #062033; }
        .fif-pad button.on { filter: brightness(1.25); transform: translateY(2px); }
        /* 棋局的表单样式是 #bg-chat-form / #bg-chat-input 这两个 id 选择器，
           冰火人用自己的 id 避免与棋局冲突，这里补上同款样式。 */
        #fif-chat-form { display: flex; gap: 6px; flex-shrink: 0; }
        #fif-chat-input {
            flex: 1; min-width: 0;
            border-radius: 9px; border: 1px solid rgba(230,199,138,.35);
            background: #11131a; color: inherit; padding: 8px;
        }
        #fif-chat-form button {
            border: 1px solid rgba(230,199,138,.45); background: transparent;
            color: #e6c78a; border-radius: 9px; padding: 8px 10px; cursor: pointer;
        }
        /* 选关条：工坊关卡一多就装不下，给横向滚动条。
           不改 .bg-size-row 本身（玩法/你控两排仍然换行），只动这一排。 */
        #fif-level-row {
            flex-wrap: nowrap;
            /* flex 子项默认 min-width:auto，会按按钮总宽撑开父栏，
               横向滚动条就永远不出现。锁成 0 才按侧栏宽度滚动。 */
            min-width: 0;
            max-width: 100%;
            overflow-x: auto;
            overflow-y: hidden;
            overscroll-behavior-x: contain;
            -webkit-overflow-scrolling: touch;
            scrollbar-width: thin;
            scrollbar-color: rgba(230,199,138,.4) transparent;
            padding-bottom: 4px;
        }
        #fif-level-row::-webkit-scrollbar { height: 6px; }
        #fif-level-row::-webkit-scrollbar-thumb { background: rgba(230,199,138,.4); border-radius: 6px; }
        #fif-level-row > span { position: sticky; left: 0; background: #1c1f27; z-index: 1; }
        #fif-level-row button { flex: 0 0 auto; }
        #fif-level-row button.fif-custom { border-style: dashed; }

        /* ============================================================
           冰火人工坊（icefire-workshop.js，默认不加载）
           ============================================================ */
        body.fifw-on { overflow: hidden; }
        #fif-workshop {
            position: fixed; inset: 0; z-index: 94000;
            display: flex; flex-direction: column;
            background: #14161c; color: #e8e4da;
            font-size: 14px;
        }
        #fif-workshop[hidden] { display: none; }
        .fifw-head { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-bottom: 1px solid #343844; }
        .fifw-head h3 { margin: 0; font-size: 1.05rem; color: #e6c78a; display: flex; align-items: center; gap: 8px; }
        .fifw-x { margin-left: auto; border: 0; background: none; color: #ddd; font-size: 1.3rem; cursor: pointer; }
        .fifw-body { flex: 1; min-height: 0; display: grid; grid-template-columns: 132px minmax(0, 1fr) 280px; }
        .fifw-tools { overflow-y: auto; padding: 10px; border-right: 1px solid #343844; display: flex; flex-direction: column; gap: 4px; }
        .fifw-tools b { margin: 8px 0 2px; color: #9a8f78; font-size: .75rem; font-weight: 600; }
        .fifw-tool { text-align: left; border: 1px solid #3c4150; background: #1d2028; color: #ddd; border-radius: 7px; padding: 5px 8px; cursor: pointer; font: inherit; font-size: .82rem; }
        .fifw-tool.on { border-color: #e6c78a; color: #e6c78a; }
        .fifw-stage { min-width: 0; min-height: 0; display: flex; flex-direction: column; padding: 10px; gap: 8px; }
        .fifw-stage-bar { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
        .fifw-stage-bar label { display: flex; align-items: center; gap: 4px; font-size: .8rem; color: #b7b3a8; }
        .fifw-stage-bar select, .fifw-stage-bar input, .fifw-side input, .fifw-side textarea, .fifw-side select {
            background: #11131a; color: #eee; border: 1px solid #454a57; border-radius: 6px; padding: 4px 6px; font: inherit;
        }
        .fifw-stage-bar input[type=number] { width: 58px; }
        .fifw-stage-bar button, .fifw-share button, .fifw-art-btns button {
            border: 1px solid rgba(230,199,138,.45); background: transparent; color: #e6c78a;
            border-radius: 7px; padding: 5px 9px; cursor: pointer; font: inherit; font-size: .8rem;
        }
        .fifw-grid-scroll { flex: 1; min-height: 0; overflow: auto; border: 1px solid #343844; border-radius: 8px; padding: 8px; background: #101218; }
        .fifw-grid { display: grid; gap: 1px; width: max-content; }
        .fifw-grid i { width: 26px; height: 26px; display: block; position: relative; background: #1a1d25; cursor: crosshair; box-sizing: border-box; }
        .fifw-grid i.sel { outline: 2px solid #fff; outline-offset: -2px; z-index: 1; }
        .fifw-grid i.bsel { outline: 2px dashed #ffd75e; outline-offset: -2px; z-index: 1; }
        .fifw-batchbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; padding: 8px 10px; border: 1px solid rgba(230,199,138,.45); border-radius: 8px; background: rgba(230,199,138,.08); }
        .fifw-batchbar[hidden] { display: none; }
        .fifw-batch-n { font-size: .8rem; color: #e6c78a; }
        .fifw-batchbar button { border: 1px solid rgba(230,199,138,.45); background: transparent; color: #e6c78a; border-radius: 7px; padding: 5px 9px; cursor: pointer; font: inherit; font-size: .8rem; }
        .fifw-batch-color { display: flex; align-items: center; gap: 6px; font-size: .8rem; color: #b7b3a8; }
        .fifw-batch-color input { width: 34px; height: 26px; padding: 0; border: 1px solid #454a57; border-radius: 6px; background: #11131a; cursor: pointer; }

        /* 缓存优化面板（AI 配置）与缓存命中率表（界面外观） */
        .co-panel { border: 1px solid #454a57; border-radius: 8px; background: #14161d; }
        .co-panel > summary { list-style: none; cursor: pointer; padding: 10px 12px; color: #e6c78a; font-size: .92em; display: flex; align-items: center; gap: 8px; }
        .co-panel > summary::-webkit-details-marker { display: none; }
        .co-panel > summary::after { content: '▸'; margin-left: auto; color: #8d8a80; transition: transform .15s; }
        .co-panel[open] > summary::after { transform: rotate(90deg); }
        .co-body { padding: 4px 12px 12px; display: flex; flex-direction: column; gap: 9px; }
        .co-hint, .co-note { font-size: .78em; color: #9aa0ad; line-height: 1.7; margin: 0; }
        .co-note { color: #6f7480; }
        .co-row { display: flex; align-items: center; gap: 9px; font-size: .85em; color: #c9c3b4; flex-wrap: wrap; }
        .co-row input[type="text"], .co-row select { background: #11131a; color: #eee; border: 1px solid #454a57; border-radius: 6px; padding: 5px 8px; font: inherit; }
        .co-stats { width: 100%; border-collapse: collapse; font-size: .82em; }
        .co-stats th, .co-stats td { border-bottom: 1px solid #343844; padding: 6px 8px; text-align: left; color: #c9c3b4; }
        .co-stats th { color: #e6c78a; font-weight: 600; }
        .co-stats-actions { margin-top: 8px; }
        #cache-stats-box .co-hint { margin: 0; }
        .fifw-grid i img { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; pointer-events: none; }
        .fifw-legend, .fifw-note, .fifw-mini, .fifw-empty { color: #8d8a80; font-size: .75rem; line-height: 1.6; margin: 0; }
        .fifw-side { overflow-y: auto; padding: 12px; border-left: 1px solid #343844; display: flex; flex-direction: column; gap: 10px; }
        .fifw-field { display: flex; flex-direction: column; gap: 4px; font-size: .8rem; color: #c9c3b4; }
        .fifw-field input, .fifw-field textarea, .fifw-field select { width: 100%; }
        .fifw-props h4 { margin: 0 0 8px; color: #e6c78a; font-size: .9rem; }
        .fifw-art { display: flex; gap: 10px; align-items: flex-start; }
        #fifw-art { width: 128px; height: 128px; background: #0d0f14; border: 1px solid #454a57; border-radius: 6px; cursor: crosshair; image-rendering: pixelated; touch-action: none; }
        .fifw-art-btns { display: flex; flex-direction: column; gap: 6px; font-size: .72rem; color: #8d8a80; }
        .fifw-share { display: flex; gap: 8px; flex-wrap: wrap; }
        @media (max-width: 860px) {
            #fif-workshop { font-size: 15px; }
            .fifw-head { padding: 10px 12px; padding-top: max(10px, env(safe-area-inset-top)); }
            /* 整页不滚：工具条钉在上面，只有地图区滚动，
               否则手指一划格子就跑出屏幕，没法连续画。 */
            .fifw-body { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden; }
            .fifw-side { max-height: 42dvh; overflow-y: auto; }
            /* 工具条横排可滑，按钮放大到手指点得中，不再挤成 150px 的一团 */
            .fifw-tools { flex-direction: row; flex-wrap: nowrap; overflow-x: auto; border-right: 0; border-bottom: 1px solid #343844; max-height: none; padding: 8px; gap: 6px; }
            .fifw-tools b { display: none; }
            .fifw-tool { flex: 0 0 auto; padding: 9px 12px; font-size: .9rem; }
            .fifw-stage { padding: 8px; }
            .fifw-stage-bar button, .fifw-share button { padding: 9px 12px; font-size: .88rem; }
            .fifw-grid i { width: 34px; height: 34px; }
            .fifw-side { border-left: 0; border-top: 1px solid #343844; min-height: 0; overflow-y: auto; padding-bottom: max(12px, env(safe-area-inset-bottom)); }
            #fifw-art { width: 160px; height: 160px; }
        }
        @media (max-width: 760px) {
            #forest-icefire {
                grid-template-columns: 1fr;
                grid-template-rows: minmax(72px, 20dvh) minmax(0, 1fr) auto;
                height: 100%;
                height: 100dvh;
            }
            #forest-icefire .bg-chat-pane, #forest-icefire .bg-side { border: 0; }
            #forest-icefire .bg-chat-pane { padding: 8px 10px; gap: 6px; }
            #forest-icefire .bg-board-pane { padding: 6px; }
            #forest-icefire .bg-side { flex-direction: row; flex-wrap: wrap; align-items: center; gap: 6px; padding: 8px 10px; max-height: 36vh; overflow-y: auto; }
            /* 窄屏侧栏改成横向换行后，选关条仍要独占一行并能横滚。
               下面那条 .bg-side button 会把按钮设成可收缩，这里压回去，
               否则关卡多了是被挤扁而不是出滚动条。 */
            #forest-icefire #fif-level-row { flex: 1 1 100%; }
            #forest-icefire #fif-level-row button { flex: 0 0 auto; }
            #forest-icefire .bg-side h3 { flex: 1 1 100%; font-size: .92em; }
            #forest-icefire .bg-side p { flex: 1 1 100%; font-size: .76em; }
            #forest-icefire .bg-side button { flex: 1 1 auto; padding: 7px 9px; font-size: .82em; white-space: nowrap; }
            #forest-icefire .bg-size-row > span { display: none; }
            #forest-icefire .bg-size-row button { flex: 0 0 auto; }
        }
        .plugin-card { border: 1px solid #3a3d47; border-radius: 12px; padding: 14px; background: rgba(255,255,255,0.03); }
        .plugin-card-header { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; }
        .plugin-card-header strong { color: #f0e6c8; font-size: 1.05em; }
        .plugin-card-header p { color: #aaa; font-size: 0.85em; margin-top: 5px; }
        .plugin-switch { color: #ddd; display: flex; align-items: center; gap: 6px; white-space: nowrap; }
        .plugin-params { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 10px; margin-top: 12px; }
        .plugin-params label { color: #bbb; font-size: 0.9em; }
        .plugin-actions { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
        .plugin-builtin-badge { color: var(--accent-gold); font-size: 0.85em; }
        .chat-plugin-window { position: absolute; right: 18px; bottom: 96px; z-index: 35; min-width: 120px; min-height: 120px; max-width: calc(100% - 36px); max-height: calc(100% - 128px); background: #15171d; border: 1px solid rgba(230,199,138,0.55); border-radius: 12px; overflow: hidden; box-shadow: 0 14px 40px rgba(0,0,0,0.45); }
        .chat-plugin-window.dragging { user-select: none; }
        .chat-plugin-window-header { height: 36px; cursor: move; display: flex; align-items: center; justify-content: space-between; padding: 0 10px; color: #f0e6c8; background: rgba(230,199,138,0.12); border-bottom: 1px solid rgba(230,199,138,0.25); }
        .chat-plugin-window-close { background: transparent; border: none; color: #ddd; cursor: pointer; font-size: 1.1em; }
        .chat-plugin-window iframe { width: 100%; height: calc(100% - 36px); border: 0; background: #fff; }

.search-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    color: var(--accent-gold);
    font-size: 0.86em;
    font-weight: 700;
    margin: 6px 0 8px;
    padding: 6px 4px;
    border-bottom: 1px solid rgba(var(--accent-gold-rgb), 0.22);
}

.search-section-toggle {
    width: 26px;
    height: 26px;
    border: 1px solid rgba(var(--accent-gold-rgb), 0.35);
    border-radius: 50%;
    background: rgba(var(--accent-gold-rgb), 0.08);
    color: var(--accent-gold);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all var(--transition-fast);
}

.search-section-toggle:hover {
    background: rgba(var(--accent-gold-rgb), 0.18);
    transform: scale(1.06);
}

body.light-theme .search-section-header {
    border-bottom-color: rgba(var(--accent-gold-rgb), 0.28);
}

/* ========================================
   动效模式：兼容模式 / ？？？模式
   ======================================== */
body.compatibility-mode,
body.compatibility-mode *,
body.compatibility-mode *::before,
body.compatibility-mode *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
}

/* ============================================================
   设置 → 知识库 → 网页抓取状态行
   ------------------------------------------------------------
   抓取过程分好几个阶段（下载 HTML → 提取正文 → 分块 → 逐块向量化），
   以前整个过程一个字都不提示，长网页要等好几分钟，用户以为卡死了。
   ============================================================ */
.kb-fetch-status {
    margin: 10px 0 0;
    font-size: 0.82em;
    color: #9a9a9a;
    line-height: 1.6;
    min-height: 1.2em;
    word-break: break-word;
}
.kb-fetch-status:empty { display: none; }
.kb-fetch-status.is-busy { color: #8fd8ff; }
.kb-fetch-status.is-ok { color: #8fe0a8; }
.kb-fetch-status.is-error { color: #f0a878; }
.kb-fetch-status i { margin-right: 4px; }
.kb-fetch-tip {
    margin: 6px 0 0;
    font-size: 0.76em;
    color: #7e818c;
    line-height: 1.6;
}
body.light-theme .kb-fetch-tip { color: #8a8578; }

/* ========================================
   ？？？模式的样式已整体搬到 mystery-motion.css
   ----------------------------------------
   旧实现是一堆**无限循环**动画（背景渐变位移 + hue-rotate、每个头像转圈、
   每个气泡扫光、每个 hover 项脉冲），结果是：
     · 常驻动画持续触发合成层重绘，低端机与手机直接掉帧；
     · hue-rotate 把整页染成青紫色，配磨砂后观感很脏。
   新实现改为「播一次就停」的弹性动效，只动 transform / opacity，
   静止时不占用 GPU。相关规则与 @keyframes 全部定义在 mystery-motion.css，
   这里不再保留任何 mystery-mode 规则，避免两套样式互相覆盖。
   ======================================== */

/* ============================================================
   游戏通用 · 专注模式（全屏 / 收起左右两栏）
   ------------------------------------------------------------
   棋局（board-games.js）与森林冰火人（forest-icefire.js）共用同一套
   三栏骨架，这里统一加三个状态类：
     .hide-chat  收起左侧「边玩边聊」栏
     .hide-side  收起右侧操作栏
     .game-full  整块铺满视口（自动收起两栏）
   选择器写成 #id.class：特异性高于文件上方的窄屏媒体查询（只写了 #id），
   手机上同样生效。
   ============================================================ */

.game-focus-bar {
    position: absolute; top: 8px; right: 8px; z-index: 6;
    display: flex; gap: 6px;
}
.game-focus-bar button {
    display: inline-flex; align-items: center; gap: 5px; height: 32px; padding: 0 9px;
    border: 1px solid rgba(230, 199, 138, .35); border-radius: 9px;
    background: rgba(20, 22, 28, .72); color: #e6c78a;
    font: inherit; font-size: .78rem; cursor: pointer; white-space: nowrap;
}
.game-focus-bar button:hover { border-color: rgba(230, 199, 138, .8); }
.game-focus-bar button.on { background: rgba(230, 199, 138, .88); color: #1a120c; border-color: transparent; }
.game-focus-bar button span { display: none; }
@media (min-width: 900px) { .game-focus-bar button span { display: inline; } }

#board-game.hide-chat,
#forest-icefire.hide-chat { grid-template-columns: minmax(0, 1fr) minmax(150px, 210px); }
#board-game.hide-side,
#forest-icefire.hide-side { grid-template-columns: minmax(180px, 250px) minmax(0, 1fr); }
#board-game.hide-chat.hide-side,
#forest-icefire.hide-chat.hide-side { grid-template-columns: minmax(0, 1fr); }

#board-game.game-full,
#forest-icefire.game-full {
    position: fixed; inset: 0; z-index: 92000;
    grid-template-columns: minmax(0, 1fr);
    background: #14161c;
}
#board-game.game-full .bg-chat-pane, #board-game.game-full .bg-side,
#forest-icefire.game-full .bg-chat-pane, #forest-icefire.game-full .bg-side { display: none; }
#board-game.game-full .bg-board-scroll { width: 100%; height: 100%; }

/* ============================================================
   森林冰火人 · 手机端
   ------------------------------------------------------------
   竖屏一行放不下 24~28 格宽的关卡（一格 34px，满宽约 820~950px），
   硬压只会糊成一片：竖屏时先给一层「把手机横过来」的提示（可跳过），
   横过来后左右两栏默认收起，画布独占屏幕。
   触屏按键重做：左下两个圆形方向键、右下大号跳跃键、中间切换操控角色。
   ============================================================ */

.fif-rotate-gate {
    position: absolute; inset: 0; z-index: 9;
    display: none; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
    padding: 24px; text-align: center;
    background: rgba(12, 13, 18, .94); color: #e8e4da;
}
.fif-rotate-gate.show { display: flex; }
.fif-rotate-gate i { font-size: 3rem; color: #e6c78a; }
.fif-rotate-gate b { font-size: 1.05rem; }
.fif-rotate-gate p { margin: 0; max-width: 340px; font-size: .82rem; line-height: 1.7; color: #b8b3a7; }
.fif-rotate-gate button {
    margin-top: 8px; padding: 10px 18px; border-radius: 10px;
    border: 1px solid rgba(230, 199, 138, .5); background: transparent; color: #e6c78a;
    font: inherit; font-size: .88rem; cursor: pointer;
}

.fif-touch {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 4;
    display: flex; align-items: flex-end; justify-content: space-between; gap: 10px;
    padding: 0 12px max(12px, env(safe-area-inset-bottom));
    pointer-events: none;
}
.fif-touch[hidden] { display: none; }
.fif-keys { display: flex; gap: 10px; pointer-events: auto; }
.fif-key {
    pointer-events: auto;
    width: 66px; height: 66px; border-radius: 50%;
    display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
    border: 2px solid rgba(255, 255, 255, .26);
    background: rgba(18, 20, 26, .5); color: #f2efe8; font: inherit;
    touch-action: none; user-select: none; -webkit-user-select: none;
    -webkit-tap-highlight-color: transparent;
    transition: transform .08s ease, filter .12s ease;
}
.fif-key i { font-size: 1.5rem; line-height: 1; pointer-events: none; }
.fif-key span { font-size: .66rem; letter-spacing: .08em; margin-top: 1px; pointer-events: none; }
.fif-key-jump { width: 86px; height: 86px; }
.fif-key-jump i { font-size: 1.9rem; }
.fif-key.on { transform: scale(.93); filter: brightness(1.55); }
.fif-touch[data-who="fire"] .fif-key { background: rgba(118, 58, 30, .62); border-color: rgba(230, 199, 138, .4); }
.fif-touch[data-who="water"] .fif-key { background: rgba(32, 56, 82, .62); border-color: rgba(150, 190, 220, .34); }
.fif-touch .fif-who {
    pointer-events: auto; align-self: flex-end; margin-bottom: 6px;
    min-height: 42px; padding: 0 14px; border-radius: 21px;
    border: 1px solid rgba(255, 255, 255, .3); background: rgba(18, 20, 26, .6);
    color: #f2efe8; font: inherit; font-size: .82rem; font-weight: 700;
    touch-action: manipulation;
}
.fif-touch .fif-who[data-who="fire"] { border-color: rgba(230, 199, 138, .5); color: #e6c78a; }
.fif-touch .fif-who[data-who="water"] { border-color: rgba(150, 190, 220, .5); color: #c3d8e6; }

/* 手机横屏：又矮又宽。按键缩一号；左右两栏压窄并强制回竖排
   （窄屏媒体查询把它们改成了横向换行，矮屏下那样会吃掉画布高度）。 */
@media (orientation: landscape) and (max-height: 540px) {
    #forest-icefire {
        grid-template-columns: minmax(120px, 168px) minmax(0, 1fr) minmax(120px, 168px);
        grid-template-rows: minmax(0, 1fr);
        height: 100%;
    }
    #forest-icefire .bg-chat-pane { padding: 8px 10px; }
    #forest-icefire .bg-side {
        flex-direction: column; flex-wrap: nowrap; align-items: stretch;
        max-height: none; overflow-y: auto; padding: 8px 10px;
    }
    #forest-icefire .bg-side h3 { font-size: .88em; }
    #forest-icefire .bg-side p { font-size: .72em; }
    #forest-icefire .bg-side button { flex: 0 0 auto; padding: 6px 8px; font-size: .78em; }
    #forest-icefire #fif-level-row { flex: 0 0 auto; }
    .fif-key { width: 54px; height: 54px; }
    .fif-key i { font-size: 1.25rem; }
    .fif-key-jump { width: 68px; height: 68px; }
    .fif-key-jump i { font-size: 1.55rem; }
    .fif-touch { padding: 0 10px max(8px, env(safe-area-inset-bottom)); }
    .fif-touch .fif-who { min-height: 34px; font-size: .74rem; }
}

/* 工坊 / 棋盘面板需要定位上下文，专注工具条才能钉在棋盘右上角
   （棋局的 .bg-board-pane 原本是 flex 居中，没有 position）。 */
#board-game .bg-board-pane { position: relative; }

/* ---------- 冰火人工坊 · 角色外观 ---------- */
.fifw-chars { display: flex; flex-direction: column; gap: 10px; }
.fifw-charcard { border: 1px solid #3c4150; border-radius: 9px; padding: 8px 10px; background: #1a1d25; }
.fifw-charhead { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.fifw-charhead b { color: #e8e4da; font-size: .86rem; }
.fifw-charhead select { margin-left: auto; background: #11131a; color: #eee; border: 1px solid #454a57; border-radius: 6px; padding: 3px 6px; font: inherit; font-size: .78rem; }
.fifw-artgroup[hidden] { display: none; }
.fifw-artpart { border-top: 1px dashed #333846; padding-top: 7px; margin-top: 7px; }
.fifw-artname { display: block; color: #b7b3a8; font-size: .78rem; margin-bottom: 5px; }
.fifw-artframe { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 6px; }
.fifw-artpick { display: inline-flex; align-items: center; gap: 4px; font-size: .74rem; color: #c9c3b4;
    border: 1px solid rgba(230, 199, 138, .35); border-radius: 6px; padding: 4px 7px; cursor: pointer; white-space: nowrap; }
.fifw-artpick input { display: none; }
.fifw-artthumb { position: relative; display: inline-block; width: 34px; height: 34px; }
.fifw-artthumb img { width: 100%; height: 100%; object-fit: contain; background: #0d0f14;
    border: 1px solid #454a57; border-radius: 4px; image-rendering: pixelated; }
.fifw-artthumb button { position: absolute; right: -5px; top: -5px; width: 16px; height: 16px; padding: 0;
    line-height: 1; border-radius: 50%; border: 0; background: #7a3232; color: #fff; font-size: 12px; cursor: pointer; }
.fifw-artempty { font-size: .72rem; color: #6f6c64; }
.fifw-artclear { width: 100%; margin-top: 8px; border: 1px solid rgba(200, 90, 90, .45); background: transparent;
    color: #c98a8a; border-radius: 7px; padding: 5px 8px; cursor: pointer; font: inherit; font-size: .78rem; }
@media (max-width: 860px) {
    .fifw-artpick { padding: 8px 10px; font-size: .84rem; }
    .fifw-artclear { padding: 9px 10px; font-size: .86rem; }
}

/* 收起某一栏时必须把该栏移出 grid 流：
   否则少了一列定义后，它会被 grid 放进自动创建的隐式列，把棋盘挤回去。 */
#board-game.hide-chat .bg-chat-pane,
#forest-icefire.hide-chat .bg-chat-pane { display: none; }
#board-game.hide-side .bg-side,
#forest-icefire.hide-side .bg-side { display: none; }

/* 竖屏提示里的主按钮：一键全屏 + 尝试锁横屏 */
#fif-rotate-go {
    border-color: transparent !important;
    background: #e6c78a !important;
    color: #1a120c !important;
    font-weight: 700;
}
#fif-rotate-go + button { margin-top: 0; }

/* 全屏后视口变高，棋盘 / 画布跟着放大，否则全屏等于白让出两栏的空间 */
#board-game.game-full #bg-board { width: min(100%, 88vh); }
#board-game.game-full .bg-board-scroll { padding: 4px; }
#forest-icefire.game-full .fif-canvas-scroll { padding: 4px; }

/* ============================================================
   棋盘 / 游戏画面顶部工具条：改成实体栏，不再浮动
   ------------------------------------------------------------
   之前用 position:absolute 浮在 .bg-board-pane 右上角。浮动定位依赖
   父级是不是「定位祖先」：一旦 .bg-board-pane 丢了 position:relative，
   它就会参照整个 #board-game 定位，跑到最右上角、压在右侧操作栏上，
   看上去就是「全屏按钮飞了」。做成占位的 flex 一行，怎么布局都稳。
   ============================================================ */
.game-focus-bar {
    flex: 0 0 auto;
    position: static;
    display: flex; justify-content: flex-end; align-items: center;
    gap: 6px; flex-wrap: wrap;
}

/* 面板改成纵向排列：工具条在上，棋盘 / 画布吃掉剩下的高度 */
#board-game .bg-board-pane,
#forest-icefire .bg-board-pane {
    flex-direction: column; align-items: stretch; justify-content: flex-start;
    gap: 6px;
}
/* height:100% 在纵向 flex 里会让滚动区连同工具条一起溢出，必须换成 flex 伸缩 */
#board-game .bg-board-scroll,
#forest-icefire .fif-canvas-scroll {
    width: auto; height: auto;
    flex: 1 1 auto; min-height: 0; min-width: 0;
}

/* ------------------------------------------------------------
   工具条按钮：跟站内的 btn-outline / 金色强调一致，不用鲜蓝鲜紫
   ------------------------------------------------------------ */
.game-focus-bar button {
    display: inline-flex; align-items: center; gap: 5px;
    height: 30px; padding: 0 10px;
    border: 1px solid rgba(230, 199, 138, .35);
    border-radius: 8px;
    background: rgba(255, 255, 255, .04);
    color: #e6c78a;
    font: inherit; font-size: .78rem;
    cursor: pointer; white-space: nowrap;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.game-focus-bar button:hover { border-color: rgba(230, 199, 138, .75); background: rgba(230, 199, 138, .1); }
.game-focus-bar button.on {
    background: rgba(230, 199, 138, .85); color: #1a120c;
    border-color: transparent; font-weight: 700;
}
.game-focus-bar button span { display: none; }
@media (min-width: 820px) { .game-focus-bar button span { display: inline; } }

/* ============================================================
   原生控件统一皮肤（干掉浏览器默认的亮蓝 / 紫）
   ------------------------------------------------------------
   站内主题是深灰 + 金色，但浏览器原生控件的默认强调色是亮蓝：
   复选框打勾、单选框、滑杆滑块、输入框聚焦光圈、下拉面板、
   颜色选择器、数字微调箭头，在暗色面板上全是那套「雷霆蓝紫」。
   这里统一改成站内金色，并让系统按暗色绘制未能自绘的原生部件。
   ============================================================ */

html { color-scheme: dark; }
/* 浅色主题的用户不该被强制暗色原生部件 */
html.light-theme, body.light-theme, html:has(body.light-theme) { color-scheme: light; }

/* 复选框 / 单选框 / 滑杆 / 进度条：都用金色，不再用系统蓝 */
input[type="checkbox"],
input[type="radio"],
input[type="range"],
progress, meter { accent-color: var(--accent-gold, #e6c78a); }
input[type="checkbox"], input[type="radio"] { cursor: pointer; }
input[type="range"] { cursor: pointer; }

/* 聚焦光圈：默认那圈高亮蓝换成低饱和金色 */
:focus-visible { outline: 2px solid rgba(230, 199, 138, .7); outline-offset: 2px; }
input:focus, textarea:focus, select:focus { outline: none; }
input:focus-visible, textarea:focus-visible, select:focus-visible {
    outline: 2px solid rgba(230, 199, 138, .55);
    outline-offset: 1px;
}

/* 原生下拉：暗底 + 金色描边 */
select {
    background-color: #1c1f27;
    color: #e6e3dc;
    border: 1px solid rgba(230, 199, 138, .26);
    border-radius: 8px;
    padding: 6px 8px;
    font: inherit;
    cursor: pointer;
}
select:hover { border-color: rgba(230, 199, 138, .5); }
select option { background-color: #1c1f27; color: #e6e3dc; }

/* 颜色选择器：去掉原生凸起边框，压成圆角色块 */
input[type="color"] {
    -webkit-appearance: none; appearance: none;
    width: 44px; height: 26px; padding: 0;
    border: 1px solid rgba(230, 199, 138, .26); border-radius: 7px;
    background: #1c1f27; cursor: pointer;
}
input[type="color"]::-webkit-color-swatch-wrapper { padding: 3px; }
input[type="color"]::-webkit-color-swatch { border: 0; border-radius: 4px; }
input[type="color"]::-moz-color-swatch { border: 0; border-radius: 4px; }

/* 文件选择的原生按钮 */
input[type="file"] { color: #b8b3a7; }
input[type="file"]::file-selector-button {
    margin-right: 8px; padding: 5px 10px;
    border: 1px solid rgba(230, 199, 138, .45); border-radius: 8px;
    background: rgba(230, 199, 138, .12); color: #e6c78a;
    font: inherit; font-size: .92em; cursor: pointer;
}
input[type="file"]::file-selector-button:hover { background: rgba(230, 199, 138, .22); }

/* 数字输入的微调箭头：默认在暗底上几乎看不见，调亮一点 */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button { opacity: .5; }

/* 滚动条兜底：暗色页面里不再突然冒出一条系统白条 */
* { scrollbar-color: rgba(230, 199, 138, .32) transparent; }

/* ============================================================
   裸露的文件选择框（没有 hidden 的那几个）
   ------------------------------------------------------------
   聊天背景 / 3D 模型 / ComfyUI workflow / 角色导入这几处是直接把
   <input type="file"> 摆在面板上的，浏览器默认外观是白底 + 系统蓝按钮，
   和暗色面板格格不入。统一成站内的「虚线导入条」。
   ============================================================ */
input[type="file"].file-input-styled {
    display: block; width: 100%; max-width: 100%;
    box-sizing: border-box;
    padding: 8px 10px;
    background: #1c1f27;
    color: #cfcabd;
    border: 1px dashed rgba(230, 199, 138, .32);
    border-radius: 9px;
    font: inherit; font-size: .88em;
    cursor: pointer;
    transition: border-color .15s ease;
}
input[type="file"].file-input-styled:hover { border-color: rgba(230, 199, 138, .6); }
input[type="file"].file-input-styled::file-selector-button {
    margin-right: 10px; padding: 6px 12px;
    border: 1px solid rgba(230, 199, 138, .5); border-radius: 7px;
    background: rgba(230, 199, 138, .14); color: #e6c78a;
    font: inherit; font-size: .95em; cursor: pointer;
}
input[type="file"].file-input-styled::file-selector-button:hover { background: rgba(230, 199, 138, .26); }

/* ------------------------------------------------------------
   测试连接按钮 / 测试结果文字
   原来用的是纯蓝 #2196F3 与鲜绿鲜红，在深色面板里就是那套「雷霆蓝」。
   测试是次要操作，降成灰蓝；结果文字也统一降低饱和度。
   ------------------------------------------------------------ */
.btn-test { background-color: #333c4a; color: #cfd6e2; }
.btn-test:hover { background-color: #3f4a5b; }
.test-result.success { color: #7fc79a; }
.test-result.error { color: #d98a8a; }
.test-result.info { color: #9db4cc; }
.test-result.warning { color: #d9b478; }

/* 「上下文压缩器」入口图标原来是亮蓝，统一到站内暗金 */
.icon-btn.ctx-compress-entry { color: #d8c08a; }
.icon-btn.ctx-compress-entry.active {
    background: rgba(230, 199, 138, .16);
    box-shadow: 0 0 0 1px rgba(230, 199, 138, .38) inset;
}

/* ============================================================
   分组拖动排序（长按分组标题整组拖动）
   main.js 的 enableGroupReorder 负责手势，这里只负责外观。
   ============================================================ */
.friend-group-header .group-title { display: flex; align-items: center; min-width: 0; }
/* 折叠时只旋转文件夹图标：旧规则 .friend-group-header i 会把
   「⋯」按钮与拖动手柄的图标一起转 90°，看着像坏掉。 */
.friend-group-header.collapsed .group-title i { transform: rotate(-90deg); }
.friend-group-header .group-menu-btn,
.friend-group-header .group-drag-hint {
    display: inline-flex; align-items: center; justify-content: center;
    width: 26px; height: 26px; margin-left: 6px; padding: 0;
    border: 0; background: transparent; color: inherit;
    border-radius: 6px; cursor: pointer; font-size: .95em; opacity: .6;
}
.friend-group-header .group-drag-hint { margin-left: 2px; cursor: grab; }
.friend-group-header .group-menu-btn:hover,
.friend-group-header .group-drag-hint:hover { opacity: 1; background: rgba(230,199,138,.14); color: var(--accent-gold); }
.friend-group-header .group-menu-btn i,
.friend-group-header .group-drag-hint i { transform: none !important; margin-right: 0; }
.friend-group-header.reordering-group {
    opacity: .6; outline: 1px dashed var(--accent-gold);
    background-color: rgba(230, 199, 138, .12); cursor: grabbing;
}
.friend-group-header.reordering-group * { cursor: grabbing; }
@media (pointer: coarse) { .friend-group-header { touch-action: pan-y; } }

/* ============================================================
   扩展功能行：可收起 / 展开
   ------------------------------------------------------------
   旧样式靠 ::before 写死「扩展功能」标题，按钮一多就占满侧边栏。
   现在标题本身是一个开关按钮，点一下把按钮区收起来（状态记在 localStorage）。
   这一行位于「添加好友 / 设置」那一行之上，收起后只剩一行标题。
   ============================================================ */
.sidebar-tools { flex-direction: column; align-items: stretch; }
.sidebar-tools::before { content: none; }
.sidebar-tools-toggle {
    display: flex; align-items: center; gap: 6px;
    width: 100%; padding: 4px 2px; border: 0; background: transparent;
    color: var(--text-muted); font-size: .68em; letter-spacing: .06em;
    text-align: left; cursor: pointer;
}
.sidebar-tools-toggle:hover { color: var(--accent-gold); }
.sidebar-tools-toggle .st-chevron { margin-left: auto; transition: transform .2s ease; }
.sidebar-tools.collapsed .sidebar-tools-toggle .st-chevron { transform: rotate(-90deg); }
.sidebar-tools-body { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.sidebar-tools.collapsed .sidebar-tools-body { display: none; }
.sidebar-tools.collapsed { border-top-color: transparent; padding-top: 4px; }

/* 表情面板里的批量导入入口 */
.emoji-item.sticker-batch-item { color: #9fd3ff; }

/* ============================================================
   模型思考过程（reasoning_content）
   ------------------------------------------------------------
   推理模型把思考内容单独返回（reasoning_content 字段），这里渲染成
   气泡上方的可折叠块：标题「已思考（用时 N 秒）」+ 展开后的思考正文。
   正文限高并内部滚动 —— 思考动辄上千字，不限制会把聊天区顶得没法用。
   ============================================================ */
.reasoning-block {
    margin: 2px 0 6px;
    border: 1px solid rgba(140, 170, 220, .28);
    border-radius: var(--radius-md, 8px);
    background: rgba(120, 150, 200, .08);
    max-width: 100%;
    overflow: hidden;
}
.reasoning-head {
    display: flex; align-items: center; gap: 6px; width: 100%;
    padding: 6px 10px; border: 0; background: transparent;
    color: #9fb6d4; font: inherit; font-size: .82em; text-align: left; cursor: pointer;
}
.reasoning-head:hover { color: var(--accent-gold); }
.reasoning-head .ri-sparkling-2-line { flex: 0 0 auto; }
.reasoning-title { flex: 1 1 auto; min-width: 0; }
.reasoning-chevron { flex: 0 0 auto; transition: transform .2s ease; }
.reasoning-block.collapsed .reasoning-chevron { transform: rotate(-90deg); }
.reasoning-body {
    padding: 0 10px 9px;
    color: #a9b6c7;
    font-size: .84em;
    line-height: 1.7;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 260px;
    overflow-y: auto;
    overscroll-behavior: contain;
}
.reasoning-block.collapsed .reasoning-body { display: none; }
.reasoning-block.streaming { border-style: dashed; }
.reasoning-block.streaming .reasoning-title { color: #cbbfa0; }
.reasoning-body::-webkit-scrollbar { width: 6px; }
.reasoning-body::-webkit-scrollbar-thumb { background: rgba(255,255,255,.25); border-radius: 3px; }
/* 手机上思考块更矮一点，避免占满整屏 */
@media (max-width: 600px) {
    .reasoning-body { max-height: 200px; font-size: .86em; }
}
body.light-theme .reasoning-block { background: #f4f6fb; border-color: #ccd6e6; }
body.light-theme .reasoning-head { color: #5a6b85; }
body.light-theme .reasoning-body { color: #4a5568; }

/* ====== vn-mode.css ====== */
/* ========================================
   视觉小说模式 (Visual Novel Mode) - Galgame 样式
   舞台覆盖「消息区」，底部保留真实输入框
   ======================================== */

/* ---------- 变量与基础 ---------- */
.vn-stage {
    --vn-box-h: 150px;
    --vn-input-h: 96px;
    --vn-top-h: 54px;
    /* 纵向尺寸单位：默认 1vh；由 JS（ResizeObserver 盯舞台实际高度）改写为
       「舞台高度 / 100」的像素值。移动端软键盘弹出时布局视口/容器被压扁，
       而 1vh 在 iOS 上不随键盘缩小 —— 正文/选项/图片若按 vh 限高会比舞台还高，
       对话框顶部被裁、输入区被键盘盖住。统一改用 --vn-vh 后，
       键盘一开，舞台变矮，各处限高自动收窄，界面整体让位给键盘。 */
    --vn-vh: 1vh;
    --vn-gold: #e6c78a;
    --vn-line: rgba(255,255,255,.14);
    --vn-ink: #0a0c14;
    --vn-em-ink: #12141c;
    --vn-text: #f3f4f7;
    --vn-shadow: 0 -10px 40px rgba(0,0,0,.55);
}

/* 顶部切换按钮（聊天头部） */
#vn-toggle-btn {
    width: 30px; height: 30px; font-size: .95em;
    border-color: rgba(230,199,138,.4);
    color: var(--vn-gold);
}
#vn-toggle-btn.active {
    background: rgba(230,199,138,.2);
    border-color: var(--vn-gold);
    color: #fff;
    box-shadow: 0 0 10px rgba(230,199,138,.45);
}

/* ---------- 舞台：只压住消息区，输入框仍可用 ---------- */
.vn-stage {
    position: absolute;
    left: 0; right: 0; top: 0;
    bottom: var(--vn-input-h, 84px);
    z-index: 4;
    overflow: hidden;
    background: var(--vn-ink);
    isolation: isolate;
    outline: none;
    opacity: 1;
    transition: opacity .26s ease, bottom .26s ease;
}
.vn-stage[hidden] { display: none !important; }
/* 点舞台 = 推进台词，所以不能让它顺手把整段对白选成蓝色；回顾面板里的文字仍可复制 */
body.vn-active .vn-stage { user-select: none; -webkit-user-select: none; }
body.vn-active .vn-stage .vn-log-list,
body.vn-active .vn-stage .vn-media,
body.vn-active .vn-stage .vn-text { user-select: text; -webkit-user-select: text; }
/* 纯观赏 / 截图模式：只留背景与立绘。
   必须一起落 visibility:hidden —— 光靠 opacity:0 元素仍会挡住点击与滚轮，
   会出现「界面上看起来隐藏了，可点哪都没反应」的幽灵热区。 */
.vn-stage.ui-hidden .vn-stage-top,
.vn-stage.ui-hidden .vn-dialogue-box,
.vn-stage.ui-hidden .vn-hint,
.vn-stage.ui-hidden .vn-log-panel,
.vn-stage.ui-hidden .vn-em-pop {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .3s ease, visibility 0s linear .3s;
}
/* 截图模式：舞台接管整个聊天区（不再给输入框与头部让位），并淡出 App 外壳。
   top 需要 !important：非全屏时 JS 会写行内 top 去避开聊天头部。 */
body.vn-shot .vn-stage { top: 0 !important; bottom: 0; }
body.vn-shot .chat-header,
body.vn-shot .disclaimer-text { visibility: hidden; opacity: 0; transition: opacity .26s ease, visibility 0s linear .26s; }
body.vn-shot .chat-input-area { visibility: hidden; }
body.vn-shot #vn-fs-input-host { opacity: 0; pointer-events: none; }
/* 舞台右下角留一个极小的恢复提示，避免用户以为「界面卡死了」 */
.vn-shot-tip {
    position: absolute;
    left: 50%; bottom: 18px;
    transform: translateX(-50%);
    z-index: 6;
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 12px;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,.1);
    background: rgba(8,9,14,.42);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    color: rgba(255,255,255,.55);
    font-size: .72em;
    letter-spacing: .06em;
    opacity: 0;
    pointer-events: none;
    transition: opacity .3s ease;
}
.vn-stage.shot-mode .vn-shot-tip { opacity: .9; }
.vn-stage.vn-enter { opacity: 0; }
.vn-stage.vn-leave { opacity: 0; pointer-events: none; }
.vn-stage.vn-enter .vn-dialogue-box { transform: translateY(18px); opacity: 0; }
/* 入场时立绘与顶栏各自带一点位移，切换模式不再是「啪」地一下出现。
   注意不要给 .vn-bg-layer 改 transform：Ken Burns 用它做 22s 缓推，
   入场样式一旦覆盖就会和长镜头动画抢过渡时长。 */
.vn-stage.vn-enter .vn-character-wrap { opacity: 0; }
.vn-stage.vn-enter .vn-stage-top .vn-chip { opacity: 0; transform: translateY(-6px); }

/* ---------- 背景（双层交叉淡入 + Ken Burns） ---------- */
.vn-bg-layer {
    position: absolute; inset: 0;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    opacity: 0;
    transform: scale(1.045);
    transition: opacity .75s ease, transform .75s ease;
    will-change: opacity, transform;
}
.vn-bg-layer.is-active {
    opacity: 1;
    filter: brightness(var(--vn-bg-dim, .82)) blur(var(--vn-bg-blur, 0));
}
.vn-stage.kenburns .vn-bg-layer.is-active {
    transform: scale(1.13) translate3d(-1.4%, -1%, 0);
    transition: opacity .75s ease, transform 22s linear;
}
.vn-bg-layer.vn-bg-fallback {
    opacity: 1;
    background-image: none !important;
    background:
        radial-gradient(120% 90% at 50% 8%, #2a2f45 0%, #171a26 55%, #0b0d15 100%);
}
.vn-vignette {
    position: absolute; inset: 0; pointer-events: none;
    background:
        linear-gradient(180deg, rgba(6,8,14,.5) 0%, rgba(6,8,14,0) 22%, rgba(6,8,14,0) 46%, rgba(6,8,14,.62) 100%),
        radial-gradient(125% 105% at 50% 45%, rgba(0,0,0,0) 52%, rgba(0,0,0,.55) 100%);
    z-index: 1;
}
/* 情绪氛围光：随情绪切换的一层极淡染色（无需用户上传素材） */
.vn-mood {
    position: absolute; inset: 0; pointer-events: none;
    z-index: 1;
    opacity: 0;
    background-repeat: no-repeat;
    background-size: 100% 100%;
    background-position: center bottom;
    transition: opacity .9s ease;
    mix-blend-mode: screen;
}
.vn-mood.on { opacity: 1; }
body.light-theme .vn-mood { mix-blend-mode: multiply; }
body.light-theme .vn-mood.on { opacity: .55; }

/* ---------- 立绘 ---------- */
.vn-character-wrap {
    position: absolute;
    left: 0; right: 0;
    top: var(--vn-top-h);
    bottom: calc(var(--vn-box-h) + 10px);
    z-index: 2;
    display: flex;
    align-items: flex-end;
    pointer-events: none;
    transition: bottom .25s ease, opacity .34s ease;
}
.vn-character-wrap[data-position="left"]   { justify-content: flex-start; padding-left: clamp(6px, 6vw, 130px); }
.vn-character-wrap[data-position="center"] { justify-content: center; }
.vn-character-wrap[data-position="right"]  { justify-content: flex-end; padding-right: clamp(6px, 6vw, 130px); }

.vn-character {
    height: 100%;
    width: auto;
    max-width: 62%;
    object-fit: contain;
    object-position: bottom center;
    filter: drop-shadow(0 20px 34px rgba(0,0,0,.6));
    transform-origin: bottom center;
    transform: translate3d(0, var(--vn-char-y, 0px), 0) scale(var(--vn-char-scale, 1));
    opacity: 1;
    transition: opacity .3s ease, transform .38s cubic-bezier(.2,.8,.2,1), filter .3s;
}
.vn-character.hidden-char { opacity: 0; transform: translate3d(0, 14px, 0) scale(.988); }
.vn-character.switching   { opacity: 0; transform: translate3d(0, 6px, 0) scale(.995); }
/* 情绪切换后的「落位」动势：轻微上浮 + 透明度补一帧，让换表情可被察觉 */
.vn-character.vn-char-in { animation: vnCharIn .34s cubic-bezier(.2,.8,.2,1); }
@keyframes vnCharIn {
    from { opacity: 0; transform: translate3d(0, calc(var(--vn-char-y, 0px) + 10px), 0) scale(calc(var(--vn-char-scale, 1) * .985)); }
    to   { opacity: 1; transform: translate3d(0, var(--vn-char-y, 0px), 0) scale(var(--vn-char-scale, 1)); }
}
/* 回退到方形头像时的独立呈现（避免被拉成怪异立绘） */
.vn-character.vn-character--avatar {
    height: auto;
    width: clamp(110px, 21vw, 210px);
    max-width: 46%;
    aspect-ratio: 1 / 1;
    object-fit: cover;
    border-radius: 18px;
    border: 1px solid rgba(255,255,255,.16);
    background: rgba(255,255,255,.05);
    margin-bottom: 6px;
    filter: drop-shadow(0 14px 26px rgba(0,0,0,.55));
}
/* 说话人是「我」或系统提示时，立绘轻微退后但不消失 */
.vn-stage.speaker-dim .vn-character { opacity: .42; filter: brightness(.7) saturate(.72); }

/* ---------- 顶部工具条 ---------- */
.vn-stage-top {
    position: absolute; top: 0; left: 0; right: 0;
    height: var(--vn-top-h);
    display: flex; align-items: center; gap: 8px;
    padding: 10px 12px;
    z-index: 4;
    pointer-events: none;
}
.vn-title-slot {
    position: absolute; left: 50%; top: 14px;
    transform: translateX(-50%);
    font-size: .78em; letter-spacing: .22em;
    color: rgba(255,255,255,.42);
    text-transform: uppercase;
    white-space: nowrap;
    pointer-events: none;
}
.vn-chip {
    pointer-events: auto;
    margin-left: 0;
    flex: 0 0 auto;
    background: rgba(10,12,20,.5);
    border: 1px solid var(--vn-line);
    color: #dcdfe8;
    height: 32px; padding: 0 11px;
    border-radius: 999px;
    backdrop-filter: blur(9px);
    -webkit-backdrop-filter: blur(9px);
    font-size: .8em;
    display: inline-flex; align-items: center; gap: 6px;
    cursor: pointer;
    transition: background .18s, border-color .18s, color .18s, transform .18s, opacity .3s ease;
}
.vn-chip i { font-size: 1.05em; }
.vn-chip:hover { background: rgba(230,199,138,.16); border-color: var(--vn-gold); color: #fff; transform: translateY(-1px); }
.vn-chip.active { background: rgba(230,199,138,.24); border-color: var(--vn-gold); color: #fff; }
.vn-chip.vn-settings-btn { margin-left: 0; }
.vn-chip.vn-log-btn { margin-left: auto; margin-right: 8px; }
.vn-chip.vn-auto-btn { margin-right: 8px; }
.vn-chip.vn-hide-btn { margin-right: 8px; }
.vn-chip.vn-exit { border-color: rgba(230,199,138,.42); color: var(--vn-gold); }
.vn-chip.vn-exit span { display: inline; }
.vn-chip:disabled { opacity: .45; cursor: not-allowed; }

/* ---------- 对话框 ---------- */
.vn-dialogue-box {
    position: absolute;
    left: 16px; right: 16px;
    margin: 0 auto;
    max-width: 1120px;
    bottom: 12px;
    z-index: 3;
    padding: 14px 22px 11px;
    color: var(--vn-text);
    border: 1px solid var(--vn-line);
    border-radius: 16px;
    background: linear-gradient(180deg, rgba(17,19,27,.9), rgba(8,9,14,.955));
    box-shadow: var(--vn-shadow), inset 0 1px 0 rgba(255,255,255,.07);
    backdrop-filter: blur(11px);
    -webkit-backdrop-filter: blur(11px);
    transition: background .3s, border-color .3s, transform .3s, opacity .3s;
}
.vn-skin-line { display: none; }
/* 停在最新一句时给一条极轻的金边提示：暗示「等你说话」 */
.vn-dialogue-box.is-latest { border-color: rgba(230,199,138,.34); }
.vn-dialogue-box.is-latest::before {
    content: ''; position: absolute; left: 22px; right: 22px; bottom: -1px;
    height: 1px; background: linear-gradient(90deg, transparent, rgba(230,199,138,.55), transparent);
    opacity: .7; pointer-events: none;
}
.vn-dialogue-box::after {
    content: ''; position: absolute; left: 16px; right: 16px; top: 47px;
    height: 1px; background: linear-gradient(90deg, transparent, rgba(230,199,138,.5), transparent);
    opacity: .8;
}

.speaker-row, .vn-speaker-row {
    display: flex; align-items: center; gap: 10px;
    min-height: 24px;
    margin-bottom: 6px;
}
.vn-spacer { flex: 1 1 auto; }
/* 说话人小头像：立绘缺失或说话人是「我」时，一眼看清是谁在说 */
.vn-name-avatar {
    flex: 0 0 auto;
    width: 22px; height: 22px;
    border-radius: 50%;
    object-fit: cover;
    border: 1px solid rgba(255,255,255,.22);
    background: rgba(255,255,255,.06);
    box-shadow: 0 2px 8px rgba(0,0,0,.4);
}
.vn-name-avatar[hidden] { display: none; }
.vn-name {
    font-weight: 700;
    color: var(--vn-gold);
    letter-spacing: .05em;
    font-size: 1.02em;
    max-width: 46%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    text-shadow: 0 2px 10px rgba(0,0,0,.6);
}
/* 群聊多说话人时由 JS 注入 --vn-name-c 染色；单聊保持默认金色 */
.vn-name.vn-name--tinted { color: var(--vn-name-c, var(--vn-gold)); }
.vn-name--mine { color: #9fd3ff; }
.vn-name--sys { color: #a7adbe; font-weight: 500; font-style: italic; letter-spacing: .02em; }
.vn-dialogue-box.vn-box--system { border-style: dashed; background: linear-gradient(180deg, rgba(24,26,34,.86), rgba(12,13,19,.92)); }
.vn-dialogue-box.vn-box--system .vn-text { color: #b6bbc8; font-size: .94em; font-style: italic; }
.vn-dialogue-box.vn-box--system::after { opacity: .35; }

/* 情绪徽标 */
.vn-badge {
    --vn-emo-color: #c9ccd8;
    display: inline-flex; align-items: center; gap: 5px;
    height: 22px; padding: 0 9px;
    font-size: .74em; font-weight: 600;
    color: var(--vn-emo-color);
    background: color-mix(in srgb, var(--vn-emo-color) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--vn-emo-color) 45%, transparent);
    border-radius: 999px;
    cursor: pointer;
    transition: transform .16s, box-shadow .16s;
}
@supports not (background: color-mix(in srgb, red 10%, blue)) {
    .vn-badge { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.22); }
}
.vn-badge:hover { transform: translateY(-1px); box-shadow: 0 0 10px color-mix(in srgb, var(--vn-emo-color) 45%, transparent); }
.vn-badge.badge-manual { border-style: dashed; }
.vn-badge.badge-tag::after { content: '#'; opacity: .55; margin-left: 1px; }
.vn-stage.no-badge .vn-badge { display: none; }

/* 流式指示 */
.vn-streaming { display: inline-flex; align-items: center; gap: 4px; }
.vn-streaming[hidden] { display: none; }
.vn-streaming i {
    width: 5px; height: 5px; border-radius: 50%;
    background: var(--vn-gold); opacity: .35;
    animation: vnDot 1.1s infinite ease-in-out;
}
.vn-streaming i:nth-child(2) { animation-delay: .16s; }
.vn-streaming i:nth-child(3) { animation-delay: .32s; }
@keyframes vnDot { 0%,100% { opacity:.25; transform: scale(.8) } 50% { opacity:1; transform: scale(1.15) } }

/* 「正在组织语言」：等待首个字到达时的小提示（打完字/收到首帧即隐藏） */
.vn-thinking { display: inline-flex; align-items: center; gap: 5px; color: rgba(255,255,255,.5); }
.vn-thinking[hidden] { display: none; }
.vn-thinking b { font-size: .68em; font-weight: 500; letter-spacing: .04em; margin-left: 2px; }
.vn-thinking i {
    width: 4px; height: 4px; border-radius: 50%;
    background: currentColor; opacity: .3;
    animation: vnDot 1.25s infinite ease-in-out;
}
.vn-thinking i:nth-child(2) { animation-delay: .18s; }
.vn-thinking i:nth-child(3) { animation-delay: .36s; }
body.light-theme .vn-thinking { color: rgba(40,44,58,.5); }

.vn-jump-latest {
    width: 26px; height: 26px; border-radius: 50%;
    border: 1px solid var(--vn-line);
    background: rgba(0,0,0,.4); color: var(--vn-gold);
    display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer;
}
.vn-jump-latest[hidden] { display: none; }
.vn-jump-latest:hover { background: rgba(230,199,138,.2); }

/* 正文 */
.vn-text {
    font-size: 16px;
    line-height: 1.85;
    min-height: 3.6em;
    max-height: calc(var(--vn-vh) * 34);
    overflow-y: auto;
    white-space: pre-wrap;
    word-break: break-word;
    letter-spacing: .01em;
    text-shadow: 0 1px 6px rgba(0,0,0,.55);
    scrollbar-width: thin;
}
/* 长文分页用的隐形量尺：与 .vn-text 同字体同宽度，只用于测量行高 */
.vn-measure {
    position: absolute;
    left: -99999px; top: 0;
    visibility: hidden;
    pointer-events: none;
    white-space: pre-wrap;
    word-break: break-word;
    user-select: none;
}
/* 页码指示（仅长句出现） */
.vn-page-ind {
    flex: 0 0 auto;
    height: 25px; line-height: 23px;
    padding: 0 8px;
    border-radius: 7px;
    border: 1px dashed rgba(230,199,138,.45);
    color: var(--vn-gold);
    font-size: .9em;
    letter-spacing: .04em;
    background: rgba(230,199,138,.07);
}
.vn-page-ind[hidden] { display: none; }
.vn-text::-webkit-scrollbar { width: 6px; }
.vn-text::-webkit-scrollbar-thumb { background: rgba(255,255,255,.18); border-radius: 3px; }
.vn-text.typing::after {
    content: '';
    display: inline-block;
    width: 9px; height: 1.05em;
    margin-left: 3px; vertical-align: -.16em;
    background: var(--vn-gold);
    animation: vnCaret .85s steps(1) infinite;
}
@keyframes vnCaret { 0%,49% { opacity: 1 } 50%,100% { opacity: 0 } }

/* 图片消息 */
.vn-media { margin: 4px 0 2px; }
.vn-media[hidden] { display: none; }
.vn-media img {
    max-height: min(calc(var(--vn-vh) * 34), 260px);
    max-width: 100%;
    border-radius: 10px;
    border: 1px solid var(--vn-line);
    cursor: zoom-in;
    display: block;
}
.vn-media video {
    max-height: min(calc(var(--vn-vh) * 38), 300px);
    width: 100%;
    border-radius: 10px;
    border: 1px solid var(--vn-line);
    background: #000;
    display: block;
}

/* 底部控制条 */
.vn-foot {
    display: flex; align-items: center; gap: 10px;
    margin-top: 8px; padding-top: 7px;
    border-top: 1px solid rgba(255,255,255,.08);
    font-size: .78em; color: rgba(255,255,255,.55);
}
.vn-controls { display: flex; align-items: center; gap: 5px; }
.vn-controls button {
    height: 25px; min-width: 25px; padding: 0 7px;
    border-radius: 7px;
    border: 1px solid var(--vn-line);
    background: rgba(255,255,255,.04);
    color: #d7dae4;
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 5px;
    transition: background .16s, border-color .16s;
}
.vn-controls button:hover { background: rgba(230,199,138,.16); border-color: var(--vn-gold); color: #fff; }
.vn-controls #vn-speed { font-size: .95em; }
.vn-continue {
    margin-left: auto;
    opacity: 0;
    color: var(--vn-gold);
    font-size: 1.15em;
    transition: opacity .2s;
    animation: vnBob 1.3s infinite ease-in-out;
}
.vn-continue.show { opacity: 1; }
.vn-continue i { display: inline-flex; }
/* 长句还有下一页时，提示变成「下一页」小胶囊，比箭头更直白 */
.vn-continue.page-next {
    font-size: .82em;
    display: inline-flex; align-items: center; gap: 5px;
    height: 22px; padding: 0 10px;
    border-radius: 999px;
    border: 1px solid rgba(230,199,138,.45);
    background: rgba(230,199,138,.12);
    animation: none;
}
.vn-continue.page-next .vn-cont-txt { letter-spacing: .03em; }
@keyframes vnBob { 0%,100% { transform: translateY(0) } 50% { transform: translateY(3px) } }

/* ---------- 空态提示 ---------- */
.vn-hint {
    position: absolute; top: 50%; left: 50%;
    transform: translate(-50%, -58%);
    z-index: 3;
    max-width: min(420px, 84vw);
    padding: 22px 26px;
    border-radius: 16px;
    border: 1px solid var(--vn-line);
    background: rgba(10,12,20,.72);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: #cfd3de;
    text-align: center;
    line-height: 1.8;
    font-size: .92em;
}
.vn-hint[hidden] { display: none; }
.vn-hint b { color: var(--vn-gold); }
.vn-hint-big { font-size: 1.2em; color: #fff; margin-bottom: 8px; }
.vn-hint-big i { font-size: 1.25em; display: block; margin-bottom: 6px; color: var(--vn-gold); }
.vn-hint-sub { color: #8b91a3; font-size: .9em; }
.vn-hint-actions { margin-top: 14px; display: flex; justify-content: center; }
.vn-hint-btn {
    height: 32px; padding: 0 14px;
    border-radius: 999px;
    border: 1px solid rgba(230,199,138,.5);
    background: rgba(230,199,138,.14);
    color: var(--vn-gold);
    font-size: .86em; cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
    transition: background .18s, transform .18s;
}
.vn-hint-btn:hover { background: rgba(230,199,138,.26); transform: translateY(-1px); }

/* ---------- 回顾面板 ---------- */
.vn-log-panel {
    position: absolute; top: var(--vn-top-h); right: 10px; bottom: calc(var(--vn-box-h) + 18px);
    width: min(340px, 84vw);
    z-index: 6;
    display: flex; flex-direction: column;
    border: 1px solid var(--vn-line);
    border-radius: 14px;
    background: rgba(9,11,17,.93);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow: -8px 0 34px rgba(0,0,0,.5);
    animation: vnSlideIn .22s ease;
    overflow: hidden;
}
.vn-log-panel[hidden] { display: none; }
@keyframes vnSlideIn { from { opacity: 0; transform: translateX(16px) } to { opacity: 1; transform: none } }
.vn-log-head {
    flex: 0 0 auto;
    display: flex; align-items: center; gap: 8px;
    padding: 11px 12px;
    font-size: .85em; color: var(--vn-gold);
    border-bottom: 1px solid var(--vn-line);
}
.vn-log-close {
    margin-left: auto; width: 24px; height: 24px;
    border: 0; border-radius: 6px; background: transparent; color: #aaa;
    cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
}
.vn-log-close:hover { background: rgba(255,255,255,.1); color: #fff; }
.vn-log-list { flex: 1 1 auto; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 2px; }
.vn-log-list::-webkit-scrollbar { width: 7px; }
.vn-log-list::-webkit-scrollbar-thumb { background: rgba(255,255,255,.16); border-radius: 4px; }
.vn-log-item {
    padding: 7px 9px; border-radius: 9px; cursor: pointer;
    font-size: .82em; line-height: 1.6; color: #cfd3de;
    border-left: 2px solid transparent;
    transition: background .15s;
}
.vn-log-item:hover { background: rgba(255,255,255,.06); }
.vn-log-item.on { background: rgba(230,199,138,.11); border-left-color: var(--vn-gold); }
.vn-log-name { display: block; font-weight: 700; font-size: .92em; margin-bottom: 2px; }
.vn-log-text { display: block; color: #b9becb; max-height: 5.4em; overflow: hidden; }

/* ---------- 情绪覆盖浮层 ---------- */
.vn-em-pop {
    position: absolute;
    left: 50%; transform: translateX(-50%);
    bottom: calc(var(--vn-box-h) + 20px);
    z-index: 7;
    width: min(420px, calc(100% - 24px));
    padding: 12px;
    border-radius: 14px;
    border: 1px solid var(--vn-line);
    background: rgba(10,12,20,.96);
    box-shadow: 0 14px 44px rgba(0,0,0,.6);
    animation: vnPopIn .18s ease;
}
.vn-em-pop[hidden] { display: none; }
@keyframes vnPopIn { from { opacity: 0; transform: translate(-50%, 10px) } to { opacity: 1; transform: translate(-50%, 0) } }
.vn-em-head {
    display: flex; align-items: center; gap: 8px;
    font-size: .8em; color: #aeb4c4; margin-bottom: 9px;
}
.vn-em-auto {
    margin-left: auto; height: 24px; padding: 0 9px;
    border-radius: 999px; border: 1px solid var(--vn-line);
    background: rgba(255,255,255,.05); color: var(--vn-gold);
    font-size: .92em; cursor: pointer;
    display: inline-flex; align-items: center; gap: 4px;
}
.vn-em-auto:hover { background: rgba(230,199,138,.18); }
.vn-em-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.vn-em-item {
    --vn-emo-color: #c9ccd8;
    display: flex; flex-direction: column; align-items: center; gap: 3px;
    padding: 8px 4px;
    border-radius: 10px;
    border: 1px solid rgba(255,255,255,.1);
    background: rgba(255,255,255,.03);
    color: #cfd3de; font-size: .76em;
    cursor: pointer;
    transition: background .15s, border-color .15s, transform .15s;
}
.vn-em-item i { color: var(--vn-emo-color); font-size: 1.3em; }
.vn-em-item:hover { background: rgba(255,255,255,.08); transform: translateY(-1px); }
.vn-em-item.on { border-color: var(--vn-emo-color); background: color-mix(in srgb, var(--vn-emo-color) 16%, transparent); color: #fff; }
/* 还没配立绘的情绪：压暗 + 虚线，提示「选了也只是回退」 */
.vn-em-item.no-art { border-style: dashed; opacity: .58; }
.vn-em-item.no-art i { filter: grayscale(1); }
.vn-em-foot { margin-top: 8px; font-size: .68em; color: #767c8d; line-height: 1.5; }

/* ---------- 皮肤：minimal ---------- */
.vn-stage.skin-minimal .vn-dialogue-box {
    border-radius: 0;
    border: 0;
    border-top: 1px solid rgba(255,255,255,.12);
    background: linear-gradient(180deg, rgba(8,9,14,.72), rgba(8,9,14,.96));
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    left: 0; right: 0; margin: 0; max-width: none;
    bottom: 0;
    box-shadow: none;
    padding: 16px clamp(18px, 6vw, 80px) 14px;
}
.vn-stage.skin-minimal .vn-dialogue-box::after { display: none; }
.vn-stage.skin-minimal .vn-name { color: #fff; font-weight: 500; }
.vn-stage.skin-minimal .vn-text { max-height: calc(var(--vn-vh) * 30); }
.vn-stage.skin-minimal .vn-vignette { opacity: .7; }

/* ---------- 皮肤：glass ---------- */
.vn-stage.skin-glass .vn-dialogue-box {
    border-radius: 24px;
    background: linear-gradient(160deg, rgba(255,255,255,.14), rgba(255,255,255,.05));
    border: 1px solid rgba(255,255,255,.26);
    backdrop-filter: blur(22px) saturate(150%);
    -webkit-backdrop-filter: blur(22px) saturate(150%);
    box-shadow: 0 18px 46px rgba(0,0,0,.42), inset 0 1px 0 rgba(255,255,255,.32);
}
.vn-stage.skin-glass .vn-dialogue-box::after { display: none; }
.vn-stage.skin-glass .vn-name { color: #fff; text-shadow: 0 0 14px rgba(180,210,255,.7); }
.vn-stage.skin-glass .vn-badge { background: rgba(255,255,255,.16); }
.vn-stage.skin-glass .vn-bg-layer.is-active { filter: brightness(var(--vn-bg-dim, .82)) blur(var(--vn-bg-blur, 0)) saturate(1.12); }

/* ---------- 懒人模式选项（Galgame 风格，跟随对话框皮肤） ---------- */
.vn-choices {
    display: flex; flex-direction: column; gap: 7px;
    margin: 10px 0 2px;
    padding: 2px 0 0;
    /* 选项多了不能把对话框撑出屏幕：正文先让位，列表内部滚 */
    max-height: min(calc(var(--vn-vh) * 38), 260px);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
}
.vn-choices[hidden] { display: none; }
.vn-choices::-webkit-scrollbar { width: 6px; }
.vn-choices::-webkit-scrollbar-thumb { background: rgba(255,255,255,.18); border-radius: 3px; }
/* 有选项时压一下正文高度，保证「正文 + 选项」整体仍在一屏内 */
.vn-dialogue-box:has(.vn-choices:not([hidden])) .vn-text { max-height: calc(var(--vn-vh) * 22); min-height: 2.4em; }
.vn-choice-item {
    display: flex; align-items: center; gap: 10px;
    width: 100%;
    min-height: 34px;
    padding: 8px 12px;
    border-radius: 10px;
    border: 1px solid var(--vn-line);
    background: linear-gradient(90deg, rgba(230,199,138,.07), rgba(255,255,255,.02));
    color: #e6e9f2;
    font-size: .95em;
    line-height: 1.6;
    text-align: left;
    cursor: pointer;
    transition: background .16s, border-color .16s, transform .16s, color .16s;
    animation: vnChoiceIn .22s ease both;
}
.vn-choice-item:nth-child(2) { animation-delay: .05s; }
.vn-choice-item:nth-child(3) { animation-delay: .1s; }
.vn-choice-item:nth-child(4) { animation-delay: .15s; }
.vn-choice-item:nth-child(5) { animation-delay: .2s; }
.vn-choice-item:nth-child(6) { animation-delay: .25s; }
@keyframes vnChoiceIn { from { opacity: 0; transform: translateY(6px) } to { opacity: 1; transform: none } }
.vn-choice-item .vn-choice-key {
    flex: 0 0 auto;
    width: 19px; height: 19px;
    border-radius: 5px;
    border: 1px solid rgba(230,199,138,.5);
    background: rgba(230,199,138,.12);
    color: var(--vn-gold);
    font-size: .72em; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center;
}
.vn-choice-item .vn-choice-text { flex: 1 1 auto; word-break: break-word; }
.vn-choice-item:hover,
.vn-choice-item.is-active {
    border-color: var(--vn-gold);
    background: linear-gradient(90deg, rgba(230,199,138,.2), rgba(230,199,138,.06));
    color: #fff;
    transform: translateX(3px);
}
.vn-choice-item.is-active { box-shadow: 0 0 0 1px rgba(230,199,138,.35), 0 4px 18px rgba(0,0,0,.35); }
.vn-choice-tip {
    display: flex; align-items: center; gap: 6px;
    font-size: .68em; color: rgba(255,255,255,.42);
    letter-spacing: .04em;
    padding-left: 2px;
}
.vn-choice-tip i { font-size: 1.05em; }
/* 皮肤：minimal —— 去掉胶囊感，改为整行左对齐 + 顶部细分隔 */
.vn-stage.skin-minimal .vn-choice-item {
    border-radius: 0;
    border-left: 2px solid rgba(255,255,255,.22);
    background: rgba(255,255,255,.03);
}
.vn-stage.skin-minimal .vn-choice-item:hover,
.vn-stage.skin-minimal .vn-choice-item.is-active {
    border-left-color: #fff;
    background: rgba(255,255,255,.09);
    transform: none;
}
/* 皮肤：glass —— 与磨砂对话框同质的通透卡片 */
.vn-stage.skin-glass .vn-choice-item {
    border-radius: 14px;
    border-color: rgba(255,255,255,.24);
    background: rgba(255,255,255,.1);
}
.vn-stage.skin-glass .vn-choice-item .vn-choice-key {
    border-color: rgba(255,255,255,.4);
    background: rgba(255,255,255,.16);
    color: #fff;
}
.vn-stage.skin-glass .vn-choice-item:hover,
.vn-stage.skin-glass .vn-choice-item.is-active {
    background: rgba(255,255,255,.22);
    border-color: rgba(255,255,255,.55);
}
body.light-theme .vn-choice-item { color: #2b2f3a; }
body.light-theme .vn-choice-tip { color: rgba(40,44,58,.45); }

/* ---------- 兼容模式 / 减少动效 ---------- */
body.compatibility-mode .vn-stage,
body.compatibility-mode .vn-dialogue-box,
body.compatibility-mode .vn-character,
body.compatibility-mode .vn-bg-layer,
body.compatibility-mode .vn-log-panel,
body.compatibility-mode .vn-em-pop { transition: none !important; animation: none !important; }
body.compatibility-mode .vn-stage.kenburns .vn-bg-layer.is-active { transform: scale(1.045) !important; }
body.compatibility-mode .vn-continue,
body.compatibility-mode .vn-streaming i { animation: none !important; }
body.compatibility-mode .vn-choice-item { animation: none !important; transition: none !important; }

@media (prefers-reduced-motion: reduce) {
    .vn-stage.kenburns .vn-bg-layer.is-active { transform: scale(1.02) !important; transition: opacity .01s !important; }
    .vn-continue { animation: none !important; }
}

/* ---------- 移动端 ---------- */
.vn-stage.mobile { --vn-top-h: 50px; }
.vn-stage.mobile .vn-chip span { display: none; }
.vn-stage.mobile .vn-chip { padding: 0 9px; }
.vn-stage.mobile .vn-title-slot { letter-spacing: .12em; font-size: .7em; top: 16px; }
.vn-stage.mobile .vn-dialogue-box {
    left: 8px; right: 8px; max-width: none;
    bottom: 8px;
    padding: 12px 14px 9px;
    border-radius: 14px;
}
.vn-stage.mobile .vn-text { font-size: 15px; line-height: 1.75; max-height: calc(var(--vn-vh) * 27); min-height: 3em; }
/* 键盘弹出时舞台被压扁：正文与对话框整体再收一档，并把对话框压到舞台底部，
   保证「输入框 + 当前台词」都留在键盘上方（与 main.js 的 kb-shrink 协同）。 */
body.kb-shrink .vn-stage.mobile .vn-text { max-height: calc(var(--vn-vh) * 21); }
body.kb-shrink .vn-stage .vn-text { max-height: calc(var(--vn-vh) * 24); }
body.kb-shrink .vn-stage .vn-media img { max-height: calc(var(--vn-vh) * 26); }
body.kb-shrink .vn-choices { max-height: calc(var(--vn-vh) * 30); }
.vn-stage.mobile .vn-name { font-size: .95em; max-width: 40%; }
.vn-stage.mobile .vn-character-wrap { bottom: calc(var(--vn-box-h) + 6px); }
.vn-stage.mobile .vn-character { max-width: 78%; }
.vn-stage.mobile .vn-character--avatar { width: clamp(88px, 26vw, 132px); }
.vn-stage.mobile .vn-em-grid { grid-template-columns: repeat(3, 1fr); }
.vn-stage.mobile .vn-log-panel { left: 8px; right: 8px; width: auto; }
.vn-stage.mobile .vn-page-ind { height: 22px; line-height: 20px; padding: 0 6px; font-size: .86em; }
/* 窄屏下控制条多了一个「复制」按钮：藏掉速度文字，只留图标，避免挤成两行 */
.vn-stage.mobile #vn-speed span { display: none; }
.vn-stage.mobile .vn-controls { gap: 4px; }
.vn-stage.mobile .vn-foot { gap: 7px; font-size: .74em; }
.vn-stage.mobile .vn-continue.page-next { height: 20px; padding: 0 8px; font-size: .76em; }

/* ---------- 浅色主题微调 ---------- */
body.light-theme .vn-dialogue-box {
    background: linear-gradient(180deg, rgba(255,255,255,.86), rgba(245,246,250,.94));
    border-color: rgba(0,0,0,.12);
    color: #23262f;
    box-shadow: 0 -8px 30px rgba(0,0,0,.18), inset 0 1px 0 rgba(255,255,255,.6);
}
body.light-theme .vn-text { color: #23262f; text-shadow: none; }
body.light-theme .vn-name { color: #9a7a2e; }
body.light-theme .vn-name.vn-name--tinted { color: var(--vn-name-c, #9a7a2e); }
body.light-theme .vn-name--mine { color: #2a6ea8; }
body.light-theme .vn-chip { background: rgba(255,255,255,.68); border-color: rgba(0,0,0,.14); color: #3a3f4b; }
body.light-theme .vn-hint { background: rgba(255,255,255,.86); color: #454a58; }
body.light-theme .vn-log-panel, body.light-theme .vn-em-pop { background: rgba(252,252,255,.96); }
body.light-theme .vn-log-item { color: #3c414e; }
body.light-theme .vn-log-text { color: #5a6070; }
body.light-theme .vn-controls button, body.light-theme .vn-em-item { background: rgba(0,0,0,.05); border-color: rgba(0,0,0,.12); color: #3c414e; }
body.light-theme .vn-em-pop, body.light-theme .vn-log-panel { color: #3c414e; }
body.light-theme .vn-stage { background: #e9ebf2; }

/* ---------- 管理弹窗内部样式 ---------- */
.vn-modal { max-width: 760px; }
.vn-modal .modal-body { padding: 16px 20px; display: block; }
.vn-modal-toolbar {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    padding: 10px 12px; margin-bottom: 14px;
    border: 1px solid var(--border-color, #333);
    border-radius: 12px;
    background: rgba(0,0,0,.18);
}
.vn-pick { display: flex; align-items: center; gap: 8px; font-size: .9em; color: #cfd3de; flex: 1 1 260px; min-width: 0; }
.vn-pick select {
    flex: 1 1 auto; min-width: 0;
    padding: 8px 10px; border-radius: 8px;
    border: 1px solid var(--border-color, #3a3d47);
    background: #22242c; color: #eee;
    font-size: .95em;
}
.vn-sec { margin-bottom: 20px; padding-bottom: 14px; border-bottom: 1px dashed rgba(255,255,255,.1); }
.vn-sec:last-of-type { border-bottom: 0; }
.vn-sec h4 { margin: 0 0 6px; color: var(--accent-gold, #e6c78a); font-size: 1em; display: flex; align-items: center; gap: 7px; }
.vn-only-filled {
    margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
    font-size: .74em; font-weight: 400; color: #a9afbd; cursor: pointer;
}
.vn-only-filled input { width: 14px; height: 14px; margin: 0; }
.vn-tip { margin: 0 0 12px; font-size: .78em; color: #8f95a6; line-height: 1.6; }
.vn-tip code { color: #ffd66b; }
.vn-btn-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 8px; }
.vn-label { font-size: .82em; color: #a9afbd; }
.vn-empty { color: #6d7385; }
.vn-foot-note { font-size: .74em; color: #767c8d; line-height: 1.7; margin: 6px 0 0; }

.vn-bg-row { display: flex; gap: 12px; align-items: stretch; flex-wrap: wrap; }
.vn-bg-preview {
    flex: 0 0 172px; height: 100px;
    border-radius: 10px; border: 1px solid var(--border-color, #3a3d47);
    background-size: cover; background-position: center;
    background-color: #191b22;
    display: flex; align-items: center; justify-content: center;
    color: #79808f; font-size: .8em;
}
.vn-bg-preview.empty { border-style: dashed; }
.vn-bg-actions { flex: 1 1 260px; min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.vn-global-box { margin-top: 10px; padding-top: 8px; border-top: 1px dashed rgba(255,255,255,.08); }

.vn-em-input-row { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.vn-url-input {
    flex: 1 1 200px; min-width: 120px;
    padding: 7px 9px; border-radius: 8px;
    border: 1px solid var(--border-color, #3a3d47);
    background: #1e2028; color: #eee; font-size: .84em;
}
.vn-url-input:focus { outline: none; border-color: var(--accent-gold, #e6c78a); }

#vn-emo-list { display: flex; flex-direction: column; gap: 8px; }
.vn-em-row {
    display: flex; gap: 11px; align-items: flex-start;
    padding: 9px 10px;
    border: 1px solid var(--border-color, #333743);
    border-radius: 11px;
    background: rgba(255,255,255,.025);
    transition: border-color .18s, background .18s;
}
.vn-em-row:hover { border-color: rgba(230,199,138,.45); background: rgba(255,255,255,.05); }
.vn-em-thumb {
    flex: 0 0 52px; width: 52px; height: 70px;
    object-fit: cover; border-radius: 7px;
    border: 1px solid var(--border-color, #3a3d47);
    background: #15171d;
}
.vn-em-meta { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
/* 情绪专用背景（可选子区块） */
.vn-em-sub {
    display: flex; gap: 9px; align-items: flex-start;
    margin-top: 4px; padding-top: 8px;
    border-top: 1px dashed rgba(255,255,255,.1);
}
.vn-em-thumb-sm {
    flex: 0 0 72px; width: 72px; height: 42px;
    object-fit: cover; border-radius: 6px;
    border: 1px solid var(--border-color, #3a3d47);
    background: #15171d;
}
.vn-em-mini { font-size: .76em; color: #9aa1b2; display: flex; align-items: center; gap: 5px; }
.vn-em-mini i { color: var(--accent-gold, #e6c78a); }
.vn-em-name { font-size: .86em; font-weight: 700; display: flex; align-items: center; gap: 6px; }
.vn-em-name code { font-size: .78em; color: #7d8494; font-weight: 400; }
.vn-em-url { font-size: .74em; color: #8b91a2; word-break: break-all; }

.vn-layout-grid { display: flex; gap: 14px; flex-wrap: wrap; }
.vn-field { display: flex; flex-direction: column; gap: 6px; font-size: .8em; color: #a9afbd; flex: 1 1 160px; }
.vn-field select {
    padding: 7px 9px; border-radius: 8px;
    border: 1px solid var(--border-color, #3a3d47);
    background: #1e2028; color: #eee;
}
.vn-field output { color: var(--accent-gold, #e6c78a); font-size: .95em; }
.vn-field input[type="range"] { width: 100%; }

.vn-modal .modal-footer { display: flex; align-items: center; gap: 8px; }

/* 外观面板区块 */
/* 视觉小说设置区：默认折叠（<details>），启用模式或用户手动展开后显示 */
.vn-appearance-details { margin-top: 12px; }
.vn-appearance-details > summary {
    display: flex; align-items: center; gap: 8px;
    cursor: pointer;
    list-style: none;
    user-select: none;
    padding: 9px 12px;
    border-radius: 9px;
    border: 1px dashed rgba(255,255,255,.18);
    background: rgba(255,255,255,.03);
    color: #aeb4c4;
    font-size: .86em;
    transition: background .18s, border-color .18s, color .18s;
}
.vn-appearance-details > summary::-webkit-details-marker { display: none; }
.vn-appearance-details > summary:hover {
    background: rgba(230,199,138,.1);
    border-color: rgba(230,199,138,.45);
    color: var(--vn-gold, #e6c78a);
}
.vn-appearance-details > summary i { transition: transform .2s ease; font-size: 1.1em; }
.vn-appearance-details[open] > summary {
    border-style: solid;
    color: var(--vn-gold, #e6c78a);
    background: rgba(230,199,138,.08);
}
.vn-appearance-details[open] > summary i { transform: rotate(180deg); }
.vn-appearance-details > summary span { flex: 1 1 auto; }
body.light-theme .vn-appearance-details > summary {
    border-color: rgba(0,0,0,.16);
    background: rgba(0,0,0,.03);
    color: #5a5f70;
}
.vn-appearance-body { display: flex; flex-direction: column; gap: 6px; }
.vn-appearance-body h3 { margin: 4px 0 2px; font-size: 1em; color: var(--accent-gold, #e6c78a); }
.vn-appearance-body p { margin: 0 0 10px; font-size: .78em; color: #8f95a6; line-height: 1.6; }
.vn-appearance-body > hr { margin: 16px 0 10px; border: 0; border-top: 1px dashed rgba(255,255,255,.12); }
.vn-status-line { font-size: .78em; color: #9aa1b2; line-height: 1.75; }
.vn-status-line i { color: #7fdca4; margin-right: 4px; }
.vn-status-keys { color: #767c8d; font-size: .96em; }
.vn-status-keys code { color: #ffd66b; background: rgba(255,255,255,.06); padding: 0 4px; border-radius: 4px; }
.vn-sec-label { margin: 14px 0 8px !important; color: var(--accent-gold, #e6c78a); font-size: .86em !important; font-weight: 700; letter-spacing: .04em; }
.vn-field-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.vn-field-row > label:first-child { flex: 0 0 76px; font-size: .84em; color: #b7bcc9; }
.vn-field-row select {
    flex: 1 1 120px; min-width: 0; padding: 7px 9px;
    border-radius: 8px; border: 1px solid var(--border-color, #3a3d47);
    background: #1e2028; color: #eee; font-size: .88em;
}
.vn-field-row output { flex: 0 0 48px; text-align: right; font-size: .8em; color: var(--accent-gold, #e6c78a); }
.vn-inline-check { justify-content: flex-start; gap: 8px; }
.vn-inline-check input { width: 16px; height: 16px; flex: 0 0 auto; }
.vn-inline-check span { flex: 1 1 auto; font-size: .84em; color: #c6cad6; }
.vn-danger-zone { margin-top: 18px; padding-top: 12px; border-top: 1px dashed rgba(255,80,80,.25); }

@media (max-width: 768px) {
    .vn-modal .modal-body { padding: 12px 14px; }
    .vn-em-row { flex-wrap: wrap; }
    .vn-em-thumb { flex: 0 0 46px; width: 46px; height: 62px; }
    .vn-url-input { flex: 1 1 100%; }
    .vn-bg-preview { flex: 1 1 100%; height: 86px; }
    .vn-modal-toolbar { flex-direction: column; align-items: stretch; }
    .vn-field-row > label:first-child { flex: 1 1 100%; }
    .vn-field-row output { flex: 0 0 auto; }
}

/* ========================================
   全屏舞台（body.vn-fullscreen）
   目标：让 Galgame 界面铺满整个屏幕 —— 侧边栏/聊天头部/免责条全部收起，
   舞台从顶到底占满视口；真实输入框被搬进 #vn-fs-input-host 悬浮在对话框之上，
   所以「全屏」不等于「不能打字」。
   说明：--vn-fs-lift 由 JS 按悬浮条实测高度写入，对话框与立绘靠它整体上移让位。
   ======================================== */
body.vn-fullscreen {
    padding: 0;
    background: #000;
    overflow: hidden;
}

/* 桌面容器直接铺满；「移动视图」的手机外框（.mobile-view）保持 430×844 不变 —— 
   那种预览场景下用户要看的正是手机比例，全屏只该让舞台占满这个框，而不是把框撑成浏览器窗口。 */
body.vn-fullscreen .app-container:not(.mobile-view) {
    width: 100vw;
    height: 100vh;
    height: 100dvh;      /* 移动端地址栏伸缩时以可见高度为准 */
    max-width: none;
    border-radius: 0;
    box-shadow: none;
}

/* 舞台之外的东西一律收起：侧边栏、两个浮动角标、聊天头部（含其中的 VN 开关，
   舞台自带工具条，退出走「退出 VN」/Esc）。免责条用 #vn-fs-input-host 那条规则处理。 */
body.vn-fullscreen .sidebar,
body.vn-fullscreen .sidebar-overlay,
body.vn-fullscreen .chat-search-bar,
body.vn-fullscreen .chat-header,
body.vn-fullscreen .mobile-menu-btn,
body.vn-fullscreen .view-toggle-btn { display: none !important; }

/* 舞台占满整屏（JS 已清掉行内 top，这里交回 CSS 决定） */
body.vn-fullscreen .vn-stage {
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    --vn-top-h: calc(54px + env(safe-area-inset-top));
}
body.vn-fullscreen .vn-stage.mobile { --vn-top-h: calc(50px + env(safe-area-inset-top)); }
body.vn-fullscreen .vn-stage-top {
    height: var(--vn-top-h);
    padding: calc(10px + env(safe-area-inset-top)) 14px 10px;
}
/* 好感度徽标是从聊天头部搬进来的，不该吃掉「记录」按钮的 margin-left:auto */
body.vn-fullscreen .vn-stage-top > .affinity-badge.in-vn + .vn-chip.vn-log-btn { margin-left: 0; }
body.vn-fullscreen .vn-title-slot { top: calc(14px + env(safe-area-inset-top)); }

/* 内容整体上移，避开悬浮输入条 */
body.vn-fullscreen .vn-dialogue-box,
body.vn-fullscreen .vn-stage.skin-minimal .vn-dialogue-box,
body.vn-fullscreen .vn-stage.skin-glass .vn-dialogue-box {
    bottom: calc(12px + var(--vn-fs-lift, 0px));
}
body.vn-fullscreen .vn-stage.mobile .vn-dialogue-box {
    bottom: calc(8px + var(--vn-fs-lift, 0px));
}
body.vn-fullscreen .vn-character-wrap {
    bottom: calc(var(--vn-box-h) + 10px + var(--vn-fs-lift, 0px));
}
body.vn-fullscreen .vn-stage.mobile .vn-character-wrap {
    bottom: calc(var(--vn-box-h) + 6px + var(--vn-fs-lift, 0px));
}
body.vn-fullscreen .vn-log-panel {
    bottom: calc(var(--vn-box-h) + 18px + var(--vn-fs-lift, 0px));
}
body.vn-fullscreen .vn-em-pop {
    bottom: calc(var(--vn-box-h) + 20px + var(--vn-fs-lift, 0px));
}
/* 舞台更高了：正文可容纳的行数随之放宽（分页仍按实测高度算，不会溢出） */
body.vn-fullscreen .vn-text { max-height: calc(var(--vn-vh) * 41); }
body.vn-fullscreen .vn-stage.mobile .vn-text { max-height: calc(var(--vn-vh) * 34); }
/* 全屏舞台 + 键盘：悬浮输入条占掉一大截，正文与选项按实测高度继续收窄 */
body.vn-fullscreen.kb-shrink .vn-text { max-height: calc(var(--vn-vh) * 26); }
/* 空态提示随舞台变高重新居中（略偏上，避免压在悬浮条上） */
body.vn-fullscreen .vn-hint { transform: translate(-50%, -62%); }

/* ---------- 悬浮输入条：搬进来的真实 footer，功能与快捷键完全不变 ---------- */
/* 用 absolute（挂在 .chat-area 里）而不是 fixed：
   fixed 会被 .app-container 上的动画/变换变成「相对视口」，在移动视图（430px 容器）下
   会飘到容器外面并被 overflow:hidden 裁掉；absolute 跟着聊天区走，宽度用百分比即可。 */
#vn-fs-input-host {
    position: absolute;
    left: 50%;
    bottom: calc(10px + env(safe-area-inset-bottom));
    transform: translateX(-50%);
    width: min(1160px, calc(100% - 24px));
    z-index: 40;
}
#vn-fs-input-host .chat-input-area {
    padding: 10px 14px;
    border: 1px solid rgba(230,199,138,.24);
    border-radius: 16px;
    background-color: rgba(9,11,17,.8);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    box-shadow: 0 14px 44px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.07);
}
/* 悬浮条宽度有限：免责条（在 footer 内部）不占位 */
#vn-fs-input-host .disclaimer-text { display: none !important; }
#vn-fs-input-host .emoji-picker,
#vn-fs-input-host .command-panel,
#vn-fs-input-host .avatar-context-menu,
#vn-fs-input-host .ai-avatar-context-menu { z-index: 60; }

/* 悬浮条本身做淡入淡出：进出全屏、以及按 H 截图时都不该「啪」地跳出来 */
#vn-fs-input-host { transition: opacity .26s ease; }
body.light-theme #vn-fs-input-host .chat-input-area {
    background-color: rgba(252,252,255,.86);
    border-color: rgba(0,0,0,.12);
    box-shadow: 0 12px 34px rgba(0,0,0,.2), inset 0 1px 0 rgba(255,255,255,.7);
}
/* H 隐藏界面（截图模式）：悬浮输入条在舞台之外，必须由 body 级 class 一起藏掉，
   否则纯画面中间会留一块输入框。 */
body.vn-ui-hidden #vn-fs-input-host { opacity: 0; pointer-events: none; }

@media (max-width: 768px) {
    /* 用百分比而不是 vw：「移动视图」下容器只有 430px，用 vw 会比容器还宽并被裁掉 */
    #vn-fs-input-host { width: calc(100% - 14px); bottom: calc(7px + env(safe-area-inset-bottom)); }
    #vn-fs-input-host .chat-input-area { padding: 8px 10px; border-radius: 14px; }
    body.vn-fullscreen .vn-dialogue-box { left: 8px; right: 8px; }
}

/* ====== ui-polish.css ====== */
/* ============================================================
 * ui-polish.css — 统一控件美化补丁
 *
 * 存在的原因：
 *  1) 世界书面板（worldbook.js）整套 DOM 用的是 wb-* 类，此前项目里
 *     没有任何一条规则定义过它们 —— 于是输入框 / 下拉框全部退化成
 *     浏览器默认白底控件，在深色弹窗里非常刺眼（「输入框好丑」的根因）。
 *  2) 设置弹窗里大量 <input> 不在 .form-group 直接子层（例如包在
 *     <div class="form-group"><div><label>… 的网格里、或 modal-body 裸放），
 *     原选择器 `.form-group input` 覆盖不到，同样是白底默认样式。
 *  3) 快捷键录入行、kbd、按钮 ghost 变体缺少定义。
 *
 * 两条硬约束：
 *  A. 只「补外观」不「改布局」——大范围规则一律不写 width，
 *     避免把别的模块用内联 style / 专属类精心调过的窄控件
 *     （气泡字号、TTS 语速、群聊数值框…）撑成整行。
 *  B. 大范围规则用 :where() 把特异性压到 0-0-0，保证任何既有的
 *     更具体规则都能自然覆盖，不会出现「补丁反过来打趴老界面」。
 * ============================================================ */

/* ---------- 0. 变量（复用主线程 token，缺省时兜底） ---------- */
:root {
    --ui-field-bg: #32353f;
    --ui-field-bg-hover: #383b45;
    --ui-field-border: #454a57;
    --ui-field-text: #ececf1;
    --ui-field-placeholder: #8b90a0;
    --ui-focus-ring: 0 0 0 3px rgba(var(--accent-gold-rgb, 230, 199, 138), .18);
    --ui-radius: 9px;
}

body.light-theme {
    --ui-field-bg: #fffdf9;
    --ui-field-bg-hover: #ffffff;
    --ui-field-border: #d3c6b1;
    --ui-field-text: #2b2f3a;
    --ui-field-placeholder: #9a8b74;
}

/* ---------- 1. 通用 form-input（部分动态面板使用，此前无任何定义） ---------- */
:where(.form-input) {
    box-sizing: border-box;
    padding: 9px 11px;
    border-radius: var(--ui-radius);
    border: 1px solid var(--ui-field-border);
    background-color: var(--ui-field-bg);
    color: var(--ui-field-text);
    font-family: inherit;
    font-size: .92em;
    line-height: 1.5;
    outline: none;
    transition: border-color .18s, box-shadow .18s, background-color .18s;
}
:where(.form-input):focus { border-color: var(--accent-gold); box-shadow: var(--ui-focus-ring); }
:where(.form-input)::placeholder { color: var(--ui-field-placeholder); }

/* ---------- 2. 弹窗 / 设置面板内的裸控件统一 ----------
   注意：不要用 :not(:hidden) —— :hidden 是 jQuery 专属伪类，
   浏览器 CSS 不认识，写进 :not() 会让整条选择器直接作废。 */
.modal-body :where(input):where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [hidden])),
.modal-body :where(textarea),
.modal-body :where(select),
.tab-content :where(input):where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [hidden])),
.tab-content :where(textarea),
.tab-content :where(select) {
    box-sizing: border-box;
    padding: 9px 11px;
    border-radius: var(--ui-radius);
    border: 1px solid var(--ui-field-border);
    background-color: var(--ui-field-bg);
    color: var(--ui-field-text);
    font-family: inherit;
    font-size: .92em;
    line-height: 1.5;
    outline: none;
    min-width: 0;
    transition: border-color .18s, box-shadow .18s, background-color .18s;
}

/* hover/focus 同样只作用于「文本类」控件，别去改滑块和复选框的原生外观 */
.modal-body :where(textarea, select):hover,
.tab-content :where(textarea, select):hover,
.modal-body :where(input):where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [hidden])):hover,
.tab-content :where(input):where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [hidden])):hover {
    background-color: var(--ui-field-bg-hover);
    border-color: #565c6b;
}

.modal-body :where(textarea, select):focus,
.tab-content :where(textarea, select):focus,
.modal-body :where(input):where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [hidden])):focus,
.tab-content :where(input):where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="color"], [hidden])):focus {
    border-color: var(--accent-gold);
    box-shadow: var(--ui-focus-ring);
    background-color: var(--ui-field-bg-hover);
}

.modal-body :where(input, textarea)::placeholder,
.tab-content :where(input, textarea)::placeholder {
    color: var(--ui-field-placeholder);
    opacity: 1;
}

.modal-body :where(input, textarea, select):disabled,
.tab-content :where(input, textarea, select):disabled {
    opacity: .5;
    cursor: not-allowed;
}

/* select：统一一个金色下拉箭头，去掉各浏览器风格差异 */
.modal-body :where(select),
.tab-content :where(select) {
    -webkit-appearance: none;
    appearance: none;
    padding-right: 30px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e6c78a' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 9px center;
    background-size: 15px 15px;
    cursor: pointer;
}

/* textarea 统一可纵向拉伸 */
.modal-body :where(textarea),
.tab-content :where(textarea) { resize: vertical; min-height: 46px; }

/* 复选 / 单选：跟金色主题一致 */
.modal-body :where(input[type="checkbox"], input[type="radio"]),
.tab-content :where(input[type="checkbox"], input[type="radio"]) {
    accent-color: var(--accent-gold);
    cursor: pointer;
}

/* range 滑块主题化（不动宽高，避免破坏既有滑块排版） */
.modal-body :where(input[type="range"]),
.tab-content :where(input[type="range"]) { accent-color: var(--accent-gold); cursor: pointer; }

/* color 拾色器 */
.modal-body :where(input[type="color"]),
.tab-content :where(input[type="color"]) {
    padding: 3px;
    border: 1px solid var(--ui-field-border);
    border-radius: var(--ui-radius);
    background: var(--ui-field-bg);
    cursor: pointer;
}

/* file 选择器：默认控件在深色背景里几乎看不见 */
.modal-body :where(input[type="file"]),
.tab-content :where(input[type="file"]) {
    color: var(--ui-field-text);
    font-size: .84em;
    padding: 8px;
    border: 1px dashed var(--ui-field-border);
    border-radius: var(--ui-radius);
    background: rgba(255, 255, 255, .02);
    cursor: pointer;
}
.modal-body :where(input[type="file"])::file-selector-button,
.tab-content :where(input[type="file"])::file-selector-button {
    margin-right: 10px;
    padding: 6px 12px;
    border: none;
    border-radius: 7px;
    background: #4a4f5d;
    color: #fff;
    font-family: inherit;
    font-size: .92em;
    cursor: pointer;
    transition: background .18s;
}
.modal-body :where(input[type="file"])::file-selector-button:hover,
.tab-content :where(input[type="file"])::file-selector-button:hover { background: var(--accent-gold); color: #23252d; }

/* ---------- 3. 世界书面板（wb-*） ---------- */

/* 3.1 空态 */
.wb-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 30px 18px;
    text-align: center;
    color: var(--text-secondary, #aaa);
    font-size: .88em;
    line-height: 1.7;
    border: 1px dashed #4a4f5b;
    border-radius: 12px;
    background: rgba(255, 255, 255, .02);
}
.wb-empty i { font-size: 34px; opacity: .35; }
.wb-empty p { margin: 0; }
.wb-empty--inline { padding: 26px 16px; }

/* 3.2 书卡片 */
.wb-book-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 13px 14px;
    margin-bottom: 10px;
    border: 1px solid #3d414d;
    border-radius: 12px;
    background: linear-gradient(180deg, rgba(255, 255, 255, .035), rgba(255, 255, 255, .012));
    transition: border-color .2s, box-shadow .2s;
}
.wb-book-card:hover { border-color: rgba(var(--accent-gold-rgb), .5); box-shadow: 0 4px 18px rgba(0, 0, 0, .28); }
.wb-book-card.is-off { opacity: .55; filter: saturate(.6); }
.wb-book-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.wb-book-name { color: var(--accent-gold); font-size: 1em; }
.wb-book-scope { color: var(--text-muted, #888); font-size: .78em; }
.wb-book-count { margin-left: auto; color: #9aa1b2; font-size: .74em; white-space: nowrap; }
.wb-book-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.wb-book-actions .btn { padding: 6px 11px; font-size: .8em; border-radius: 8px; }
.wb-btn-del:hover { border-color: #e57373; color: #e57373; }

/* 3.3 标签 */
.wb-tag {
    display: inline-flex;
    align-items: center;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: .72em;
    line-height: 1.7;
    border: 1px solid rgba(var(--accent-gold-rgb), .45);
    color: var(--accent-gold);
    background: rgba(var(--accent-gold-rgb), .1);
    white-space: nowrap;
}

/* 3.4 开关 */
.wb-switch { position: relative; display: inline-flex; flex: 0 0 auto; cursor: pointer; }
.wb-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.wb-switch-track {
    width: 38px;
    height: 21px;
    border-radius: 999px;
    background: #4b505d;
    border: 1px solid #565c6b;
    position: relative;
    transition: background .22s, border-color .22s;
}
.wb-switch-track i {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: #cfd3dd;
    transition: transform .22s cubic-bezier(.4, 0, .2, 1), background .22s;
}
.wb-switch input:checked + .wb-switch-track { background: rgba(var(--accent-gold-rgb), .35); border-color: var(--accent-gold); }
.wb-switch input:checked + .wb-switch-track i { transform: translateX(17px); background: var(--accent-gold); }
.wb-switch input:focus-visible + .wb-switch-track { box-shadow: var(--ui-focus-ring); }
.wb-switch--sm .wb-switch-track { width: 32px; height: 18px; }
.wb-switch--sm .wb-switch-track i { width: 12px; height: 12px; }
.wb-switch--sm input:checked + .wb-switch-track i { transform: translateX(14px); }

/* 3.5 世界书专用控件
   小弹窗（.wb-mini-body）与条目编辑器（.wb-editor-modal）里存在
   既无 wb-input 类、也不在 .form-group 下的裸控件（#wb-name-input、
   #wb-scope-select、#wb-target-select…），一并纳入美化范围。 */
.wb-mini-body :where(input):where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [hidden])),
.wb-mini-body :where(select, textarea),
.wb-editor-modal :where(input):where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [hidden])),
.wb-editor-modal :where(select, textarea) {
    box-sizing: border-box;
    width: 100%;
    padding: 8px 10px;
    border-radius: var(--ui-radius);
    border: 1px solid var(--ui-field-border);
    background-color: var(--ui-field-bg);
    color: var(--ui-field-text);
    font-family: inherit;
    font-size: .88em;
    line-height: 1.5;
    outline: none;
    min-width: 0;
    transition: border-color .18s, box-shadow .18s, background-color .18s;
}

.wb-input,
.wb-select,
.wb-textarea {
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    padding: 8px 10px;
    border-radius: var(--ui-radius);
    border: 1px solid var(--ui-field-border);
    background-color: var(--ui-field-bg);
    color: var(--ui-field-text);
    font-family: inherit;
    font-size: .88em;
    line-height: 1.5;
    outline: none;
    transition: border-color .18s, box-shadow .18s, background-color .18s;
}

/* hover / focus 统一态 */
.wb-mini-body :where(input, select, textarea):hover,
.wb-editor-modal :where(input, select, textarea):hover,
.wb-input:hover, .wb-select:hover, .wb-textarea:hover {
    background-color: var(--ui-field-bg-hover);
    border-color: #565c6b;
}
.wb-mini-body :where(input, select, textarea):focus,
.wb-editor-modal :where(input, select, textarea):focus,
.wb-input:focus, .wb-select:focus, .wb-textarea:focus {
    border-color: var(--accent-gold);
    box-shadow: var(--ui-focus-ring);
    background-color: var(--ui-field-bg-hover);
}
.wb-mini-body :where(input, textarea)::placeholder,
.wb-editor-modal :where(input, textarea)::placeholder,
.wb-input::placeholder,
.wb-textarea::placeholder { color: var(--ui-field-placeholder); opacity: 1; }

/* textarea：条目内容框要能纵向拉伸（autoGrow 会写内联 height，故不锁 min-height） */
.wb-mini-body :where(textarea),
.wb-editor-modal :where(textarea),
.wb-textarea { resize: vertical; }

/* 数字框保持窄身：全书深度框与条目深度框都带 wb-input--num；
   小弹窗里目前没有 number，一并给同样的窄宽度以免将来出现整行数字框。 */
.wb-input--num { width: 66px; flex: 0 0 auto; text-align: center; }
.wb-mini-body :where(input[type="number"]),
.wb-editor-modal :where(input[type="number"]) { width: 66px; text-align: center; }

/* 条目卡片头部是 flex 行：这里的控件靠 flex 伸缩，不吃 width:100% */
.wb-entry-head > :where(input, select) { width: auto; }
.wb-entry-name { flex: 1 1 190px; font-weight: 600; }
.wb-toolbar-field :where(input) { width: 66px; }
/* 上面那条 width:auto 会连带把「深度」数字框也放宽，这里补回窄尺寸。
   写在后面是为了在同特异性 (0,1,0) 下按「后出现者优先」胜出。 */
.wb-entry-head > .wb-input--num { width: 66px; flex: 0 0 auto; }

/* 下拉箭头 */
.wb-select,
.wb-mini-body :where(select),
.wb-editor-modal :where(select) {
    -webkit-appearance: none;
    appearance: none;
    cursor: pointer;
    padding-right: 28px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23e6c78a' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
    background-repeat: no-repeat;
    background-position: right 8px center;
    background-size: 14px 14px;
}
.wb-mini-body option, .wb-editor-modal option, .wb-select option { background: #2d303a; color: #ececf1; }
.wb-select--strat { flex: 0 0 auto; min-width: 126px; }
.wb-select--pos { flex: 0 0 auto; min-width: 118px; }
.wb-select--strat option[value="constant"] { color: #7fc4ff; }
.wb-select--strat option[value="normal"] { color: #8fd18f; }
.wb-select--strat option[value="selective"] { color: #f0d48a; }

/* 3.6 表单字段组（弹窗内） */
.wb-field { margin-bottom: 14px; }
.wb-field > label {
    display: block;
    margin-bottom: 6px;
    font-size: .82em;
    color: #a8afc0;
    letter-spacing: .01em;
}
.wb-field--inline { display: grid; grid-template-columns: 74px 1fr; align-items: start; gap: 10px; margin-bottom: 9px; }
.wb-field--inline > label { margin: 0; padding-top: 9px; }
.wb-row { display: flex; gap: 12px; }
.wb-row--2 > .wb-field { flex: 1 1 0; min-width: 0; }
.wb-req {
    margin-left: 4px;
    padding: 1px 6px;
    border-radius: 4px;
    background: rgba(229, 115, 115, .16);
    color: #ef8a8a;
    font-size: .82em;
    font-weight: 600;
}
.wb-hint-inline { color: var(--text-muted, #888); font-size: .85em; font-weight: 400; }
.wb-dialog-hint {
    display: flex;
    gap: 7px;
    align-items: flex-start;
    margin: 4px 0 0;
    padding: 9px 11px;
    border-radius: 9px;
    border-left: 2px solid rgba(var(--accent-gold-rgb), .55);
    background: rgba(var(--accent-gold-rgb), .07);
    color: #b9bfd0;
    font-size: .78em;
    line-height: 1.6;
}
.wb-dialog-hint i { color: var(--accent-gold); flex: 0 0 auto; }
.wb-dialog-hint b { color: var(--accent-gold); }

/* 3.7 小弹窗（创建书 / 新建条目 / 确认删除） */
.wb-mini-mask {
    position: fixed;
    inset: 0;
    z-index: 10002;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 18px;
    background: rgba(8, 9, 12, .72);
    backdrop-filter: blur(3px);
    animation: wbMiniFade .18s ease-out;
}
.wb-mini-panel {
    width: min(520px, 96vw);
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    border: 1px solid #454a57;
    border-radius: 14px;
    background: linear-gradient(180deg, #32353f, #2b2e37);
    box-shadow: 0 24px 60px rgba(0, 0, 0, .55);
    animation: wbMiniUp .22s cubic-bezier(.2, .8, .3, 1);
}
.wb-mini-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 15px 18px;
    border-bottom: 1px solid #3d414d;
    flex: 0 0 auto;
}
.wb-mini-head h3 { margin: 0; font-size: 1.05em; color: var(--accent-gold); }
.wb-mini-x {
    background: none;
    border: none;
    color: #9aa1b2;
    font-size: 1.35em;
    line-height: 1;
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 6px;
    transition: color .18s, background .18s;
}
.wb-mini-x:hover { color: #fff; background: rgba(255, 255, 255, .08); }
.wb-mini-body { padding: 18px; overflow-y: auto; flex: 1 1 auto; }
.wb-mini-foot {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    padding: 13px 18px;
    border-top: 1px solid #3d414d;
    flex: 0 0 auto;
}
@keyframes wbMiniFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes wbMiniUp { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }

/* 3.8 条目编辑器：工具栏吸顶
   （用户点名：「添加条目」要跟「完成并关闭」一样常驻顶部，
     条目一多就不用自己先滑到底创建、再滑回顶部编辑。） */
.wb-editor-modal { z-index: 10001; }
.wb-editor-modal .modal-content { overflow: hidden; }
.wb-editor-title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 1.12em; min-width: 0; }
.wb-editor-title i { color: var(--accent-gold); }
.wb-editor-bookname { color: var(--accent-gold); }
.wb-editor-scope { color: var(--text-muted, #888); font-size: .72em; }
.wb-editor-body { padding: 0; }
/* 上面刻意不再写 display:flex; flex-direction:column ——
   flex 子项默认 flex-shrink:1，会把条目列表压缩到刚好填满容器，
   于是容器永远不溢出；而 sticky 只有在「真的发生溢出」时才会吸顶，
   表现就是「添加条目那一排跟着内容一起滚走」。保持块级流式即可。 */

.wb-editor-toolbar {
    position: sticky;
    top: 0;
    z-index: 6;
    flex: 0 0 auto;
    padding: 14px 20px 12px;
    border-bottom: 1px solid #3d414d;
    background: linear-gradient(180deg, #343843 0%, #2f323b 100%);
    box-shadow: 0 6px 16px rgba(0, 0, 0, .3);
}
.wb-toolbar-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.wb-toolbar-field { display: flex; align-items: center; gap: 9px; }
.wb-toolbar-field > label { margin: 0; font-size: .82em; color: #a8afc0; white-space: nowrap; }
.wb-toolbar-hint { margin: 0; flex: 1 1 210px; min-width: 0; color: var(--text-muted, #888); font-size: .74em; line-height: 1.5; }
.wb-toolbar-actions { display: flex; gap: 9px; margin-left: auto; flex: 0 0 auto; }
.wb-toolbar-actions .btn { padding: 7px 14px; font-size: .84em; border-radius: 9px; }

.wb-toolbar-stat {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 10px;
    padding-top: 9px;
    border-top: 1px dashed rgba(66, 70, 82, .9);
    color: #979eb0;
    font-size: .76em;
}
.wb-toolbar-stat b { color: #dfe3ec; font-weight: 600; }
.wb-autosave { margin-left: auto; display: inline-flex; align-items: center; gap: 4px; color: #7cb87c; opacity: .9; }

.wb-entry-list { padding: 14px 20px 22px; display: flex; flex-direction: column; gap: 11px; }

/* 卡片必须是 flex:0 0 auto：列表容器用 flex 排布只是为了拿 gap 间距，
   若允许收缩，条目一多卡片会被压扁、内容框直接看不见也点不到。 */
.wb-entry-list > .wb-entry-card { flex: 0 0 auto; }

/* 3.9 条目卡片 */
.wb-entry-card {
    border: 1px solid #3f4450;
    border-radius: 12px;
    background: rgba(255, 255, 255, .028);
    padding: 10px 12px 12px;
    transition: border-color .18s, background .18s;
}
.wb-entry-card:hover { border-color: rgba(var(--accent-gold-rgb), .4); }
.wb-entry-card.is-disabled { opacity: .5; }
.wb-entry-card.is-disabled .wb-entry-head { filter: grayscale(.5); }
.wb-entry-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.wb-entry-index {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: rgba(var(--accent-gold-rgb), .14);
    color: var(--accent-gold);
    font-size: .74em;
    font-weight: 600;
}
.wb-entry-depth { display: inline-flex; align-items: center; gap: 5px; color: #98a0b0; font-size: .76em; white-space: nowrap; }
.wb-entry-order { display: inline-flex; gap: 2px; }
.wb-entry-del { flex: 0 0 auto; width: 34px; justify-content: center; padding: 5px 0; }
.wb-entry-del:hover { border-color: #e57373; color: #e57373; }
.wb-entry-fields { margin-top: 10px; padding-top: 10px; border-top: 1px dashed #424652; }

.wb-icon-btn {
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid #4b5060;
    border-radius: 7px;
    background: transparent;
    color: #a8afc0;
    font-size: 1.05em;
    cursor: pointer;
    transition: border-color .16s, color .16s, background .16s;
}
.wb-icon-btn:hover:not(:disabled) { border-color: var(--accent-gold); color: var(--accent-gold); background: rgba(var(--accent-gold-rgb), .1); }
.wb-icon-btn:disabled { opacity: .3; cursor: not-allowed; }

/* 世界书列表滚动条（列表容器带内联 overflow-y，这里只补观感） */
#worldbook-list { padding-right: 4px; }
#worldbook-list::-webkit-scrollbar { width: 6px; }
#worldbook-list::-webkit-scrollbar-thumb { background: #555a68; border-radius: 3px; }

/* ---------- 4. 快捷键设置行 ---------- */
.shortcut-row > label { display: block; margin-bottom: 7px; color: #a8afc0; font-size: .86em; }
.shortcut-input-wrap { display: flex; gap: 8px; align-items: stretch; }
/* 特异性要点：style.css 的 `.form-group input`（0,1,1）带着 width:100%，
   若这里写成 `:where(...)`（0,1,0）就会被它压过，输入框撑满整行、
   把右侧两个按钮挤出去。故用 .form-group 前缀抬到 (0,3,0)。 */
.form-group .shortcut-input-wrap .shortcut-setting-input {
    flex: 1 1 auto;
    width: auto;
    min-width: 0;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    letter-spacing: .04em;
}
.shortcut-setting-input.capturing {
    border-color: var(--accent-gold);
    box-shadow: var(--ui-focus-ring);
    background: rgba(var(--accent-gold-rgb), .08);
    color: var(--accent-gold);
}
.shortcut-input-wrap .btn { flex: 0 0 auto; padding: 0 12px; }
.field-hint { display: block; margin-top: 6px; color: var(--text-muted, #888); font-size: .74em; line-height: 1.6; }

/* 帮助面板脚注 + 浏览器保留键警示 */
.shortcut-help-note {
    display: flex;
    gap: 7px;
    align-items: flex-start;
    margin: 16px 0 0;
    padding: 9px 11px;
    border-radius: 9px;
    border-left: 2px solid rgba(var(--accent-gold-rgb), .5);
    background: rgba(var(--accent-gold-rgb), .07);
    color: #b9bfd0;
    font-size: .76em;
    line-height: 1.6;
}
.shortcut-help-note i { color: var(--accent-gold); flex: 0 0 auto; }
.shortcut-list li .shortcut-reserved {
    font-style: normal;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 4px;
    background: rgba(229, 115, 115, .16);
    color: #ef8a8a;
    font-size: .82em;
}

kbd {
    display: inline-block;
    min-width: 20px;
    padding: 1px 6px;
    margin: 0 2px;
    border: 1px solid #4d5364;
    border-bottom-width: 2px;
    border-radius: 5px;
    background: #3b3f4b;
    color: #e8eaf1;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .9em;
    line-height: 1.5;
    text-align: center;
    white-space: nowrap;
}
body.light-theme kbd { background: #fff; border-color: #cdbb9f; color: #33291c; }

/* ghost 按钮（工具条上的图标按钮） */
.btn-ghost {
    background: transparent;
    border: 1px solid #4b5060;
    color: #a8afc0;
    transition: border-color .16s, color .16s, background .16s;
}
.btn-ghost:hover { border-color: var(--accent-gold); color: var(--accent-gold); background: rgba(var(--accent-gold-rgb), .09); }

/* ---------- 5. 浅色主题微调 ---------- */
/* style.css 的 `body.light-theme .form-group input`（特异性 0,2,2）盖过了暗色
   主题那套 hover/focus（0,2,1），会让浅色下「聚焦边框不变色、内阴影吃掉光晕、
   hover 边框还是灰的」。这里用 (0,3,1) 把交互反馈拿回来。 */
body.light-theme .form-group input:focus,
body.light-theme .form-group select:focus,
body.light-theme .form-group textarea:focus,
body.light-theme .modal-body input:focus,
body.light-theme .modal-body select:focus,
body.light-theme .modal-body textarea:focus,
body.light-theme .tab-content input:focus,
body.light-theme .tab-content select:focus,
body.light-theme .tab-content textarea:focus {
    border-color: var(--accent-gold);
    background-color: #ffffff;
    box-shadow: var(--ui-focus-ring);
}
body.light-theme .form-group input:hover,
body.light-theme .form-group select:hover,
body.light-theme .form-group textarea:hover,
body.light-theme .modal-body input:hover,
body.light-theme .modal-body select:hover,
body.light-theme .modal-body textarea:hover,
body.light-theme .tab-content input:hover,
body.light-theme .tab-content select:hover,
body.light-theme .tab-content textarea:hover {
    background-color: #ffffff;
    border-color: #bfae91;
}

body.light-theme .wb-mini-panel { background: linear-gradient(180deg, #fffdf8, #f8f2e6); border-color: #d3c6b1; }
body.light-theme .wb-mini-head,
body.light-theme .wb-mini-foot { border-color: #e2d7c4; }
body.light-theme .wb-mini-x { color: #8a7760; }
body.light-theme .wb-editor-toolbar { background: linear-gradient(180deg, #fbf6ec, #f5eee0); border-color: #e2d7c4; }
body.light-theme .wb-toolbar-stat { color: #6b7180; }
body.light-theme .wb-toolbar-stat b { color: #2b2f3a; }
body.light-theme .wb-book-card,
body.light-theme .wb-entry-card { background: rgba(255, 255, 255, .62); border-color: #e0d5c2; }
body.light-theme .wb-mini-body option,
body.light-theme .wb-editor-modal option,
body.light-theme .wb-select option { background: #fffdf8; color: #2b2f3a; }
body.light-theme .wb-mini-body :where(select),
body.light-theme .wb-editor-modal :where(select),
body.light-theme .wb-select {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23a2802f' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
}
body.light-theme .wb-empty { border-color: #ddd0b9; background: rgba(255, 255, 255, .5); color: #6b7180; }
body.light-theme .btn-ghost { border-color: #d3c6b1; color: #6b7180; }
body.light-theme .modal-body :where(input[type="file"])::file-selector-button,
body.light-theme .tab-content :where(input[type="file"])::file-selector-button { background: #efe6d5; color: #33291c; }

/* ---------- 6. 移动端收敛 ---------- */
@media (max-width: 640px) {
    .wb-toolbar-actions { margin-left: 0; width: 100%; }
    .wb-toolbar-actions .btn { flex: 1 1 0; justify-content: center; }
    .wb-toolbar-stat { font-size: .72em; }
    .wb-autosave { display: none; }
    .wb-field--inline { grid-template-columns: 1fr; gap: 4px; }
    .wb-field--inline > label { padding-top: 0; }
    .wb-entry-name { flex-basis: 100%; }
    .wb-editor-toolbar { padding: 12px 14px 10px; }
    .wb-entry-list { padding: 12px 14px 18px; }
    .wb-select--strat, .wb-select--pos { flex: 1 1 46%; min-width: 0; }
    .wb-mini-panel { width: 98vw; }
    .wb-row { flex-direction: column; gap: 0; }
}

/* 帮助面板要能从「设置」等其它弹窗之上唤出（按 ? 时焦点往往还在设置弹窗里）。
   两者同为 .modal-overlay（z-index:1000），而 #shortcut-help-modal 在 DOM 里
   排在 #ai-settings-modal 之前 —— 后面的同级元素绘制在上层，于是帮助面板被
   设置弹窗整个盖住，表现就是「按了 ? 什么也没发生」。抬高一层解决。 */
#shortcut-help-modal { z-index: 1600; }

/* 尊重「减少动效」偏好 */
@media (prefers-reduced-motion: reduce) {
    .wb-mini-mask, .wb-mini-panel { animation: none; }
    .wb-input, .wb-select, .wb-textarea, .btn-ghost, .wb-switch-track i { transition: none; }
}

/* ============================================================
 * 12. 功能专用模型面板（设置 → AI 配置 → 功能专用模型）
 *     以及编辑角色页的「提示词优化器」
 *     —— 两块都默认折叠，靠 <details> 控制，样式与深色面板统一。
 * ============================================================ */

/* ---------- 12.1 功能专用模型 ---------- */
.fm-block .fm-item {
    border: 1px solid var(--ui-field-border, #454a57);
    border-radius: 10px;
    background: rgba(255, 255, 255, .025);
    margin-bottom: 8px;
    overflow: hidden;
}
.fm-block .fm-item > summary {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    cursor: pointer;
    list-style: none;
    user-select: none;
    font-size: .9em;
    color: var(--ui-field-text, #ececf1);
    transition: background .18s;
}
.fm-block .fm-item > summary::-webkit-details-marker { display: none; }
.fm-block .fm-item > summary:hover { background: rgba(230, 199, 138, .08); }
.fm-block .fm-item > summary > i { color: var(--accent-gold, #e6c78a); }
.fm-block .fm-item > summary > span { flex: 0 0 auto; font-weight: 600; }
.fm-block .fm-item .fm-state {
    margin-left: auto;
    font-style: normal;
    font-size: .78em;
    color: #8b90a0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 45%;
}
.fm-block .fm-item .fm-state.fm-state-on { color: #72d572; }
.fm-block .fm-item .fm-body {
    padding: 4px 12px 12px;
    border-top: 1px dashed rgba(255, 255, 255, .1);
}
.fm-block .fm-hint { margin: 8px 0 10px; font-size: .78em; color: #8b90a0; line-height: 1.6; }
.fm-block .fm-adv {
    margin-top: 4px;
    border: 1px dashed rgba(255, 255, 255, .12);
    border-radius: 8px;
    background: rgba(0, 0, 0, .12);
}
.fm-block .fm-adv > summary {
    padding: 7px 10px;
    cursor: pointer;
    list-style: none;
    font-size: .8em;
    color: #9aa0b0;
    user-select: none;
}
.fm-block .fm-adv > summary::-webkit-details-marker { display: none; }
.fm-block .fm-adv > summary:hover { color: var(--accent-gold, #e6c78a); }
.fm-block .fm-adv .fm-body { padding: 2px 10px 10px; border-top: 0; }
.fm-block .fm-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 6px; }

/* ---------- 12.2 提示词优化器（编辑角色页） ---------- */
.prompt-doctor { margin-top: 10px; }
.prompt-doctor-block {
    border: 1px solid var(--ui-field-border, #454a57);
    border-radius: 10px;
    background: linear-gradient(180deg, rgba(230, 199, 138, .05), rgba(255, 255, 255, .02));
    overflow: hidden;
}
.prompt-doctor-block > summary {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 9px 12px;
    cursor: pointer;
    list-style: none;
    user-select: none;
    font-size: .9em;
    font-weight: 600;
    color: var(--accent-gold, #e6c78a);
    transition: background .18s;
}
.prompt-doctor-block > summary::-webkit-details-marker { display: none; }
.prompt-doctor-block > summary:hover { background: rgba(230, 199, 138, .1); }
.prompt-doctor-block > summary .pd-model {
    margin-left: auto;
    font-style: normal;
    font-weight: 400;
    font-size: .78em;
    color: #8b90a0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 48%;
}
.prompt-doctor-block > summary .pd-model b { color: #9fd3ff; font-weight: 600; }
.prompt-doctor-block .pd-inner { padding: 4px 12px 12px; }
.prompt-doctor-block .pd-tip { margin: 6px 0 10px; font-size: .78em; color: #9aa0b0; line-height: 1.7; }
.prompt-doctor-block .pd-note-label { display: block; font-size: .8em; color: #9aa0b0; margin-bottom: 4px; }
.prompt-doctor-block .pd-note { width: 100%; margin-bottom: 8px; }
.prompt-doctor-block .pd-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.prompt-doctor-block .pd-result { margin-top: 12px; }
.prompt-doctor-block .pd-cols {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}
.prompt-doctor-block .pd-col { display: flex; flex-direction: column; min-width: 0; }
.prompt-doctor-block .pd-col-head {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: .78em;
    color: #9aa0b0;
    margin-bottom: 5px;
}
.prompt-doctor-block .pd-col-head i { color: var(--accent-gold, #e6c78a); }
.prompt-doctor-block .pd-col textarea {
    width: 100%;
    min-height: 210px;
    max-height: 46vh;
    resize: vertical;
    font-size: .82em;
    line-height: 1.7;
    font-family: inherit;
}
.prompt-doctor-block .pd-notes { margin-top: 10px; }
.prompt-doctor-block .pd-notes-body {
    margin: 0;
    padding: 9px 11px;
    border-radius: 8px;
    border: 1px dashed rgba(255, 255, 255, .12);
    background: rgba(0, 0, 0, .18);
    color: #cfd3de;
    font-family: inherit;
    font-size: .8em;
    line-height: 1.75;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 170px;
    overflow: auto;
}
.prompt-doctor-block .pd-confirm { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.prompt-doctor-block .pd-result[hidden] { display: none; }
.prompt-doctor-block .pd-actions [hidden],
.prompt-doctor-block [data-pd-close][hidden] { display: none; }

/* 移动端：角色弹窗里两栏改单栏，避免文本框被挤成一条缝 */
@media (max-width: 720px) {
    .prompt-doctor-block .pd-cols { grid-template-columns: 1fr; }
    .prompt-doctor-block .pd-col textarea { min-height: 140px; }
}

body.light-theme .prompt-doctor-block,
body.light-theme .fm-block .fm-item { border-color: #d3c6b1; background: rgba(0, 0, 0, .02); }
body.light-theme .prompt-doctor-block .pd-notes-body { background: #fffdf9; color: #3b4050; border-color: #e0d6c4; }
body.light-theme .fm-block .fm-adv { background: rgba(0, 0, 0, .03); border-color: #e0d6c4; }

/* ---------- 12.3 知识库文档预览 / 编辑弹窗 ---------- */
/* 它是在「系统设置」弹窗之上打开的二级弹窗，必须盖住设置弹窗（两者默认同为 1000） */
#kb-doc-modal { z-index: 1400; }
.kb-doc-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    padding: 9px 11px;
    border-radius: 8px;
    border: 1px solid var(--ui-field-border, #454a57);
    background: rgba(255, 255, 255, .03);
    font-size: .78em;
    color: #9aa0b0;
}
.kb-doc-meta span { white-space: nowrap; }
.kb-doc-meta a { color: #9fd3ff; text-decoration: none; }
.kb-doc-meta a:hover { text-decoration: underline; }
.kb-doc-modal textarea#kb-doc-content {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.kb-file-row:hover {
    background: rgba(230, 199, 138, .09) !important;
    border-color: rgba(230, 199, 138, .3) !important;
}

/* ---------- 12.4 自定义加载界面（实验室） ---------- */
.boot-preview {
    position: relative;
    width: 100%;
    height: 168px;
    border-radius: 10px;
    border: 1px dashed var(--ui-field-border, #454a57);
    background: repeating-conic-gradient(rgba(255, 255, 255, .04) 0% 25%, transparent 0% 50%) 50% / 18px 18px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 10px;
}
.boot-preview img,
.boot-preview video {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    display: block;
}
.boot-preview.cover img,
.boot-preview.cover video { width: 100%; height: 100%; object-fit: cover; }
.boot-preview .boot-empty { font-size: .8em; color: #8b90a0; }
.boot-preview.is-video video { outline: none; }
.boot-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.boot-row .btn, .boot-row input[type="text"], .boot-row input[type="url"] { flex: 1 1 auto; min-width: 0; }
.boot-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.boot-hint { font-size: .76em; color: #8b90a0; line-height: 1.7; margin-top: 8px; }
.boot-hint b { color: var(--accent-gold, #e6c78a); }

/* ---------- 12.5 加载界面本体（index.html 顶部 #boot-splash） ---------- */
#boot-splash {
    position: fixed;
    inset: 0;
    z-index: 99999;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #14161d;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .34s ease, visibility 0s linear .34s;
}
#boot-splash.boot-show { opacity: 1; visibility: visible; pointer-events: auto; transition: opacity .34s ease; }
#boot-splash .boot-slot { position: absolute; inset: 0; }
#boot-splash .boot-media {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    background: #14161d;
}
#boot-splash .boot-media.contain { object-fit: contain; }
#boot-splash .boot-dim { position: absolute; inset: 0; background: rgba(10, 11, 16, .35); pointer-events: none; }
/* 副标题：改为脱离文档流的绝对定位，位置由 #boot-splash[data-caption-pos] 决定。
   原先它是 flex item（position:relative），被父级 align-items:center 拉到画面正中，
   与设置里「显示在画面下方」的描述相互矛盾，也和进度条抢位置。 */
#boot-splash .boot-caption {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    width: min(92%, 760px);
    z-index: 2;
    text-align: center;
    color: #fff;
    font-size: clamp(.85em, 2.4vw, 1.05em);
    letter-spacing: .12em;
    padding: 0 24px;
    text-shadow: 0 2px 12px rgba(0, 0, 0, .8);
    pointer-events: none;
    transition: opacity .3s ease;
}
/* --boot-bars-bottom 必须定义在 #boot-splash 自身上：
   原先写在 .boot-bars 规则里，只对进度条元素生效，
   .boot-caption（#boot-splash 的直接子元素、并非 .boot-bars 的后代）取不到该变量，
   导致 bottom: calc(var(--boot-bars-bottom) + 18px) 整条声明在计算值阶段失效，
   top/bottom 双双 auto → 绝对定位元素退回静态位置，而静态位置又被父级
   align-items:center 拉到画面正中 —— 这就是「副标题选了显示在下方却出现在中间」的原因。 */
#boot-splash { --boot-bars-bottom: clamp(26px, 8vh, 72px); }
#boot-splash .boot-bars { bottom: var(--boot-bars-bottom); }
#boot-splash[data-caption-pos="bottom"] .boot-caption,
#boot-splash:not([data-caption-pos]) .boot-caption {
    top: auto;
    bottom: calc(var(--boot-bars-bottom) + 18px);
}
#boot-splash[data-caption-pos="middle"] .boot-caption {
    top: 50%;
    bottom: auto;
    transform: translate(-50%, -50%);
}
#boot-splash[data-caption-pos="top"] .boot-caption {
    top: calc(var(--boot-bars-bottom) - 6px);
    bottom: auto;
}
#boot-splash .boot-bars {
    position: absolute;
    left: 50%;
    bottom: clamp(26px, 8vh, 72px);
    transform: translateX(-50%);
    width: min(190px, 42vw);
    height: 3px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .18);
    overflow: hidden;
    z-index: 2;
}
#boot-splash .boot-bars i {
    display: block;
    height: 100%;
    width: 40%;
    border-radius: 999px;
    background: linear-gradient(90deg, transparent, #e6c78a, transparent);
    animation: bootSlide 1.25s ease-in-out infinite;
}
@keyframes bootSlide { 0% { transform: translateX(-110%) } 100% { transform: translateX(280%) } }
#boot-splash .boot-skip {
    position: absolute;
    right: 18px;
    bottom: 16px;
    z-index: 3;
    height: 30px;
    padding: 0 14px;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .22);
    background: rgba(0, 0, 0, .35);
    color: rgba(255, 255, 255, .78);
    font-size: .78em;
    cursor: pointer;
}
#boot-splash .boot-skip:hover { background: rgba(0, 0, 0, .55); color: #fff; }
body.compatibility-mode #boot-splash .boot-bars i { animation: none; width: 100%; }
body.compatibility-mode #boot-splash { transition: none; }

/* ============================================================
 * 13. 插件参数：长文本参数用 textarea（上下文压缩器的「压缩提示词」）
 *     原 .plugin-params 是 auto-fit 网格，长提示词被挤成一小格完全没法编辑，
 *     这里让含 textarea 的那一格独占整行。
 * ============================================================ */
/* 不用 :has()（旧内核不支持会导致整条规则失效），改由 JS 直接加 .plugin-param-wide */
.plugin-params .plugin-param-wide {
    grid-column: 1 / -1;
}
.plugin-params textarea {
    display: block;
    width: 100%;
    margin-top: 5px;
    box-sizing: border-box;
    min-height: 84px;
    resize: vertical;
    line-height: 1.7;
    font-size: .84em;
    font-family: inherit;
}

/* ============================================================
 * 14. 分组管理界面（#group-manager-modal，右键 / 长按分组标题进入）
 *     替代原来的两次原生 prompt。列表每行 = 组名 + 角色数 + 重命名 / 删除，
 *     底部一个「新建分组」。样式对齐站内 .modal-* / .friend-group-option 语言，
 *     但操作按钮做成正方形图标按钮，比原生弹窗好点得多（移动端尤其明显）。
 * ============================================================ */
#group-manager-modal .modal-body {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.gm-hint {
    font-size: .8em;
    line-height: 1.65;
    color: #98a0b3;
    padding: 9px 11px;
    border-radius: 10px;
    background: rgba(230, 199, 138, .07);
    border: 1px solid rgba(230, 199, 138, .18);
}
.gm-list {
    display: flex;
    flex-direction: column;
    gap: 7px;
    /* 分组可能很多：限高滚动，避免把弹窗顶出屏幕 */
    max-height: min(46vh, 340px);
    overflow-y: auto;
    padding-right: 2px;
}
.gm-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: 10px;
    background: #32353f;
    border: 1px solid transparent;
    transition: background .16s ease, border-color .16s ease;
}
.gm-item:hover { background: #3b3f4a; }
/* 从哪个分组标题进来的，那一条高亮一下，视线不用重新找 */
.gm-item.is-focused {
    border-color: rgba(230, 199, 138, .55);
    background: rgba(230, 199, 138, .09);
}
.gm-name {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
    flex: 1 1 auto;
    font-size: .92em;
    font-weight: 500;
    /* 组名过长时省略号，别把右边的按钮挤没 */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.gm-name i { color: var(--accent-gold, #e6c78a); flex: 0 0 auto; }
.gm-count {
    flex: 0 0 auto;
    font-size: .76em;
    color: #8b90a0;
    padding: 2px 8px;
    border-radius: 999px;
    background: rgba(255, 255, 255, .06);
}
.gm-ops { flex: 0 0 auto; display: inline-flex; gap: 6px; margin-left: auto; }
.gm-op {
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, .14);
    background: rgba(255, 255, 255, .05);
    color: inherit;
    font-size: .95em;
    cursor: pointer;
    transition: background .16s ease, color .16s ease, transform .12s ease;
}
.gm-op:hover:not(:disabled) { background: rgba(230, 199, 138, .16); color: var(--accent-gold, #e6c78a); }
.gm-op:active:not(:disabled) { transform: scale(.94); }
.gm-op-danger:hover:not(:disabled) { background: rgba(255, 90, 90, .18); color: #ff8b8b; border-color: rgba(255, 90, 90, .35); }
.gm-op:disabled { opacity: .32; cursor: not-allowed; }
.gm-empty { text-align: center; color: #7d8291; font-size: .85em; padding: 18px 0; }
.gm-create-btn { width: 100%; justify-content: center; gap: 6px; }

/* 移动端：按钮加大到 34px（拇指更好按），组名仍可省略号 */
@media (max-width: 768px) {
    .gm-list { max-height: 42vh; }
    .gm-item { padding: 8px 10px; gap: 8px; }
    .gm-op { width: 34px; height: 34px; }
    .gm-count { font-size: .7em; padding: 2px 6px; }
    /* 窄屏下说明文字压一小即可，不必占掉半个屏幕 */
    .gm-hint { font-size: .74em; line-height: 1.55; }
}

body.light-theme .gm-item { background: #f2f3f7; }
body.light-theme .gm-item:hover { background: #e9ebf1; }
body.light-theme .gm-item.is-focused { background: rgba(230, 199, 138, .16); }
body.light-theme .gm-count { background: rgba(0, 0, 0, .06); color: #6b7180; }
body.light-theme .gm-op { background: rgba(0, 0, 0, .04); border-color: rgba(0, 0, 0, .14); }
body.light-theme .gm-name i { color: #b8912f; }

/* ---------- 论坛分享卡片(主站聊天里的帖子分享) ---------- */
.forum-share-card {
    display: block;
    max-width: 320px;
    padding: 12px 14px;
    border-radius: 12px;
    border: 1px solid rgba(230, 199, 138, .45);
    background: linear-gradient(160deg, #2b2f3a, #20232c);
    color: #e8e9ee;
    cursor: pointer;
    transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.forum-share-card:hover,
.forum-share-card:focus-visible {
    border-color: #e6c78a;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .35);
    outline: none;
}
.forum-share-card:active { transform: scale(.98); }
.forum-share-card .fsc-tag { font-size: .72em; color: #e6c78a; display: flex; align-items: center; gap: 4px; margin-bottom: 6px; }
.forum-share-card .fsc-title { font-weight: 600; font-size: .95em; line-height: 1.4; word-break: break-word; }
.forum-share-card .fsc-meta { font-size: .74em; color: #9aa0ad; margin-top: 4px; }
.forum-share-card .fsc-excerpt { font-size: .82em; color: #c9ccd6; margin-top: 6px; line-height: 1.5; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.forum-share-card .fsc-hint { font-size: .74em; color: #e6c78a; margin-top: 8px; text-align: right; }
body.light-theme .forum-share-card { background: #fffdf9; color: #2b2f3a; border-color: #d3c6b1; }
body.light-theme .forum-share-card .fsc-excerpt { color: #5b6170; }

/* ====== context-compressor.css ====== */
/* ============================================================
   上下文压缩器（默认插件）样式
   ------------------------------------------------------------
   入口按钮复用 .icon-btn，只加一点强调色；面板浮在聊天区右上。
   选择模式（body.cc-picking）下每条消息左侧出现勾选按钮。
   ============================================================ */

.icon-btn.ctx-compress-entry { color: #9fd3ff; }
.icon-btn.ctx-compress-entry.active { background: rgba(159, 211, 255, .18); box-shadow: 0 0 0 1px rgba(159, 211, 255, .4) inset; }

.cc-panel {
    position: absolute;
    top: 58px;
    right: 14px;
    z-index: 900;
    width: min(380px, calc(100% - 24px));
    max-height: calc(100% - 120px);
    overflow-y: auto;
    border: 1px solid #454a57;
    border-radius: 14px;
    background: linear-gradient(180deg, #2c2f38, #23262d);
    box-shadow: 0 22px 60px rgba(0, 0, 0, .55);
    color: #dfe2ea;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity .18s ease, transform .18s ease, visibility 0s linear .18s;
}
.cc-panel.show { opacity: 1; visibility: visible; transform: none; transition: opacity .18s ease, transform .18s ease; }

.cc-head {
    position: sticky;
    top: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 11px 13px;
    background: #2c2f38;
    border-bottom: 1px solid #3d424e;
    color: var(--accent-gold, #e6c78a);
    font-size: .95em;
    z-index: 2;
}
.cc-head b { flex: 1 1 auto; }
.cc-x {
    width: 24px; height: 24px;
    border: 0; border-radius: 6px;
    background: transparent; color: #9aa0b0;
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
}
.cc-x:hover { background: rgba(255, 255, 255, .1); color: #fff; }

.cc-body { padding: 12px 13px 14px; }
.cc-desc { margin: 0 0 8px; font-size: .78em; line-height: 1.7; color: #9aa0b0; }
.cc-desc b { color: var(--accent-gold, #e6c78a); }
.cc-count { margin: 0 0 12px; font-size: .78em; color: #8b90a0; }
.cc-count b { color: #9fd3ff; }

.cc-section {
    padding: 10px 0 12px;
    border-top: 1px dashed rgba(255, 255, 255, .1);
    margin-top: 4px;
}
.cc-section-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: .84em;
    font-weight: 600;
    color: #cfd3de;
    margin-bottom: 8px;
}
.cc-toggle {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: .86em;
    font-weight: 400;
    color: #9aa0b0;
    cursor: pointer;
}
.cc-field {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    font-size: .8em;
    color: #a7adbe;
    margin-bottom: 7px;
}
.cc-field input {
    width: 68px;
    padding: 5px 7px;
    border-radius: 6px;
    border: 1px solid #454a57;
    background: #32353f;
    color: #ececf1;
    font-size: .95em;
}
.cc-field input:focus { border-color: var(--accent-gold, #e6c78a); outline: none; }
.cc-field:last-of-type { margin-bottom: 8px; }
.cc-tip { margin: 0 0 8px; font-size: .74em; line-height: 1.65; color: #8b90a0; }
.cc-range-status {
    min-height: 1.5em;
    margin-bottom: 8px;
    padding: 6px 9px;
    border-radius: 7px;
    border: 1px dashed rgba(159, 211, 255, .35);
    background: rgba(159, 211, 255, .07);
    font-size: .76em;
    color: #a8d8ff;
}
.cc-panel .btn { margin-right: 6px; }
.cc-panel .btn:disabled { opacity: .45; cursor: not-allowed; }
.cc-adv { margin-top: 4px; border-top: 1px dashed rgba(255, 255, 255, .1); padding-top: 8px; }
.cc-adv > summary {
    cursor: pointer;
    list-style: none;
    font-size: .8em;
    color: #9aa0b0;
    display: flex; align-items: center; gap: 6px;
    user-select: none;
}
.cc-adv > summary::-webkit-details-marker { display: none; }
.cc-adv > summary:hover { color: var(--accent-gold, #e6c78a); }
.cc-prompt {
    width: 100%;
    margin-top: 8px;
    padding: 8px 10px;
    border-radius: 8px;
    border: 1px solid #454a57;
    background: #32353f;
    color: #ececf1;
    font-size: .78em;
    line-height: 1.7;
    font-family: inherit;
    resize: vertical;
    box-sizing: border-box;
}

/* ---------- 面板内消息清单（方式二） ---------- */
.cc-list {
    max-height: 240px;
    overflow-y: auto;
    border: 1px solid #3d424e;
    border-radius: 9px;
    background: rgba(0, 0, 0, .22);
    padding: 4px;
    margin-bottom: 8px;
    scrollbar-width: thin;
}
.cc-list::-webkit-scrollbar { width: 7px; }
.cc-list::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .16); border-radius: 4px; }
.cc-row {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 4px 5px;
    border-radius: 6px;
    font-size: .76em;
    color: #b9becb;
    cursor: pointer;
}
.cc-row:hover { background: rgba(255, 255, 255, .06); }
.cc-row.is-picked { background: rgba(159, 211, 255, .13); color: #e2f0ff; }
.cc-row .cc-pick {
    flex: 0 0 auto;
    width: 22px; height: 22px;
    padding: 0;
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: 6px;
    background: rgba(0, 0, 0, .25);
    color: #7d8496;
    cursor: pointer;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 1.05em;
}
.cc-row .cc-pick:hover { border-color: #9fd3ff; color: #9fd3ff; }
.cc-row.is-picked .cc-pick { border-color: #9fd3ff; background: rgba(159, 211, 255, .2); color: #9fd3ff; }
.cc-row .cc-idx { flex: 0 0 auto; width: 30px; text-align: right; color: #6d7385; font-variant-numeric: tabular-nums; }
.cc-row .cc-who { flex: 0 0 auto; width: 34px; font-weight: 600; }
.cc-row .cc-who.mine { color: #9fd3ff; }
.cc-row .cc-who.ai { color: var(--accent-gold, #e6c78a); }
.cc-row .cc-who.sys { color: #8b90a0; }
.cc-row .cc-text { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-empty { padding: 8px 6px; font-size: .78em; color: #8b90a0; text-align: center; margin: 0; }
.cc-mini-btn {
    margin-left: auto;
    height: 22px;
    padding: 0 8px;
    border-radius: 6px;
    border: 1px solid #454a57;
    background: transparent;
    color: #9aa0b0;
    font-size: .82em;
    cursor: pointer;
}
.cc-mini-btn:hover { color: var(--accent-gold, #e6c78a); border-color: var(--accent-gold, #e6c78a); }
/* 气泡压缩摘要：与普通系统消息区分开，一眼看出「这里被压过」 */
.bubble.ctx-summary-bubble {
    background: rgba(159, 211, 255, .09) !important;
    border: 1px dashed rgba(159, 211, 255, .45) !important;
    border-radius: 12px !important;
    width: 100%;
    max-width: 100% !important;
    box-sizing: border-box;
}
body.light-theme .bubble.ctx-summary-bubble { color: #2b3f57 !important; }
body.light-theme .cc-row .cc-pick { background: #fff; border-color: #d3c6b1; color: #8b8577; }
body.light-theme .cc-row.is-picked { background: rgba(60, 120, 200, .12); color: #22344a; }
body.light-theme .cc-list { background: rgba(0, 0, 0, .04); border-color: #e0d6c4; }
body.light-theme .cc-row { color: #4b5263; }
body.light-theme .cc-range-status { background: rgba(60, 120, 200, .08); border-color: rgba(60, 120, 200, .35); color: #2f6ea8; }
body.light-theme .ctx-summary-tag { color: #2f6ea8; }
body.light-theme .cc-mini-btn { color: #7a7266; border-color: #d3c6b1; }
body.light-theme .cc-list::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, .18); }
body.light-theme .cc-prompt:focus { border-color: var(--accent-gold, #b8912f); }
.ctx-summary-tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: .82em;
    color: #9fd3ff;
    margin-bottom: 5px;
    letter-spacing: .03em;
}
.ctx-summary-meta { margin-top: 6px; font-size: .74em; color: #7f889c; }

/* 压缩摘要气泡（历史被折叠成一条） */
.message.is-ctx-summary { justify-content: center; }
.message.is-ctx-summary .message-content { max-width: 88%; align-items: center; }
.message.is-ctx-summary .nickname { display: none; }
.ctx-summary-tag {
    display: flex;
    align-items: center;
    gap: 5px;
    font-size: .74em;
    color: #9fd3ff;
    margin: 2px 0 4px;
    letter-spacing: .02em;
}

@media (max-width: 640px) {
    .cc-panel { top: 50px; right: 8px; left: 8px; width: auto; }
}

/* ------------------------------------------------------------
   移动端 / 触屏优化
   ------------------------------------------------------------
   面板里的勾选框、行高在桌面下合适，但手机上 22px 的命中区根本点不准，
   而这张列表又恰恰是「选区间压缩」唯一的交互入口。 */
@media (pointer: coarse) {
    .cc-row { padding: 7px 6px; gap: 8px; }
    .cc-row .cc-pick { width: 32px; height: 32px; font-size: 1.2em; }
    .cc-row .cc-who { width: auto; max-width: 62px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .cc-list { max-height: 40vh; }
    .cc-field input { min-height: 38px; }
    .cc-panel .btn { min-height: 40px; }
}

@media (max-width: 640px) {
    .cc-panel {
        top: 46px;
        right: 6px;
        left: 6px;
        width: auto;
        /* 面板很长（三种方式 + 高级折叠），小屏下必须能滑到底，
           否则「全部压缩」那个按钮永远在可视区外。 */
        max-height: calc(100% - 60px);
    }
    .cc-head { position: sticky; top: 0; z-index: 2; }
    .cc-row { font-size: .74em; }
    .cc-row .cc-idx { width: 26px; }
    .cc-section-title { font-size: .84em; }
}

body.light-theme .cc-panel { background: linear-gradient(180deg, #fffdf9, #f6f1e7); border-color: #d3c6b1; color: #2b2f3a; }
body.light-theme .cc-head { background: #fffdf9; border-bottom-color: #e0d6c4; }
body.light-theme .cc-x { color: #7a7266; }
body.light-theme .cc-field input,
body.light-theme .cc-prompt { background: #fff; border-color: #d3c6b1; color: #2b2f3a; }
body.light-theme .cc-pick { background: rgba(255, 255, 255, .7); border-color: #cfc7b6; color: #8b8577; }

/* ====== mystery-motion.css ====== */
/* ============================================================
   高级动效(???模式 v3)—— 丝滑,覆盖全部交互
   ------------------------------------------------------------
   v3 相对旧版的修复:
   · 入场动画统一 animation-fill-mode: backwards。
     旧版 both 会让 transform / clip-path 永久残留:弹窗内浮层被裁切、
     position:fixed 菜单相对弹窗错位、侧边栏 transform 残留导致手机端关不掉。
   · 弹窗收起时遮罩淡出时长与收起动画对齐(0.42s),不再突然消失。
   · 覆盖补齐:弹窗 / 侧边栏 / 顶栏 / 输入区 / 右键与头像菜单 / Toast /
     图片预览 / 标签页 / 按钮与输入框反馈 / 消息入场。
   · 只动 transform 与 opacity;没有常驻动画,will-change 仅在动画期间挂载。
   ============================================================ */

: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-out: cubic-bezier(.33, 1, .68, 1);
    --mo-d1: .18s;
    --mo-d2: .32s;
    --mo-d3: .5s;
    --mo-radius: 12px;
}

/* ------------------------------------------------------------
   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;
}

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. 弹窗:从触发按钮里「拽出来」,收起时塞回去
   ------------------------------------------------------------ */
body.mystery-mode .modal-overlay {
    transition: opacity .42s var(--mo-out), visibility 0s linear .42s;
}

body.mystery-mode .modal-overlay.show {
    transition: opacity var(--mo-d2) var(--mo-apple), visibility 0s linear 0s;
}

body.mystery-mode .modal-overlay .modal-content {
    transform-origin: var(--mo-ox, 50%) var(--mo-oy, 110%);
    transition: none;
    transform: none;
}

body.mystery-mode .modal-overlay.show .modal-content {
    transform: none;
}

body.mystery-mode .modal-overlay.mo-animating .modal-content {
    will-change: transform, opacity;
}

/* 展开:backwards,结束后不残留 clip-path / transform */
body.mystery-mode .modal-overlay.mo-opened .modal-content {
    animation: moDetach var(--mo-d3) var(--mo-spring) backwards;
}

/* 收起: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) backwards;
    animation-delay: calc(70ms + var(--mo-i, 0) * 38ms);
}

/* ------------------------------------------------------------
   3. 侧边栏 / 顶栏 / 输入区 入场 + 手机侧边栏收起修复
   ------------------------------------------------------------
   【修复】侧边栏收起靠 .sidebar.hidden 的 transform 过渡。
   入场动画若用 both 会残留 transform:none 压住它 → 手机上点遮罩关不掉。
   这里统一 backwards,并在 .hidden 时彻底关掉动画,让过渡接管。 */
body.mystery-mode .sidebar,
body.mystery-mode .chat-header,
body.mystery-mode .chat-input-area {
    animation: moShellIn .46s var(--mo-apple) backwards;
}

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

body.mystery-mode .sidebar.hidden {
    animation: none;
}

/* 切角色时聊天区「聚焦」入场 */
body.mystery-mode #chat-area.mo-view-in {
    animation: moFocusIn var(--mo-d2) var(--mo-apple) backwards;
}

/* ------------------------------------------------------------
   4. 设置标签页:弹性滑动的指示块
   ------------------------------------------------------------ */
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;
}

/* ------------------------------------------------------------
   5. 浮层菜单:右键菜单、头像菜单、上下文压缩面板
   ------------------------------------------------------------
   这些元素靠 .show 切换 display / opacity,动画在显示瞬间自动播放。
   用 backwards,结束后不残留 transform,保证 fixed 定位的菜单位置正确。 */
body.mystery-mode .friend-context-menu.show,
body.mystery-mode .ai-avatar-context-menu.show,
body.mystery-mode .avatar-context-menu.show,
body.mystery-mode .cc-panel.show {
    animation: moPop var(--mo-d2) var(--mo-spring) backwards;
}

body.mystery-mode .friend-context-menu.show,
body.mystery-mode .ai-avatar-context-menu.show,
body.mystery-mode .cc-panel.show {
    transform-origin: 0 0;
}

body.mystery-mode .avatar-context-menu.show {
    transform-origin: 0 100%;
}

/* ------------------------------------------------------------
   6. Toast:弹性上浮,收起时平滑下沉
   ------------------------------------------------------------ */
body.mystery-mode .toast-container {
    transition: opacity .32s var(--mo-apple), transform .46s var(--mo-spring), visibility 0s linear .32s;
}

body.mystery-mode .toast-container.show {
    transition: opacity .32s var(--mo-apple), transform .46s var(--mo-spring), visibility 0s linear 0s;
}

/* ------------------------------------------------------------
   7. 图片预览:图片从小到大弹出
   ------------------------------------------------------------ */
body.mystery-mode .image-preview-modal:not([hidden]) .image-preview-stage img {
    animation: moZoomIn .36s var(--mo-spring) backwards;
}

/* 回到底部按钮:显示时弹一下 */
body.mystery-mode .scroll-to-bottom-btn:not([hidden]) {
    animation: moPop .3s var(--mo-spring) backwards;
}

/* ------------------------------------------------------------
   8. 按压 / 悬停反馈:所有可点元素统一回弹
   ------------------------------------------------------------ */
body.mystery-mode button:not(:disabled),
body.mystery-mode [role="button"],
body.mystery-mode .btn,
body.mystery-mode .icon-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),
                background-color var(--mo-d1) ease,
                border-color var(--mo-d1) ease,
                color var(--mo-d1) ease,
                box-shadow var(--mo-d1) ease,
                opacity var(--mo-d1) ease;
}

body.mystery-mode button:not(:disabled):active,
body.mystery-mode [role="button"]:active,
body.mystery-mode .btn:active,
body.mystery-mode .icon-btn:active,
body.mystery-mode .friend-menu-item:active,
body.mystery-mode .avatar-menu-item:active,
body.mystery-mode .bubble-style-option:active {
    transform: scale(.94);
}

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);
}

/* ------------------------------------------------------------
   9. 输入框 / 开关:聚焦时光晕渐显,拨动时轻微回弹
   ------------------------------------------------------------ */
body.mystery-mode input:not([type="checkbox"]):not([type="range"]),
body.mystery-mode textarea,
body.mystery-mode select {
    transition: border-color .2s ease, box-shadow .28s var(--mo-out), background-color .2s ease;
}

body.mystery-mode input:not([type="checkbox"]):not([type="range"]):focus,
body.mystery-mode textarea:focus,
body.mystery-mode select:focus {
    box-shadow: 0 0 0 3px rgba(230, 199, 138, .18);
}

body.mystery-mode input[type="checkbox"] {
    transition: transform .2s var(--mo-spring);
}

body.mystery-mode input[type="checkbox"]:active {
    transform: scale(.88);
}

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

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

/* 丰富档:一次追加多条时按 --mo-i 交错入场 */
body.motion-rich .message.mo-enter {
    animation-delay: calc(var(--mo-i, 0) * 42ms);
}

/* 丰富档:新气泡上掠过一道窄高光(宽度固定,重绘面积与气泡大小无关) */
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;
}

/* ------------------------------------------------------------
   11. 轻量档:只保留弹窗、菜单与按压反馈
   ------------------------------------------------------------
   【修复】侧边栏只关动画,不再关 transition,否则手机侧边栏无法滑动收起。 */
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;
}

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

/* ------------------------------------------------------------
   12. 关键帧
   ------------------------------------------------------------ */
@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);
        clip-path: inset(0 0 0 0 round var(--mo-radius));
    }
    100% {
        opacity: 1;
        transform: translate3d(0, 0, 0) scale(1);
        clip-path: inset(0 0 0 0 round var(--mo-radius));
    }
}

@keyframes moReturn {
    0% {
        opacity: 1;
        transform: translate3d(0, 0, 0) scale(1);
        clip-path: inset(0 0 0 0 round var(--mo-radius));
    }
    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; }
}

@keyframes moPop {
    from { opacity: 0; transform: translate3d(0, -6px, 0) scale(.94); }
    to { opacity: 1; transform: none; }
}

@keyframes moZoomIn {
    from { opacity: 0; transform: scale(.9); }
    to { opacity: 1; transform: none; }
}

@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; }
}

@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; }
}

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

/* ------------------------------------------------------------
   13. 系统「减少动效」:全部动画与过渡瞬时完成
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
    body.mystery-mode *,
    body.mystery-mode *::before,
    body.mystery-mode *::after {
        animation-duration: .01ms !important;
        animation-delay: 0s !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        transition-delay: 0s !important;
    }
}

/* ====== avatar-frame.css ====== */
/* ============================================================
   自定义头像框
   ------------------------------------------------------------
   框是紧跟在头像 <img> 后面的一层覆盖图，尺寸按头像的百分比算，
   这样 35px 的输入框头像和 45px 的消息头像用同一套缩放与偏移。
   覆盖层 pointer-events: none，头像原有的点击 / 右键不受影响。
   ============================================================ */

/* 头像本身是 <img>，绝对定位的框不会以它为参照（img 不能当包含块）。
   所以在头像外面套一层 .af-host：尺寸跟着头像走，框相对这一层定位。 */
.af-host {
    position: relative;
    display: inline-flex;
    flex: 0 0 auto;
    line-height: 0;
    vertical-align: top;
}

/* 角色列表是横向 flex，包一层后头像原来的右边距要留在盒子上，
   否则名字会贴到头像上。 */
.af-host-friend {
    margin-right: 12px;
    align-self: center;
}
.af-host-friend > img.friend-avatar { margin-right: 0; }

img.af-frame {
    position: absolute;
    z-index: 2;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 140%;
    height: 140%;
    max-width: none;
    object-fit: contain;
    pointer-events: none;
    user-select: none;
    -webkit-user-drag: none;
    border-radius: 0;
    background: none;
    border: 0;
}

/* ---------- 设置面板里的预览 ---------- */

.af-layout {
    display: flex;
    gap: 18px;
    align-items: flex-start;
    flex-wrap: wrap;
}

.af-preview-col {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
}

.af-stage {
    position: relative;
    width: 96px;
    height: 96px;
    border-radius: 16px;
    background:
        linear-gradient(45deg, #2a2d36 25%, transparent 25%),
        linear-gradient(-45deg, #2a2d36 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, #2a2d36 75%),
        linear-gradient(-45deg, transparent 75%, #2a2d36 75%);
    background-size: 18px 18px;
    background-position: 0 0, 0 9px, 9px -9px, -9px 0;
    background-color: #23262e;
    border: 1px solid #444;
    display: grid;
    place-items: center;
}

.af-stage .af-avatar {
    width: 64px;
    height: 64px;
    border-radius: 50%;
    object-fit: cover;
    background: #3a3d47;
}

/* 预览里的头像也包一层 .af-host，让框的百分比基准 = 头像本身（64px），
   和聊天里的真实头像完全一致。之前框直接以 96px 的 .af-stage 为定位基准，
   同一个滑杆值在预览里会明显偏大、偏外 —— 表现为「实际刚好套住、预览套不住」。 */
.af-stage .af-host {
    display: block;
    width: 64px;
    height: 64px;
}

.af-stage .af-frame {
    position: absolute;
    z-index: 2;
}

.af-preview-hint {
    margin: 0;
    max-width: 140px;
    text-align: center;
    font-size: 0.75em;
    color: #888;
}

.af-controls { flex: 1 1 240px; min-width: 0; display: flex; flex-direction: column; gap: 10px; }

.af-row label {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 0.85em;
    margin-bottom: 4px;
}

.af-row output { color: #e6c78a; font-size: 0.95em; }

.af-row input[type="range"] { width: 100%; accent-color: #e6c78a; }

.af-url-line { display: flex; gap: 8px; align-items: center; }
.af-url-line input { flex: 1; min-width: 0; }

.af-btn-line { display: flex; gap: 8px; flex-wrap: wrap; }
.af-btn-line .btn { flex: 1 1 auto; justify-content: center; min-width: 120px; }

.af-status { margin: 0; font-size: 0.78em; color: #9a9da6; }

@media (max-width: 560px) {
    .af-layout { gap: 12px; }
    .af-preview-col { flex-direction: row; width: 100%; }
    .af-preview-hint { max-width: none; text-align: left; }
}

/* ====== voice-lab.css ====== */
/* ============================================================
   voice-lab.css —— 语音通话 / 视频通话 / 声音工坊
   ------------------------------------------------------------
   通话界面由 voice-lab.js 动态创建（自注入 DOM + 本样式），
   所以这里的选择器全部以 .vl- 开头，不与站内既有类名打架。

   【视频通话布局（微信式）】
   .vl-call[data-layout] 决定「谁占中间主画面、谁缩到右下小窗」：
     data-layout='ai' → .vl-face（AI 形象）主画面，.vl-video（我的摄像头）小窗
     data-layout='me' → 反过来
   点一下 stage 任意位置即互换（voice-lab.js 里绑的 click）。
   ============================================================ */

.vl-call {
    position: fixed;
    inset: 0;
    z-index: 95000;
    display: flex;
    flex-direction: column;
    background: radial-gradient(1000px 520px at 50% -10%, #252b3d, #111319 72%);
    color: #e8eaf0;
    overflow: hidden;
}
.vl-call[hidden] { display: none !important; }

.vl-head {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 18px;
    border-bottom: 1px solid rgba(255, 255, 255, .08);
}
.vl-head img { width: 42px; height: 42px; border-radius: 50%; object-fit: cover; background: #2b3040; }
.vl-head .vl-name { font-weight: 700; }
.vl-head .vl-sub { font-size: .75em; color: #9aa0ae; }
.vl-head .vl-spacer { flex: 1; }

.vl-icon-btn {
    border: 0;
    background: rgba(255, 255, 255, .07);
    color: #e8eaf0;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    cursor: pointer;
    font-size: 1.15em;
    display: grid;
    place-items: center;
    transition: background .15s ease, color .15s ease;
}
.vl-icon-btn:hover { background: rgba(255, 255, 255, .16); }
.vl-icon-btn.on { background: rgba(230, 199, 138, .22); color: #e6c78a; }
.vl-icon-btn.danger { background: #c04a56; color: #fff; }

/* ---------------- 舞台：主画面 + 小窗 ---------------- */

.vl-stage { flex: 1; min-height: 0; position: relative; overflow: hidden; }

/* 主画面：占满整个舞台区 */
.vl-call[data-layout='ai'] .vl-face,
.vl-call[data-layout='me'] .vl-video {
    position: absolute;
    inset: 0;
    width: auto;
    height: auto;
    aspect-ratio: auto;
    border: 0;
    border-radius: 0;
}

/* 小窗：缩到右下角（画中画）。top/left 必须显式归 auto，
   否则从主画面切回来时残留的 top:0 会把 aspect-ratio 撑爆 */
.vl-call[data-layout='ai'] .vl-video,
.vl-call[data-layout='me'] .vl-face {
    position: absolute;
    top: auto;
    left: auto;
    right: 16px;
    bottom: 16px;
    width: min(30vw, 220px);
    height: auto;
    aspect-ratio: 4 / 3;
    border: 1px solid rgba(255, 255, 255, .16);
    border-radius: 14px;
    overflow: hidden;
    background: #000;
    box-shadow: 0 6px 24px rgba(0, 0, 0, .35);
}

/* 位置切换的过渡（谁挪到中间 / 缩到小窗都带动画） */
.vl-face, .vl-video {
    transition: width .25s ease, height .25s ease,
        right .25s ease, bottom .25s ease, border-radius .25s ease;
}

/* ---------------- AI 形象（.vl-face 容器内部） ---------------- */

.vl-face { display: grid; place-items: center; cursor: pointer; }

.vl-orb { position: relative; width: 150px; height: 150px; border-radius: 50%; display: grid; place-items: center; }
.vl-orb img { width: 130px; height: 130px; border-radius: 50%; object-fit: cover; background: #2b3040; }
/* 挤进小窗时头像圆环等比缩小 */
.vl-call[data-layout='me'] .vl-face .vl-orb { transform: scale(.58); }

/* 配置了形象（静图 / 动图 / Live2D）后铺满所在区域：主画面 contain 防裁头，
   缩到小窗时改 cover 填满 */
.vl-face-img, .vl-face-vid {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    animation: vl-facein .3s ease;
}
.vl-call[data-layout='me'] .vl-face-img,
.vl-call[data-layout='me'] .vl-face-vid { object-fit: cover; }

.vl-face-l2d { position: absolute; inset: 0; overflow: hidden; }

@keyframes vl-facein {
    from { opacity: 0; }
    to { opacity: 1; }
}

.vl-ring { position: absolute; inset: 0; border-radius: 50%; border: 2px solid rgba(230, 199, 138, .55); opacity: 0; }
.vl-call[data-state='listening'] .vl-ring { opacity: 1; animation: vl-pulse 1.6s ease-out infinite; }
.vl-call[data-state='thinking'] .vl-ring { opacity: 1; border-color: rgba(180, 140, 255, .7); animation: vl-pulse 1.9s ease-out infinite; }
.vl-call[data-state='speaking'] .vl-ring { opacity: 1; border-color: rgba(140, 200, 255, .7); animation: vl-pulse 1.1s ease-out infinite; }
@keyframes vl-pulse {
    0% { transform: scale(.92); opacity: .85; }
    100% { transform: scale(1.35); opacity: 0; }
}

/* ---------------- 我的摄像头画面 ---------------- */

.vl-video { background: #000; object-fit: cover; cursor: pointer; }
.vl-video[hidden] { display: none !important; }
/* 前置摄像头镜像（照镜子的习惯）；后置不镜像。翻转按钮切换这个类 */
.vl-video.vl-mirror { transform: scaleX(-1); }

.vl-status {
    position: absolute;
    top: 16px;
    left: 50%;
    transform: translateX(-50%);
    padding: 6px 14px;
    border-radius: 999px;
    background: rgba(0, 0, 0, .42);
    font-size: .82em;
    color: #cfd4e0;
    white-space: nowrap;
    pointer-events: none;
    z-index: 2;
}
.vl-caption {
    position: absolute;
    left: 50%;
    bottom: 18px;
    transform: translateX(-50%);
    max-width: min(760px, 92%);
    text-align: center;
    font-size: 1.02em;
    line-height: 1.6;
    color: #f2f4f9;
    text-shadow: 0 2px 10px rgba(0, 0, 0, .6);
    pointer-events: none;
    z-index: 2;
}

.vl-log { max-height: 24vh; overflow-y: auto; padding: 0 18px 10px; display: flex; flex-direction: column; gap: 8px; }
.vl-line { display: flex; gap: 8px; font-size: .85em; line-height: 1.55; }
.vl-line .who { flex: none; color: #e6c78a; font-weight: 700; }
.vl-line.me .who { color: #8fd8ff; }
.vl-line .txt { color: #c8ccd8; white-space: pre-wrap; word-break: break-word; }

.vl-foot { display: flex; align-items: center; justify-content: center; gap: 14px; padding: 14px 18px 20px; border-top: 1px solid rgba(255, 255, 255, .08); }
.vl-mic {
    width: 64px; height: 64px; border-radius: 50%; border: 0;
    background: #e6c78a; color: #22242c; font-size: 1.6em;
    cursor: pointer; display: grid; place-items: center; transition: transform .15s ease;
}
.vl-mic:hover { transform: scale(1.05); }
.vl-mic.rec { background: #e0575f; color: #fff; animation: vl-pulse 1.4s ease-out infinite; }
.vl-foot-tip { text-align: center; font-size: .75em; color: #8d93a2; padding-bottom: 10px; min-height: 1.2em; }

/* ---------------- 声音工坊（实验室面板内） ---------------- */
.vl-hr { border: 0; border-top: 1px dashed #4a4e5c; margin: 14px 0; }
.vl-lab-title { margin: 0 0 8px; font-size: .95em; color: #e6c78a; }
.vl-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.vl-field label { font-size: .85em; color: #bbb; }
.vl-field input, .vl-field textarea, .vl-field select {
    width: 100%; padding: 9px 10px; border-radius: 8px;
    border: 1px solid #4b505f; background: #20232c; color: #eee;
    font: inherit; font-size: .88em;
}
.vl-field textarea { min-height: 76px; resize: vertical; }
.vl-row { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.vl-profiles { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.vl-profile {
    display: flex; align-items: center; gap: 10px; padding: 10px;
    border: 1px solid #414653; border-radius: 10px; background: rgba(255, 255, 255, .03);
}
.vl-profile.active { border-color: #e6c78a; background: rgba(230, 199, 138, .1); }
.vl-profile .meta { flex: 1; min-width: 0; }
.vl-profile b { display: block; font-size: .92em; }
.vl-profile small { display: block; color: #9198a6; font-size: .75em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vl-chip { display: inline-block; padding: 2px 8px; border-radius: 999px; background: rgba(255, 255, 255, .08); font-size: .72em; color: #b9bfcd; margin-right: 6px; }
.vl-empty { color: #8d93a2; font-size: .84em; padding: 6px 0; }
/* 音高 / 克隆区块的说明小字：比 .laboratory-hint 更轻，贴在控件正下方 */
.vl-tip { display: block; margin: 0; font-size: .76em; line-height: 1.7; color: #8d93a2; }
.vl-tip code { padding: 0 4px; border-radius: 4px; background: rgba(255, 255, 255, .07); font-size: .94em; }
.vl-badge-clone {
    display: inline-block; margin-left: 6px; padding: 1px 6px; border-radius: 999px;
    background: rgba(230, 199, 138, .18); border: 1px solid rgba(230, 199, 138, .5);
    color: #f0d9a8; font-size: .72em; font-weight: 400; vertical-align: 1px;
}
/* 克隆：模型 / GroupID 两列（窄面板自动折成一列） */
.vl-clone-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.vl-clone-grid .vl-field { margin-bottom: 0; }
.vl-clone-checks { gap: 14px; margin-top: 10px; font-size: .85em; color: #bbb; }
.vl-clone-checks label { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; }
/* 拖拽区：整块可点，drag 时高亮 */
.vl-drop {
    display: flex; flex-direction: column; align-items: center; gap: 6px;
    padding: 18px 12px; border-radius: 10px; text-align: center; cursor: pointer;
    border: 1px dashed #565b6b; background: rgba(255, 255, 255, .02);
    transition: border-color .15s ease, background .15s ease;
}
.vl-drop:hover, .vl-drop:focus-visible, .vl-drop.drag {
    border-color: #e6c78a; background: rgba(230, 199, 138, .08); outline: none;
}
.vl-drop > i { font-size: 1.7em; color: #e6c78a; }
.vl-drop > b { font-size: .9em; font-weight: 600; word-break: break-all; }
.vl-drop > small { font-size: .76em; color: #8d93a2; }
/* 克隆过程日志：一行一步，出错标红 */
.vl-clone-log {
    margin-top: 10px; padding: 8px 10px; max-height: 160px; overflow: auto;
    border: 1px solid #414653; border-radius: 10px; background: rgba(0, 0, 0, .22);
    display: flex; flex-direction: column; gap: 6px;
}
.vl-clone-line { display: flex; gap: 8px; align-items: flex-start; font-size: .8em; line-height: 1.6; color: #c3c8d4; }
.vl-clone-line i { flex: none; margin-top: 2px; color: #8d93a2; }
.vl-clone-line.ok { color: #9fe0b8; }
.vl-clone-line.ok i { color: #7cd5a4; }
.vl-clone-line.err { color: #f0a6a6; }
.vl-clone-line.err i { color: #e0575f; }
@media (max-width: 560px) {
    .vl-clone-grid { grid-template-columns: 1fr; }
}

body.light-theme .vl-call { background: radial-gradient(1000px 520px at 50% -10%, #f2f4fa, #dfe3ee 72%); color: #252932; }
body.light-theme .vl-log .txt, body.light-theme .vl-head .vl-sub { color: #4a5160; }
body.light-theme .vl-icon-btn { background: rgba(0, 0, 0, .06); color: #252932; }
body.light-theme .vl-status { background: rgba(255, 255, 255, .7); color: #3a4050; }

@media (max-width: 560px) {
    .vl-call[data-layout='ai'] .vl-video,
    .vl-call[data-layout='me'] .vl-face { width: 38vw; right: 10px; bottom: 10px; }
    .vl-mic { width: 56px; height: 56px; }
    .vl-log { max-height: 20vh; }
}

/* ---- 通话内文字输入框（可拖动 / 可关闭）---- */
.vl-textbox {
    position: fixed; right: 16px; bottom: 96px; z-index: 100001;
    width: min(300px, calc(100vw - 24px));
    background: rgba(24, 27, 35, .92); color: #eee;
    border: 1px solid #4b505f; border-radius: 12px;
    box-shadow: 0 8px 28px rgba(0, 0, 0, .45);
    backdrop-filter: blur(6px); overflow: hidden;
}
.vl-tb-head {
    display: flex; align-items: center; gap: 6px;
    padding: 7px 10px; font-size: .78em; color: #9aa1b0;
    background: rgba(255, 255, 255, .04); cursor: grab; user-select: none;
    touch-action: none;
}
.vl-tb-head:active { cursor: grabbing; }
.vl-tb-head span { flex: 1; }
.vl-tb-close {
    border: 0; background: transparent; color: #9aa1b0; cursor: pointer;
    font-size: 1.1em; padding: 0 2px; line-height: 1;
}
.vl-tb-close:hover { color: #fff; }
.vl-tb-row { display: flex; align-items: flex-end; gap: 6px; padding: 8px; }
.vl-tb-input {
    flex: 1; resize: none; border-radius: 8px;
    border: 1px solid #4b505f; background: #20232c; color: #eee;
    font: inherit; font-size: .86em; padding: 7px 9px;
    max-height: 120px;
}
.vl-tb-input:focus { outline: none; border-color: #e6c78a; }
.vl-tb-send {
    border: 0; border-radius: 8px; cursor: pointer;
    width: 36px; height: 36px; flex: 0 0 36px;
    background: #e6c78a; color: #221d10; font-size: 1.05em;
    display: flex; align-items: center; justify-content: center;
}
.vl-tb-send:active { transform: scale(.94); }
body.light-theme .vl-textbox { background: rgba(255, 255, 255, .94); color: #252932; border-color: #c9cede; }
body.light-theme .vl-tb-head { color: #6a7180; background: rgba(0, 0, 0, .04); }
body.light-theme .vl-tb-input { background: #fff; color: #252932; }



/* ====== learn-tutor.css ======（原为 learn-tutor.js 动态注入，现随主包加载） */
/* ============================================================
   learn-tutor.css —— 学习辅导（拍题讲解 + 错题本）
   深色为默认；body.light-theme 时整体换浅色。移动端竖屏单栏优先。
   ============================================================ */

/* ---------------- 实验室面板（设置 → 实验室） ---------------- */
.lt-panel-hint { font-size: .83em; color: #8d93a2; line-height: 1.8; margin: 8px 0 14px; }
.lt-panel-btns { display: flex; gap: 12px 14px; flex-wrap: wrap; margin: 10px 0 4px; }
/* 面板按钮太挤：拉开呼吸感，每颗按钮至少 150px，窄面板下会自动折行 */
.lt-panel-btns .btn { flex: 1 1 auto; min-width: 150px; justify-content: center; margin: 0; padding: 11px 18px; }
/* 人设面板：站内角色分组标题 + 角色头像行 */
.lt-persona-sec-head {
    display: flex; align-items: center; gap: 6px;
    margin: 14px 0 8px; font-weight: 600; color: #e6c78a; font-size: .92em;
}
.lt-persona-sec-head i { color: #e6c78a; }
.lt-persona-head { display: flex; align-items: center; gap: 8px; }
.lt-persona-avatar { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; flex: none; }
.lt-off-tip {
    display: flex; align-items: flex-start; gap: 8px;
    background: rgba(230,199,138,.08); border: 1px solid rgba(230,199,138,.35);
    border-radius: 10px; padding: 10px 12px; font-size: .84em; color: #d9c9a4; line-height: 1.6;
}
.lt-off-tip i { flex: none; margin-top: 2px; color: #e6c78a; }
/* 科目管理：和上面的按钮区分开，独立成块；标签 / 输入框走类名，窄屏好覆盖。
   选择器带 .lt-subj-manage 前缀是为了压过 .form-group label / input 的通用样式。 */
.lt-subj-manage {
    display: flex; flex-direction: column; gap: 10px;
    margin-top: 16px; padding-top: 14px;
    border-top: 1px dashed rgba(255, 255, 255, .14);
}
.lt-subj-manage .lt-subj-label { margin: 0; font-size: .85em; color: #9aa0ad; line-height: 1.7; }
.lt-subj-manage .lt-subj-add { max-width: 280px; }
.lt-subj-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.lt-chip {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 12px; border-radius: 999px; font-size: .84em; line-height: 1.4;
    border: 1px solid #4a4e5c; color: #cfd3dd; background: transparent; cursor: pointer;
}
.lt-chip.active { border-color: #e6c78a; background: rgba(230,199,138,.16); color: #f3dcae; }
.lt-chip .lt-chip-x { color: #987; font-size: .9em; }
.lt-chip .lt-chip-x:hover { color: #e07a7a; }

/* ---------------- 全屏学习界面 ---------------- */
.lt-stage {
    position: fixed; inset: 0; z-index: 8600;
    display: flex; flex-direction: column;
    background: #12141c; color: #e8e8ee;
    font-size: 15px;
}
.lt-stage * { box-sizing: border-box; }

/* 顶栏 */
.lt-top {
    flex: none; display: flex; align-items: center; gap: 8px; row-gap: 8px; flex-wrap: wrap;
    padding: 10px 12px calc(10px);
    border-bottom: 1px solid #2b2e39; background: #171922;
}
.lt-icon-btn {
    flex: none; display: inline-flex; align-items: center; justify-content: center;
    width: 38px; height: 38px; border-radius: 10px;
    border: 1px solid #3c3f4b; background: #20222b; color: #cfd3dd;
    font-size: 1.15em; cursor: pointer;
}
.lt-icon-btn:hover { border-color: #e6c78a; color: #e6c78a; }
.lt-sel {
    flex: 1 1 auto; min-width: 0; height: 38px; padding: 0 8px;
    border-radius: 10px; border: 1px solid #3c3f4b; background: #20222b; color: #e8e8ee;
    font-size: .92em; max-width: 130px;
}
.lt-top .lt-spacer { flex: 1 1 auto; }
/* 顶栏图标按钮分组（buildStage 里统一包一层）：桌面与选择器同行，
   空间不够或窄屏时整组换行，不再和选择器挤在一条里 */
.lt-top-icons { flex: none; display: flex; align-items: center; gap: 8px; }

/* 模式切换（三段 pill） */
.lt-modes {
    flex: none; display: flex; gap: 6px; padding: 8px 12px;
    background: #171922; border-bottom: 1px solid #2b2e39; overflow-x: auto;
}
.lt-mode-pill {
    flex: 1 1 0; min-width: 96px; padding: 8px 6px; border-radius: 999px;
    border: 1px solid #3c3f4b; background: transparent; color: #aeb4c0;
    font-size: .88em; cursor: pointer; white-space: nowrap; text-align: center;
}
.lt-mode-pill.active { border-color: #e6c78a; background: rgba(230,199,138,.14); color: #f3dcae; font-weight: 600; }

/* 讲解区 */
.lt-flow {
    flex: 1 1 auto; overflow-y: auto; padding: 14px 12px 18px;
    display: flex; flex-direction: column; gap: 12px;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin; scrollbar-color: rgba(230,199,138,.35) transparent;
}
/* 【消息滚动条】细金条，悬停加深；触摸板/手机走原生 */
.lt-flow::-webkit-scrollbar { width: 8px; }
.lt-flow::-webkit-scrollbar-track { background: transparent; }
.lt-flow::-webkit-scrollbar-thumb {
    background: rgba(230,199,138,.28); border-radius: 999px;
}
.lt-flow::-webkit-scrollbar-thumb:hover { background: rgba(230,199,138,.55); }
.lt-empty { margin: auto; text-align: center; color: #7d8390; font-size: .95em; line-height: 1.9; }
.lt-empty i { font-size: 2.2em; color: #3c3f4b; display: block; margin-bottom: 10px; }

/* 【回到底部】离底部超过一屏 1/3 时浮现 */
.lt-jump-btn {
    display: none; position: absolute; right: 16px; bottom: 118px; z-index: 30;
    align-items: center; gap: 5px;
    padding: 8px 14px; border-radius: 999px;
    border: 1px solid rgba(230,199,138,.5); background: rgba(23,25,34,.92);
    color: #f3dcae; font-size: .85em; cursor: pointer;
    box-shadow: 0 4px 14px rgba(0,0,0,.35);
}
.lt-jump-btn.show { display: inline-flex; }
.lt-jump-btn:hover { background: rgba(230,199,138,.18); }

/* 题目卡 */
.lt-qcard {
    border: 1px solid #3c3f4b; background: #1c1e28; border-radius: 14px;
    padding: 12px 14px; position: relative;
}
.lt-qcard .lt-qtag {
    display: inline-block; font-size: .74em; color: #e6c78a;
    border: 1px solid rgba(230,199,138,.4); border-radius: 999px; padding: 2px 9px; margin-bottom: 8px;
}
.lt-qcard img { max-width: 100%; border-radius: 10px; display: block; margin-top: 8px; }
.lt-qcard .lt-q-del {
    position: absolute; top: 10px; right: 10px;
    border: 0; background: rgba(255,255,255,.06); color: #98a0b0;
    width: 28px; height: 28px; border-radius: 8px; cursor: pointer; font-size: .95em;
}
.lt-qcard .lt-q-del:hover { color: #e07a7a; }

/* 讲解消息气泡 */
.lt-msg { max-width: 100%; }
.lt-msg .lt-msg-head { font-size: .78em; color: #8d93a2; margin-bottom: 4px; display: flex; gap: 8px; align-items: center; }
.lt-msg .lt-msg-head .lt-follow-tag { color: #8fb5e6; }
.lt-msg .lt-msg-body {
    background: #1c1e28; border: 1px solid #2f323e; border-radius: 14px;
    padding: 12px 14px; line-height: 1.75; word-break: break-word; overflow-wrap: anywhere;
}
.lt-msg.streaming .lt-msg-body { border-color: rgba(230,199,138,.45); }
.lt-msg .lt-msg-body p { margin: .35em 0; }

/* 【聊天式】学生自己的消息：右对齐、金边、保留换行 */
.lt-msg.mine { align-self: flex-end; max-width: 86%; }
.lt-msg.mine .lt-msg-body {
    background: rgba(230,199,138,.10); border-color: rgba(230,199,138,.45);
    border-bottom-right-radius: 4px;
}
.lt-msg.mine .lt-msg-body img { max-width: 100%; max-height: 180px; border-radius: 10px; margin-bottom: 6px; }
.lt-msg.mine .lt-mine-text { white-space: pre-wrap; word-break: break-word; overflow-wrap: anywhere; }
.lt-msg.mine .lt-msg-head { justify-content: flex-end; }
.lt-msg.mine .lt-msg-head .lt-mine-tag { color: #e6c78a; font-weight: 600; }
.lt-msg .lt-msg-body pre { background: #12141c; border: 1px solid #2f323e; border-radius: 10px; padding: 10px; overflow-x: auto; }
.lt-msg .lt-msg-body code { background: #12141c; border-radius: 5px; padding: 1px 5px; }
.lt-msg .lt-msg-body pre code { padding: 0; background: none; }
.lt-msg .lt-msg-body table { border-collapse: collapse; }
.lt-msg .lt-msg-body th, .lt-msg .lt-msg-body td { border: 1px solid #3c3f4b; padding: 4px 8px; }
.lt-msg .lt-msg-body img { max-width: 100%; border-radius: 10px; }
.lt-caret {
    display: inline-block; width: 8px; height: 1.05em; vertical-align: -2px;
    background: #e6c78a; animation: lt-blink 1s steps(2) infinite; border-radius: 2px;
}
@keyframes lt-blink { 50% { opacity: 0; } }

/* 步骤卡片（分步讲解） */
.lt-step {
    border: 1px solid #2f323e; border-radius: 14px; background: #1c1e28;
    padding: 12px 14px; line-height: 1.75;
}
.lt-step.pending { opacity: .38; border-style: dashed; }
.lt-step .lt-step-head {
    display: flex; align-items: center; gap: 8px; margin-bottom: 6px;
    font-weight: 600; color: #f3dcae;
}
.lt-step .lt-step-no {
    flex: none; width: 24px; height: 24px; border-radius: 50%;
    background: rgba(230,199,138,.15); border: 1px solid rgba(230,199,138,.5);
    display: inline-flex; align-items: center; justify-content: center; font-size: .8em;
}
.lt-step .lt-step-ask {
    margin-left: auto; flex: none;
    border: 1px solid #4a4e5c; background: transparent; color: #9fb6d8;
    border-radius: 999px; padding: 3px 10px; font-size: .78em; cursor: pointer;
}
.lt-step .lt-step-ask:hover { border-color: #8fb5e6; color: #8fb5e6; }
.lt-step.lt-step-answer { border-color: rgba(140,200,140,.5); }
.lt-step .lt-step-head .lt-ans-tag { color: #8cc88c; font-size: .85em; }

/* 分步控制条 */
.lt-stepbar {
    flex: none; display: none; gap: 8px; padding: 8px 12px;
    border-top: 1px solid #2b2e39; background: #171922;
}
.lt-stepbar.show { display: flex; }
.lt-stepbar .lt-step-pos { flex: 1; display: flex; align-items: center; justify-content: center; color: #8d93a2; font-size: .85em; }
.lt-btn {
    border: 1px solid #4a4e5c; background: #262933; color: #e2e2ea;
    border-radius: 10px; padding: 9px 16px; font-size: .92em; cursor: pointer;
}
.lt-btn:hover { border-color: #e6c78a; }
.lt-btn.primary { background: #e6c78a; border-color: #e6c78a; color: #23242c; font-weight: 600; }
.lt-btn.primary:hover { background: #f0d5a0; }
.lt-btn.ghost { background: transparent; }
.lt-btn.danger { color: #e08585; border-color: #6b4242; }
.lt-btn:disabled { opacity: .45; cursor: not-allowed; }

/* 讲完一题的操作行 */
.lt-after { display: flex; gap: 8px; flex-wrap: wrap; }
.lt-after .lt-btn { flex: 1 1 auto; }

/* 输入区 */
.lt-input-wrap {
    flex: none; border-top: 1px solid #2b2e39; background: #171922;
    padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px));
}
.lt-img-prev { display: none; position: relative; margin-bottom: 8px; }
.lt-img-prev.show { display: block; }
.lt-img-prev img { max-height: 120px; border-radius: 10px; border: 1px solid #3c3f4b; }
.lt-img-prev .lt-img-x {
    position: absolute; top: 6px; left: 6px; width: 26px; height: 26px; border-radius: 50%;
    border: 0; background: rgba(0,0,0,.6); color: #fff; cursor: pointer;
}
.lt-img-prev .lt-img-note { margin-left: 10px; font-size: .78em; color: #8d93a2; }
.lt-input-row { display: flex; align-items: flex-end; gap: 8px; }
.lt-input-row .lt-icon-btn { height: 42px; width: 42px; }
.lt-textarea {
    flex: 1 1 auto; min-width: 0; resize: none;
    min-height: 42px; max-height: 132px; padding: 10px 12px;
    border-radius: 12px; border: 1px solid #3c3f4b; background: #20222b; color: #e8e8ee;
    font-size: .95em; line-height: 1.5; font-family: inherit;
}
.lt-textarea:focus { outline: none; border-color: rgba(230,199,138,.6); }
.lt-send { height: 42px; padding: 0 14px; border-radius: 12px; }
.lt-send.stop { background: #6b4242; border-color: #6b4242; color: #ffd9d9; }

/* ---------------- 错题本（管理界面，独立 overlay） ---------------- */
.lt-book { position: fixed; inset: 0; z-index: 8700; display: flex; flex-direction: column; background: #12141c; color: #e8e8ee; }
.lt-book-top {
    flex: none; display: flex; align-items: center; gap: 8px; padding: 10px 12px;
    border-bottom: 1px solid #2b2e39; background: #171922;
}
.lt-book-top h3 { margin: 0; font-size: 1em; color: #f3dcae; display: flex; gap: 6px; align-items: center; }
.lt-book-tools {
    flex: none; display: flex; gap: 6px; padding: 8px 12px; flex-wrap: wrap;
    border-bottom: 1px solid #2b2e39; background: #171922;
}
.lt-book-tools .lt-sel { flex: 0 1 auto; max-width: none; min-width: 96px; }
.lt-book-tools .lt-search { flex: 1 1 130px; min-width: 0; }
.lt-book-tools input.lt-search {
    height: 38px; padding: 0 10px; border-radius: 10px; border: 1px solid #3c3f4b;
    background: #20222b; color: #e8e8ee; font-size: .9em;
}
.lt-book-list { flex: 1 1 auto; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.lt-mistake { border: 1px solid #2f323e; border-radius: 14px; background: #1c1e28; padding: 12px 14px; }
.lt-mistake .lt-m-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; flex-wrap: wrap; }
.lt-mistake .lt-m-meta { font-size: .78em; color: #8d93a2; }
.lt-mistake .lt-m-star { border: 0; background: none; color: #6b7080; cursor: pointer; font-size: 1.05em; }
.lt-mistake .lt-m-star.on { color: #e6c78a; }
.lt-mistake .lt-m-q { line-height: 1.65; word-break: break-word; }
.lt-mistake img { max-width: 100%; max-height: 180px; border-radius: 10px; margin: 8px 0 4px; }
.lt-mistake details { margin-top: 8px; }
.lt-mistake details summary { cursor: pointer; color: #9fb6d8; font-size: .88em; }
.lt-mistake .lt-m-exp { margin-top: 8px; border-top: 1px dashed #3c3f4b; padding-top: 8px; line-height: 1.7; }
.lt-mistake .lt-m-ops { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.lt-mistake .lt-m-ops .lt-btn { padding: 5px 10px; font-size: .8em; border-radius: 8px; }
.lt-book-empty { margin: auto; text-align: center; color: #7d8390; line-height: 2; }

/* 复习模式遮罩 */
.lt-review-q { border: 1px solid rgba(230,199,138,.4); border-radius: 14px; background: rgba(230,199,138,.06); padding: 14px; }

/* ---------------- 老师人设选择 ---------------- */
.lt-persona {
    position: fixed; inset: 0; z-index: 8700; display: flex; flex-direction: column;
    background: #12141c; color: #e8e8ee;
}
.lt-persona-list { flex: 1 1 auto; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.lt-persona-card {
    border: 1px solid #2f323e; border-radius: 14px; background: #1c1e28;
    padding: 12px 14px; cursor: pointer; transition: border-color .15s;
}
.lt-persona-card:hover { border-color: rgba(230,199,138,.5); }
.lt-persona-card.active { border-color: #e6c78a; background: rgba(230,199,138,.07); }
.lt-persona-card .lt-persona-head { display: flex; align-items: center; gap: 7px; font-size: .98em; }
.lt-persona-card .lt-persona-head i { color: #e6c78a; }
.lt-persona-card .lt-persona-on { color: #8cc88c; font-size: .82em; margin-left: auto; }
.lt-persona-card .lt-persona-desc { font-size: .82em; color: #8d93a2; margin-top: 5px; line-height: 1.6; }
.lt-persona-wb { flex: none; padding: 10px 14px calc(12px + env(safe-area-inset-bottom, 0px)); border-top: 1px solid #2b2e39; background: #171922; }
.lt-persona-wb label { display: flex; gap: 8px; align-items: flex-start; font-size: .84em; color: #aeb4c0; line-height: 1.6; cursor: pointer; }
.lt-persona-wb input { margin-top: 3px; }
.lt-persona-edit {
    position: fixed; inset: 0; z-index: 8800; display: flex; flex-direction: column; justify-content: center;
    gap: 10px; padding: 22px; background: rgba(0,0,0,.55);
}
.lt-persona-edit h4 { margin: 0; color: #f3dcae; }
.lt-persona-edit input, .lt-persona-edit textarea {
    width: 100%; border-radius: 10px; border: 1px solid #3c3f4b; background: #20222b; color: #e8e8ee;
    padding: 10px 12px; font-size: .92em; font-family: inherit; resize: vertical;
}
.lt-persona-edit textarea { min-height: 110px; }
.lt-persona-edit-btns { display: flex; gap: 8px; justify-content: flex-end; }

/* ---------------- 学习档案 ---------------- */
.lt-profile-body { flex: 1 1 auto; overflow-y: auto; padding: 12px 14px calc(16px + env(safe-area-inset-bottom, 0px)); display: flex; flex-direction: column; gap: 10px; }
.lt-profile-note-label { font-size: .86em; color: #e6c78a; display: flex; gap: 6px; align-items: center; margin-top: 6px; }
.lt-profile-note {
    width: 100%; border-radius: 10px; border: 1px solid #3c3f4b; background: #20222b; color: #e8e8ee;
    padding: 10px 12px; font-size: .92em; font-family: inherit; resize: vertical; min-height: 70px;
}
.lt-profile-note:focus { outline: none; border-color: rgba(230,199,138,.6); }
.lt-profile-list { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.lt-profile-item { border: 1px solid #2f323e; border-radius: 12px; background: #1c1e28; padding: 10px 12px; }
.lt-profile-item .lt-profile-title { font-size: .92em; margin-top: 3px; line-height: 1.6; word-break: break-word; }
.lt-profile-item .lt-profile-brief { font-size: .8em; color: #8d93a2; margin-top: 4px; line-height: 1.6; word-break: break-word; }

/* KaTeX 溢出保护 */
.lt-flow .katex-display { overflow-x: auto; overflow-y: hidden; max-width: 100%; padding: 2px 0; }
.lt-flow .katex { font-size: 1.04em; }

/* ---------------- 浅色主题 ---------------- */
body.light-theme .lt-stage,
body.light-theme .lt-book { background: #f2f3f7; color: #2b2d36; }
body.light-theme .lt-top,
body.light-theme .lt-modes,
body.light-theme .lt-stepbar,
body.light-theme .lt-book-top,
body.light-theme .lt-book-tools,
body.light-theme .lt-input-wrap { background: #ffffff; border-color: #dfe2ea; }
body.light-theme .lt-icon-btn,
body.light-theme .lt-sel,
body.light-theme .lt-textarea,
body.light-theme .lt-book-tools input.lt-search { background: #fff; border-color: #c9cdd8; color: #2b2d36; }
body.light-theme .lt-qcard,
body.light-theme .lt-msg .lt-msg-body,
body.light-theme .lt-step,
body.light-theme .lt-mistake { background: #ffffff; border-color: #d8dbe4; }
body.light-theme .lt-msg .lt-msg-body pre,
body.light-theme .lt-msg .lt-msg-body code { background: #f0f1f5; border-color: #d8dbe4; color: #2b2d36; }
body.light-theme .lt-mode-pill { border-color: #c9cdd8; color: #5a5f6d; }
body.light-theme .lt-mode-pill.active { border-color: #b8860b; background: rgba(184,134,11,.1); color: #8a6508; }
body.light-theme .lt-chip { border-color: #c9cdd8; color: #4a4f5c; }
body.light-theme .lt-chip.active { border-color: #b8860b; background: rgba(184,134,11,.12); color: #8a6508; }
body.light-theme .lt-panel-hint { color: #6b7280; }
body.light-theme .lt-subj-manage { border-top-color: rgba(0, 0, 0, .12); }
body.light-theme .lt-subj-manage .lt-subj-label { color: #6b7280; }
body.light-theme .lt-empty,
body.light-theme .lt-msg .lt-msg-head,
body.light-theme .lt-mistake .lt-m-meta,
body.light-theme .lt-stepbar .lt-step-pos { color: #7a7f8c; }
body.light-theme .lt-btn { background: #fff; border-color: #c9cdd8; color: #2b2d36; }
body.light-theme .lt-btn.primary { background: #b8860b; border-color: #b8860b; color: #fff; }
body.light-theme .lt-step.pending { opacity: .45; }
body.light-theme .lt-off-tip { background: rgba(184,134,11,.08); border-color: rgba(184,134,11,.4); color: #7a5c10; }
body.light-theme .lt-persona,
body.light-theme .lt-book { background: #f2f3f7; color: #2b2d36; }
body.light-theme .lt-persona-wb { background: #fff; border-color: #dfe2ea; color: #5a5f6d; }
body.light-theme .lt-persona-card,
body.light-theme .lt-profile-item { background: #fff; border-color: #d8dbe4; }
body.light-theme .lt-persona-card.active { border-color: #b8860b; background: rgba(184,134,11,.08); }
body.light-theme .lt-persona-edit input,
body.light-theme .lt-persona-edit textarea,
body.light-theme .lt-profile-note { background: #fff; border-color: #c9cdd8; color: #2b2d36; }
body.light-theme .lt-jump-btn { background: rgba(255,255,255,.95); color: #8a6508; border-color: rgba(184,134,11,.5); }
body.light-theme .lt-msg.mine .lt-msg-body { background: rgba(184,134,11,.08); border-color: rgba(184,134,11,.45); }
body.light-theme .lt-flow::-webkit-scrollbar-thumb { background: rgba(184,134,11,.3); }

/* 窄屏（手机）：顶栏拆两行、按钮与输入更贴手，避免全部挤成一坨 */
@media (max-width: 560px) {
    /* 顶栏：上排「返回 + 科目 / 学段 / 年级」等分，下排七个图标按钮均分一整行 */
    .lt-top { padding: 10px 10px 12px; }
    .lt-top .lt-spacer { display: none; }
    .lt-top .lt-sel { flex: 1 1 0; min-width: 0; max-width: none; height: 40px; font-size: 15px; padding: 0 6px; }
    .lt-top-icons { flex: 1 1 100%; justify-content: space-between; gap: 4px; }
    .lt-icon-btn { width: 36px; height: 36px; border-radius: 9px; font-size: 1.05em; }
    .lt-sel { max-width: 108px; padding: 0 6px; font-size: .88em; }
    .lt-modes { padding: 8px 10px; gap: 8px; }
    .lt-mode-pill { min-width: 84px; padding: 9px 6px; font-size: .86em; }
    .lt-flow { padding: 12px 12px 16px; }
    .lt-msg.mine { max-width: 94%; }
    .lt-jump-btn { right: 10px; bottom: 112px; }
    /* 分步控制条：一排四个控件，按钮收窄一点才放得下 */
    .lt-stepbar { gap: 6px; padding: 8px 10px; }
    .lt-stepbar .lt-btn { padding: 9px 10px; font-size: .86em; }
    .lt-stepbar .lt-step-pos { font-size: .8em; }
    /* 错题本工具条：搜索整行，各筛选器两两一排 */
    .lt-book-tools { gap: 8px; padding: 8px 10px; }
    .lt-book-tools .lt-sel { flex: 1 1 42%; min-width: 0; }
    .lt-book-tools .lt-search { flex: 1 1 100%; }
    /* iOS 对字号 <16px 的输入框聚焦时会自动放大整页，这里统一拉到 16px */
    .lt-textarea,
    .lt-book-tools input.lt-search,
    .lt-profile-note,
    .lt-persona-edit input,
    .lt-persona-edit textarea { font-size: 16px; }
    .lt-input-wrap { padding: 8px 10px calc(10px + env(safe-area-inset-bottom, 0px)); }
    .lt-persona-edit { padding: 18px 14px; }
    /* 设置面板：按钮一颗一行、添加框占满，手指点得中 */
    .lt-panel-btns { gap: 10px; }
    .lt-panel-btns .btn { flex: 1 1 100%; min-width: 0; }
    .lt-subj-manage .lt-subj-add { max-width: none; width: 100%; }
}

/* ---------------- 画图(Mermaid 渲染结果) ---------------- */
.lt-diagram { margin: 8px 0; padding: 10px; background: #1b1d26; border: 1px solid #3c3f4b; border-radius: 10px; overflow-x: auto; text-align: center; }
.lt-diagram svg { max-width: 100%; height: auto; }
.lt-diagram-err { font-size: .82em; color: #e0a0a0; margin: 6px 0; }
body.light-theme .lt-diagram { background: #fffdf9; border-color: #d3c6b1; }
/* ============================================================
 * 20. AI 回复队列（可视化预览面板 + 悬浮角标）
 *    由 mysw-core.js 动态注入 DOM，样式独立成段，不与旧规则耦合。
 * ============================================================ */
#ai-queue-badge {
    position: fixed;
    right: 20px;
    bottom: 104px;
    z-index: 1450;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 10px 14px;
    border: 1px solid rgba(230, 199, 138, .55);
    border-radius: 999px;
    background: linear-gradient(180deg, #4a4030, #38311f);
    color: #f3dcae;
    font-size: .9rem;
    cursor: pointer;
    box-shadow: 0 6px 18px rgba(0, 0, 0, .4);
    transition: transform .15s ease, box-shadow .15s ease;
}
#ai-queue-badge:hover { transform: translateY(-2px); box-shadow: 0 10px 24px rgba(0, 0, 0, .5); }
#ai-queue-badge.busy { animation: aiq-pulse 1.4s ease-in-out infinite; }
@keyframes aiq-pulse {
    0%, 100% { box-shadow: 0 6px 18px rgba(0, 0, 0, .4); }
    50% { box-shadow: 0 6px 24px rgba(230, 199, 138, .45); }
}
#ai-queue-badge .ai-queue-count { font-weight: 700; }

#ai-queue-panel-overlay {
    position: fixed;
    inset: 0;
    z-index: 1500;
    background: rgba(0, 0, 0, .55);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}
.ai-queue-modal {
    width: min(560px, 94vw);
    max-height: 82vh;
    display: flex;
    flex-direction: column;
    background: var(--bg-secondary, #262933);
    border: 1px solid var(--border-color, #3b3f4b);
    border-radius: 14px;
    box-shadow: 0 18px 48px rgba(0, 0, 0, .55);
    overflow: hidden;
}
.ai-queue-head { display: flex; align-items: center; gap: 10px; padding: 14px 16px; border-bottom: 1px solid var(--border-color, #3b3f4b); }
.ai-queue-head h3 { margin: 0; font-size: 1.02rem; color: var(--accent-gold, #e6c78a); display: flex; align-items: center; gap: 8px; flex: 1 1 auto; }
.ai-queue-head-ops { display: flex; gap: 8px; flex: none; }
.ai-queue-btn { border: 1px solid var(--border-color, #4a4f5d); background: transparent; color: #d5d9e4; border-radius: 8px; padding: 6px 10px; font-size: .8rem; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; }
.ai-queue-btn:hover { border-color: var(--accent-gold, #e6c78a); color: var(--accent-gold, #e6c78a); }
.ai-queue-btn.icon-only { padding: 6px 8px; }
.ai-queue-list { flex: 1 1 auto; overflow-y: auto; padding: 6px 0; }
.ai-queue-item { display: flex; gap: 10px; align-items: flex-start; padding: 10px 14px; border-bottom: 1px dashed rgba(255, 255, 255, .07); }
.ai-queue-item:last-child { border-bottom: none; }
.ai-queue-item.running { background: rgba(230, 199, 138, .06); }
.ai-queue-avatar { width: 36px; height: 36px; border-radius: 50%; object-fit: cover; flex: none; background: #3a3f4b; }
.ai-queue-main { flex: 1 1 auto; min-width: 0; }
.ai-queue-name { font-size: .85rem; color: #cfd4e2; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ai-queue-name small { color: #8b91a3; font-weight: 400; }
.ai-queue-content { margin-top: 4px; font-size: .86rem; line-height: 1.55; color: #e8eaf2; word-break: break-word; white-space: pre-wrap; max-height: 5.2em; overflow: hidden; }
.ai-queue-tag { display: inline-flex; align-items: center; gap: 3px; margin-right: 6px; padding: 1px 7px; border-radius: 999px; border: 1px solid rgba(230, 199, 138, .4); color: var(--accent-gold, #e6c78a); font-size: .72rem; }
.ai-queue-running { color: var(--accent-gold, #e6c78a); font-size: .75rem; display: inline-flex; align-items: center; gap: 4px; }
.ai-queue-wait { color: #8b91a3; font-size: .72rem; }
.ai-queue-ops { display: flex; gap: 4px; align-items: center; flex: none; }
.ai-queue-op { width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid #454a57; background: transparent; color: #cdd2e0; border-radius: 7px; cursor: pointer; font-size: .95rem; }
.ai-queue-op:hover:not(:disabled) { border-color: var(--accent-gold, #e6c78a); color: var(--accent-gold, #e6c78a); }
.ai-queue-op:disabled { opacity: .35; cursor: not-allowed; }
.ai-queue-op.danger:hover:not(:disabled) { border-color: #e57373; color: #e57373; }
.ai-queue-ops-hint { font-size: .72rem; color: #8b91a3; white-space: nowrap; }
.ai-queue-empty { text-align: center; padding: 42px 10px; color: #8b91a3; }
.ai-queue-empty i { font-size: 2rem; }
.ai-queue-tip { margin: 0; padding: 9px 16px 12px; border-top: 1px solid var(--border-color, #3b3f4b); color: #8b91a3; font-size: .74rem; }
@media (max-width: 640px) {
    #ai-queue-badge { right: 14px; bottom: 88px; padding: 8px 12px; font-size: .84rem; }
}

        /* ============================================================
           毛玻璃开关（设置 → 界面外观 → 毛玻璃效果）
           ------------------------------------------------------------
           以前只是给 <html> 加了 .glass-off 类，但样式表里没有任何规则响应它，
           所以开关勾掉之后模糊照样在 —— 这就是「关了还有一堆毛玻璃」的原因。
           这里做两件事：
             1. 把 .glass-off 下所有 backdrop-filter 一律清掉（含伪元素），
                用 !important 保证盖得住后面各种主题/插件加的玻璃规则；
             2. 玻璃面板的底色调成不透明（原本靠 blur 遮住的半透明底色，
                一旦没有模糊，后面的内容会直接透出来糊成一片，比开着更难看）。
           只影响观感，不动任何布局与功能。
           ============================================================ */
        html.glass-off,
        html.glass-off body,
        html.glass-off *,
        html.glass-off *::before,
        html.glass-off *::after {
            backdrop-filter: none !important;
            -webkit-backdrop-filter: none !important;
        }

        /* 这里刻意不逐条改背景色。
           原因：各主题的面板底色来自不同变量（默认主题用 --bg-secondary，
           星铁主题用 --sr-glass / --sr-window），在这里猜一个颜色只会把
           主题配色弄坏 —— 曾经把星铁主题的好友卡片染成了浅灰。
           真正需要"模糊没了补实底"的主题，在它自己的样式文件里按变量处理
           （见 sr-theme.css 末尾的 glass-off 段）。 */

        /* ============================================================
           虚拟滚动（设置 → 界面外观 → 虚拟滚动）
           ------------------------------------------------------------
           虚拟滚动只把可视窗口里的十几条消息放进 DOM，其余用占位符撑高。
           而「性能补丁」给 .message 加了 content-visibility: auto —— 两者
           都在"跳过渲染"。叠加的结果是：滚动时新渲染出来的那十几条被浏览器
           判成"离屏"，高度直接塌成 0，屏幕上只剩背景图（用户报的
           「开了虚拟滚动，滚了一下就空了」就是这么来的）。
           这里在虚拟滚动接管期间强制关掉它。窗口内本来就只有十几条，
           跳过渲染没有任何收益；关掉后高度测量也才是真实值。
           ============================================================ */
        .chat-messages.vs-active > .message {
            content-visibility: visible !important;
            contain-intrinsic-size: none !important;
        }

        /* ============================================================
           文件消息（气泡里的文件卡片）
           ------------------------------------------------------------
           文本文件不再把全文塞进气泡：气泡里是一张固定高度的卡片，
           点开才在弹窗里看完整内容。这样发一个几千行的 txt，
           聊天区也只是多了一张卡片，不会把整屏顶穿。
           ============================================================ */
        .message .bubble.file-bubble {
            display: flex;
            align-items: center;
            gap: 10px;
            min-width: 240px;
            max-width: min(420px, 78%);
            padding: 10px 12px;
            cursor: pointer;
            user-select: none;
            transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
        }
        .message .bubble.file-bubble:hover {
            transform: translateY(-1px);
            box-shadow: 0 6px 18px rgba(0, 0, 0, .22);
        }
        .message .bubble.file-bubble:focus-visible {
            outline: 2px solid rgba(230, 199, 138, .75);
            outline-offset: 2px;
        }
        .file-bubble-icon {
            flex: 0 0 auto;
            width: 34px;
            height: 34px;
            border-radius: 9px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: rgba(255, 255, 255, .09);
            color: #e6c78a;
            font-size: 1.15rem;
        }
        .message.mine .file-bubble-icon {
            background: rgba(0, 0, 0, .16);
            color: inherit;
        }
        .file-bubble-main {
            min-width: 0;
            flex: 1 1 auto;
            display: flex;
            flex-direction: column;
            gap: 2px;
        }
        .file-bubble-name {
            font-size: .92em;
            font-weight: 600;
            line-height: 1.35;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        .file-bubble-meta {
            font-size: .74em;
            opacity: .72;
            line-height: 1.3;
        }
        .file-bubble-action {
            flex: 0 0 auto;
            opacity: .55;
            font-size: 1.05rem;
            display: flex;
            align-items: center;
        }
        .message .bubble.file-bubble:hover .file-bubble-action { opacity: 1; }

        /* 文件预览弹窗 */
        .file-preview-modal {
            position: fixed;
            inset: 0;
            z-index: 9999;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 24px;
        }
        .file-preview-modal[hidden] { display: none; }
        .fp-backdrop {
            position: absolute;
            inset: 0;
            background: rgba(6, 8, 14, .72);
            backdrop-filter: blur(3px);
        }
        .fp-card {
            position: relative;
            width: min(920px, 100%);
            max-height: min(80vh, 780px);
            display: flex;
            flex-direction: column;
            background: #1c1e26;
            color: #e8e8ee;
            border: 1px solid rgba(255, 255, 255, .12);
            border-radius: 14px;
            box-shadow: 0 24px 60px rgba(0, 0, 0, .55);
            overflow: hidden;
        }
        body.light-theme .fp-card {
            background: #fff;
            color: #24262e;
            border-color: rgba(0, 0, 0, .1);
        }
        .fp-head {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 12px 14px;
            border-bottom: 1px solid rgba(255, 255, 255, .08);
            flex: 0 0 auto;
        }
        body.light-theme .fp-head { border-bottom-color: rgba(0, 0, 0, .08); }
        .fp-head-icon {
            font-size: 1.3rem;
            color: #e6c78a;
            flex: 0 0 auto;
        }
        .fp-title-wrap { min-width: 0; flex: 1 1 auto; }
        .fp-title {
            font-weight: 600;
            font-size: .98em;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        .fp-sub { font-size: .76em; opacity: .66; margin-top: 2px; }
        .fp-btn {
            flex: 0 0 auto;
            display: inline-flex;
            align-items: center;
            gap: 5px;
            padding: 6px 10px;
            font-size: .82em;
            color: inherit;
            background: rgba(255, 255, 255, .06);
            border: 1px solid rgba(255, 255, 255, .12);
            border-radius: 8px;
            cursor: pointer;
            transition: background .12s ease;
        }
        body.light-theme .fp-btn { background: rgba(0, 0, 0, .04); border-color: rgba(0, 0, 0, .12); }
        .fp-btn:hover { background: rgba(230, 199, 138, .18); }
        .fp-close { padding: 6px 9px; }
        .fp-body {
            flex: 1 1 auto;
            margin: 0;
            padding: 14px 16px;
            overflow: auto;
            font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
            font-size: 12.5px;
            line-height: 1.6;
            white-space: pre-wrap;
            word-break: break-word;
            background: rgba(0, 0, 0, .18);
        }
        body.light-theme .fp-body { background: rgba(0, 0, 0, .03); }
        .fp-foot {
            flex: 0 0 auto;
            padding: 8px 14px;
            font-size: .74em;
            opacity: .6;
            border-top: 1px solid rgba(255, 255, 255, .07);
            display: flex;
            align-items: center;
            gap: 6px;
        }
        body.light-theme .fp-foot { border-top-color: rgba(0, 0, 0, .07); }
        @media (max-width: 640px) {
            .file-preview-modal { padding: 0; }
            .fp-card { width: 100%; max-height: 100%; height: 100%; border-radius: 0; }
            .fp-btn span { display: none; }
        }

        /* ============================================================
           设置面板 · 折叠板（功能开关）
           ------------------------------------------------------------
           「聊天增强」6 项 + 「界面按钮与面板」26 项，以前是两块全展开的
           勾选框，一进设置就先看到三十多个开关，把真正想改的东西挤到两屏外。
           现在收进一个折叠板里，标题行显示「已开启 N / M」。
           ============================================================ */
        .set-fold-head {
            display: flex;
            align-items: center;
            gap: 12px;
            width: 100%;
            padding: 12px 14px;
            background: linear-gradient(180deg, rgba(255, 255, 255, .055), rgba(255, 255, 255, .025));
            border: 1px solid rgba(255, 255, 255, .1);
            border-radius: 12px;
            color: #e6c78a;
            text-align: left;
            cursor: pointer;
            transition: border-color .15s ease, background .15s ease;
        }
        .set-fold-head:hover { background: rgba(230, 199, 138, .1); border-color: rgba(230, 199, 138, .38); }
        .set-fold-head:focus-visible { outline: 2px solid rgba(230, 199, 138, .6); outline-offset: 2px; }
        .set-fold-icon {
            flex: 0 0 auto;
            width: 34px; height: 34px;
            border-radius: 10px;
            display: flex; align-items: center; justify-content: center;
            background: rgba(230, 199, 138, .14);
            font-size: 1.1rem;
        }
        .set-fold-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
        .set-fold-text b { font-size: 1.02em; font-weight: 600; color: #f0dfb8; letter-spacing: .2px; }
        .set-fold-text small { font-size: .76em; color: #9a9aa4; font-weight: 400; }
        .set-fold-sum {
            flex: 0 0 auto;
            font-size: .74em;
            color: #cbb98f;
            background: rgba(230, 199, 138, .13);
            border: 1px solid rgba(230, 199, 138, .22);
            border-radius: 999px;
            padding: 3px 10px;
            white-space: nowrap;
        }
        .set-fold-caret {
            flex: 0 0 auto;
            font-size: 1.15rem;
            color: #b6a983;
            transition: transform .18s ease;
        }
        .set-fold-head[aria-expanded="true"] .set-fold-caret { transform: rotate(180deg); }
        .set-fold-body { padding: 14px 4px 2px; animation: setFoldIn .16s ease both; }
        @keyframes setFoldIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
        .set-fold-tip {
            font-size: .82em;
            line-height: 1.75;
            color: #a8a8b2;
            margin: 0 0 14px;
        }
        .set-fold-section + .set-fold-section { margin-top: 18px; padding-top: 16px; border-top: 1px dashed rgba(255, 255, 255, .1); }
        .set-fold-section-head {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: .92em;
            font-weight: 600;
            color: #d9c79b;
            margin-bottom: 10px;
        }
        .set-fold-section-head i { color: #e6c78a; }
        .set-fold-section-desc { font-size: .8em; color: #90909a; line-height: 1.7; margin: 0 0 10px; }
        body.light-theme .set-fold-head {
            background: rgba(0, 0, 0, .03);
            border-color: rgba(0, 0, 0, .1);
            color: #8a6d2f;
        }
        body.light-theme .set-fold-text b { color: #6d5423; }
        body.light-theme .set-fold-text small { color: #8b8b96; }
        body.light-theme .set-fold-tip,
        body.light-theme .set-fold-section-desc { color: #6f6f7a; }
        body.light-theme .set-fold-section-head { color: #7a6128; }
        @media (max-width: 560px) {
            .set-fold-sum { display: none; }
            .set-fold-head { gap: 10px; padding: 10px 12px; }
        }

        /* ============================================================
           插件权限（v2）：折叠板 + 风险标签 + 代码体检 + 调用审计
           ============================================================ */
        .plugin-perm-head {
            display: flex;
            align-items: center;
            gap: 10px;
            width: 100%;
            padding: 10px 12px;
            background: rgba(255, 255, 255, .045);
            border: 1px solid rgba(255, 255, 255, .1);
            border-radius: 10px;
            color: #e6c78a;
            cursor: pointer;
            text-align: left;
        }
        .plugin-perm-head:hover { background: rgba(230, 199, 138, .1); border-color: rgba(230, 199, 138, .34); }
        .plugin-perm-head > i:first-child { font-size: 1.15rem; flex: 0 0 auto; }
        .plugin-perm-head-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
        .plugin-perm-head-text b { font-size: .96em; color: #f0dfb8; }
        .plugin-perm-head-text small { font-size: .74em; color: #93939d; }
        .plugin-perm-sum {
            flex: 0 0 auto;
            font-size: .74em;
            padding: 2px 9px;
            border-radius: 999px;
            background: rgba(230, 199, 138, .13);
            border: 1px solid rgba(230, 199, 138, .22);
            color: #cbb98f;
            white-space: nowrap;
        }
        .plugin-perm-caret { flex: 0 0 auto; transition: transform .18s ease; font-size: 1.05rem; }
        .plugin-perm-head[aria-expanded="true"] .plugin-perm-caret { transform: rotate(180deg); }
        .plugin-perm-body { padding-top: 12px; }
        .plugin-perm-group { margin-top: 12px; }
        .plugin-perm-group-head {
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: .84em;
            font-weight: 600;
            color: #b9a880;
            margin-bottom: 6px;
        }
        .plugin-perm-group-head i { color: #e6c78a; }
        .perm-risk {
            display: inline-block;
            font-style: normal;
            font-size: .68em;
            font-weight: 500;
            padding: 1px 7px;
            border-radius: 999px;
            margin-left: 6px;
            vertical-align: 1px;
        }
        .perm-risk.low { color: #8fd6a4; background: rgba(98, 199, 132, .14); border: 1px solid rgba(98, 199, 132, .3); }
        .perm-risk.mid { color: #f0cc86; background: rgba(230, 180, 90, .14); border: 1px solid rgba(230, 180, 90, .3); }
        .perm-risk.high { color: #f09393; background: rgba(230, 100, 100, .14); border: 1px solid rgba(230, 100, 100, .32); }
        .plugin-perm-foot {
            margin: 14px 0 2px;
            padding: 9px 11px;
            font-size: .78em;
            line-height: 1.7;
            color: #9a9aa4;
            background: rgba(255, 255, 255, .03);
            border: 1px dashed rgba(255, 255, 255, .12);
            border-radius: 8px;
        }
        .plugin-perm-foot i { color: #8fa8d8; }

        .plugin-scan-tip {
            margin-top: 8px;
            padding: 8px 11px;
            font-size: .78em;
            line-height: 1.65;
            color: #e8c79a;
            background: rgba(230, 180, 90, .08);
            border: 1px solid rgba(230, 180, 90, .28);
            border-radius: 8px;
        }
        .plugin-scan-tip i { margin-right: 4px; }

        .plugin-audit { margin-top: 8px; font-size: .78em; }
        .plugin-audit summary {
            cursor: pointer;
            color: #9fb4d8;
            padding: 5px 8px;
            border-radius: 7px;
            background: rgba(120, 160, 220, .08);
            list-style: none;
        }
        .plugin-audit summary::-webkit-details-marker { display: none; }
        .plugin-audit summary:hover { background: rgba(120, 160, 220, .16); }
        .plugin-audit-list {
            margin-top: 6px;
            max-height: 190px;
            overflow: auto;
            border: 1px solid rgba(255, 255, 255, .08);
            border-radius: 7px;
            padding: 4px 6px;
        }
        .plugin-audit-list > div {
            display: flex;
            gap: 8px;
            padding: 3px 2px;
            border-bottom: 1px dashed rgba(255, 255, 255, .06);
            line-height: 1.5;
        }
        .plugin-audit-list > div:last-child { border-bottom: 0; }
        .pa-time { flex: 0 0 auto; color: #7d7d88; font-variant-numeric: tabular-nums; }
        .pa-act { flex: 0 0 auto; color: #a8c0e8; }
        .pa-detail { flex: 1 1 auto; color: #9a9aa4; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

        /* 插件受控界面：右下角按钮坞 + 悬浮面板 */
        .plugin-ui-dock {
            position: fixed;
            right: 18px;
            bottom: 96px;
            z-index: 60;
            display: flex;
            flex-direction: column;
            gap: 8px;
            align-items: flex-end;
        }
        .plugin-ui-btn {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            padding: 8px 12px;
            font-size: .84em;
            color: #f0dfb8;
            background: rgba(38, 34, 28, .92);
            border: 1px solid rgba(230, 199, 138, .38);
            border-radius: 999px;
            box-shadow: 0 6px 18px rgba(0, 0, 0, .35);
            cursor: pointer;
            transition: transform .12s ease, background .12s ease;
        }
        .plugin-ui-btn:hover { transform: translateY(-1px); background: rgba(230, 199, 138, .18); }
        body.light-theme .plugin-ui-btn { background: #fff; color: #6d5423; border-color: rgba(0, 0, 0, .12); }
        .plugin-ui-panel {
            position: fixed;
            right: 18px;
            bottom: 96px;
            z-index: 61;
            max-height: min(70vh, 560px);
            display: flex;
            flex-direction: column;
            background: #1c1e26;
            color: #e8e8ee;
            border: 1px solid rgba(255, 255, 255, .14);
            border-radius: 12px;
            box-shadow: 0 18px 50px rgba(0, 0, 0, .5);
            overflow: hidden;
        }
        body.light-theme .plugin-ui-panel { background: #fff; color: #24262e; border-color: rgba(0, 0, 0, .1); }
        .plugin-ui-panel-head {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 8px;
            padding: 9px 12px;
            font-size: .86em;
            font-weight: 600;
            border-bottom: 1px solid rgba(255, 255, 255, .08);
        }
        body.light-theme .plugin-ui-panel-head { border-bottom-color: rgba(0, 0, 0, .08); }
        .plugin-ui-panel-close {
            background: transparent;
            border: 0;
            color: inherit;
            opacity: .62;
            cursor: pointer;
            font-size: 1rem;
            line-height: 1;
        }
        .plugin-ui-panel-close:hover { opacity: 1; }
        .plugin-ui-panel-body {
            padding: 10px 12px;
            overflow: auto;
            font-size: .86em;
            line-height: 1.65;
        }
        @media (max-width: 560px) {
            .plugin-ui-dock { right: 12px; bottom: 88px; }
            .plugin-ui-panel { left: 12px; right: 12px; width: auto !important; }
        }

        /* 权限勾选框：默认样式在深色面板里几乎看不见 */
        #plugin-perm-body input[type="checkbox"] {
            width: 17px;
            height: 17px;
            margin-top: 2px;
            accent-color: #e6c78a;
            flex: 0 0 auto;
        }
        #plugin-perm-body .plugin-permission-item { align-items: flex-start; }
        .plugin-audit-list .pa-empty {
            padding: 8px 4px;
            color: #7d7d88;
            font-size: .95em;
        }

        /* ==========================================================
           界面主题选择卡（设置 → 界面外观）
           ----------------------------------------------------------
           五套主题各一张卡：色块用 --sw1/--sw2 两个变量拼成左右两色，
           这样不用为一套主题写一条 CSS（新增主题只加一个 button 即可）。
           卡片本身只管版式，配色由当前主题的 body.*-theme 规则接管，
           所以这里一律用 currentColor / 半透明白黑，不写死颜色。
           ========================================================== */
        .theme-cards {
            display: grid;
            /* 5 张卡一行放得下就一行（96px 会挤成 4+1，把最小宽度收到 84px） */
            grid-template-columns: repeat(auto-fit, minmax(76px, 1fr));
            gap: 8px;
        }
        .theme-card {
            display: flex;
            flex-direction: column;
            align-items: flex-start;
            gap: 4px;
            padding: 9px 10px;
            border: 1px solid var(--border-color, #444);
            border-radius: 10px;
            background: transparent;
            color: inherit;
            cursor: pointer;
            text-align: left;
            font: inherit;
            line-height: 1.25;
            transition: border-color .15s, transform .15s, background .15s;
        }
        .theme-card:hover { border-color: var(--accent-gold, #e6c78a); transform: translateY(-1px); }
        .theme-card b { font-size: .88em; font-weight: 700; white-space: nowrap; }
        .theme-card small { font-size: .68em; opacity: .62; white-space: nowrap; }
        .theme-swatch {
            width: 100%;
            height: 22px;
            border-radius: 6px;
            border: 1px solid rgba(127, 127, 127, .35);
            /* 左底色 / 右强调色的左右分割，比斜切渐变更容易一眼看出「这套主题什么色」 */
            background: linear-gradient(90deg, var(--sw1, #222) 0 56%, var(--sw2, #e6c78a) 56% 100%);
        }
        .theme-card.active {
            border-color: var(--accent-gold, #e6c78a);
            box-shadow: 0 0 0 2px rgba(230, 199, 138, .35) inset;
        }
        /* 选中勾挂在右上角（绝对定位）而不是塞进标题文字里：
           卡片只有 80 来像素宽，行内加个 ✓ 会把「星铁·浅」挤成两行。 */
        .theme-card { position: relative; }
        .theme-card.active::after {
            content: '✓';
            position: absolute;
            bottom: 5px;
            right: 6px;
            font-size: .82em;
            font-weight: 700;
            color: var(--accent-gold, #e6c78a);
            line-height: 1;
        }

        /* ==========================================================
           语音合成面板的小节标题 / 说明
           ----------------------------------------------------------
           「设置 → AI 配置 → 语音合成」现在把接口、默认声音、音色工坊、
           音色克隆并成了一页，用这几个小标题分段，读起来不至于糊成一大坨。
           颜色全走主题变量，星铁 / 绝区零主题下自动跟着变。
           ========================================================== */
        .tts-section-title {
            display: flex;
            align-items: center;
            gap: 8px;
            margin: 20px 0 10px;
            padding-top: 14px;
            border-top: 1px dashed var(--border-light, rgba(127, 127, 127, .32));
            font-size: .95em;
            font-weight: 700;
            letter-spacing: .02em;
            color: var(--text-primary);
        }
        .tts-section-title:first-of-type { margin-top: 14px; padding-top: 0; border-top: 0; }
        .tts-section-title i { color: var(--accent-gold); font-size: 1.05em; }

        .tts-hint {
            margin: 0 0 10px;
            font-size: .78em;
            line-height: 1.7;
            color: var(--text-secondary);
        }

        /* 工坊注入块：它自带的是 .vl-lab-title / .vl-hr（原本是实验室面板里的层级），
           并进「语音合成」后要跟上面的 .tts-section-title 一个样，否则一页里出现
           两种小节标题，看着像两块拼起来的。 */
        .vl-workshop-block { margin-top: 4px; }
        .vl-workshop-block .vl-hr:first-child { display: none; }
        .vl-workshop-block .vl-lab-title {
            display: flex;
            align-items: center;
            gap: 8px;
            margin: 20px 0 10px;
            padding-top: 14px;
            border-top: 1px dashed var(--border-light, rgba(127, 127, 127, .32));
            font-size: .95em;
            font-weight: 700;
            letter-spacing: .02em;
            color: var(--text-primary);
        }
        .vl-workshop-block .vl-lab-title i { color: var(--accent-gold); font-size: 1.05em; }
        .vl-workshop-block .vl-hr { display: none; }
        /* 克隆块自带的标题前面已经有一条分隔线了，别再叠一条 */
        .vl-workshop-block .vl-clone .vl-lab-title { margin-top: 4px; padding-top: 0; border-top: 0; }

        /* ==========================================================
           悬浮按钮（汉堡 / 视图切换）的主题适配
           ----------------------------------------------------------
           这两颗按钮浮在 app-container 里、直接压在页面背景上，
           所以不能只靠 --bg-* 继承，得按主题各给一组值。
           顺序：浅色 → 星铁浅 → 星铁深 → 绝区零。
           ========================================================== */
        body.light-theme {
            --float-btn-bg: rgba(255, 252, 246, 0.94);
            --float-btn-bg-hover: #fffdf9;
            --float-btn-border: #cdbb9f;
            --float-btn-text: #6b6157;
            --float-btn-text-hover: #2c2620;
        }

        /* 星铁·浅：白窗体系里的圆钮（玻璃感靠半透明白 + 细深描边） */
        body.sr-theme {
            --float-btn-bg: rgba(244, 242, 240, 0.94);
            --float-btn-bg-hover: #f7f5f3;
            --float-btn-border: var(--sr-border, #595556);
            --float-btn-text: #3c3e44;
            --float-btn-text-hover: #17181c;
        }

        body.sr-theme.sr-dark-theme {
            --float-btn-bg: rgba(17, 19, 27, 0.92);
            --float-btn-bg-hover: rgba(26, 29, 39, 0.98);
            --float-btn-border: rgba(255, 255, 255, 0.18);
            --float-btn-text: #c3c6cd;
            --float-btn-text-hover: #eef0f4;
        }

        body.zzz-theme {
            --float-btn-bg: rgba(20, 20, 22, 0.94);
            --float-btn-bg-hover: #1c1c1e;
            --float-btn-border: rgba(255, 255, 255, 0.22);
            --float-btn-text: #f5f5f7;
            --float-btn-text-hover: #fff;
        }

        /* 尺寸与圆角统一交给基础样式里的 --float-btn-size + 50%：
           顶栏那排 .icon-btn 各主题各断点尺寸不同（实测窄屏 30px 正圆，
           宽屏 40px），如果这里再按主题写死 40px 胶囊，一排圆钮里就会
           混进一个不一样大的方块 —— 中心对齐了看着还是不齐。 */
