[
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Build Plugin\n\non:\n  push:\n    branches: [ \"v5\" ]\n  workflow_dispatch:\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v4\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n          cache: 'npm'\n\n      - name: 'Install dependencies'\n        run: npm install\n\n      - name: Build plugin\n        run: npm run build\n\n      - name: Unzip artifact for clean upload\n        run: |\n          mkdir -p release\n          unzip mspring-theme.zip -d release\n\n      - name: Upload artifact\n        uses: actions/upload-artifact@v4\n        with:\n          name: mspring-theme\n          path: release/\n"
  },
  {
    "path": ".gitignore",
    "content": "# 忽略编译输出目录\n/src/style.min.css\n/src/heti-addon.js\n/src/heti-m.css\nmspring-theme.zip\n\n\n# 忽略 Node.js 模块\n/node_modules\n\n# 忽略日志文件\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# 忽略 IDE 和操作系统文件\n.idea/\n.vscode/\n.DS_Store\nThumbs.db\n\n# gemini cli 上下文文件\nGEMINI.md\n\n.continue/"
  },
  {
    "path": "AGENTS.md",
    "content": "# AGENTS.md\n\n本文件用于说明本仓库在使用自动化代理/AI 助手（例如 Copilot、ChatGPT、Claude、Continue 等）协作开发时的约定与边界，便于贡献者与自动化工具遵循一致的工作流。\n\n## 仓库概览\n\n- 项目：MSpring Theme\n- 类型：LiteLoaderQQNT / QwQNT 主题（theme）\n- 打包：通过 `npm run build` 生成 `mspring-theme.zip`，并发布到 GitHub Release\n\n## 目录结构（简述）\n\n- `src/`：主题样式与相关静态资源（`style.scss` 源码、`style.min.css` 构建产物等）\n- `renderer/`、`preload/`、`main/`：注入脚本\n- `res/`：图标与 README 截图等资源\n- `manifest.json`：LiteLoaderQQNT 插件清单\n- `package.json`：构建脚本与 QwQNT 元信息（含 `qwqnt.dependencies`）\n- `pack.js`：打包脚本（输出 `mspring-theme.zip`）\n\n## 版本与发布\n\n### 版本号规则\n\n- 发布前需要同步更新：\n  - `package.json` 的 `version`\n  - `manifest.json` 的 `version`\n- Tag 规则：`vX.Y.Z`（例如 `v2.0.1`）\n\n### 发布流程（人工或自动化工具执行）\n\n1. 确认工作区干净（`git status`）\n2. 更新版本号并提交\n3. 构建与打包：\n   - 推荐：`npm run build`（包含清理旧产物、重新构建 CSS、执行打包）\n4. 创建 tag 并推送\n5. 创建 GitHub Release 并上传 `mspring-theme.zip`\n\n> 注意：Release 资产文件名固定为 `mspring-theme.zip`（见 `manifest.json` 的 `repository.release.file`）。\n\n## 依赖与兼容性\n\n- QwQNT 侧依赖在 `package.json -> qwqnt.dependencies` 中维护。\n- 如需迁移依赖或更改最低版本要求，请同时更新 README 的安装/前置信息。\n\n## 代码与样式约定\n\n### 样式\n\n- 样式源文件：`src/style.scss`\n- 构建产物：`src/style.min.css`（由构建脚本生成；不建议手工编辑）\n\n### 注释与文案\n\n- 除非特殊要求，仓库内注释与字符串建议使用中文，保持与现有风格一致。\n\n## 自动化代理工作约定\n\n### 可以做的事\n\n- 按 issue/PR 描述修改代码、样式、文档\n- 运行 `npm run build` 验证打包\n- 更新版本号、补充 changelog/release notes（按维护者要求）\n\n### 不应该做的事\n\n- 不要提交隐私/敏感信息（token、cookie、个人账号数据）\n- 不要引入未说明用途的大型依赖\n- 不要在没有说明的情况下大范围重构/格式化（避免产生噪音 diff）\n\n### 提交信息（建议）\n\n- `feat:` 新功能\n- `fix:` 修复问题\n- `docs:` 文档\n- `chore:` 杂项（依赖、脚本、版本号等）\n- `refactor:` 重构\n\n## 联系与反馈\n\n- 作者：MUKAPP\n- 问题反馈：优先使用 GitHub Issues\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2023 MUK\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<img src=\"./res/github/intro.png\" style=\"zoom:200%;\" />\n\n# MSpring Theme\n\n[LiteLoaderQQNT](https://github.com/LiteLoaderQQNT/LiteLoaderQQNT)/[QwQNT](https://qwqnt-community.github.io/docs/) 主题，优雅 · 粉粉 · 细致\n\n目前适配了大部分日间模式以及夜间模式场景，对很多地方的细节都进行了处理，欢迎使用 & star\n\nMUK 的 TG 频道：[MUKAPP](https://t.me/MUKAPP_Personal)\n\n## 目录\n\n- [MSpring Theme](#mspring-theme)\n  - [目录](#目录)\n  - [注意事项](#注意事项)\n  - [截图](#截图)\n    - [日间模式](#日间模式)\n    - [夜间模式](#夜间模式)\n    - [优化消息排版演示](#优化消息排版演示)\n  - [安装方法](#安装方法)\n    - [LiteLoaderQQNT](#liteloaderqqnt)\n      - [管理器安装](#管理器安装)\n      - [插件列表查看](#插件列表查看)\n      - [PluginInstaller](#plugininstaller)\n    - [QwQNT](#qwqnt)\n  - [插件冲突分析](#插件冲突分析)\n  - [其他](#其他)\n\n## 注意事项\n\n> [!TIP]\n> Windows11 22H2 及以上的版本推荐搭配 [More Materials](https://github.com/mo-jinran/More-Materials) 插件使用。\\\n> Linux (KDE) 请配合 [More Materials](https://github.com/mo-jinran/More-Materials) 插件使用。\\\n> Linux 更改主题颜色后需要重启 QQ 才能生效\\\n> 其他平台请自行尝试\n\n> [!CAUTION]\n> **不要在 QQ 官方群聊发送*任何*可以看出你使用了第三方插件的截图，不论是本主题还是其他主题其他插件**\n\n作者之前没怎么接触过前端开发，所以非常菜鸡（）\\\n如果你发现哪里还没有适配或者哪里有问题，欢迎提 Issues\n\n## 截图\n\n### 日间模式\n\n![总览](./res/github/screenshots/1.png \"总览\")\n![更换主题色](./res/github/screenshots/7.png \"更换主题色\")\n![独立聊天窗口](./res/github/screenshots/2.png \"独立聊天窗口\")\n![设置界面](./res/github/screenshots/3.png \"设置界面\")\n\n### 夜间模式\n\n![总览](./res/github/screenshots/4.png \"总览\")\n![独立聊天窗口](./res/github/screenshots/5.png \"独立聊天窗口\")\n![设置界面](./res/github/screenshots/6.png \"设置界面\")\n\n### 优化消息排版演示\n\n![优化消息排版](./res/github/screenshots/8.png \"优化消息排版\")\n\n## 安装方法\n\n### LiteLoaderQQNT\n\n#### 管理器安装\n\n下载 [release](https://github.com/MUKAPP/mspring-theme/releases/latest) 内的 `mspring-theme.zip`，进入 LiteLoaderQQNT 设置，找到“安装新插件”右侧的“选择文件”按钮，选择刚刚下载的 zip 文件。\n\n#### 插件列表查看\n\n安装 [插件列表查看](https://github.com/ltxhhz/LL-plugin-list-viewer) 插件，打开对应设置页面，找到本插件，点击 **安装** - **使用 Release 包**，安装完成之后重启\n\n#### PluginInstaller\n\n安装 [PluginInstaller](https://github.com/xinyihl/LiteLoaderQQNT-PluginInstaller) 插件，打开对应设置页面，在安装插件输入框内输入 `https://raw.githubusercontent.com/MUKAPP/mspring-theme/v5/manifest.json`，点击确定按钮\\\n或者也可以同时安装 [Protocio](https://github.com/PRO-2684/protocio) 插件，然后点击 [该链接](https://mukapp.github.io/mspring-theme/res/github/protocio-install.html) 直接拉起 PluginInstaller 安装插件\n\n### QwQNT\n\n前置插件：[qwqnt-hako](https://github.com/qwqnt-community/qwqnt-hako)\n\n下载 [release](https://github.com/MUKAPP/mspring-theme/releases/latest) 内的 `mspring-theme.zip`，将下载的 zip 文件解压，解压出的文件夹移动至 `qwqnt/qwqnt-storage/plugins/` 内，重启 QQ 即可\\\n（如果解压之后不是一个文件夹，而是几个文件夹和几个文件，那么请创建一个文件夹，将解压出来的文件夹和文件放进去，然后再移动到上述路径内）\n\n## 插件冲突分析\n\n- **优化消息排版** 功能在 [**Markdown 插件**](https://github.com/d0j1a1701/LiteLoaderQQNT-Markdown) 开启时会失效，Markdown 插件自带了 `pangu.js` 的中英混排优化，开启二者之一就可以了\n\n## 其他\n\n<picture>\n  <source\n    media=\"(prefers-color-scheme: dark)\"\n    srcset=\"\n      https://api.star-history.com/svg?repos=MUKAPP/mspring-theme&type=Date&theme=dark\n    \"\n  />\n  <source\n    media=\"(prefers-color-scheme: light)\"\n    srcset=\"\n      https://api.star-history.com/svg?repos=MUKAPP/mspring-theme&type=Date\n    \"\n  />\n  <img\n    alt=\"Star History Chart\"\n    src=\"https://api.star-history.com/svg?repos=MUKAPP/mspring-theme&type=Date\"\n    style=\"width: 100%;\n      max-width: 600px;\n      border-radius: 4px;\n      box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);\"\n  />\n</picture>\n"
  },
  {
    "path": "main/index.js",
    "content": "const fs = require(\"fs\");\nconst fsPromises = require(\"fs\").promises;\nconst path = require(\"path\");\nconst { BrowserWindow, ipcMain, shell, net } = require(\"electron\");\n\n// 框架类型检测\nconst frameworkType = global.MSPRING_FRAMEWORK_TYPE\n\nfunction log(...args) {\n    console.log(`[MSpring Theme]`, ...args);\n}\n\n// log(\"框架类型\", frameworkType);\n\nfunction openWeb(url) {\n    shell.openExternal(url);\n}\n\nfunction fetchData(url) {\n    return new Promise((resolve, reject) => {\n        const request = net.request({\n            method: 'GET',\n            url: url,\n            redirect: 'follow' // 处理重定向\n        });\n\n        request.on('response', (response) => {\n            const finalUrl = response.headers.location || response.url;\n            let data = '';\n\n            response.on('data', (chunk) => {\n                data += chunk;\n            });\n\n            response.on('end', () => {\n                resolve({ url: finalUrl, content: data });\n            });\n        });\n\n        request.on('error', (error) => {\n            reject(error);\n        });\n\n        request.end();\n    });\n}\n\n// 防抖函数\nfunction debounce(fn, time) {\n    let timer = null;\n    return function (...args) {\n        timer && clearTimeout(timer);\n        timer = setTimeout(() => {\n            fn.apply(this, args);\n        }, time);\n    }\n}\n\n/**\n * 将十六进制颜色值转换为 RGB 值\n * @param {string} hex 表示十六进制颜色的字符串，例如 \"#ff0000\"\n * @returns {Array} 包含 RGB 值的数组，例如 [255, 0, 0]\n */\nfunction hexToRGB(hex) {\n    // 分别提取并转换红色、绿色、蓝色的十六进制值到整数\n    var r = parseInt(hex.slice(1, 3), 16);\n    var g = parseInt(hex.slice(3, 5), 16);\n    var b = parseInt(hex.slice(5, 7), 16);\n    return [r, g, b];\n}\n\n/**\n * 将 RGB 值转换为十六进制颜色值\n * @param {Array} rgb 包含 RGB 值的数组，例如 [255, 0, 0]\n * @returns {string} 表示十六进制颜色的字符串，例如 \"#ff0000\"\n */\nfunction RGBToHex(rgb) {\n    var r = rgb[0].toString(16).padStart(2, '0');\n    var g = rgb[1].toString(16).padStart(2, '0');\n    var b = rgb[2].toString(16).padStart(2, '0');\n    return '#' + r + g + b;\n}\n\n/**\n * 混合两个颜色的 RGB 值\n * @param {Array} color1 第一个颜色的 RGB 值数组\n * @param {Array} color2 第二个颜色的 RGB 值数组\n * @param {number} ratio 混合比率，范围在 0 到 1 之间\n * @returns {Array} 混合后的 RGB 值数组\n */\nfunction blendColors(color1, color2, ratio) {\n    var blendedColor = [];\n    for (var i = 0; i < 3; i++) {\n        blendedColor[i] = Math.round(color1[i] * (1 - ratio) + color2[i] * ratio);\n    }\n    return blendedColor;\n}\n\n/**\n * 计算给定RGB颜色的亮度\n * @param {number} r - 红色通道的值（0-255）\n * @param {number} g - 绿色通道的值（0-255）\n * @param {number} b - 蓝色通道的值（0-255）\n * @returns {number} - 该颜色的亮度值\n */\nfunction luminance(r, g, b) {\n    const a = [r, g, b].map(function (v) {\n        v /= 255;\n        return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\n    });\n    return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;\n}\n\n/**\n * 根据背景颜色的十六进制值判断最佳文字颜色（黑色或白色）\n * @param {string} hexColor - 十六进制表示的背景颜色，如 \"#FFFFFF\"\n * @returns {string} - 最佳文字颜色，'black' 或 'white'\n */\nfunction getBestTextColor(hexColor) {\n    const [r, g, b] = hexToRGB(hexColor);\n    const lum = luminance(r, g, b);\n    return lum > 0.5 ? 'black' : 'white';\n}\n\n\n// 更新样式\nasync function updateStyle(webContents, settingsPath) {\n    try {\n        // 检查 webContents 是否仍然有效\n        if (!webContents || webContents.isDestroyed()) {\n            log(\"WebContents 已被销毁，跳过样式更新\");\n            return;\n        }\n\n        // 读取settings.json\n        const data = await fsPromises.readFile(settingsPath, \"utf-8\");\n        const config = JSON.parse(data);\n        const themeColor = config.themeColor;\n        // 将themeColorDark1设置成themeColor和10%的黑色的混合色\n        // const themeColorDark1 = RGBToHex(blendColors(hexToRGB(themeColor), [0, 0, 0], 0.1));\n        // 将themeColorDark2设置成themeColor和20%的黑色的混合色\n        // const themeColorDark2 = RGBToHex(blendColors(hexToRGB(themeColor), [0, 0, 0], 0.2));\n        const backgroundOpacity = config.backgroundOpacity;\n        // 将backgroundOpacity(是个0-100的整数值)转为两位hex值作为RGBA的透明度（注意不要出现小数）\n        const backgroundOpacityHex = Math.round(backgroundOpacity * 2.55).toString(16).padStart(2, \"0\");\n\n        const onThemeTextColor = getBestTextColor(themeColor) === \"black\" ? \"#000000\" : \"#FFFFFF\";\n\n        const csspath = path.join(frameworkType === \"liteloader\"\n            ? LiteLoader.plugins[\"mspring-theme\"].path.plugin\n            : qwqnt.framework.plugins[\"mspring-theme\"].meta.path, \"src/style.min.css\");\n        const cssData = await fsPromises.readFile(csspath, \"utf-8\");\n\n            // --theme-color-dark1: ${themeColorDark1};\n            // --theme-color-dark2: ${themeColorDark2};\n            // --theme-color-alpha: ${themeColor + \"3f\"};\n            // --text-selected-color: ${themeColor + \"7f\"};\n            // --theme-tag-color: ${themeColor + \"3f\"};\n        let preloadString = `:root {\n            --theme-color: ${themeColor};\n            --background-color-light: #FFFFFF${backgroundOpacityHex};\n            --background-color-dark: #171717${backgroundOpacityHex};\n            --on-theme-text-color: ${onThemeTextColor};\n        }`\n\n        // 在发送之前再次检查\n        if (!webContents.isDestroyed()) {\n            webContents.send(\n                \"mspring_theme.updateStyle\",\n                // 将主题色插入到style.css中\n                preloadString + \"\\n\\n\" + cssData\n            );\n        } else {\n            log(\"WebContents 在处理过程中被销毁，跳过发送\");\n        }\n    } catch (err) {\n        log(\"更新样式出错\", err);\n    }\n}\n\n\n// 存储监听器的 Map，用于清理\nconst watchersMap = new WeakMap();\n\n// 监听CSS修改-开发时候用的\nfunction watchCSSChange(webContents, settingsPath) {\n    const cssFilePath = path.join(frameworkType === \"liteloader\"\n        ? LiteLoader.plugins[\"mspring-theme\"].path.plugin\n        : qwqnt.framework.plugins[\"mspring-theme\"].meta.path, \"src/style.min.css\");\n\n    const watcher = fs.watch(cssFilePath, debounce((eventType, filename) => {\n        log(`CSS文件 ${filename} 发生变动, 重新加载样式...`);\n        if (!webContents.isDestroyed()) {\n            updateStyle(webContents, settingsPath);\n        } else {\n            log(\"WebContents 已被销毁，清理 CSS 监听器\");\n            watcher.close();\n        }\n    }, 100));\n\n    // 存储监听器以便后续清理\n    if (!watchersMap.has(webContents)) {\n        watchersMap.set(webContents, []);\n    }\n    watchersMap.get(webContents).push(watcher);\n}\n\n// 监听配置文件修改\nfunction watchSettingsChange(webContents, settingsPath) {\n    const watcher = fs.watch(settingsPath, \"utf-8\", debounce(() => {\n        if (!webContents.isDestroyed()) {\n            updateStyle(webContents, settingsPath);\n        } else {\n            log(\"WebContents 已被销毁，清理设置监听器\");\n            watcher.close();\n        }\n    }, 100));\n\n    // 存储监听器以便后续清理\n    if (!watchersMap.has(webContents)) {\n        watchersMap.set(webContents, []);\n    }\n    watchersMap.get(webContents).push(watcher);\n}\n\n// 加载插件时触发\nconst pluginDataPath = frameworkType === \"liteloader\"\n    ? LiteLoader.plugins[\"mspring-theme\"].path.data\n    : path.join(qwqnt.framework.paths.configs, \"mspring-theme\");\nconst settingsPath = path.join(pluginDataPath, \"settings.json\");\n\n// 判断插件路径是否存在，如果不存在则创建（同时创建父目录（如果不存在的话））\nif (!fs.existsSync(pluginDataPath)) {\n    fs.mkdirSync(pluginDataPath, { recursive: true });\n}\n\n// 迁移配置\nif (frameworkType === \"qwqnt\") {\n    const oldPluginDataPath = path.join(qwqnt.framework.paths.data, \"mspring-theme\");\n    const oldSettingsPath = path.join(oldPluginDataPath, \"settings.json\");\n    const oldSettingsPathExists = fs.existsSync(oldSettingsPath);\n\n    if (!fs.existsSync(settingsPath) && oldSettingsPathExists) {\n        try {\n            const oldData = fs.readFileSync(oldSettingsPath, \"utf-8\");\n            fs.writeFileSync(settingsPath, oldData, \"utf-8\");\n            log(\"已从旧路径迁移 settings.json\");\n            fs.unlinkSync(oldSettingsPath);\n            log(\"已删除旧的 settings.json\");\n            const remainingFiles = fs.readdirSync(oldPluginDataPath);\n            // 如果目录为空，则删除它\n            if (remainingFiles.length === 0) {\n                fs.rmdirSync(oldPluginDataPath);\n                log(\"旧插件目录为空，已删除\");\n            } else {\n                log(\"旧插件目录中仍有其他文件，不删除目录\");\n            }\n        } catch (error) {\n            log(\"迁移旧 settings.json 时出错\", error);\n        }\n    }\n}\n\nconst defaultConfig = {\n    \"themeColor\": \"#cb82be\",\n    \"backgroundOpacity\": \"70\",\n    \"heti\": false,\n    \"forceHostBubbleColor\": false,\n    \"forceNightModeBackground\": true,\n    \"logToMain\": false,\n};\n\n// 检查和更新配置文件\ntry {\n    if (!fs.existsSync(settingsPath)) {\n        // 如果文件不存在，直接写入默认配置\n        fs.writeFileSync(settingsPath, JSON.stringify(defaultConfig, null, 4), \"utf-8\");\n    } else {\n        // 如果文件存在，读取并检查缺失的键\n        const data = fs.readFileSync(settingsPath, \"utf-8\");\n        const config = JSON.parse(data);\n        let updated = false;\n\n        // 遍历默认配置的键，如果当前配置中不存在，则添加它\n        for (const key in defaultConfig) {\n            if (config[key] === undefined) {\n                config[key] = defaultConfig[key];\n                updated = true;\n            }\n        }\n\n        // 如果有任何更新，则只写一次文件\n        if (updated) {\n            fs.writeFileSync(settingsPath, JSON.stringify(config, null, 4), \"utf-8\");\n        }\n    }\n} catch (error) {\n    log(\"更新 settings.json 时出错\", error);\n    // 如果发生错误（如JSON损坏），可以用默认配置覆盖它\n    fs.writeFileSync(settingsPath, JSON.stringify(defaultConfig, null, 4), \"utf-8\");\n}\n\nipcMain.on(\n    \"mspring_theme.rendererReady\",\n    (event, message) => {\n        const window = BrowserWindow.fromWebContents(event.sender);\n        updateStyle(window.webContents, settingsPath);\n    }\n);\n\n// 监听渲染进程的updateStyle事件\nipcMain.on(\n    \"mspring_theme.updateStyle\",\n    (event, settingsPath) => {\n        const window = BrowserWindow.fromWebContents(event.sender);\n        updateStyle(window.webContents, settingsPath);\n    });\n\n// 监听渲染进程的watchCSSChange事件\nipcMain.on(\n    \"mspring_theme.watchCSSChange\",\n    (event, settingsPath) => {\n        const window = BrowserWindow.fromWebContents(event.sender);\n        watchCSSChange(window.webContents, settingsPath);\n    });\n\n// 监听渲染进程的watchSettingsChange事件\nipcMain.on(\n    \"mspring_theme.watchSettingsChange\",\n    (event, settingsPath) => {\n        const window = BrowserWindow.fromWebContents(event.sender);\n        watchSettingsChange(window.webContents, settingsPath);\n    });\n\nipcMain.handle(\n    \"mspring_theme.getFrameworkType\",\n    (event) => {\n        return frameworkType;\n    }\n);\n\nipcMain.handle(\n    \"mspring_theme.getSettings\",\n    async (event, message) => {\n        try {\n            const data = await fsPromises.readFile(settingsPath, \"utf-8\");\n            const config = JSON.parse(data);\n            return config;\n        } catch (error) {\n            log(error);\n            return {};\n        }\n    }\n);\n\nipcMain.handle(\n    \"mspring_theme.setSettings\",\n    (event, content) => {\n        try {\n            const new_config = JSON.stringify(content);\n            fs.writeFileSync(settingsPath, new_config, \"utf-8\");\n        } catch (error) {\n            log(error);\n        }\n    }\n);\n\nipcMain.on(\"mspring_theme.openWeb\", (event, ...message) =>\n    openWeb(...message)\n);\n\nipcMain.handle(\"mspring_theme.logToMain\", (event, ...args) => {\n    log(...args);\n}\n);\n\nipcMain.handle(\"mspring_theme.fetchData\", (event, url) => {\n    return fetchData(url);\n});\n\nipcMain.handle(\"mspring_theme.readFile\", async (event, filePath) => {\n    try {\n        return await fsPromises.readFile(filePath, \"utf-8\");\n    } catch (error) {\n        log(\"读取文件时出错\", error);\n        return null; // 或返回错误信息\n    }\n});\n\n// 监听来自设置窗口强行覆盖气泡颜色的通知\nipcMain.on(\"mspring_theme.updateForceBubbleColor\", (event, state) => {\n    // 遍历所有窗口\n    for (const window of BrowserWindow.getAllWindows()) {\n        // 向每个窗口的渲染进程发送应用样式的指令\n        window.webContents.send(\"mspring_theme.applyForceBubbleColor\", state);\n    }\n});\n\n// 监听来自设置窗口强制覆盖夜间模式背景的通知\nipcMain.on(\"mspring_theme.updateForceNightModeBackground\", (event, state) => {\n    for (const window of BrowserWindow.getAllWindows()) {\n        window.webContents.send(\"mspring_theme.applyForceNightModeBackground\", state);\n    }\n});\n\n// 清理监听器\nfunction cleanupWatchers(webContents) {\n    const watchers = watchersMap.get(webContents);\n    if (watchers) {\n        watchers.forEach(watcher => {\n            try {\n                watcher.close();\n                log(\"已清理文件监听器\");\n            } catch (error) {\n                log(\"清理监听器时出错\", error);\n            }\n        });\n        watchersMap.delete(webContents);\n    }\n}\n\n// 创建窗口时触发\nfunction browserWindowCreated(window) {\n    const settingsPath = path.join(pluginDataPath, \"settings.json\");\n\n    window.on(\"ready-to-show\", () => {\n        const url = window.webContents.getURL();\n        if (url.includes(\"app://./renderer/\")) {\n            watchCSSChange(window.webContents, settingsPath);\n            watchSettingsChange(window.webContents, settingsPath);\n        }\n    });\n\n    // 窗口关闭时清理监听器\n    window.on(\"closed\", () => {\n        log(\"窗口被关闭，清理监听器\");\n        cleanupWatchers(window.webContents);\n    });\n\n    // webContents 销毁时也清理监听器\n    window.webContents.on(\"destroyed\", () => {\n        log(\"webContents被销毁，清理监听器\");\n        cleanupWatchers(window.webContents);\n    });\n}\n\nif (frameworkType === \"liteloader\") {\n    module.exports.onBrowserWindowCreated = window => {\n        browserWindowCreated(window);\n    }\n} else {\n    qwqnt.main.hooks.whenBrowserWindowCreated.peek((window) => {\n        browserWindowCreated(window);\n    });\n}"
  },
  {
    "path": "main/liteloader.js",
    "content": "// LiteLoader 框架入口文件\n\nglobal.MSPRING_FRAMEWORK_TYPE = 'liteloader';\nmodule.exports = require('./index.js');"
  },
  {
    "path": "main/qwqnt.js",
    "content": "// QwQNT 框架入口文件\n\nglobal.MSPRING_FRAMEWORK_TYPE = 'qwqnt';\nmodule.exports = require('./index.js');\n"
  },
  {
    "path": "manifest.json",
    "content": "{\n  \"manifest_version\": 4,\n  \"type\": \"theme\",\n  \"name\": \"MSpring Theme\",\n  \"slug\": \"mspring-theme\",\n  \"description\": \"LiteLoaderQQNT 主题，优雅 · 粉粉 · 细致\",\n  \"version\": \"2.0.3\",\n  \"icon\": \"./res/icon.png\",\n  \"thumb\": \"./res/brush_FILL0_wght300_GRAD0_opsz24.svg\",\n  \"authors\": [\n    {\n      \"name\": \"MUKAPP\",\n      \"link\": \"https://github.com/MUKAPP\"\n    }\n  ],\n  \"platform\": [\n    \"win32\",\n    \"linux\",\n    \"darwin\"\n  ],\n  \"injects\": {\n    \"renderer\": \"./renderer/liteloader.js\",\n    \"main\": \"./main/liteloader.js\",\n    \"preload\": \"./preload/index.js\"\n  },\n  \"repository\": {\n    \"repo\": \"MUKAPP/mspring-theme\",\n    \"branch\": \"v5\",\n    \"release\": {\n      \"tag\": \"latest\",\n      \"file\": \"mspring-theme.zip\"\n    }\n  }\n}"
  },
  {
    "path": "pack.js",
    "content": "const fs = require('fs');\nconst archiver = require('archiver');\n\nconsole.log('Creating release zip...');\n\nconst output = fs.createWriteStream('mspring-theme.zip');\nconst archive = archiver('zip', {\n  zlib: { level: 9 }\n});\n\noutput.on('close', function () {\n  console.log(archive.pointer() + ' total bytes');\n  console.log('Release zip created successfully: mspring-theme.zip');\n});\n\narchive.on('warning', function (err) {\n  if (err.code === 'ENOENT') {\n    console.warn(err);\n  } else {\n    throw err;\n  }\n});\n\narchive.on('error', function (err) {\n  throw err;\n});\n\narchive.pipe(output);\n\n// 1. 添加完整的源码目录\narchive.directory('main/', 'main');\narchive.directory('preload/', 'preload');\narchive.directory('renderer/', 'renderer');\n\n// 2. 精细化添加 src 目录中的文件\n// 使用 glob 模式匹配 src 下的所有文件，但排除不需要的\narchive.glob('**/*', {\n  cwd: 'src',\n  ignore: [\n    'scss/**',       // 排除 css 文件夹及其内容\n    'style.scss',   // 排除 style.scss 源文件\n    '*.map'         // 可选：排除可能产生的 sourcemap 文件\n  ]\n}, { prefix: 'src' });\n\n// 3. 添加 res 目录\narchive.glob('**/*', {\n  cwd: 'res',\n  ignore: ['github/**']\n}, { prefix: 'res' });\n\n// 4. 添加根目录下的关键文件\narchive.file('manifest.json', { name: 'manifest.json' });\narchive.file('package.json', { name: 'package.json' });\n// 如果有 README 或 LICENSE 也可以加进来\narchive.file('README.md', { name: 'README.md' });\narchive.file('LICENSE', { name: 'LICENSE' });\n\narchive.finalize();"
  },
  {
    "path": "package.json",
    "content": "{\n  \"$schema\": \"https://raw.githubusercontent.com/qwqnt-community/types/main/plugin.schema.json\",\n  \"name\": \"mspring-theme\",\n  \"version\": \"2.0.3\",\n  \"description\": \"QwQNT 主题，优雅 · 粉粉 · 细致\",\n  \"main\": \"./main/qwqnt.js\",\n  \"type\": \"commonjs\",\n  \"author\": \"MUKAPP\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"clean\": \"rimraf dist src/style.min.css src/heti-addon.js src/heti-m.css mspring-theme.zip\",\n    \"build:heti:css\": \"sass --silence-deprecation=import,global-builtin --no-source-map vendor/heti/heti-m.scss src/heti-m.css\",\n    \"build:heti:js\": \"esbuild vendor/heti/js/heti-entry.js --bundle --format=iife --platform=browser --charset=utf8 --outfile=src/heti-addon.js\",\n    \"build:heti\": \"npm run build:heti:css && npm run build:heti:js\",\n    \"build:css\": \"sass src/style.scss | postcss -o src/style.min.css\",\n    \"build\": \"npm run clean && npm run build:heti && npm run build:css && node pack.js\",\n    \"dev\": \"npm run build:heti && npm run build:css && nodemon --watch src/style.scss --watch src/scss --watch vendor/heti -e scss,js --ignore src/heti-addon.js --ignore src/style.min.css --ignore src/heti-m.css --exec \\\"npm run build:heti && npm run build:css\\\"\"\n  },\n  \"qwqnt\": {\n    \"name\": \"MSpring Theme\",\n    \"icon\": \"./res/brush_FILL0_wght300_GRAD0_opsz24.svg\",\n    \"inject\": {\n      \"preload\": \"./preload/index.js\",\n      \"renderer\": \"./renderer/qwqnt.js\"\n    },\n    \"dependencies\": {\n      \"qwqnt-hako\": \"^1.0.1\"\n    }\n  },\n  \"devDependencies\": {\n    \"archiver\": \"^7.0.1\",\n    \"autoprefixer\": \"^10.4.21\",\n    \"cssnano\": \"^7.1.2\",\n    \"esbuild\": \"^0.28.0\",\n    \"heti-findandreplacedomtext\": \"^0.5.0\",\n    \"nodemon\": \"^3.1.10\",\n    \"postcss\": \"^8.5.6\",\n    \"postcss-cli\": \"^11.0.1\",\n    \"rimraf\": \"^6.1.0\",\n    \"sass\": \"^1.93.3\"\n  }\n}"
  },
  {
    "path": "postcss.config.js",
    "content": "module.exports = {\n  plugins: [\n    require('autoprefixer'),\n    require('cssnano')({\n      preset: 'default',\n    }),\n  ],\n};\n"
  },
  {
    "path": "preload/index.js",
    "content": "const { contextBridge, ipcRenderer } = require(\"electron\");\n\n\ncontextBridge.exposeInMainWorld(\"mspring_theme\", {\n    updateStyle: (callback) => ipcRenderer.on(\n        \"mspring_theme.updateStyle\",\n        callback\n    ),\n    rendererReady: () => ipcRenderer.send(\n        \"mspring_theme.rendererReady\"\n    ),\n    getFrameworkType: () => ipcRenderer.invoke(\n        \"mspring_theme.getFrameworkType\"\n    ),\n    getPlatform: () => process.platform,\n    getSettings: () => ipcRenderer.invoke(\n        \"mspring_theme.getSettings\"\n    ),\n    setSettings: content => ipcRenderer.invoke(\n        \"mspring_theme.setSettings\",\n        content\n    ),\n    logToMain: (...args) => ipcRenderer.invoke(\n        \"mspring_theme.logToMain\",\n        ...args\n    ),\n    openWeb: (url) => ipcRenderer.send(\"mspring_theme.openWeb\", url),\n    fetchData: (url) => ipcRenderer.invoke(\"mspring_theme.fetchData\", url),\n    readFile: (path) => ipcRenderer.invoke(\"mspring_theme.readFile\", path),\n    // 强制覆盖气泡颜色 从设置页通知主进程\n    updateForceBubbleColor: (state) => ipcRenderer.send(\n        \"mspring_theme.updateForceBubbleColor\",\n        state\n    ),\n    // 强制覆盖气泡颜色 在所有窗口接收主进程的通知\n    onApplyForceBubbleColor: (callback) => ipcRenderer.on(\n        \"mspring_theme.applyForceBubbleColor\",\n        callback\n    ),\n    // 强制覆盖夜间模式背景 从设置页通知主进程\n    updateForceNightModeBackground: (state) => ipcRenderer.send(\n        \"mspring_theme.updateForceNightModeBackground\",\n        state\n    ),\n    // 强制覆盖夜间模式背景 在所有窗口接收主进程的通知\n    onApplyForceNightModeBackground: (callback) => ipcRenderer.on(\n        \"mspring_theme.applyForceNightModeBackground\",\n        callback\n    ),\n});"
  },
  {
    "path": "renderer/features.js",
    "content": "\nasync function insertHeti(messageListElement, selector, mspring_theme, plugin_path) {\n    // 在页面header插入heti的css和js\n    const hetiAddonCSS = await mspring_theme.readFile(`${plugin_path}/src/heti-m.css`);\n    const hetiStyleElement = document.createElement(\"style\");\n    hetiStyleElement.textContent = hetiAddonCSS;\n    document.head.appendChild(hetiStyleElement);\n\n    const hetiAddonJS = await mspring_theme.readFile(`${plugin_path}/src/heti-addon.js`);\n    const hetiScriptElement = document.createElement(\"script\");\n    hetiScriptElement.textContent = hetiAddonJS;\n    document.head.appendChild(hetiScriptElement);\n\n    const hetiSpacingElementScriptElement = document.createElement(\"script\");\n    hetiSpacingElementScriptElement.textContent = `\n            function hetiSpacingElement(element) {\n                let heti = new Heti();\n                heti.spacingElement(element);\n            }\n        `;\n    document.head.appendChild(hetiSpacingElementScriptElement);\n\n    function applyHetiToElement(element) {\n        if (!element.matches(selector) || element.querySelector(\"heti-spacing, heti-adjacent, heti-close\")) {\n            return;\n        }\n\n        element.classList.add(\"heti\");\n        hetiSpacingElement(element);\n    }\n\n    // 页面变化时，遍历 class 中包含 text-normal 的所有元素\n    function processHeti(rootElement) {\n        if (!rootElement || rootElement.nodeType !== 1) {\n            return;\n        }\n\n        applyHetiToElement(rootElement);\n        rootElement.querySelectorAll(selector).forEach(applyHetiToElement);\n    }\n\n    let processTimer = null;\n    const pendingRoots = new Set();\n\n    function scheduleHetiProcess(element) {\n        if (!element || element.nodeType !== 1) {\n            return;\n        }\n\n        pendingRoots.add(element);\n\n        if (processTimer !== null) {\n            return;\n        }\n\n        processTimer = requestAnimationFrame(() => {\n            pendingRoots.forEach(processHeti);\n            pendingRoots.clear();\n            processTimer = null;\n        });\n    }\n\n    // 处理页面上已经存在的元素\n    processHeti(messageListElement);\n\n    // 设置监听器，处理新增元素和后续文本重渲染\n    const observer = new MutationObserver((mutationsList) => {\n        for (const mutation of mutationsList) {\n            if (mutation.type === \"childList\") {\n                if (mutation.target.nodeType === 1) {\n                    scheduleHetiProcess(mutation.target);\n                }\n\n                mutation.addedNodes.forEach(node => {\n                    if (node.nodeType === 1) {\n                        scheduleHetiProcess(node);\n                    }\n                });\n            } else if (mutation.type === \"characterData\" && mutation.target.parentElement) {\n                scheduleHetiProcess(mutation.target.parentElement);\n            }\n        }\n    });\n    observer.observe(messageListElement, { childList: true, subtree: true, characterData: true });\n}\n\nfunction compareVersions(v1, v2) {\n    const parts1 = v1.split('.').map(Number);\n    const parts2 = v2.split('.').map(Number);\n\n    for (let i = 0; i < parts1.length; i++) {\n        if (parts2.length === i) {\n            return 1;\n        }\n\n        if (parts1[i] !== parts2[i]) {\n            return parts1[i] > parts2[i] ? 1 : -1;\n        }\n    }\n\n    return parts1.length === parts2.length ? 0 : -1;\n}\n\nasync function setupThemeFeatures(settings, { log, mspring_theme, frameworkType, plugin_path, observeElement }) {\n    try {\n        // 判断操作系统类型\n        var osType = \"\";\n        const platform = mspring_theme.getPlatform();\n\n        if (platform === \"win32\") {\n            osType = \"windows\";\n        } else if (platform === \"linux\") {\n            osType = \"linux\";\n        } else if (platform === \"darwin\") {\n            osType = \"mac\";\n        }\n        document.documentElement.classList.add(osType);\n\n        // 判断是否强制覆盖自己的气泡颜色\n        if (settings.forceHostBubbleColor) {\n            document.documentElement.classList.add(\"mspring_force_host_bubble_color\");\n        }\n\n        // 强制覆盖气泡颜色 设置监听\n        mspring_theme.onApplyForceBubbleColor((event, state) => {\n            const docElement = document.documentElement;\n            log(`设置修改强制气泡颜色: ${state}`);\n            if (state) {\n                docElement.classList.add(\"mspring_force_host_bubble_color\");\n            } else {\n                docElement.classList.remove(\"mspring_force_host_bubble_color\");\n            }\n        });\n\n        // 判断是否强制覆盖夜间模式主页背景\n        if (settings.forceNightModeBackground) {\n            document.documentElement.classList.add(\"mspring_force_night_mode_background\");\n        }\n\n        // 强制覆盖夜间模式背景 设置监听\n        mspring_theme.onApplyForceNightModeBackground((event, state) => {\n            const docElement = document.documentElement;\n            log(`设置修改强制夜间模式背景: ${state}`);\n            if (state) {\n                docElement.classList.add(\"mspring_force_night_mode_background\");\n            } else {\n                docElement.classList.remove(\"mspring_force_night_mode_background\");\n            }\n        });\n\n        if (frameworkType === \"liteloader\") {\n            // 判断插件background_plugin是否存在且启用\n            if (LiteLoader.plugins[\"background_plugin\"] && !LiteLoader.plugins[\"background_plugin\"].disabled) {\n                log(\"[检测]\", \"已启用背景插件\");\n                document.documentElement.classList.add(\"mspring_background_plugin_enabled\");\n            }\n\n            // 判断插件lite_tools是否存在且启用\n            if (LiteLoader.plugins[\"lite_tools\"] && !LiteLoader.plugins[\"lite_tools\"].disabled) {\n                log(\"[检测]\", \"已启用轻量工具箱\");\n                const ltData = await mspring_theme.readFile(LiteLoader.plugins[\"lite_tools\"].path.data + \"/config.json\");\n                const ltOptions = JSON.parse(ltData);\n                if (ltOptions && ltOptions.background) {\n                    if (ltOptions.background.enabled) {\n                        log(\"[检测]\", \"已启用轻量工具箱-自定义背景\");\n                        document.documentElement.classList.add(\"mspring_lite_tool_background_enabled\");\n                    }\n                }\n            }\n            log(document.documentElement.classList);\n        }\n\n        let more_materials_enabled = frameworkType === \"liteloader\"\n            ? LiteLoader.plugins[\"more_materials\"] && !LiteLoader.plugins[\"more_materials\"].disabled\n            : false;\n\n        if (more_materials_enabled) {\n            log(\"[检测]\", \"已启用 More Materials\");\n        }\n\n        const url = window.location.href;\n        log(\"[检测]\", \"当前页面\", url);\n\n        if (url.startsWith(\"app://./renderer/login.html\")) {\n            log(\"[检测]\", \"登录页面\");\n            // 判断窗口是否是夜间模式\n            let isDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;\n            let colorKey = isDarkMode ? 'dark' : 'light';\n            let defaultColor = isDarkMode ? '#171717' : '#ffffff';\n\n            document.body.style.backgroundColor = more_materials_enabled ? `var(--background-color-${colorKey})` : defaultColor;\n        }\n\n        // Heti 功能初始化\n        let applyHeti = null;\n        if (settings.heti && url.startsWith(\"app://./renderer/index.html\")) {\n            let hetiApplied = false;\n\n            applyHeti = () => {\n                if (hetiApplied) {\n                    return;\n                }\n\n                const currentHash = window.location.hash;\n\n                if (currentHash.includes(\"#/main/message\") || currentHash.includes(\"#/forward\")) {\n                    log(\"[设置]\", \"应用赫蹏，聊天页面，hash:\", currentHash);\n                    try {\n                        observeElement('#ml-root', (element) => {\n                            insertHeti(element, \".text-normal\", mspring_theme, plugin_path);\n                        }, false);\n                        hetiApplied = true;\n                    } catch (error) {\n                        log(\"[错误]\", \"赫蹏加载出错\", error);\n                    }\n                }\n            };\n\n            // 立即尝试应用（如果已经在目标页面）\n            applyHeti();\n        }\n\n        // 通用 URL 变化监听\n        const wrapHistory = (type) => {\n            const original = history[type];\n            return function (...args) {\n                const result = original.apply(this, args);\n                // 创建并派发一个自定义事件\n                const event = new Event(type);\n                event.arguments = args;\n                window.dispatchEvent(event);\n                return result;\n            };\n        };\n\n        // 重写 pushState 和 replaceState\n        history.pushState = wrapHistory('pushState');\n        history.replaceState = wrapHistory('replaceState');\n\n        // URL 变化时的通用处理\n        const onUrlChange = () => {\n            log(\"[检测]\", \"URL 变化:\", window.location.href);\n\n            // 调用各个功能的处理函数\n            if (applyHeti) {\n                applyHeti();\n            }\n        };\n\n        // 监听所有可能导致 URL 变化的情况\n        window.addEventListener('hashchange', onUrlChange);     // 手动修改 hash\n        window.addEventListener('popstate', onUrlChange);       // 浏览器前进/后退\n        window.addEventListener('pushState', onUrlChange);      // 代码调用 pushState\n        window.addEventListener('replaceState', onUrlChange);   // 代码调用 replaceState\n\n    } catch (error) {\n        log(\"[渲染进程错误]\", error);\n    }\n}\n\n\nexport {\n    insertHeti,\n    compareVersions,\n    setupThemeFeatures\n};\n"
  },
  {
    "path": "renderer/index.js",
    "content": "import { initTheme } from './theme.js';\nimport { setupThemeFeatures } from './features.js';\nimport { settingWindowCreated } from './settings.js';\n\n// --- Shared State & Utilities ---\n\nlet themeSettings = {};\n\nfunction log(...args) {\n    console.log(`[MSpring Theme]`, ...args);\n    if (themeSettings && themeSettings.logToMain) {\n        mspring_theme.logToMain(...args);\n    }\n}\n\nconst frameworkType = await mspring_theme.getFrameworkType();\n\nconst plugin_path = frameworkType === \"liteloader\"\n    ? LiteLoader.plugins[\"mspring-theme\"].path.plugin\n    : qwqnt.framework.plugins[\"mspring-theme\"].meta.path;\n\nfunction observeElement(selector, callback, callbackEnable = true, interval = 100) {\n    const timer = setInterval(function () {\n        const element = document.querySelector(selector);\n        if (element) {\n            if (callbackEnable) {\n                callback();\n            } else {\n                callback(element);\n            }\n            log(\"已检测到\", selector);\n            clearInterval(timer);\n        }\n    }, interval);\n}\n\n// --- Initialization Logic ---\n\nconst dependencyContext = {\n    log,\n    mspring_theme,\n    frameworkType,\n    plugin_path,\n    observeElement\n};\n\nasync function main() {\n    const settings = await initTheme(dependencyContext);\n    themeSettings = settings; // Update shared settings object\n    await setupThemeFeatures(settings, dependencyContext);\n}\n\nif (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', main);\n} else {\n    main();\n}\n\n// --- Exports for Entry Points ---\n\n// This function will be called by settingWindowCreated from the outside\nasync function handleSettingWindowCreated(view) {\n    // We need to re-fetch settings within the settings window context\n    const currentSettings = await mspring_theme.getSettings();\n    themeSettings = currentSettings;\n    // Pass the full context to the settings handler\n    await settingWindowCreated(view, dependencyContext);\n}\n\nexport {\n    log,\n    observeElement,\n    initTheme,\n    setupThemeFeatures,\n    handleSettingWindowCreated as settingWindowCreated, // Rename for clarity\n    plugin_path,\n    frameworkType\n};\n"
  },
  {
    "path": "renderer/liteloader.js",
    "content": "// LiteLoader 框架入口文件\n\nimport { settingWindowCreated } from './index.js';\n\nexport const onSettingWindowCreated = async (view) => {\n    settingWindowCreated(view);\n};"
  },
  {
    "path": "renderer/qwqnt.js",
    "content": "// QWQNT框架入口文件\n\nconst sharedModulePromise = import('./index.js');\n\nRendererEvents.onSettingsWindowCreated(async () => {\n    const { settingWindowCreated, log } = await sharedModulePromise;\n    try {\n\n        const packageJson = __self ? __self.meta.packageJson : {};\n        const view = await PluginSettings.renderer.registerPluginSettings(packageJson);\n\n        settingWindowCreated(view);\n    } catch (error) {\n        log('[MSpring Theme] 设置窗口创建时出错:', error);\n    }\n});"
  },
  {
    "path": "renderer/settings.js",
    "content": "import { compareVersions } from \"./features.js\";\n\nasync function settingWindowCreated(view, { log, mspring_theme, frameworkType, plugin_path }) {\n    log(\"[设置]\", \"打开设置界面\");\n    try {\n        const htmlContent = await mspring_theme.readFile(`${plugin_path}/src/settings.html`);\n        view.innerHTML = htmlContent;\n\n        // 获取设置\n        const settings = await mspring_theme.getSettings();\n        \n        const themeColor = settings.themeColor;\n\n        // 给pick-color(input)设置默认颜色\n        const pickColor = view.querySelector(\".pick-color\");\n        pickColor.value = themeColor;\n\n        // 给pick-color(input)添加事件监听\n        pickColor.addEventListener(\"change\", (event) => {\n            // 修改settings的themeColor值\n            settings.themeColor = event.target.value;\n            // 将修改后的settings保存到settings.json\n            mspring_theme.setSettings(settings);\n        });\n\n        // 背景颜色透明\n        const backgroundOpacity = settings.backgroundOpacity;\n        // 给pick-opacity(input)设置默认值\n        const pickOpacity = view.querySelector(\".pick-opacity\");\n        pickOpacity.value = backgroundOpacity;\n        // 给pick-opacity(input)添加事件监听 \n        pickOpacity.addEventListener(\"change\", (event) => {\n            // 修改settings的backgroundOpacity值 \n            settings.backgroundOpacity = event.target.value;\n            // 将修改后的settings保存到settings.json \n            mspring_theme.setSettings(settings);\n        });\n\n        // 选择id为heti的setting-switch\n        const hetiSwitch = view.querySelector(\"#heti\");\n        if (settings.heti) {\n            hetiSwitch.setAttribute(\"is-active\", \"\");\n        }\n        // 给hetiSwitch添加点击监听\n        hetiSwitch.addEventListener(\"click\", (event) => {\n            const isActive = event.currentTarget.hasAttribute(\"is-active\");\n\n            if (isActive) {\n                event.currentTarget.removeAttribute(\"is-active\")\n                // 修改settings的heti值为false\n                settings.heti = false;\n            } else {\n                event.currentTarget.setAttribute(\"is-active\", \"\");\n                // 修改settings的heti值为true\n                settings.heti = true;\n            }\n\n            // 将修改后的settings保存到settings.json\n            mspring_theme.setSettings(settings);\n        });\n\n        // 选择id为force-host-bubble-color的setting-switch\n        const forceHostBubbleColorSwitch = view.querySelector(\"#force-host-bubble-color\");\n        if (settings.forceHostBubbleColor) {\n            forceHostBubbleColorSwitch.setAttribute(\"is-active\", \"\");\n        }\n        // 给forceHostBubbleColorSwitch添加点击监听\n        forceHostBubbleColorSwitch.addEventListener(\"click\", (event) => {\n            const isActive = event.currentTarget.hasAttribute(\"is-active\");\n\n            if (isActive) {\n                event.currentTarget.removeAttribute(\"is-active\");\n                settings.forceHostBubbleColor = false;\n                mspring_theme.updateForceBubbleColor(false);\n            } else {\n                event.currentTarget.setAttribute(\"is-active\", \"\");\n                settings.forceHostBubbleColor = true;\n                mspring_theme.updateForceBubbleColor(true);\n            }\n\n            // 将修改后的settings保存到settings.json\n            mspring_theme.setSettings(settings);\n        });\n\n        // 选择 id 为 force-night-mode-background 的 setting-switch\n        const forceNightModeBackgroundSwitch = view.querySelector(\"#force-night-mode-background\");\n        if (settings.forceNightModeBackground) {\n            forceNightModeBackgroundSwitch.setAttribute(\"is-active\", \"\");\n        }\n        // 添加点击监听\n        forceNightModeBackgroundSwitch.addEventListener(\"click\", (event) => {\n            const isActive = event.currentTarget.hasAttribute(\"is-active\");\n\n            if (isActive) {\n                event.currentTarget.removeAttribute(\"is-active\");\n                settings.forceNightModeBackground = false;\n                mspring_theme.updateForceNightModeBackground(false);\n            } else {\n                event.currentTarget.setAttribute(\"is-active\", \"\");\n                settings.forceNightModeBackground = true;\n                mspring_theme.updateForceNightModeBackground(true);\n            }\n\n            mspring_theme.setSettings(settings);\n        });\n\n        // 版本更新\n        const version = view.querySelector(\"#mst-settings-version\");\n        version.textContent = frameworkType === \"liteloader\"\n            ? LiteLoader.plugins[\"mspring-theme\"].manifest.version\n            : qwqnt.framework.plugins[\"mspring-theme\"].meta.packageJson.version\n\n        const updateButton = view.querySelector(\"#mst-settings-go-to-update\");\n        updateButton.style.display = \"none\";\n\n        mspring_theme.fetchData(\"https://github.com/MUKAPP/LiteLoaderQQNT-MSpring-Theme/releases/latest\")\n            .then(({ url, content }) => {\n                const versionMatch = content.match(/\\/releases\\/tag\\/v(\\d+\\.\\d+\\.\\d+)/);\n                const urlMatch = content.match(/https:\\/\\/github\\.com\\/[\\w-]+\\/[\\w-]+\\/releases\\/tag\\/v\\d+\\.\\d+\\.\\d+/);\n                log(\"urlMatch\", urlMatch[0]);\n                if (versionMatch) {\n                    const new_version = versionMatch[1];\n                    log(\"[版本]\", \"最新版本\", new_version);\n                    if (compareVersions(new_version, frameworkType === \"liteloader\"\n                        ? LiteLoader.plugins[\"mspring-theme\"].manifest.version\n                        : qwqnt.framework.plugins[\"mspring-theme\"].meta.packageJson.version) > 0) {\n                        updateButton.style.display = \"block\";\n                        version.innerHTML += ` <span style=\"color: #ff4d4f;\">(有新版本: ${new_version})</span>`;\n\n                        // 判断 plugininstaller 插件是否存在并启用\n                        if (frameworkType === \"liteloader\") {\n                            if (LiteLoader.plugins[\"plugininstaller\"] && !LiteLoader.plugins[\"plugininstaller\"].disabled) {\n                                updateButton.addEventListener(\"click\", () => {\n                                    plugininstaller.updateBySlug(\"mspring-theme\");\n                                });\n                            } else {\n                                version.innerHTML += \"<br>未安装PluginInstaller，安装之后可以一键更新，当前需要手动更新\"\n                                updateButton.addEventListener(\"click\", () => {\n                                    mspring_theme.openWeb(urlMatch[0]);\n                                });\n                            }\n                        } else {\n                            // version.innerHTML += \"<br>未安装PluginInstaller，安装之后可以一键更新，当前需要手动更新\"\n                            updateButton.addEventListener(\"click\", () => {\n                                mspring_theme.openWeb(urlMatch[0]);\n                            });\n                        }\n                    } else {\n                        version.innerHTML += ` (已是最新版本)`;\n                    }\n                } else {\n                    version.innerHTML += ` (版本更新检查失败)`;\n                    log(\"版本更新检查失败\", content);\n                }\n            })\n            .catch((error) => {\n                version.innerHTML += ` (版本更新检查失败: ${error.message})`;\n                log(\"版本更新检查失败\", error);\n            });\n\n        // tg 频道\n        const tgChannel = view.querySelector(\"#msp-tg-channel\");\n        if (tgChannel) {\n            tgChannel.addEventListener(\"click\", () => {\n                mspring_theme.openWeb(\"https://t.me/MUKAPP_Personal\");\n\n            });\n        }\n\n        // 输出日志到主进程\n        const logToMainSwitch = view.querySelector(\"#msp-log-to-main\");\n        if (settings.logToMain) {\n            logToMainSwitch.setAttribute(\"is-active\", \"\");\n        }\n        logToMainSwitch.addEventListener(\"click\", (event) => {\n            const isActive = event.currentTarget.hasAttribute(\"is-active\");\n\n            if (isActive) {\n                event.currentTarget.removeAttribute(\"is-active\");\n                settings.logToMain = false;\n            } else {\n                event.currentTarget.setAttribute(\"is-active\", \"\");\n                settings.logToMain = true;\n            }\n\n            mspring_theme.setSettings(settings);\n        });\n\n\n        /**\n         * 为单个组件元素注入样式的函数\n         * @param {HTMLElement} element - 要注入样式的组件元素，如 <setting-button>\n         */\n        function applyCustomStyles(element) {\n            const shadow = element.shadowRoot;\n\n            // 如果没有 shadow root 或者已经注入过样式，则直接返回，防止重复操作\n            if (!shadow || shadow.querySelector('.custom-style-injected')) {\n                return;\n            }\n\n            // 创建一个新的 <style> 元素\n            const style = document.createElement('style');\n            // 添加一个类名作为标记，表示已处理\n            style.classList.add('custom-style-injected');\n\n            const tagName = element.tagName.toLowerCase();\n\n            // 根据不同的组件标签，应用不同的样式\n            if (tagName === 'setting-button') {\n                log(`[样式注入] 发现新的 ${tagName}，应用样式...`);\n                style.textContent = `\n                    button { \n                        border-radius: 8px !important; \n                    }\n                    :host([data-type=\"secondary\"]) button { \n                        background-color: var(--msp-container) !important;\n                    }\n                    :host([data-type=\"secondary\"]) button:hover { \n                        background-color: var(--msp-container-active) !important;\n                    }\n                `;\n            } else if (tagName === 'setting-select') {\n                log(`[样式注入] 发现新的 ${tagName}，应用样式...`);\n                style.textContent = `\n                    .menu-button { \n                        background-color: var(--msp-container); \n                        border-radius: 8px; \n                    }\n                    .menu-button:hover { \n                        background-color: var(--msp-container-active); \n                    }\n                    ul { \n                        border-radius: 8px; \n                    }\n                `;\n            }\n\n            // 将样式表注入到 Shadow DOM 中\n            shadow.appendChild(style);\n        }\n\n        /**\n         * 启动一个 MutationObserver 来监听整个文档的变化\n         */\n        function observeAndApplyStyles() {\n            console.log(\"样式注入脚本已启动\");\n\n            // 1. 创建观察器实例，当有节点变化时调用 applyCustomStyles\n            const observer = new MutationObserver((mutationsList) => {\n                for (const mutation of mutationsList) {\n                    // 我们只关心被添加到页面中的节点\n                    if (mutation.type === 'childList') {\n                        for (const node of mutation.addedNodes) {\n                            // 确保是元素节点\n                            if (node.nodeType === Node.ELEMENT_NODE) {\n                                // 检查被添加的节点本身是不是我们的目标组件\n                                if (node.matches('setting-button, setting-select')) {\n                                    applyCustomStyles(node);\n                                }\n                                // 同时检查被添加的节点的子孙元素，因为组件可能被包裹在其他div里一起添加进来\n                                node.querySelectorAll('setting-button, setting-select').forEach(applyCustomStyles);\n                            }\n                        }\n                    }\n                }\n            });\n\n            // 2. 配置观察器：监视 document.body 下的所有后代节点的添加和删除\n            observer.observe(document.body, {\n                childList: true, // 观察子节点的变动\n                subtree: true    // 观察所有后代节点\n            });\n\n            // 3. 对页面加载时可能已经存在的元素，立即执行一次\n            document.querySelectorAll('setting-button, setting-select').forEach(applyCustomStyles);\n        }\n\n\n        // 启动！\n        observeAndApplyStyles();\n\n    } catch (error) {\n        log(\"[设置页面错误]\", error);\n    }\n}\n\nexport {\n    settingWindowCreated\n}\n"
  },
  {
    "path": "renderer/theme.js",
    "content": "\nasync function initTheme({ log, mspring_theme }) {\n    log(\"[渲染进程初始化]\", `开始初始化`);\n    try {\n        // 页面加载完成时触发\n        const element = document.createElement(\"style\");\n        document.head.appendChild(element);\n\n        mspring_theme.updateStyle((event, message) => {\n            element.textContent = message;\n        });\n\n        mspring_theme.rendererReady();\n\n        const settings = await mspring_theme.getSettings();\n        return settings;\n\n    } catch (error) {\n        log(\"[渲染进程错误]\", error);\n        return {};\n    }\n}\n\nexport {\n    initTheme\n}"
  },
  {
    "path": "res/github/protocio-install.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>正在跳转...</title>\n    <script>\n        window.onload = function() {\n            window.location.href = \"llqqnt://plugininstaller/MUKAPP/LiteLoaderQQNT-MSpring-Theme/v4/manifest.json\";\n        };\n    </script>\n</head>\n\n<body>\n    <p>如果没有自动跳转，请点击<a href=\"llqqnt://plugininstaller/MUKAPP/LiteLoaderQQNT-MSpring-Theme/v4/manifest.json\">这里</a>.</p>\n</body>\n\n</html>"
  },
  {
    "path": "res/github/qq.css",
    "content": "/* color-tokens */\n.q-theme-tokens-light {\n    --brand_standard: #0099ffff;\n    --on_brand_primary: #ffffffff;\n    --on_brand_secondary: #ffffffff;\n    --brand_light: #0099ff33;\n    --text_primary: #000000ff;\n    --text_primary_light: #00000099;\n    --text_secondary_02: #ccccccff;\n    --text_white: #ffffffff;\n    --text_secondary_01: #999999ff;\n    --text_black: #000000ff;\n    --on_bg_text: #999999ff;\n    --text_link: #2d77e5ff;\n    --text_secondary: #00000080;\n    --text_tertiary: #0000004d;\n    --brand_text: #0099ffff;\n    --text_allwhite_primary: #ffffff;\n    --icon_primary: #000000ff;\n    --icon_secondary_01: #999999ff;\n    --icon_secondary_02: #ccccccff;\n    --icon_white: #ffffffff;\n    --icon_red: #ff3352ff;\n    --icon_black: #000000ff;\n    --icon_secondary: #00000066;\n    --icon_tertiary: #0000004d;\n    --feedback_success: #15d173ff;\n    --feedback_warning: #ffb300ff;\n    --feedback_error: #f74c30ff;\n    --bg_grey_standard: #f2f2f2ff;\n    --bg_white: #ffffffff;\n    --bg_list: #ffffffff;\n    --bg_aio_1: #eaf1ffff;\n    --bg_aio_2: #fff3ffff;\n    --bg_aio_3: #e0ebffff;\n    --bg_aio_4: #d6e9ffff;\n    --bg_nav: #f2f2f2ff;\n    --mac_bg_nav: #ffffff1a;\n    --bg_bottom_standard: #f5f5f5ff;\n    --bg_bottom_light: #ffffffff;\n    --bg_middle_standard: #f2f2f2ff;\n    --bg_middle_light: #ffffffff;\n    --bg_top_standard: #f2f2f2ff;\n    --bg_top_light: #ffffffff;\n    --bg_nav_secondary: #ffffffff;\n    --bubble_host: #ccebffff;\n    --bubble_guest: #ffffffff;\n    --on_bubble_host_text: #000000ff;\n    --bubble_guest_text: #000000ff;\n    --bubble_host_1: #0099ffff;\n    --bubble_host_2: #0099ffff;\n    --fg_grey_standard: #00000033;\n    --fg_white: #ffffffff;\n    --fg_grey_light: #0000000a;\n    --fill_standard_secondary: #0000000a;\n    --fill_standard_primary: #00000033;\n    --fill_light_primary: #ffffffff;\n    --fill_light_secondary: #ffffffff;\n    --divider_standard: #0000000a;\n    --divider_dark: #00000014;\n    --border_standard: #0000000a;\n    --border_dark: #00000014;\n    --overlay_hover: #0000000a;\n    --overlay_hover_brand: #00000014;\n    --overlay_pressed_brand: #00000029;\n    --overlay_active_brand: #0099ffff;\n    --overlay_top: #0000000a;\n    --overlay_mask_standard: #00000080;\n    --overlay_mask_dark: #00000099;\n    --overlay_pressed: #0000001f;\n    --overlay_active: #00000014;\n    --overlay_mask_aio: #00000000;\n    --blur_standard: #ffffffcc;\n    --blur_superlight: #ffffff1a;\n    --blur_middle_standard: #ffffffcc;\n    --blur_bottom_superlight: #ffffff1a;\n    --extend_blue: #eaf1ffff;\n    --svip_red: #ff4222ff;\n    --tag_sage_green_bg: #76969833;\n    --tag_sage_green_text: #769698ff;\n    --tag_red_bg: #ff3f3233;\n    --tag_red_text: #f74c30ff;\n    --tag_orange_text: #ff8d40ff;\n    --tag_orange_bg: #ff862e33;\n    --tag_purple_text: #aa76f6ff;\n    --tag_purple_bg: #aa76f633;\n    --tag_blue_text: #0099ffff;\n    --tag_blue_bg: #0099ff33;\n    --tag_blue: #0099ff33;\n    --tag_red: #ff862e33;\n    --tag_gray_bg: #9e9e9e33;\n    --tag_gray_text: #9e9e9eff;\n    --border_white: #ffffffff;\n    --border_secondary: #0000000f;\n    --border_primary: #00000014;\n    --border_light: rgba(0, 0, 0, 0.04);\n    --mac_border_primary: #00000014;\n    --mac_border_secondary: #0000000f;\n    --host_bubble_bg_css_value: #0099ff;\n    --fill_search_light: #ffffff80;\n    --fill_search_dark: #ffffff33;\n\n}\n\n.q-theme-tokens-dark {\n    --brand_standard: #0066ccff;\n    --on_brand_primary: #ffffffff;\n    --on_brand_secondary: #ffffffff;\n    --brand_light: #0066cc33;\n    --text_primary: #ffffffe6;\n    --text_primary_light: #ffffff99;\n    --text_secondary_02: #666666ff;\n    --text_white: #ffffffe6;\n    --text_secondary_01: #808080ff;\n    --text_black: #000000ff;\n    --on_bg_text: #808080ff;\n    --text_link: #2d77e5ff;\n    --text_secondary: #ffffff99;\n    --text_tertiary: #ffffff66;\n    --brand_text: #0066ccff;\n    --text_allwhite_primary: #ffffff;\n    --icon_primary: #ffffffb3;\n    --icon_secondary_01: #666666ff;\n    --icon_secondary_02: #4d4d4dff;\n    --icon_white: #ffffffff;\n    --icon_red: #ff3352ff;\n    --icon_black: #000000ff;\n    --icon_secondary: #ffffff80;\n    --icon_tertiary: #ffffff66;\n    --feedback_success: #15d173ff;\n    --feedback_warning: #ffb300ff;\n    --feedback_error: #f74c30ff;\n    --bg_grey_standard: #1a1a1aff;\n    --bg_white: #262626ff;\n    --bg_list: #1b1b1bff;\n    --bg_aio_1: #1d2433ff;\n    --bg_aio_2: #322933ff;\n    --bg_aio_3: #141b28ff;\n    --bg_aio_4: #142131ff;\n    --bg_nav: #111111ff;\n    --mac_bg_nav: #0000001a;\n    --bg_bottom_standard: #111111ff;\n    --bg_bottom_light: #1b1b1bff;\n    --bg_middle_standard: #1b1b1bff;\n    --bg_middle_light: #262626ff;\n    --bg_top_standard: #262626ff;\n    --bg_top_light: #303030ff;\n    --bg_nav_secondary: #1b1b1bff;\n    --bubble_host: #666666ff;\n    --bubble_guest: #262626ff;\n    --on_bubble_host_text: #ffffffff;\n    --bubble_guest_text: #f2f2f2ff;\n    --bubble_host_1: #262626ff;\n    --bubble_host_2: #262626ff;\n    --fg_grey_standard: #ffffff33;\n    --fg_white: #262626ff;\n    --fg_grey_light: #00000033;\n    --fill_standard_secondary: #ffffff0f;\n    --fill_standard_primary: #ffffff33;\n    --fill_light_primary: #262626ff;\n    --fill_light_secondary: #ffffff0f;\n    --divider_standard: #ffffff0a;\n    --divider_dark: #ffffff14;\n    --border_standard: #ffffff0f;\n    --border_dark: #ffffff14;\n    --overlay_hover: #ffffff14;\n    --overlay_hover_brand: #ffffff14;\n    --overlay_pressed_brand: #00000029;\n    --overlay_active_brand: #0066ccff;\n    --overlay_top: #ffffff0f;\n    --overlay_mask_standard: #00000080;\n    --overlay_mask_dark: #00000099;\n    --overlay_pressed: #00000029;\n    --overlay_active: #ffffff1f;\n    --overlay_mask_aio: #00000000;\n    --blur_standard: #000000cc;\n    --blur_superlight: #0000001a;\n    --blur_middle_standard: #262626cc;\n    --blur_bottom_superlight: #0000001a;\n    --extend_blue: #002f65ff;\n    --svip_red: #ff4222ff;\n    --tag_sage_green_bg: #76969833;\n    --tag_sage_green_text: #769698ff;\n    --tag_red_bg: #ff3f3233;\n    --tag_red_text: #f74c30ff;\n    --tag_orange_text: #ff8d40ff;\n    --tag_orange_bg: #ff862e33;\n    --tag_purple_text: #aa76f6ff;\n    --tag_purple_bg: #aa76f633;\n    --tag_blue_text: #0066ccff;\n    --tag_blue_bg: #0099ff33;\n    --tag_blue: #0099ff40;\n    --tag_red: #ff862e33;\n    --tag_gray_bg: #9e9e9e33;\n    --tag_gray_text: #9e9e9eff;\n    --border_white: #262626ff;\n    --border_secondary: #ffffff33;\n    --border_primary: #ffffff29;\n    --border_light: rgba(255, 255, 255, 0.04);\n    --mac_border_primary: #ffffff29;\n    --mac_border_secondary: #ffffff33;\n    --host_bubble_bg_css_value: #0099ff;\n    --fill_search_light: #ffffff0d;\n    --fill_search_dark: #ffffff0d;\n\n}\n\n/* border-tokens */\n.q-theme-tokens-light {\n    --border_secondary: 1px solid rgba(0, 0, 0, 0.06);\n    --border_primary: 1px solid rgba(0, 0, 0, 0.08);\n\n}\n\n.q-theme-tokens-dark {\n    --border_secondary: 1px solid rgba(255, 255, 255, 0.2);\n    --border_primary: 1px solid rgba(255, 255, 255, 0.16);\n\n}\n\n/* mix-tokens */\n.q-theme-tokens-light {\n    --nt_brand_standard_2_overlay_hover_brand_2_mix: #008debff;\n    --nt_brand_standard_2_overlay_pressed_brand_2_mix: #0080d6ff;\n    --nt_feedback_error_2_overlay_hover_brand_2_mix: #e4462cff;\n    --nt_feedback_error_2_overlay_pressed_brand_2_mix: #cf4028ff;\n    --nt_icon_white_2_overlay_hover_2_mix: #f5f5f5ff;\n    --nt_icon_white_2_overlay_pressed_2_mix: #e0e0e0ff;\n    --nt_brand_standard_2_blend_white_020_2_mix: #33adffff;\n    --nt_bg_top_light_2_overlay_hover_2_mix: #f5f5f5ff;\n    --nt_bg_top_light_2_overlay_pressed_2_mix: #e0e0e0ff;\n    --nt_icon_secondary_02_2_0_2_alpha: rgba(204, 204, 204, 0);\n    --nt_icon_secondary_02_2_70_2_alpha: rgba(204, 204, 204, 0.7);\n    --nt_fill_standard_primary_2_overlay_hover_brand_2_mix: #00000043;\n    --nt_text_link_2_50_2_alpha: rgba(45, 119, 229, 0.5);\n    --nt_bg_nav_2_60_2_alpha: rgba(242, 242, 242, 0.6);\n    --nt_bg_bottom_standard_2_50_2_alpha: rgba(245, 245, 245, 0.5);\n    --nt_bubble_host_2_overlay_pressed_brand_2_mix: #abc5d6ff;\n    --nt_bg_white_2_overlay_pressed_brand_2_mix: #d6d6d6ff;\n    --nt_bg_white_2_overlay_hover_2_mix: #f5f5f5ff;\n    --nt_bg_white_2_overlay_pressed_2_mix: #e0e0e0ff;\n    --nt_fg_white_2_overlay_hover_2_mix: #f5f5f5ff;\n    --nt_fg_white_2_overlay_pressed_2_mix: #e0e0e0ff;\n    --nt_icon_red_2_overlay_hover_2_mix: #f5314fff;\n    --nt_icon_red_2_overlay_pressed_2_mix: #e02d48ff;\n    --nt_fg_grey_standard_2_overlay_hover_2_mix: #0000003b;\n    --nt_fg_grey_standard_2_overlay_pressed_2_mix: #0000004c;\n    --nt_bubble_guest_2_overlay_pressed_2_mix: #e0e0e0ff;\n    --nt_icon_primary_2_20_2_alpha: rgba(0, 0, 0, 0.2);\n    --nt_bg_grey_standard_2_95_2_alpha: rgba(242, 242, 242, 0.95);\n    --nt_tag_red_2_20_2_alpha: rgba(255, 134, 46, 0.2);\n    --nt_tag_red_2_25_2_alpha: rgba(255, 134, 46, 0.25);\n    --nt_tag_blue_2_20_2_alpha: rgba(0, 153, 255, 0.2);\n    --nt_tag_blue_2_25_2_alpha: rgba(0, 153, 255, 0.25);\n    --nt_tag_blue_2_10_2_alpha: rgba(0, 153, 255, 0.1);\n    --nt_brand_standard_2_20_2_alpha: rgba(0, 153, 255, 0.2);\n    --nt_feedback_error_2_20_2_alpha: rgba(247, 76, 48, 0.2);\n    --nt_text_white_2_60_2_alpha: rgba(255, 255, 255, 0.6);\n    --nt_bg_white_2_70_2_alpha: rgba(255, 255, 255, 0.7);\n    --nt_bg_white_2_60_2_alpha: rgba(255, 255, 255, 0.6);\n    --nt_bg_white_2_90_2_alpha: rgba(255, 255, 255, 0.9);\n    --nt_bg_white_2_97_2_alpha: rgba(255, 255, 255, 0.97);\n    --nt_bg_white_2_50_2_alpha: rgba(255, 255, 255, 0.5);\n    --nt_bg_white_2_40_2_alpha: rgba(255, 255, 255, 0.4);\n    --nt_bg_white_2_30_2_alpha: rgba(255, 255, 255, 0.3);\n    --nt_text_white_2_80_2_alpha: rgba(255, 255, 255, 0.8);\n    --nt_brand_standard_2_50_2_alpha: rgba(0, 153, 255, 0.5);\n    --nt_bg_nav_secondary_2_60_2_alpha: rgba(255, 255, 255, 0.6);\n    --nt_feedback_error_2_10_2_alpha: rgba(247, 76, 48, 0.1);\n    --nt_brand_standard_2_10_2_alpha: rgba(0, 153, 255, 0.1);\n    --nt_on_brand_primary_2_40_2_alpha: rgba(255, 255, 255, 0.4);\n    --nt_text_primary_2_72_2_alpha: rgba(0, 0, 0, 0.72);\n    --nt_text_white_2_72_2_alpha: rgba(255, 255, 255, 0.72);\n    --nt_fill_standard_primary_2_4_2_alpha: rgba(0, 0, 0, 0.04);\n    --nt_brand_light_2_20_2_alpha: rgba(0, 153, 255, 0.2);\n    --nt_host_bubble_bg_css_value_2_40_2_alpha: rgba(0, 153, 255, 0.4);\n    --nt_brand_light_2_40_2_alpha: rgba(0, 153, 255, 0.4);\n    --nt_icon_white_2_20_2_alpha: rgba(255, 255, 255, 0.2);\n    --nt_fill_standard_secondary_2_overlay_hover_brand_2_mix: #0000001d;\n    --nt_fill_standard_secondary_2_overlay_pressed_brand_2_mix: #00000031;\n    --nt_fill_light_secondary_2_overlay_hover_brand_2_mix: #ebebebff;\n    --nt_fill_light_secondary_2_overlay_pressed_brand_2_mix: #d6d6d6ff;\n    --nt_text_link_2_overlay_hover_2_mix: #2b72dcff;\n    --nt_text_link_2_overlay_pressed_2_mix: #2869c9ff;\n    --nt_tag_red_text_2_10_2_alpha: rgba(247, 76, 48, 0.1);\n    --nt_tag_blue_text_2_10_2_alpha: rgba(0, 153, 255, 0.1);\n    --nt_brand_standard_2_0_2_alpha: rgba(0, 153, 255, 0);\n    --nt_text_black_2_5_2_alpha: rgba(0, 0, 0, 0.05);\n    --nt_bg_nav_2_40_2_alpha: rgba(242, 242, 242, 0.4);\n    --nt_bg_nav_2_80_2_alpha: rgba(242, 242, 242, 0.8);\n    --nt_text_primary_2_20_2_alpha: rgba(0, 0, 0, 0.2);\n    --nt_on_brand_primary_2_5_2_alpha: rgba(255, 255, 255, 0.05);\n    --nt_on_brand_primary_2_8_2_alpha: rgba(255, 255, 255, 0.08);\n    --nt_icon_secondary_02_2_80_2_alpha: rgba(204, 204, 204, 0.8);\n    --nt_blur_bottom_superlight_2_30_2_alpha: rgba(255, 255, 255, 0.3);\n    --nt_fill_standard_secondary_2_8_2_alpha: rgba(0, 0, 0, 0.08);\n    --nt_overlay_active_brand_2_40_2_alpha: rgba(0, 153, 255, 0.4);\n    --nt_border_white_2_80_2_alpha: rgba(255, 255, 255, 0.8);\n    --nt_bubble_guest_text_2_60_2_alpha: rgba(0, 0, 0, 0.6);\n    --nt_text_primary_2_60_2_alpha: rgba(0, 0, 0, 0.6);\n    --nt_fill_light_primary_2_40_2_alpha: rgba(255, 255, 255, 0.4);\n\n}\n\n.q-theme-tokens-dark {\n    --nt_brand_standard_2_overlay_hover_brand_2_mix: #1472d0ff;\n    --nt_brand_standard_2_overlay_pressed_brand_2_mix: #0056abff;\n    --nt_feedback_error_2_overlay_hover_brand_2_mix: #f85a40ff;\n    --nt_feedback_error_2_overlay_pressed_brand_2_mix: #cf4028ff;\n    --nt_icon_white_2_overlay_hover_2_mix: #ffffffff;\n    --nt_icon_white_2_overlay_pressed_2_mix: #d6d6d6ff;\n    --nt_brand_standard_2_blend_white_020_2_mix: #3385d6ff;\n    --nt_bg_top_light_2_overlay_hover_2_mix: #404040ff;\n    --nt_bg_top_light_2_overlay_pressed_2_mix: #282828ff;\n    --nt_icon_secondary_02_2_0_2_alpha: rgba(77, 77, 77, 0);\n    --nt_icon_secondary_02_2_70_2_alpha: rgba(77, 77, 77, 0.7);\n    --nt_fill_standard_primary_2_overlay_hover_brand_2_mix: #ffffff43;\n    --nt_text_link_2_50_2_alpha: rgba(45, 119, 229, 0.5);\n    --nt_bg_nav_2_60_2_alpha: rgba(17, 17, 17, 0.6);\n    --nt_bg_bottom_standard_2_50_2_alpha: rgba(17, 17, 17, 0.5);\n    --nt_bubble_host_2_overlay_pressed_brand_2_mix: #565656ff;\n    --nt_bg_white_2_overlay_pressed_brand_2_mix: #202020ff;\n    --nt_bg_white_2_overlay_hover_2_mix: #373737ff;\n    --nt_bg_white_2_overlay_pressed_2_mix: #202020ff;\n    --nt_fg_white_2_overlay_hover_2_mix: #373737ff;\n    --nt_fg_white_2_overlay_pressed_2_mix: #202020ff;\n    --nt_icon_red_2_overlay_hover_2_mix: #ff4360ff;\n    --nt_icon_red_2_overlay_pressed_2_mix: #d62b45ff;\n    --nt_fg_grey_standard_2_overlay_hover_2_mix: #ffffff43;\n    --nt_fg_grey_standard_2_overlay_pressed_2_mix: #82828254;\n    --nt_bubble_guest_2_overlay_pressed_2_mix: #202020ff;\n    --nt_icon_primary_2_20_2_alpha: rgba(255, 255, 255, 0.2);\n    --nt_bg_grey_standard_2_95_2_alpha: rgba(26, 26, 26, 0.95);\n    --nt_tag_red_2_20_2_alpha: rgba(255, 134, 46, 0.2);\n    --nt_tag_red_2_25_2_alpha: rgba(255, 134, 46, 0.25);\n    --nt_tag_blue_2_20_2_alpha: rgba(0, 153, 255, 0.2);\n    --nt_tag_blue_2_25_2_alpha: rgba(0, 153, 255, 0.25);\n    --nt_tag_blue_2_10_2_alpha: rgba(0, 153, 255, 0.1);\n    --nt_brand_standard_2_20_2_alpha: rgba(0, 102, 204, 0.2);\n    --nt_feedback_error_2_20_2_alpha: rgba(247, 76, 48, 0.2);\n    --nt_text_white_2_60_2_alpha: rgba(255, 255, 255, 0.6);\n    --nt_bg_white_2_70_2_alpha: rgba(38, 38, 38, 0.7);\n    --nt_bg_white_2_60_2_alpha: rgba(38, 38, 38, 0.6);\n    --nt_bg_white_2_90_2_alpha: rgba(38, 38, 38, 0.9);\n    --nt_bg_white_2_97_2_alpha: rgba(38, 38, 38, 0.97);\n    --nt_bg_white_2_50_2_alpha: rgba(38, 38, 38, 0.5);\n    --nt_bg_white_2_40_2_alpha: rgba(38, 38, 38, 0.4);\n    --nt_bg_white_2_30_2_alpha: rgba(38, 38, 38, 0.3);\n    --nt_text_white_2_80_2_alpha: rgba(255, 255, 255, 0.8);\n    --nt_brand_standard_2_50_2_alpha: rgba(0, 102, 204, 0.5);\n    --nt_bg_nav_secondary_2_60_2_alpha: rgba(27, 27, 27, 0.6);\n    --nt_feedback_error_2_10_2_alpha: rgba(247, 76, 48, 0.1);\n    --nt_brand_standard_2_10_2_alpha: rgba(0, 102, 204, 0.1);\n    --nt_on_brand_primary_2_40_2_alpha: rgba(255, 255, 255, 0.4);\n    --nt_text_primary_2_72_2_alpha: rgba(255, 255, 255, 0.72);\n    --nt_text_white_2_72_2_alpha: rgba(255, 255, 255, 0.72);\n    --nt_fill_standard_primary_2_4_2_alpha: rgba(255, 255, 255, 0.04);\n    --nt_brand_light_2_20_2_alpha: rgba(0, 102, 204, 0.2);\n    --nt_host_bubble_bg_css_value_2_40_2_alpha: rgba(0, 153, 255, 0.4);\n    --nt_brand_light_2_40_2_alpha: rgba(0, 102, 204, 0.4);\n    --nt_icon_white_2_20_2_alpha: rgba(255, 255, 255, 0.2);\n    --nt_fill_standard_secondary_2_overlay_hover_brand_2_mix: #ffffff22;\n    --nt_fill_standard_secondary_2_overlay_pressed_brand_2_mix: #3c3c3c36;\n    --nt_fill_light_secondary_2_overlay_hover_brand_2_mix: #ffffff22;\n    --nt_fill_light_secondary_2_overlay_pressed_brand_2_mix: #3c3c3c36;\n    --nt_text_link_2_overlay_hover_2_mix: #3d82e7ff;\n    --nt_text_link_2_overlay_pressed_2_mix: #2664c0ff;\n    --nt_tag_red_text_2_10_2_alpha: rgba(247, 76, 48, 0.1);\n    --nt_tag_blue_text_2_10_2_alpha: rgba(0, 102, 204, 0.1);\n    --nt_brand_standard_2_0_2_alpha: rgba(0, 102, 204, 0);\n    --nt_text_black_2_5_2_alpha: rgba(0, 0, 0, 0.05);\n    --nt_bg_nav_2_40_2_alpha: rgba(17, 17, 17, 0.4);\n    --nt_bg_nav_2_80_2_alpha: rgba(17, 17, 17, 0.8);\n    --nt_text_primary_2_20_2_alpha: rgba(255, 255, 255, 0.2);\n    --nt_on_brand_primary_2_5_2_alpha: rgba(255, 255, 255, 0.05);\n    --nt_on_brand_primary_2_8_2_alpha: rgba(255, 255, 255, 0.08);\n    --nt_icon_secondary_02_2_80_2_alpha: rgba(77, 77, 77, 0.8);\n    --nt_blur_bottom_superlight_2_30_2_alpha: rgba(0, 0, 0, 0.3);\n    --nt_fill_standard_secondary_2_8_2_alpha: rgba(255, 255, 255, 0.08);\n    --nt_overlay_active_brand_2_40_2_alpha: rgba(0, 102, 204, 0.4);\n    --nt_border_white_2_80_2_alpha: rgba(38, 38, 38, 0.8);\n    --nt_bubble_guest_text_2_60_2_alpha: rgba(242, 242, 242, 0.6);\n    --nt_text_primary_2_60_2_alpha: rgba(255, 255, 255, 0.6);\n    --nt_fill_light_primary_2_40_2_alpha: rgba(38, 38, 38, 0.4);\n\n}\n\n/* ancient-tokens */\n.q-theme-tokens-light {\n    --text-primary: #000;\n    --text-primary-light: #666;\n    --text-secondary-01: #999;\n    --text-secondary-02: #ccc;\n    --text-white: #fff;\n    --text-brand: #0099ff;\n    --text-link: #2d77e5;\n    --text-success: #12d173;\n    --text-warning: #ffb300;\n    --text-error: #ff5967;\n    --icon-primary: #000;\n    --icon-secondary-01: #999999;\n    --icon-secondary-02: #cccccc;\n    --icon-white: #fff;\n    --icon-brand: #0099ff;\n    --icon-success: #15d173;\n    --icon-warning: #ffb300;\n    --icon-error: #ff5967;\n    --button-primary-default: #0099ff;\n    --button-primary-hover: #4DB7FF;\n    --button-primary-pressed: #0089E5;\n    --button-primary-disable: #CCEBFF;\n    --button-secondary-default: #ccc;\n    --button-secondary-hover: #E5E5E5;\n    --button-secondary-pressed: #B2B2B2;\n    --button-secondary-disable: #F0F0F0;\n    --button-white-default: #FFFFFF;\n    --button-white-hover: #E5E5E5;\n    --button-white-pressed: #B2B2B2;\n    --button-white-disable: #ffffff4d;\n    --button-error-default: #FF5967;\n    --button-error-hover: #FF8B94;\n    --button-error-pressed: #E6505C;\n    --button-error-disable: #FFEEEF;\n    --bubble-host: #0099FF;\n    --bubble-guest: #EBEBEB;\n    --divider-standard: #E5E5E5;\n    --divider-light: #F5F5F5;\n    --divider-brand: #0099FF;\n    --background-01: #000;\n    --background-02: #E5E5E5;\n    --background-03: #F5F5F5;\n    --background-04: #FAFAFA;\n    --background-05: #FFFFFF;\n    --background-dialogue: #FFFFFF;\n    --hover-list: #F0F0F0;\n    --hover-icon: #EBEBEB;\n    --hover-link: #81ADEF;\n    --press-list: #E5E5E5;\n    --press-icon: #E5E5E5;\n    --press-link: #286BCE;\n    --badge-brand: #0099FF;\n    --badge-red: #FF5967;\n    --badge-grey: #CCCCCC;\n    --audio-hangup: #FF3350;\n    --gray-black: #000;\n    --gray-20: #333333;\n    --gray-40: #666666;\n    --gray-60: #999999;\n    --gray-80: #cccccc;\n    --gray-90: #e5e5e5;\n    --gray-96: #f5f5f5;\n    --gray-white: #ffffff;\n    --blue-dark: #0089E5;\n    --blue-standard: #0099FF;\n    --blue-light: #4DB7FF;\n    --blue-superlight: #E6F5FF;\n    --green-dark: #12BC67;\n    --green-standard: #15D173;\n    --green-light: #5BDE9D;\n    --green-superlight: #E8FAF1;\n    --yellow-dark: #E5A000;\n    --yellow-standard: #FFB300;\n    --yellow-light: #FFC94C;\n    --yellow-superlight: #FFF7E5;\n    --orange-dark: #E57E39;\n    --orange-standard: #FF8D40;\n    --orange-light: #FFAE78;\n    --orange-superlight: #FFF3EB;\n    --red-dark: #E6505C;\n    --red-standard: #FF5967;\n    --red-light: #FF8B94;\n    --red-superlight: #FFEEEF;\n    --pink-dark: #E55BA0;\n    --pink-standard: #FF66B3;\n    --pink-light: #FF93C9;\n    --pink-superlight: #FFEFF7;\n    --indigo-dark: #775CE6;\n    --indigo-standard: #8566FF;\n    --indigo-light: #A994FF;\n    --indigo-superlight: #F3F0FF;\n    --list-hover: rgba(243, 243, 243);\n    --list-pressed: rgba(226, 226, 226);\n    --background_01: #000000;\n    --background_02: #E6E6E6;\n    --background_03: #F5F5F5;\n    --background_04: #FAFAFA;\n    --background_05: #FFFFFF;\n    --background_dialogue: #FFFFFF;\n    --sidebar_win: #ebebeb;\n    --sidebar_mac: rgba(255, 255, 255, 0.1);\n\n}\n\n.q-theme-tokens-dark {\n    --text-primary: #FFFFFF;\n    --text-primary-light: #CCCCCC;\n    --text-secondary-01: #999;\n    --text-secondary-02: #666666;\n    --text-white: #fff;\n    --text-brand: #0099ff;\n    --text-link: #2d77e5;\n    --text-success: #12d173;\n    --text-warning: #ffb300;\n    --text-error: #ff5967;\n    --icon-primary: #999999;\n    --icon-secondary-01: #999999;\n    --icon-secondary-02: #999999;\n    --icon-white: #fff;\n    --icon-brand: #0099ff;\n    --icon-success: #15d173;\n    --icon-warning: #ffb300;\n    --icon-error: #ff5967;\n    --button-primary-default: #0066CC;\n    --button-primary-hover: #19467F;\n    --button-primary-pressed: #0A1F33;\n    --button-primary-disable: #232323;\n    --button-secondary-default: #232323;\n    --button-secondary-hover: #1F1F1F;\n    --button-secondary-pressed: #1A1A1A;\n    --button-secondary-disable: #1A1A1A;\n    --button-white-default: #FFFFFF;\n    --button-white-hover: #FAFAFA;\n    --button-white-pressed: #F5F5F5;\n    --button-white-disable: #FFFFFF;\n    --button-error-default: #FF5967;\n    --button-error-hover: #FF8B94;\n    --button-error-pressed: #E6505C;\n    --button-error-disable: #FFEEEF;\n    --bubble-host: #262626;\n    --bubble-guest: #262626;\n    --divider-standard: #242424;\n    --divider-light: #4D4D4D;\n    --divider-brand: #0099FF;\n    --background-01: #FFFFFF;\n    --background-02: #242424;\n    --background-03: #181818;\n    --background-04: #1F1F1F;\n    --background-05: #000000;\n    --background-dialogue: #262626;\n    --hover-list: #292929;\n    --hover-icon: #333333;\n    --hover-link: #81ADEF;\n    --press-list: #383838;\n    --press-icon: #262626;\n    --press-link: #286BCE;\n    --badge-brand: #0099FF;\n    --badge-red: #FF5967;\n    --badge-grey: #4D4D4D;\n    --audio-hangup: #FF3350;\n    --gray-black: #000;\n    --gray-20: #333333;\n    --gray-40: #666666;\n    --gray-60: #999999;\n    --gray-80: #cccccc;\n    --gray-90: #e5e5e5;\n    --gray-96: #f5f5f5;\n    --gray-white: #ffffff;\n    --blue-dark: #0057BD;\n    --blue-standard: #0066CC;\n    --blue-light: #0072E4;\n    --blue-superlight: #E6F5FF;\n    --green-dark: #12BC67;\n    --green-standard: #15D173;\n    --green-light: #5BDE9D;\n    --green-superlight: #E8FAF1;\n    --yellow-dark: #E5A000;\n    --yellow-standard: #FFB300;\n    --yellow-light: #FFC94C;\n    --yellow-superlight: #FFF7E5;\n    --orange-dark: #E57E39;\n    --orange-standard: #FF8D40;\n    --orange-light: #FFAE78;\n    --orange-superlight: #FFF3EB;\n    --red-dark: #E6505C;\n    --red-standard: #FF5967;\n    --red-light: #FF8B94;\n    --red-superlight: #FFEEEF;\n    --pink-dark: #E55BA0;\n    --pink-standard: #FF66B3;\n    --pink-light: #FF93C9;\n    --pink-superlight: #FFEFF7;\n    --indigo-dark: #775CE6;\n    --indigo-standard: #8566FF;\n    --indigo-light: #A994FF;\n    --indigo-superlight: #F3F0FF;\n    --list-hover: rgba(71, 71, 71);\n    --list-pressed: rgba(28, 28, 28);\n    --background_01: #ffffff;\n    --background_02: #292929;\n    --background_03: #1A1A1A;\n    --background_04: #212121;\n    --background_05: #212121;\n    --background_dialogue: #292929;\n    --sidebar_win: rgba(0, 0, 0, 0.8);\n    --sidebar_mac: rgba(0, 0, 0, 0.1);\n\n}\n\n/* blend-tokens */\n:root {\n    --blend_brightness_white_004: 1.04;\n    --blend_brightness_white_008: 1.08;\n    --blend_brightness_white_010: 1.10;\n    --blend_brightness_white_016: 1.16;\n    --blend_brightness_white_020: 1.20;\n    --blend_brightness_black_004: 0.96;\n    --blend_brightness_black_008: 0.92;\n    --blend_brightness_black_010: 0.90;\n    --blend_brightness_black_016: 0.84;\n    --blend_brightness_black_020: 0.80;\n    --blend_white_004: rgba(255, 255, 255, 0.04);\n    --blend_white_008: rgba(255, 255, 255, 0.08);\n    --blend_white_010: rgba(255, 255, 255, 0.10);\n    --blend_white_016: rgba(255, 255, 255, 0.16);\n    --blend_white_020: rgba(255, 255, 255, 0.20);\n    --blend_black_004: rgba(0, 0, 0, 0.04);\n    --blend_black_008: rgba(0, 0, 0, 0.08);\n    --blend_black_010: rgba(0, 0, 0, 0.10);\n    --blend_black_016: rgba(0, 0, 0, 0.16);\n    --blend_black_020: rgba(0, 0, 0, 0.20);\n    --blend_transparent: rgba(0, 0, 0, 0);\n\n}"
  },
  {
    "path": "src/scss/_base.scss",
    "content": "/* 基础、重置和全局通用样式 */\n@use \"variables\" as *;\n\n// 背景透明样式 - 根据是否强制覆盖使用不同优先级\n%bg-none {\n    background: none;\n}\n\n// 强制覆盖背景样式（用于夜间模式）\n// 当 html 有 mspring_force_night_mode_background 时使用 !important\n// 否则使用普通样式\n@mixin bg-none-conditional {\n    background: none;\n    \n    html.mspring_force_night_mode_background & {\n        background: none !important;\n    }\n}\n\n#app {\n\n    // 主页\n    .global-container {\n        .container-content {\n\n            // 消息列表和聊天界面\n            .message-panel,\n            // 左侧消息列表\n            .recent-contact {\n                @include bg-none-conditional;\n            }\n\n            // 侧栏\n            .sidebar {\n                .sidebar-nav {\n                    @include bg-none-conditional;\n                }\n            }\n\n            // 联系人界面\n            .contact-layout {\n\n                // 联系人列表和联系人详情\n                &,\n                // 联系人列表\n                .contact,\n                // 联系人详情\n                .contact-profile {\n                    @include bg-none-conditional;\n                }\n\n                // 好友通知/群通知界面\n                .sys-notify {\n\n                    // 界面\n                    &,\n                    // 列表\n                    .sys-notify-list .viewport-list__inner {\n                        @extend %bg-none;\n                    }\n                }\n\n                // 联系人列表\n                .contact {\n                    @extend %bg-none;\n\n                    .tab {\n\n                        // 切换 tab\n                        .tab-header {\n                            @extend %bg-none;\n                        }\n                    }\n                }\n            }\n        }\n\n        /* QQ主题背景 */\n        .q-miracle-background {\n            @include bg-none-conditional;\n        }\n    }\n\n    // 独立聊天界面\n    .chat-container {\n        .container-content {\n\n            // 消息列表和聊天界面\n            &,\n            // 左侧消息列表\n            .recent-contact {\n                @include bg-none-conditional;\n            }\n        }\n\n        /* QQ主题背景 */\n        .q-miracle-background {\n            @include bg-none-conditional;\n        }\n    }\n\n    // 文件管理页面\n    .container:has(.file-manager-main) {\n\n        // 侧栏\n        .nav-bar-container {\n            @extend %bg-none;\n        }\n\n        .file-manager-main {\n            @extend %bg-none;\n        }\n    }\n\n    // 收藏界面\n    .favorites-layout {\n\n        // 顶栏\n        .panel-header {\n            @extend %bg-none;\n        }\n    }\n\n    // 申请加群/加好友界面\n    .discover_container {\n        .discover-contact-info {\n            @include bg-none-conditional;\n        }\n\n        .form-item__action {\n            @extend %bg-none;\n        }\n    }\n\n    // 独立好友信息界面（窗口暂时背景没有透明，故先不启用）\n    .standalone-mini-profile-container {\n        @extend %bg-none;\n\n        #mini-buddy-profile {\n            @extend %bg-none;\n        }\n    }\n\n    // 同上\n    .mini-buddy {\n        @extend %bg-none;\n    }\n\n\n    // 好友管理器\n    .contact-management {\n        .viewport-list__inner {\n            @extend %bg-none;\n        }\n    }\n}\n\n#app {\n\n    // 输入框、下拉菜单按钮\n    .q-input,\n    .q-textarea,\n    .q-pulldown-menu-button {\n        border-radius: 8px;\n        background: var(--msp-container);\n\n        /* 搜索框等点击之后粉线的圆角 */\n        .q-input__inner:focus,\n        .q-textarea__inner:focus {\n            border-radius: 8px !important;\n        }\n    }\n\n    // 发送按钮\n    .send-btn-wrap,\n    // .top-bar__adder,\n    // .search-input,\n    // .record-search,\n    // .search,\n    // .guilds-item-btn .q-button,\n    // 好友界面切换tab\n    .radio-tab {\n        border-radius: 8px !important;\n    }\n\n    .q-button {\n        border-radius: 8px;\n    }\n}"
  },
  {
    "path": "src/scss/_channels.scss",
    "content": "/* 频道（服务器）界面的相关样式 */\n@use \"variables\" as *;\n\n// /* 频道 成员列表 */\n// .guild-main .channel-main .channel .chatDragDropArea .userList {\n//     background: none;\n// }\n\n// /* \n//     频道 别人消息背景\n//     频道 帖子列表项目背景\n//          */\n// .guild-main .message:not(.message-gray-tip, .message-self) .message-content,\n// .guild-main .topic-list-item {\n//     background: var(--msp-container);\n// }\n\n// .guild-main .topic-list-item.is-active {\n//     background: var(--msp-container-active);\n// }\n\n// .guilds-item {\n//     border-radius: 16px !important;\n//     height: initial !important;\n//     min-width: auto !important;\n// }\n\n// /* \n//     管理员标签（群成员列表）\n//     群公告置顶标签\n//  */\n// .group-user .q-tag.group-user__role:not(.primary),\n// .notice__container .top-flag {\n//     color: var(--theme-color);\n//     background: var(--theme-tag-color);\n// }\n\n// @media (prefers-color-scheme: light) {\n//     /* 频道三个侧栏 */\n//     #app .guild-main .main-area .main-area-left,\n//     #channelList .channel-container,\n//     #channelList .session-container {\n//         background: var(--background-color-light);\n//     }\n// }\n\n// @media (prefers-color-scheme: dark) {\n//     /* 频道三个侧栏 */\n//     #app .guild-main .main-area .main-area-left,\n//     #channelList .channel-container,\n//     #channelList .session-container {\n//         background: var(--background-color-dark);\n//     }\n// }\n"
  },
  {
    "path": "src/scss/_chat.scss",
    "content": "/* 聊天界面、消息气泡、输入框等样式 */\n@use \"variables\" as *;\n\n#app {\n\n    // 聊天界面\n    .container-content {\n\n        // 聊天框\n        .chat-input-area {\n            border-radius: 16px 16px 0px 0px;\n        }\n\n        .aio {\n\n            // 回顶回底按钮背景模糊\n            // .chat-msg-area__tip--top>*, // 回顶因为有父布局无法生效\n            .chat-msg-area__tip--bottom {\n                backdrop-filter: $blur-backdrop-filter-16;\n                mix-blend-mode: multiply;\n            }\n\n            // 更多面板\n            .more-panel .side-panel {\n                backdrop-filter: $blur-backdrop-filter-32;\n                mix-blend-mode: multiply;\n            }\n\n            /* 编辑框选中文字背景色 */\n            .qq-msg-editor {\n                ::selection {\n                    background: rgba(from var(--theme-color) r g b / 30%);\n                }\n            }\n        }\n    }\n\n    // 聊天消息列表\n    // 聊天界面和合并转发消息都要用到，所以放出来\n    #ml-root {\n        .message {\n            .message-container {\n                .message-content__wrapper {\n\n                    // 消息气泡\n                    .msg-content-container {\n                        .message-content {\n\n                            // AT\n                            .text-element--at {\n                                font-weight: bold;\n                            }\n                        }\n\n                        // 其他人的消息\n                        &.container--others {\n                            &:focus {\n                                background: var(--msp-container-active);\n                            }\n\n                            .message-content {\n                                ::selection {\n                                    background: rgba(from var(--theme-color) r g b / 30%);\n                                }\n                            }\n                        }\n\n                        // 自己的消息\n                        &.container--self {\n                            background: var(--theme-color);\n                            \n                            .mspring_force_host_bubble_color & {\n                                background: var(--theme-color) !important;\n                            }\n\n                            // background: var(--theme-color) !important;\n                            // color: var(--on_bubble_host_text) !important;\n                            // backdrop-filter: none !important;\n                            .message-content {\n\n                                // 链接\n                                .text-link {\n                                    color: var(--on-theme-text-color);\n                                }\n\n                                ::selection {\n                                    background: rgba(from var(--on-theme-text-color) r g b / 30%);\n                                }\n                            }\n                        }\n\n                        // 卡片链接\n                        &.ark-msg-content-container {\n                            .rich-ui-app-wrapper [data-view-id=\"app\"] {\n                                background: var(--msp-container) !important;\n                            }\n                        }\n                    }\n\n                    // 合并转发的聊天记录\n                    .forward-msg,\n                    // 文件\n                    .normal-file {\n                        background-color: var(--msp-container);\n\n                        &:hover {\n                            background-color: var(--msp-container-hover);\n                        }\n\n                        &:active {\n                            background-color: var(--msp-container-active);\n                        }\n                    }\n                }\n\n                // 表情回应\n                .message-tips {\n                    .reaction-item-bg {\n                        background-color: var(--msp-container);\n                        border-radius: 8px;\n                    }\n\n                    .reaction-item-bg--clicked {\n                        background-color: var(--host_bubble_bg_css_value);\n                        opacity: 0.8;\n                    }\n\n                    .more-reaction-item {\n                        border-radius: 8px;\n                        background: var(--msp-container);\n\n                        &:hover {\n                            background: var(--msp-container-hover);\n                        }\n\n                        &:active {\n                            background: var(--msp-container-active);\n                        }\n                    }\n                }\n            }\n\n            // 聊天界面 提示（时间等） */\n            .babble {\n                background: var(--msp-container);\n            }\n        }\n    }\n\n    // 历史记录页面\n    .record #ml-root {\n        .message {\n            .message-container {\n                .message-content__wrapper {\n                    .msg-content-container {\n                        &.container--self {\n                            background: initial;\n\n                            ::selection {\n                                background: rgba(from var(--theme-color) r g b / 30%);\n                            }\n                        }\n                    }\n                }\n            }\n        }\n    }\n\n    .standalone-mini-profile-container {\n        #mini-buddy-profile {\n\n            // 去除 vip 名字特殊效果\n            .buddy-profile__header-name {\n                color: unset !important;\n            }\n        }\n    }\n}\n\n/* 聊天框 */\n// html:not(.mspring_background_plugin_enabled) .chat-input-area {\n//     border-radius: 16px 16px 0px 0px;\n// }\n\n// /* 强制覆盖自己的气泡颜色 */\n// html.mspring_force_host_bubble_color #app .chat-msg-area .ml-list .message .msg-content-container.container--self {\n//     background: var(--theme-color) !important;\n//     color: var(--on_bubble_host_text) !important;\n//     backdrop-filter: none !important;\n// }\n\n// html.mspring_background_plugin_enabled:not(.mspring_force_host_bubble_color) #app .chat-msg-area .ml-list .message .reply-element.reply-element--self {\n//     color: var(--text_primary) !important;\n// }\n\n// html:is(.linux) .more-panel .side-panel {\n//     backdrop-filter: none !important;\n//     mix-blend-mode: initial !important;\n// }\n\n// /* 防撤回提示 */\n// html:not(.mspring_background_plugin_enabled, .mspring_lite_tool_background_enabled) .message-content-recalled {\n//     background: var(--msp-container) !important;\n//     backdrop-filter: initial !important;\n// }\n\n// html:is(.linux) #app .q-notification.theme-default {\n//     backdrop-filter: none !important;\n//     mix-blend-mode: initial !important;\n// }\n\n// @media (prefers-color-scheme: light) {\n//     #ml-root .container--others .ptt-element__button .q-icon {\n//         color: #ffffff;\n//     }\n// }\n\n// @media (prefers-color-scheme: dark) {\n//     #ml-root .container--others .ptt-element__button .q-icon {\n//         color: #171717;\n//     }\n// }"
  },
  {
    "path": "src/scss/_contact-management.scss",
    "content": "/* 好友管理器页面的相关样式 */\n@use \"variables\" as *;\n\nbody:has(.contact-management) {\n    #app {\n\n        // 好友管理器\n        .contact-management {\n\n            .contact-table {\n                background: var(--msp-container);\n                margin-bottom: 20px;\n            }\n        }\n\n    }\n\n    .q-dialog {\n\n        // 权限设置对话框\n        .permission-setting .form-item-category .option-list {\n            background: var(--msp-container);\n        }\n    }\n}"
  },
  {
    "path": "src/scss/_file-manager.scss",
    "content": "/* 文件管理界面的相关样式 */\n@use \"variables\" as *;\n\n#app {\n    .container:has(.file-manager-main) {\n\n        // 右侧主要内容\n        .file-manager-main {\n            border: 0;\n\n            // 左侧联系人/群列表\n            .main-left {\n                .user-list-container {\n                    padding-top: unset;\n\n                    // 折叠列表标题（无折叠列表时直接显示好友/群列表）\n                    .q-collapse-item__header {\n                        margin-bottom: 8px;\n\n                        .user-list {\n                            border-radius: 8px;\n                        }\n                    }\n\n                    // 折叠列表内容\n                    .q-collapse-item__content {\n                        .user-list-margin.user-list {\n                            margin-bottom: 8px;\n                            border-radius: 8px;\n                        }\n                    }\n                }\n            }\n\n            // 右侧文件列表\n            .file-area {\n                .file-area-shortcut {\n                    margin-top: unset;\n\n                    .shortcut-item {\n                        // border-radius: 8px;\n                    }\n                }\n\n                .file-area-container {\n                    padding-bottom: 20px;\n\n                    .file-list-normal-scroll-border {\n                        border-top-left-radius: 0;\n                        border-top-right-radius: 0;\n                    }\n\n                    // 文件列表 折叠标题\n                    .file-list-normal-sort-title-height {\n                        border-radius: 0;\n                        background: rgb(from var(--bg_white) r g b / 0.8);\n                    }\n\n                    // 群文件 footer\n                    .file-area-container-group-file-footer {\n                        border-radius: 0;\n                        background: rgb(from color-mix(in srgb, var(--msp-container), var(--bg_white)) r g b / 1);\n                        backdrop-filter: $blur-backdrop-filter-16;\n                        mix-blend-mode: multiply;\n                    }\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/scss/_frame.scss",
    "content": "/* 主应用框架、顶栏、侧边栏等样式 */\n@use \"variables\" as *;\n\n#app {\n\n    // 左侧栏\n    .sidebar-nav {\n        .sidebar__upper {\n            padding-top: 4px;\n\n            // 动画开始\n            .tab-item:hover .tab-item-mask {\n                opacity: 0.05;\n            }\n\n            // 悬浮\n            @keyframes maskZoomIn {\n                100% {\n                    opacity: 0.05;\n                }\n            }\n\n            // 激活\n            .tab-item-mask.is-active {\n                opacity: 0.1;\n            }\n\n            // 点击\n            @keyframes maskZoomPress {\n                100% {\n                    opacity: 0.05;\n                }\n            }\n        }\n    }\n\n    /* 主页 下半部分 */\n    .container-content {\n        /* 去除边距 */\n        margin: 0;\n\n        /* 聊天界面 顶栏 */\n        .panel-header {\n            padding-top: 0;\n            padding-bottom: 8px;\n            height: unset;\n\n            // 去除 vip 名字特殊效果\n            .chat-header__contact-name {\n                color: unset !important;\n            }\n        }\n    }\n\n    /* 左侧消息列表 顶部搜索 */\n    .two-col-layout__aside .contact-top-bar {\n        padding-top: 4px;\n\n        // 搜索结果\n        .search-content {\n            left: 8px;\n            backdrop-filter: $blur-backdrop-filter-32;\n            mix-blend-mode: multiply;\n        }\n    }\n\n    /* 主页顶栏天气 */\n    .topbar .user-profile-card__widgets {\n        display: none;\n    }\n}"
  },
  {
    "path": "src/scss/_lists.scss",
    "content": "/* 消息列表、联系人列表等通用列表样式 */\n@use \"variables\" as *;\n\n#app {\n    .container-content {\n        .two-col-layout__aside {\n\n            // 主页、独立聊天界面 列表条目\n            .viewport-list .viewport-list__inner {\n                display: flex;\n                flex-direction: column;\n                gap: 8px;\n                padding: 8px;\n                border-radius: 12px;\n\n                .recent-contact-item .item__content,\n                .list-item.contact-item {\n                    position: relative;\n                    border-radius: 12px;\n\n                    &::before {\n                        position: absolute;\n                        inset: 0;\n                        border-radius: inherit;\n                    }\n\n                    // 去除 vip 名字特殊效果\n                    .main-info .text-ellipsis {\n                        color: unset !important;\n                    }\n                }\n\n                // 选中聊天\n                .recent-contact-item--selected .item__content {\n                    &::before {\n                        background: var(--theme-color) !important;\n                    }\n\n                    .item__title {\n                        .main-info {\n                            color: var(--on-theme-text-color);\n                        }\n\n                        .secondary-info {\n                            color: rgba(from var(--on-theme-text-color) r g b / 40%);\n                        }\n                    }\n\n                    .item__summary {\n\n                        .summary-main,\n                        .summary-bubble .q-icon {\n                            color: rgba(from var(--on-theme-text-color) r g b / 50%);\n                        }\n                    }\n                }\n\n                .recent-contact-item:not(.recent-contact-item--selected) {\n\n                    // 置顶状态\n                    &.recent-contact-item--top .item__content {\n                        background: none;\n\n                        &::before {\n                            background: var(--msp-container);\n                        }\n                    }\n\n                    // hover 状态\n                    &:hover .item__content::before,\n                    &.recent-contact-item--top:hover .item__content::before {\n                        background: var(--msp-container-hover) !important;\n                    }\n                }\n\n                .recent-contact-item.recent-contact-item--menu {\n                    border-radius: inherit;\n\n                    .item__content::after {\n                        inset: 0;\n                        border-radius: inherit;\n                    }\n                }\n            }\n\n            // 联系人分组 折叠标题\n            .q-collapse-item__header {\n                background: rgb(from var(--bg_white) r g b / 0.8)\n            }\n        }\n\n        .two-col-layout__main {\n\n            // 好友通知、群通知列表项\n            .sys-notify__container .sys-notify-card {\n                background: var(--msp-container);\n            }\n\n            // 去除 vip 名字特殊效果\n            .buddy-profile__info-name {\n                color: unset !important;\n            }\n\n        }\n    }\n\n    // 任务栏消息通知\n    .container .msg {\n        .list-item {\n            .list-item__content {\n                border-radius: 8px;\n            }\n        }\n\n        // 底部按钮\n        .text-button {\n            color: var(--theme-color);\n\n            &:hover {\n                color: var(--theme-color-hover);\n            }\n\n            &:active {\n                color: var(--theme-color-pressed);\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/scss/_login.scss",
    "content": "/* 登录界面的相关样式 */\n@use \"variables\" as *;\n\n/* 登录页面背景 */\n#login {\n    // background: none !important;\n    background-color: var(--bg_white) !important;\n\n    #polar {\n        display: none;\n    }\n\n    #app {\n        .login-panel {\n            .account-list {\n                backdrop-filter: $blur-backdrop-filter-16;\n                mix-blend-mode: multiply;\n                background: var(--bg_white) !important;\n            }\n\n            .password {\n\n                .q-input,\n                .password {\n                    border-radius: 8px;\n                    background: var(--msp-container);\n\n                    .q-input__inner,\n                    .input {\n                        background: none;\n                    }\n                }\n            }\n\n            .auto-login {\n                .avatar {\n                    box-shadow: 0 2px 28px 0 rgb(from var(--theme-color) r g b / 40%);\n                }\n\n            }\n        }\n\n    }\n}"
  },
  {
    "path": "src/scss/_modals.scss",
    "content": "/* 菜单、弹窗、卡片等浮动元素的样式 */\n@use \"variables\" as *;\n\n#app {\n\n    /* 申请加群/加好友 */\n    #discover .discover-application {\n\n        .q-select,\n        .option-list {\n            background: var(--msp-container);\n            border-radius: 8px;\n        }\n    }\n\n    .aio {\n        .menu-stickers-panel {\n            border-radius: 8px;\n            backdrop-filter: $blur-backdrop-filter-16;\n            mix-blend-mode: multiply;\n        }\n    }\n}\n\n// 菜单\n.q-context-menu:not(.is-pure),\n.q-context-sub-menu__container:not(.is-pure),\n.q-popover {\n    backdrop-filter: $blur-backdrop-filter-16;\n    mix-blend-mode: multiply;\n    background: var(--bg_white) !important;\n\n    &::before {\n        backdrop-filter: none;\n        mix-blend-mode: none;\n    }\n}\n\n// 顶部表情回应区域\n.q-context-menu {\n    .menu-stickers-wrapper {\n        border-radius: 8px;\n\n        .menu-stickers {\n            border-radius: 8px !important;\n        }\n    }\n}"
  },
  {
    "path": "src/scss/_plugins.scss",
    "content": "/* 第三方插件的兼容性样式 */\n@use \"variables\" as *;\n\n/* 轻量工具箱 +1和外置时间 */\n// html:not(.mspring_lite_tool_background_enabled) .message-content-replace::after,\n// /* html:not(.mspring_lite_tool_background_enabled) .lite-tools-time.bubble-outside::after, */\n// html:not(.mspring_lite_tool_background_enabled) .lite-tools-slot.outside-slot::after {\n//     background: var(--msp-container);\n//     backdrop-filter: initial;\n// }\n\n// @media (prefers-color-scheme: dark) {\n//     /* DeepL插件 他人的消息框分割线颜色 */\n//     .container--others #deepl-divider {\n//         background: var(--msp-container-active) !important;\n//     }\n// }\n\n// /* DeepL插件 自己的消息框分割线颜色 */\n// .msg-content-container.container--self #deepl-divider {\n//     background: #ffffff3f !important;\n// }\n\n// /* 开启背景插件后的搜索框多的双层方形背景 */\n// html.mspring_background_plugin_enabled .main-search {\n//     background: none !important;\n// }\n"
  },
  {
    "path": "src/scss/_settings.scss",
    "content": "/* 设置界面以及插件设置的相关样式 */\n@use \"variables\" as *;\n\n// /* 设置界面链接文字颜色 */\n// :is(.liteloader, .qwqnt.q-scroll-view) {\n//     a {\n//         color: var(--theme-color) !important;\n\n//         &:hover {\n//             color: var(--theme-color-dark2) !important;\n//         }\n//     }\n// }\n\n/* 设置页面 input 样式 */\n:is(.liteloader, .qwqnt.q-scroll-view) {\n\n    // 颜色选择器\n    input[type=\"color\"] {\n        padding: 4px;\n    }\n\n    ::-webkit-color-swatch-wrapper {\n        padding: 0px;\n    }\n\n    ::-webkit-color-swatch {\n        border-radius: 4px;\n        border: transparent solid 1px;\n    }\n\n    input:is([type=\"color\"], [type=\"range\"]).q-button:focus {\n        border: 1px solid #424242 !important;\n    }\n\n    // 滑块（Range Slider）\n    input[type=\"range\"].q-button {\n        appearance: none;\n        -webkit-appearance: none;\n        background: transparent;\n        cursor: pointer;\n\n        // 滑轨\n        &::-webkit-slider-runnable-track {\n            background: none;\n            border-radius: 4px;\n            height: 6px;\n        }\n\n        // 圆点\n        &::-webkit-slider-thumb {\n            appearance: none;\n            -webkit-appearance: none;\n            background: var(--theme-color);\n            border-radius: 50%;\n            height: 16px;\n            width: 16px;\n            margin-top: -5px; // 居中对齐\n            cursor: pointer;\n\n            &:hover {\n                background: var(--theme-color-hover);\n            }\n\n            &:active {\n                background: var(--theme-color-pressed);\n            }\n        }\n    }\n\n    // 文本输入框\n    setting-panel input[type=\"text\"] {\n        border-radius: 8px !important;\n    }\n\n    input[type=\"text\"] {\n        border-radius: 8px;\n        padding-left: 8px;\n\n        // 浅色模式\n        @media (prefers-color-scheme: light) {\n            background: var(--msp-container);\n\n            &:focus {\n                background: var(--msp-container-active);\n                padding-left: 10px;\n            }\n        }\n\n        // 深色模式\n        @media (prefers-color-scheme: dark) {\n            background: #ffffff10;\n\n            &:focus {\n                background: var(--msp-container);\n                padding-left: 10px;\n            }\n        }\n    }\n}"
  },
  {
    "path": "src/scss/_variables.scss",
    "content": "/* 主题所使用的各类 CSS 变量 */\n\n/* 变量 */\n// :root {\n//     --el-color-primary: var(--theme-color);\n// }\n\n.q-theme-tokens-light {\n    /* mspring */\n    --theme-color-hover: color-mix(in srgb, var(--theme-color), black 10%);\n    --theme-color-active: color-mix(in srgb, var(--theme-color), black 20%);\n    --theme-color-pressed: color-mix(in srgb, var(--theme-color), black 30%);\n\n    --msp-container: rgba(0, 0, 0, 0.05);\n    --msp-container-hover: rgba(0, 0, 0, 0.1);\n    --msp-container-active: rgba(0, 0, 0, 0.2);\n    --msp-container-pressed: rgba(0, 0, 0, 0.3);\n\n    --msp-text-1: rgba(0, 0, 0, 0.87);\n    --msp-text-2: rgba(0, 0, 0, 0.6);\n    --msp-text-3: rgba(0, 0, 0, 0.38);\n    --msp-text-4: rgba(0, 0, 0, 0.12);\n\n    --msp-white-variable: #ffffff;\n\n    /* color-tokens */\n    // 主题色\n    --brand_standard: var(--theme-color);\n    // --on_brand_primary: var(--on-theme-text-color);\n    // --on_brand_secondary: var(--on-theme-text-color);\n    --text_primary: var(--msp-text-1);\n    --text_primary_light: var(--msp-text-2);\n    --on_bg_text: var(--msp-text-3);\n    --text_link: var(--theme-color);\n    // --bg_list: TRANSPARENT;\n    --bg_nav: var(--background-color-light);\n    --bg_bottom_standard: var(--background-color-light);\n    // /* --bg_bottom_light: var(--background-color-light); */\n    --bg_nav_secondary: var(--background-color-light);\n    // 自己的消息气泡颜色\n    --bubble_host: var(--theme-color);\n    // 其他人的消息气泡颜色\n    --bubble_guest: var(--msp-container);\n    // 自己的消息气泡文本颜色\n    --on_bubble_host_text: var(--on-theme-text-color);\n    // 其他人的消息气泡文本颜色\n    --bubble_guest_text: var(--msp-text-1);\n\n    --fill_light_primary: var(--msp-container);\n\n    --overlay_hover: var(--msp-container-hover);\n    --overlay_active_brand: var(--theme-color);\n    --overlay_active: var(--msp-container-active);\n    --overlay_pressed: var(--msp-container-pressed);\n    --svip_red: none;\n    // 管理员标签\n    --tag_blue_text: var(--theme-color);\n    --tag_blue_bg: rgb(from var(--theme-color) r g b / 20%);\n    // --brand_text: var(--theme-color);\n    // 表情回应背景\n    --host_bubble_bg_css_value: var(--theme-color);\n\n    /* ancient-tokens */\n    --text-primary: var(--msp-text-1);\n    --text-primary-light: var(--msp-text-2);\n    --text-secondary-01: var(--msp-text-3);\n    --text-secondary-02: var(--msp-text-4);\n    // --text-brand: var(--theme-color);\n    --text-link: var(--theme-color);\n\n    /* mix-tokens */\n    // 主题色 hover\n    --nt_brand_standard_2_overlay_hover_brand_2_mix: var(--theme-color-hover);\n    // 主题色按下\n    --nt_brand_standard_2_overlay_pressed_brand_2_mix: var(--theme-color-pressed);\n    --nt_brand_standard_2_10_2_alpha: rgba(from var(--theme-color) r g b / 10%);\n    // --nt_brand_standard_2_20_2_alpha: var(--theme-color-alpha);\n    --nt_bg_nav_secondary_2_60_2_alpha: var(--background-color-light);\n    --nt_bg_nav_2_60_2_alpha: var(--background-color-light);\n}\n\n.q-theme-tokens-dark {\n    /* mspring */\n    --theme-color-hover: color-mix(in srgb, var(--theme-color), black 10%);\n    --theme-color-active: color-mix(in srgb, var(--theme-color), black 20%);\n    --theme-color-pressed: color-mix(in srgb, var(--theme-color), black 30%);\n\n    --msp-container: rgba(255, 255, 255, 0.05);\n    --msp-container-hover: rgba(255, 255, 255, 0.1);\n    --msp-container-active: rgba(255, 255, 255, 0.2);\n    --msp-container-pressed: rgba(255, 255, 255, 0.3);\n\n    --msp-text-1: rgba(255, 255, 255, 0.87);\n    --msp-text-2: rgba(255, 255, 255, 0.6);\n    --msp-text-3: rgba(255, 255, 255, 0.38);\n    --msp-text-4: rgba(255, 255, 255, 0.12);\n\n    --msp-white-variable: #000000;\n\n    /* color-tokens */\n    // 主题色\n    --brand_standard: var(--theme-color);\n    // --on_brand_primary: var(--on-theme-text-color);\n    // --on_brand_secondary: var(--on-theme-text-color);\n    --text_primary: var(--msp-text-1);\n    --text_primary_light: var(--msp-text-2);\n    --on_bg_text: var(--msp-text-3);\n    --text_link: var(--theme-color);\n    // --bg_list: TRANSPARENT;\n    --bg_nav: var(--background-color-dark);\n    --bg_bottom_standard: var(--background-color-dark);\n    // /* --bg_bottom_light: var(--background-color-dark); */\n    --bg_nav_secondary: var(--background-color-dark);\n    // 自己的消息气泡颜色\n    --bubble_host: var(--theme-color);\n    // 其他人的消息气泡颜色\n    --bubble_guest: var(--msp-container);\n    // 自己的消息气泡文本颜色\n    --on_bubble_host_text: var(--on-theme-text-color);\n    // 其他人的消息气泡文本颜色\n    --bubble_guest_text: var(--msp-text-1);\n\n    --fill_light_primary: var(--msp-container);\n\n    --overlay_hover: var(--msp-container-hover);\n    --overlay_active_brand: var(--theme-color);\n    --overlay_active: var(--msp-container-active);\n    --overlay_pressed: var(--msp-container-pressed);\n    --svip_red: none;\n    // 管理员标签\n    --tag_blue_text: var(--theme-color);\n    --tag_blue_bg: rgb(from var(--theme-color) r g b / 20%);\n    // --brand_text: var(--theme-color);\n    // 表情回应背景\n    --host_bubble_bg_css_value: var(--theme-color);\n\n    /* ancient-tokens */\n    --text-primary: var(--msp-text-1);\n    --text-primary-light: var(--msp-text-2);\n    --text-secondary-01: var(--msp-text-3);\n    --text-secondary-02: var(--msp-text-4);\n    // --text-brand: var(--theme-color);\n    --text-link: var(--theme-color);\n\n    /* mix-tokens */\n    // 主题色 hover\n    --nt_brand_standard_2_overlay_hover_brand_2_mix: var(--theme-color-hover);\n    // 主题色按下\n    --nt_brand_standard_2_overlay_pressed_brand_2_mix: var(--theme-color-pressed);\n    // --nt_brand_standard_2_20_2_alpha: var(--theme-color-alpha);\n    --nt_brand_standard_2_10_2_alpha: rgba(from var(--theme-color) r g b / 10%);\n    --nt_bg_nav_secondary_2_60_2_alpha: var(--background-color-dark);\n    --nt_bg_nav_2_60_2_alpha: var(--background-color-dark);\n}\n\n$blur-backdrop-filter-16: blur(16px) saturate(150%) opacity(40%);\n$blur-backdrop-filter-32: blur(32px) saturate(150%) opacity(40%);"
  },
  {
    "path": "src/settings.html",
    "content": "<style>\n    /* 背景颜色透明度滑条 */\n    .mspring_theme input[type='range']::-webkit-slider-thumb {\n        margin-top: -8px;\n        -webkit-appearance: none;\n        height: 16px;\n        width: 16px;\n        border-radius: 8px;\n        background: var(--theme-color);\n        cursor: pointer;\n    }\n\n    .mspring_theme input[type='range']::-webkit-slider-runnable-track {\n        height: 0px;\n        background: transparent;\n    }\n\n    .pick-opacity {\n        padding: 4px;\n    }\n</style>\n\n<setting-section data-title=\"提示\" class=\"tips\">\n    <setting-panel>\n        <setting-list data-direction=\"column\">\n            <setting-item data-direction=\"row\">\n                <setting-text>若使用新版 QQ 请在 超级调色盘 中使用 <strong>极简白</strong></setting-text>\n            </setting-item>\n        </setting-list>\n    </setting-panel>\n</setting-section>\n\n<setting-section data-title=\"外观\" class=\"appearance\">\n    <setting-panel>\n        <setting-list data-direction=\"column\">\n            <setting-item data-direction=\"row\">\n                <setting-text>主题颜色</setting-text>\n                <input type=\"color\" value=\"#ff0000\" class=\"q-button q-button--small q-button--secondary pick-color\" />\n            </setting-item>\n            <setting-item data-direction=\"row\" id=\"mst-settings-background-opacity\">\n                <div>\n                    <setting-text>背景颜色透明度</setting-text>\n                    <setting-text data-type=\"secondary\" style=\"-webkit-line-clamp: initial; line-clamp: initial;\">该选项在启用\n                        <b>轻量工具箱-自定义背景</b>\n                        之后不会生效</setting-text>\n                </div>\n                <input type=\"range\" value=\"1\" min=\"0\" max=\"100\" step=\"1\"\n                    class=\"q-button q-button--small q-button--secondary pick-opacity\"\n                    style=\"width: 61%; height:25px;\" />\n            </setting-item>\n            <setting-item data-direction=\"row\">\n                <div>\n                    <setting-text>强制覆盖自己发送的气泡颜色</setting-text>\n                    <setting-text data-type=\"secondary\"\n                        style=\"-webkit-line-clamp: initial; line-clamp: initial; margin-right: 8px;\">默认情况下不需要开启。如果想要在开启其他修改背景的插件时，让自己的气泡背景显示为主题色，就需要开启该功能</setting-text>\n                </div>\n                <setting-switch id=\"force-host-bubble-color\" style=\"min-width: 28px;\"></setting-switch>\n            </setting-item>\n            <setting-item data-direction=\"row\">\n                <div>\n                    <setting-text>强制覆盖夜间模式主页背景</setting-text>\n                    <setting-text data-type=\"secondary\"\n                        style=\"-webkit-line-clamp: initial; line-clamp: initial; margin-right: 8px;\">默认开启。由于新版 QQ 夜间模式下会使用 !important 覆盖部分属性，所以主题只能强行覆盖。如果影响到其他插件的效果，请关闭该功能</setting-text>\n                </div>\n                <setting-switch id=\"force-night-mode-background\" style=\"min-width: 28px;\"></setting-switch>\n            </setting-item>\n        </setting-list>\n    </setting-panel>\n</setting-section>\n\n<setting-section data-title=\"增强\" class=\"enhancement\">\n    <setting-panel>\n        <setting-list data-direction=\"column\">\n            <setting-item data-direction=\"row\">\n                <div>\n                    <setting-text>优化消息排版</setting-text>\n                    <setting-text data-type=\"secondary\" style=\"-webkit-line-clamp: initial; line-clamp: initial;\">使用\n                        赫蹏，提供中英文混排美化、标点挤压 (修改之后重启生效)</setting-text>\n                </div>\n                <setting-switch id=\"heti\"></setting-switch>\n            </setting-item>\n        </setting-list>\n    </setting-panel>\n</setting-section>\n\n<setting-section data-title=\"关于\" class=\"about\">\n    <setting-panel>\n        <setting-list data-direction=\"column\">\n            <setting-item data-direction=\"row\">\n                <div>\n                    <setting-text>版本号</setting-text>\n                    <setting-text data-type=\"secondary\" id=\"mst-settings-version\"\n                        style=\"-webkit-line-clamp: initial; line-clamp: initial\">没问题的话这里显示的是版本号</setting-text>\n                </div>\n                <setting-button data-type=\"primary\" id=\"mst-settings-go-to-update\">去更新</setting-button>\n            </setting-item>\n            <setting-item data-direction=\"row\">\n                <div>\n                    <setting-text>Telegram 频道</setting-text>\n                    <setting-text data-type=\"secondary\">https://t.me/MUKAPP_Personal</setting-text>\n                </div>\n                <setting-button data-type=\"secondary\" id=\"msp-tg-channel\">进去瞅瞅</setting-button>\n            </setting-item>\n        </setting-list>\n    </setting-panel>\n</setting-section>\n\n<setting-section data-title=\"其他\" class=\"others\">\n    <setting-panel>\n        <setting-list data-direction=\"column\">\n            <setting-item data-direction=\"row\">\n                <div>\n                    <setting-text>输出日志到主进程</setting-text>\n                    <setting-text data-type=\"secondary\" style=\"-webkit-line-clamp: initial; line-clamp: initial;\">\n                        非调试不建议开启\n                    </setting-text>\n                </div>\n                <setting-switch id=\"msp-log-to-main\"></setting-switch>\n            </setting-item>\n        </setting-list>\n    </setting-panel>\n</setting-section>"
  },
  {
    "path": "src/style.scss",
    "content": "@charset \"UTF-8\";\n\n@use \"./scss/variables\";\n@use \"./scss/base\";\n@use \"./scss/frame\";\n@use \"./scss/lists\";\n@use \"./scss/chat\";\n@use \"./scss/channels\";\n@use \"./scss/settings\";\n@use \"./scss/login\";\n@use \"./scss/modals\";\n@use \"./scss/file-manager\";\n@use \"./scss/contact-management\";\n@use \"./scss/plugins\";\n"
  },
  {
    "path": "vendor/heti/heti-m.scss",
    "content": "/*!\n * Project: Heti\n * URL: https://github.com/sivan/heti\n * Author: Sivan [sun.sivan@gmail.com]\n * MUKAPP 修改：聊天场景使用的精简样式入口\n */\n\n@import \"lib/variables\";\n@import \"lib/helpers/add-on\";\n\n#{$root-selector} {\n    overflow-wrap: break-word;\n    word-wrap: break-word;\n    hyphens: auto;\n    letter-spacing: $letter-spacing-medium;\n\n    p {\n        text-align: justify;\n\n        @include non-cjk-block {\n            text-align: start;\n        }\n    }\n\n    pre {\n        overflow: auto;\n        white-space: pre;\n        word-wrap: normal;\n    }\n\n    @include non-cjk-block {\n        letter-spacing: $letter-spacing-normal;\n    }\n\n    a,\n    abbr,\n    code,\n    heti-spacing,\n    [lang=\"en-US\"] {\n        letter-spacing: normal;\n    }\n\n    table {\n        word-break: break-word;\n    }\n\n    q {\n        quotes: map-get(map-get($chinese-quote-presets, $chinese-quote-set), \"horizontal\");\n\n        @include non-cjk-block {\n            quotes: initial;\n            quotes: auto;\n        }\n    }\n\n    @include hetiAddOns();\n}\n"
  },
  {
    "path": "vendor/heti/js/heti-addon.js",
    "content": "/**\n * Heti add-on v0.1.0\n * Add right spacing between CJK & ANS characters\n *\n * 源码基于：https://github.com/sivan/heti/blob/master/js/heti-addon.js\n * 本地补丁：将 heti-adjacent 加入跳过列表，避免在聊天场景重复处理时出现多层嵌套包裹。\n */\nimport Finder from 'heti-findandreplacedomtext';\n\nconst hasOwn = {}.hasOwnProperty;\n\nconst HETI_NON_CONTIGUOUS_ELEMENTS = Object.assign({}, Finder.NON_CONTIGUOUS_PROSE_ELEMENTS, {\n    ins: 1,\n    del: 1,\n    s: 1,\n    a: 1,\n});\n\nconst HETI_SKIPPED_ELEMENTS = Object.assign({}, Finder.NON_PROSE_ELEMENTS, {\n    pre: 1,\n    code: 1,\n    sup: 1,\n    sub: 1,\n    'heti-spacing': 1,\n    'heti-close': 1,\n    'heti-adjacent': 1,\n});\n\nconst HETI_SKIPPED_CLASS = 'heti-skip';\n\n// 部分正则表达式修改自 pangu.js\n// https://github.com/vinta/pangu.js\nconst CJK = '\\u2e80-\\u2eff\\u2f00-\\u2fdf\\u3040-\\u309f\\u30a0-\\u30fa\\u30fc-\\u30ff\\u3100-\\u312f\\u3200-\\u32ff\\u3400-\\u4dbf\\u4e00-\\u9fff\\uf900-\\ufaff';\nconst A = 'A-Za-z\\u0080-\\u00ff\\u0370-\\u03ff';\nconst N = '0-9';\nconst S = '`\\~!@#\\\\$%\\\\^&\\\\*\\\\(\\\\)-_=\\\\+\\\\[\\\\]{}\\\\\\\\\\\\|;:\\'\",<.>\\\\/\\\\?';\nconst ANS = `${A}${N}${S}`;\n\nconst REG_CJK_FULL = `(?<=[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`;\nconst REG_CJK_START = `([${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`;\nconst REG_CJK_END = `(?<=[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)*)`;\n\nconst REG_CJK_FULL_WITHOUT_LOOKBEHIND = `(?:[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)* *)(?=[${CJK}])`;\nconst REG_CJK_END_WITHOUT_LOOKBEHIND = `(?:[${CJK}])( *[${ANS}]+(?: +[${ANS}]+)*)`;\n\nconst REG_BD_STOP = `。．，、：；！‼？⁇`;\nconst REG_BD_SEP = `·・‧`;\nconst REG_BD_OPEN = `「『（《〈【〖〔［｛`;\nconst REG_BD_CLOSE = `」』）》〉】〗〕］｝`;\nconst REG_BD_START = `${REG_BD_OPEN}${REG_BD_CLOSE}`;\nconst REG_BD_END = `${REG_BD_STOP}${REG_BD_OPEN}${REG_BD_CLOSE}`;\nconst REG_BD_HALF_OPEN = `“‘`;\nconst REG_BD_HALF_CLOSE = `”’`;\nconst REG_BD_HALF_START = `${REG_BD_HALF_OPEN}${REG_BD_HALF_CLOSE}`;\n\nclass Heti {\n    constructor(rootSelector) {\n        let supportLookBehind = true;\n\n        try {\n            new RegExp(`(?<=\\\\d)\\\\d`, 'g').test('');\n        } catch (error) {\n            console.info(error.name, '该浏览器尚未实现 RegExp positive lookbehind');\n            supportLookBehind = false;\n        }\n\n        this.rootSelector = rootSelector || '.heti';\n        this.REG_FULL = new RegExp(\n            supportLookBehind ? REG_CJK_FULL : REG_CJK_FULL_WITHOUT_LOOKBEHIND,\n            'g'\n        );\n        this.REG_START = new RegExp(REG_CJK_START, 'g');\n        this.REG_END = new RegExp(\n            supportLookBehind ? REG_CJK_END : REG_CJK_END_WITHOUT_LOOKBEHIND,\n            'g'\n        );\n        this.offsetWidth = supportLookBehind ? 0 : 1;\n\n        this.funcForceContext = function forceContext(element) {\n            return hasOwn.call(HETI_NON_CONTIGUOUS_ELEMENTS, element.nodeName.toLowerCase());\n        };\n\n        this.funcFilterElements = function filterElements(element) {\n            return !(\n                (element.classList && element.classList.contains(HETI_SKIPPED_CLASS))\n                || hasOwn.call(HETI_SKIPPED_ELEMENTS, element.nodeName.toLowerCase())\n            );\n        };\n    }\n\n    spacingElements(elementList) {\n        for (const rootElement of elementList) {\n            this.spacingElement(rootElement);\n        }\n    }\n\n    spacingElement(element) {\n        const commonConfig = {\n            forceContext: this.funcForceContext,\n            filterElements: this.funcFilterElements,\n        };\n\n        const getWrapper = function (elementName, classList, text) {\n            const wrapper = document.createElement(elementName);\n            wrapper.className = classList;\n            wrapper.textContent = text.trim();\n            return wrapper;\n        };\n\n        Finder(element, Object.assign({}, commonConfig, {\n            find: this.REG_FULL,\n            replace: portion => getWrapper('heti-spacing', 'heti-spacing-start heti-spacing-end', portion.text),\n            offset: this.offsetWidth,\n        }));\n\n        Finder(element, Object.assign({}, commonConfig, {\n            find: this.REG_START,\n            replace: portion => getWrapper('heti-spacing', 'heti-spacing-start', portion.text),\n        }));\n\n        Finder(element, Object.assign({}, commonConfig, {\n            find: this.REG_END,\n            replace: portion => getWrapper('heti-spacing', 'heti-spacing-end', portion.text),\n            offset: this.offsetWidth,\n        }));\n\n        Finder(element, Object.assign({}, commonConfig, {\n            find: new RegExp(\n                `([${REG_BD_STOP}])(?=[${REG_BD_START}])|([${REG_BD_OPEN}])(?=[${REG_BD_OPEN}])|([${REG_BD_CLOSE}])(?=[${REG_BD_END}])`,\n                'g'\n            ),\n            replace: portion => getWrapper('heti-adjacent', 'heti-adjacent-half', portion.text),\n            offset: this.offsetWidth,\n        }));\n\n        Finder(element, Object.assign({}, commonConfig, {\n            find: new RegExp(\n                `([${REG_BD_SEP}])(?=[${REG_BD_OPEN}])|([${REG_BD_CLOSE}])(?=[${REG_BD_SEP}])`,\n                'g'\n            ),\n            replace: portion => getWrapper('heti-adjacent', 'heti-adjacent-quarter', portion.text),\n            offset: this.offsetWidth,\n        }));\n\n        // 使用弯引号时，在停顿符号接弯引号或弯引号接全角开引号时，间距缩进调整到四分之一。\n        Finder(element, Object.assign({}, commonConfig, {\n            find: new RegExp(\n                `([${REG_BD_STOP}])(?=[${REG_BD_HALF_START}])|([${REG_BD_HALF_OPEN}])(?=[${REG_BD_OPEN}])`,\n                'g'\n            ),\n            replace: portion => getWrapper('heti-adjacent', 'heti-adjacent-quarter', portion.text),\n            offset: this.offsetWidth,\n        }));\n    }\n\n    autoSpacing() {\n        const callback = () => {\n            const rootList = document.querySelectorAll(this.rootSelector);\n\n            for (const rootElement of rootList) {\n                this.spacingElement(rootElement);\n            }\n        };\n\n        if (document.readyState === 'complete') {\n            setTimeout(callback);\n        } else {\n            document.addEventListener('DOMContentLoaded', callback);\n        }\n    }\n}\n\nexport default Heti;\n"
  },
  {
    "path": "vendor/heti/js/heti-entry.js",
    "content": "/**\n * Heti 浏览器注入入口。\n * 将默认导出挂到全局，保持与当前主题脚本注入方式兼容。\n */\nimport Heti from './heti-addon.js';\n\nglobalThis.Heti = Heti;\n"
  },
  {
    "path": "vendor/heti/lib/_variables.scss",
    "content": "// Author: Sivan [sun.sivan@gmail.com]\n// Description: define variables, alias etc.\n\n// 定义赫蹏根 class 名\n$root-selector: '.heti' !default;\n$darkmode: true !default; // true | false | 'manual'\n$manualmode-auto-selector: '[data-darkmode=\"auto\"] &' !default;\n$manualmode-dark-selector: '[data-darkmode=\"dark\"] &' !default;\n\n// 字体 Fonts\n// 字体栈 Font Stacks\n$_font-stack-sans: \"Helvetica Neue\", helvetica, arial !default;\n$_font-stack-serif: \"Times New Roman\", times !default;\n$_font-stack-mono: \"SFMono-Regular\", consolas, \"Liberation Mono\", menlo, courier !default;\n$_font-stack-symbol: \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\" !default;\n\n// 字体族 Font Families\n$font-family-hei: $_font-stack-sans, \"Heti Hei\", sans-serif, $_font-stack-symbol !default;\n$font-family-song: $_font-stack-serif, \"Heti Song\", serif, $_font-stack-symbol !default;\n$font-family-kai: $_font-stack-serif, \"Heti Kai\", serif, $_font-stack-symbol !default;\n$font-family-hei-black: $_font-stack-sans, \"Heti Hei Black\", sans-serif, $_font-stack-symbol !default;\n$font-family-song-black: $_font-stack-serif, \"Heti Song Black\", serif, $_font-stack-symbol !default;\n$font-family-kai-black: $_font-stack-serif, \"Heti Kai Black\", serif, $_font-stack-symbol !default;\n$font-family-mono: $_font-stack-mono, monospace, $_font-stack-symbol !default;\n\n// 字重 Font Weights\n$font-weight-bolder: 800 !default;\n$font-weight-bold: 600 !default;\n$font-weight-normal: 400 !default;\n$font-weight-lighter: 200 !default;\n\n// 字号 Font Sizes\n$font-size-normal: 16px !default;\n$font-size-x-large: 20px !default;\n$font-size-large: 18px !default;\n$font-size-small: 14px !default;\n$font-size-x-small: 12px !default;\n$font-size-h1: 32px !default;\n$font-size-h2: 24px !default;\n$font-size-h3: 20px !default;\n$font-size-h4: 18px !default;\n$font-size-h5: 16px !default;\n$font-size-h6: 14px !default;\n\n// 行 Lines\n// 行宽\n$line-length: 42em !default;\n\n// 行高 Line Heights\n$line-height-normal: 1.5 !default;\n$line-height-expanded-ultra: 2.25 !default;\n\n// 字符间距\n$letter-spacing-normal: 0 !default;\n$letter-spacing-small: 0.01em !default;\n$letter-spacing-medium: 0.02em !default;\n$letter-spacing-large: 0.05em !default;\n\n$line-height-size-normal: $font-size-normal * $line-height-normal !default;\n$line-height-size-large: $line-height-size-normal !default;\n$line-height-size-x-large: $font-size-x-large * $line-height-normal !default;\n$line-height-size-small: $line-height-size-normal !default;\n$line-height-size-x-small: 18px !default;\n$line-height-size-h1: 48px !default;\n$line-height-size-h2: 36px !default;\n$line-height-size-h3: 36px !default;\n$line-height-size-h4: 24px !default;\n$line-height-size-h5: 24px !default;\n$line-height-size-h6: 24px !default;\n\n// 段落 Paragraphs\n// 标准网格单位变量 Standard Length\n$std-block-unit: $line-height-size-normal !default;\n$std-inline-unit: $font-size-normal !default;\n\n// 示例：缩进单位 = 二倍文字宽度\n$text-indent-length: 2em !default;\n$text-indent-size: $font-size-normal * 2 !default;\n\n// 中文引号 Chinese Quote Set\n$chinese-quote-presets: (\n    \"cn\": (\n        \"horizontal\": \"“\" \"”\" \"‘\" \"’\",\n        \"vertical\": \"『\" \"』\" \"「\" \"」\"\n    ),\n    \"tw\": (\n        \"horizontal\": \"「\" \"」\" \"『\" \"』\",\n        \"vertical\": \"「\" \"」\" \"『\" \"』\"\n    ),\n    \"common\": (\n        \"horizontal\": \"「\" \"」\" \"『\" \"』\",\n        \"vertical\": \"「\" \"」\" \"『\" \"』\"\n    )\n) !default;\n$chinese-quote-set: \"common\" !default;\n\n// 栏 Columns\n$column-count-list: (1, 2, 3, 4) !default;\n$column-width-list: (16em, 20em, 24em, 28em, 32em, 36em, 40em, 44em, 48em) !default;\n\n// 开发用配置项 Develop Configs\n$_css-reset-scheme: \"reset\";\n\n// 混合 Mix-ins\n@mixin clear-float {\n    &::before,\n    &::after {\n        content: \"\";\n        display: table;\n    }\n\n    &::after {\n        clear: both;\n    }\n}\n\n@mixin non-cjk-block {\n    &:not(:lang(zh)):not(:lang(ja)):not(:lang(ko)),\n    &:not(:lang(zh)) {\n        @content;\n    }\n}\n\n@mixin hang {\n    position: absolute;\n    line-height: inherit;\n    text-indent: 0;\n}\n\n@mixin darkmode-style(\n    $darkmode: $darkmode,\n    $dark-selector: $manualmode-dark-selector,\n    $auto-selector: $manualmode-auto-selector\n) {\n    @if $darkmode == 'manual' {\n        #{$dark-selector} {\n            @content;\n        }\n\n        @media (prefers-color-scheme: dark) {\n            #{$auto-selector} {\n                @content;\n            }\n        }\n    } @else if $darkmode {\n        @media (prefers-color-scheme: dark) {\n            @content;\n        }\n    }\n}\n\n// 函数 Functions\n@function batch-fix-list($list, $prefix: '', $suffix: '') {\n    $_list: () !default;\n\n    @each $item in $list {\n        $_list: append($_list, #{$prefix}#{$item}#{$suffix}, comma);\n    }\n\n    @return $_list;\n}\n"
  },
  {
    "path": "vendor/heti/lib/helpers/_add-on.scss",
    "content": "// Author: Sivan [sun.sivan@gmail.com]\n// Description: define add-ons.\n\n@import \"../variables\";\n\n@mixin hetiAddOns {\n    // 用于中西文混排增加边距\n    heti-spacing {\n        display: inline;\n\n        & + sup,\n        & + sub {\n            margin-inline-start: 0;\n        }\n    }\n\n    .heti-spacing-start {\n        margin-inline-end: 0.25em;\n    }\n\n    .heti-spacing-end {\n        margin-inline-start: 0.25em;\n    }\n\n    heti-adjacent {\n        display: inline;\n        text-spacing-trim: space-all;\n        unicode-bidi: isolate;\n        // 解决苹方等字体下标点过度挤压的问题\n    }\n\n    .heti-adjacent-half {\n        margin-inline-end: -0.5em;\n    }\n\n    .heti-adjacent-quarter {\n        margin-inline-end: -0.25em;\n    }\n}\n"
  }
]