// ==UserScript==
// @name 洛谷深色模式 · Luogu Dark
// @namespace https://www.luogu.com.cn/
// @version 5.4.5
// @description 给洛谷全部页面(题目/列表/比赛/排行榜/记录/个人中心/团队/讨论/题解/提交)的卡片赋予 #383838 半透明深色效果;统一色板变量、修复残留白块(下拉浮层、弹窗、编辑器、分页、上传框)、适配 Prism 与 CodeMirror 代码配色,并支持一键开关与半透明度调节
// @author You
// @match https://www.luogu.com.cn/*
// @match https://*.luogu.com.cn/*
// @match https://*.luogu.com/*
// @match https://*.luogu.me/*
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @run-at document-end
// ==/UserScript==
/* =============================================================================
* 设计理念(与原 luogu-dark.txt 保持一致,只是做得更彻底)
* -----------------------------------------------------------------------------
* 1. 只改「卡片」,不强制整页变黑。页面底色仍交给洛谷自己的主题,
* 我们只在卡片上铺一层 #383838 @ 55% 的半透明深色,让站点主题透出来。
* 2. 一切颜色走 token。所有色值集中在「色板」一节,并同时以 CSS 变量
* --ld-* 暴露在 :root 上,方便用 Stylus 或 DevTools 单独微调,
* 不必再进脚本里全文搜索色值。
* 3. 优先复用洛谷自带的主题变量。高亮色一律用
* var(--lcolor--primary, 52,152,219) 这类变量兜底,站点换主题时自动跟随。
* 4. 尊重站点原有的「内联颜色」。用户的等级色、题目难度色等是站点用
* style="color:..." 写死的,我们一律用 :not([style*="color"]) 放行,
* 不做「统一刷白」这种破坏信息的覆盖。
* 5. 半透明 + 低对比层次。文字分三档(主/次/弱),边框 8% 白,阴影柔和,
* 避免在深色卡片上出现纯白大色块(下拉浮层、弹窗、编辑器是重灾区)。
* 6. 不靠 DOM 硬改来做视觉。除「给站点内联色补 alpha」这一处必要修补外,
* 全部用 CSS 完成;JS 只负责注入、路由分包与性能控制,尽量不影响页面逻辑。
* ========================================================================== */
(function () {
'use strict';
/* =========================================================================
* ① 可调配置(改这里就够了)
* ====================================================================== */
// 卡片底色与透明度:CARD_ALPHA 越小越透,1 表示不透明
var CARD_RGB = '56, 56, 56'; // #383838
// ★ 默认取 0.85:P13501 实测 0.55 在白底宿主上会合成为 rgb(146,146,146) 中灰,
// 全页会有 144 个元素对比度低于 2.2(标题 2.14、侧栏小字 1.19)。
// 0.85 合成成 rgb(56,56,56),实测可用;滑条可随时调回 0.55 或更低。
var CARD_ALPHA = 0.55;
var CARD_ALPHA_MIN = 0.55; // 「原脚本观感档」,面板里给一个快捷按钮
// ★ 设置面板
var PANEL_KEY = 'Alt+L'; // 打开/关闭设置面板(可改 'Alt+Shift+L')
var ALPHA_MIN = 0.30; // 允许调到很透(浅色宿主下会偏灰,用户自选)
var ALPHA_MAX = 1.00;
var UI_FONT = '-apple-system, "Segoe UI", "Microsoft YaHei", sans-serif';
var UI_BG = '#2a2a2a'; // 面板底色:不透明,避免和页面半透明层叠加
var UI_BG_SOFT = '#333333';
var UI_BORDER = '#555555';
var UI_FG = '#f0f0f0';
// 站点内联色(题目标签、难度条、进度格)统一补到的透明度
var TAG_ALPHA = 0.55;
// 输入框 / 浮层 / 按钮底的透明度(比卡片更浅一点,保持层次)
var PANEL_RGB = '0, 0, 0';
var PANEL_ALPHA = 0.25;
// 代码框底色:站点默认透明,叠在半透明卡片上几乎看不出边界。
// 改成不透明深色底(与提交框编辑器同色),边界清楚,也和截图一致。
var CODE_RGB = '30, 30, 30'; // #1e1e1e
var CODE_ALPHA = 1;
// 圆角
var RADIUS = '6px';
// ★ 层级透明度:都按「卡片 alpha × 百分比」派生,保证永远是「比卡片略深的半透明」,
// 而不是死黑实色。样例框 80%、引用框 70%。
var SAMPLE_RATIO = 0.80;
var QUOTE_RATIO = 0.70;
var QUOTE_RGB = '0, 0, 0'; // 引用框叠加用的基色(半透明,不是实色底)
// 是否把整页背景也压暗(默认关闭,保持原脚本「只改卡片」的理念)
var COVER_PAGE = false;
// ★ 代码框斜度:卡片 alpha × 该倍率 → 比卡片略深的半透明底(不是死黑实色)。
// CODE_RGB/CODE_ALPHA 保留作后备,但代码框优先走这个倍率。
var CODE_RATIO = 0.85;
// ★ 样例区代码框单独一档:比普通代码框更透,避免在样例框(0.68)里再陷出一层。
// = 卡片 alpha × 0.40(默认 0.85 → 0.34)
var SAMPLE_CODE_RATIO = 0.40;
// 是否把 #383838 之类的中性色内联样式也补 alpha(默认关闭,只处理彩色)
var ALPHA_NEUTRAL = false;
// ★ 底栏:文字统一白色;可整块隐藏(面板里切换,默认展示)
var HIDE_FOOTER = true;
// 多个脚本副本同时注入时,只让第一个生效
if (window.__LUOGU_DARK_CARD__) return;
window.__LUOGU_DARK_CARD__ = true;
/* =========================================================================
* ② 色板:唯一色值来源
* 改动这里会同时影响 CSS 变量与全部规则
* ====================================================================== */
var PALETTE = {
fg: '#ffffff', // 卡片内主文字
fgSoft: '#d6d6d6', // 正文
fgMuted: '#a0a0a0', // 次要说明、时间、计数
fgFaint: '#888888', // 占位符、极弱信息
fgHeading: '#f0f0f0', // 标题
link: '#7fc4ff',
linkHover: '#b8ddff',
primary: 'rgb(var(--lcolor--primary, 52, 152, 219))',
primaryDark: '#2980b9',
primarySoft: '#5dade2',
vip: '#d1af60',
inlineCode: '#ffc4c4',
code: '#d4d4d4', // 代码文字
codeBg: 'rgba(' + CODE_RGB + ', ' + CODE_ALPHA + ')', // 代码块底色
// 浮层 / 输入类控件(不透明,避免透过内容)
surface: '#2a2a2a',
surfaceHi: '#333333',
surfaceDeep: '#2b2b2b',
border: '#555555',
borderHi: '#888888',
// 边框与分隔(白 + 透明度)
hairline: 'rgba(255, 255, 255, 0.08)',
hairlineSoft:'rgba(255, 255, 255, 0.06)',
track: '#252526',
thumb: '#555555',
thumbHi: '#777777',
// ★ VS Code One Dark Pro 代码配色(键名保持不变,只换值)
synKeyword: '#c678dd', // 关键字 int / for / if / using / namespace
synControl: '#56b6c2', // 预处理 #include / #define
synFunction: '#61afef', // 函数名 work / min / max
synNumber: '#d19a66', // 数字 1003 / 0 / -1
synString: '#98c379', // 字符串
synComment: '#5c6370', // 注释 // 更新两次
synType: '#e5c07b', // 类型名 long long / size_t
// One Dark Pro 的「变量 / 属性」红,以及运算符浅灰;Dark+ 表里没有这两项
synVariable: '#e06c75', // 变量 / 属性
synOperator: '#abb2bf', // 运算符
// 编辑器结构色
editorBg: '#1e1e1e',
editorGutter:'#858585',
editorActive:'#2a2a2a',
editorSelect:'#264f78',
// 语义色
success: '#a5dc86',
// 卡片本体不在这里定义:--ld-card 由 4.1 直接写在 :root 上
// (放在色板里会变成 var(--ld-card, var(--ld-card…)) 自引用,整条声明会失效)
// 样例框:按原脚本设计保持透明,只靠卡片底色托着。
// 不要再给它独立背景色 —— 否则「输入输出样例」下面会套出三层框。
layerFallback1: 'transparent',
layerFallback2: 'transparent',
panel: 'rgba(' + PANEL_RGB + ', ' + PANEL_ALPHA + ')',
shadow: 'rgba(0, 0, 0, 0.4)',
shadowDeep: 'rgba(0, 0, 0, 0.6)'
};
// 暴露成 CSS 变量:--ld-fg、--ld-surface……
var ROOT_VARS = (function () {
var out = ':root{';
Object.keys(PALETTE).forEach(function (k) {
// card / panel / code 等组合值也一并暴露,便于外部覆盖
out += '\n --ld-' + k.replace(/[A-Z]/g, function (c) {
return '-' + c.toLowerCase();
}) + ': ' + PALETTE[k] + ';';
});
return out + '\n}';
})();
/* =========================================================================
* ③ 选择器片段(集中管理,方便补新组件)
* ====================================================================== */
// 浮层类:下拉菜单、语言选择、Popper 弹层……
var SEL_POPOVER = 'body .dropdown, body .v-popper__popper, body .v-popper__inner, ' +
'body .v-popper--theme-dropdown, body [class*="lang-select"], ' +
'body [class*="language-select"], body [class*="select-menu"], ' +
'body .lfe-dropdown, body .lfe-select, body .combo-wrapper.full';
// 站点「带内联颜色」的元素一律放行(等级色、难度色、题目状态色)
var NOT_INLINE_COLOR = ':not([style*="color"])';
/* =========================================================================
* ④ 样式表
* ====================================================================== */
var CSS_PARTS = [];
/* ---------- 4.1 色板变量与「只用于注入,不影响页面」的初始化 -------------- */
CSS_PARTS.push(ROOT_VARS + '\n' + [
'/* 让 color-scheme 走深色,原生控件(滚动条、日期选择)自动跟随 */',
':root { color-scheme: dark !important; }',
'/* ★ 卡片透明度:沿用原脚本设计(rgba + alpha),不做任何颜色加深。',
' 滑条写 --ld-layer-alpha;浅色宿主额外加一个补偿量(默认 0.55+0.30=0.85),',
' 这是原脚本缺的「宿主主题检测」,深色宿主仍严格等于滑条值。 */',
':root {',
' --ld-layer-alpha: ' + CARD_ALPHA + ';',
' --ld-card-alpha: var(--ld-layer-alpha);',
' --ld-card: rgba(' + CARD_RGB + ', var(--ld-card-alpha, ' + CARD_ALPHA + '));',
' /* ★ 样例框 / 引用框:卡片 alpha × 百分比 → 比卡片略深,但仍是半透明,不是死黑 */',
' --ld-sample-alpha: calc(var(--ld-layer-alpha) * ' + SAMPLE_RATIO + ');',
' --ld-quote-alpha: calc(var(--ld-layer-alpha) * ' + QUOTE_RATIO + ');',
' /* ★ 代码框:卡片 alpha × 0.85,半透明比卡片略深,不再是死黑实色 */',
' --ld-code-alpha: calc(var(--ld-layer-alpha) * ' + CODE_RATIO + ');',
' --ld-sample: rgba(' + CARD_RGB + ', var(--ld-sample-alpha));',
' --ld-quote: rgba(' + QUOTE_RGB + ', var(--ld-quote-alpha));',
' --ld-code-bg: rgba(' + CARD_RGB + ', var(--ld-code-alpha));',
' /* ★ 样例区代码框专用(更透,避免在样例框里再陷出第三层);',
' 题解页 markdown 代码框与提交页 CodeMirror 继续用 --ld-code-bg,不受影响 */',
' --ld-sample-code-alpha: calc(var(--ld-layer-alpha) * ' + SAMPLE_CODE_RATIO + ');',
' --ld-sample-code-bg: rgba(' + CARD_RGB + ', var(--ld-sample-code-alpha));',
' /* ★ 测试点方块专属透明度(Alt+L 面板可调)。',
' 站点用 .lcolor-bg-green-3 等语义类把底色写死为不透明 rgb(),',
' 所以这里不重写颜色(保住色相),只调整个方块的不透明度。 */',
' --ld-testcase-alpha: 1;',
' /* ★ 全局「淡度」:由 Alt+L 面板滑块写入 --ld-saturate(默认 100%,即不修改)。',
' 作用在 html 上做 saturate() 降饱和,用于「颜色太艳、看久了眼睛累」的场景。',
' 放在 html 上不会改变 position:fixed 的包含块(根元素的包含块本就是视口)。 */',
' --ld-saturate: 100%;',
' --ld-layer-1: var(--ld-sample);',
' --ld-layer-2: var(--ld-code-bg);',
' /* 语法高亮:与截图一致的统一色值,Prism 与 CodeMirror 共用同一套 */',
' --ld-syn-keyword: ' + PALETTE.synKeyword + ';',
' --ld-syn-control: ' + PALETTE.synControl + ';',
' --ld-syn-function: ' + PALETTE.synFunction + ';',
' --ld-syn-number: ' + PALETTE.synNumber + ';',
' --ld-syn-string: ' + PALETTE.synString + ';',
' --ld-syn-comment: ' + PALETTE.synComment + ';',
' --ld-syn-type: ' + PALETTE.synType + ';',
' --ld-syn-variable: ' + PALETTE.synVariable + ';',
' --ld-syn-operator: ' + PALETTE.synOperator + ';',
' --ld-syn-plain: ' + PALETTE.code + ';',
'}',
'html { filter: saturate(var(--ld-saturate, 100%)) !important; }',
'/* ★ 卡片本体兜底文字色:站点默认 #404040,在深色卡上几乎不可见 */',
'.l-card { color: var(--ld-fg-soft) !important; }'
].join('\n'));
/* ---------- 4.2 卡片本体 ------------------------------------------------- */
CSS_PARTS.push([
'/* ========== 卡片背景 ========== */',
'.theme-page {',
' --theme-card-background: var(--ld-card) !important;',
' --theme-card-backdrop-filter: none !important;',
'}',
'.l-card,',
'.l-card::before,',
'.l-card::after {',
' background: var(--ld-card) !important;',
' backdrop-filter: none !important;',
' -webkit-backdrop-filter: none !important;',
' border: 1px solid var(--ld-hairline) !important;',
' box-shadow: 0 4px 20px var(--ld-shadow) !important;',
'}',
'/* 卡片内的分区不再叠第二层底色,避免越套越黑 */',
'.l-card .l-card { background: transparent !important; box-shadow: none !important; }'
].join('\n'));
/* ---------- 4.3 文字层次 ------------------------------------------------- */
CSS_PARTS.push([
'/* ========== 文字层次 ========== */',
'.l-card .stat .stat-text, .l-card .stat .name, .l-card .stat .value,',
'.l-card .header-card .stat-text,',
'.l-card .l-flex-info-row > a.name,',
'.l-card .l-flex-info-row time,',
'.l-card .menu .entry,',
'footer, footer p, footer a, footer span, footer .copyright, footer .copyright a {',
' color: var(--ld-fg) !important;',
'}',
'.l-card .l-flex-info-row > span:last-child:not([class*="lcolor"]) {',
' color: var(--ld-fg) !important;',
'}',
'.l-card p,',
'.l-card .lfe-marked, .l-card .lfe-marked p, .l-card .lfe-marked li,',
'.l-card .lfe-marked strong, .l-card .lfe-marked em,',
'.l-card .lfe-marked td, .l-card .lfe-marked th,',
'.l-card .attachments, .l-card .attachments .item, .l-card .attachments span,',
'.l-card .attachments svg,',
'.l-card .lfe-h2, .l-card .lfe-h3, .l-card .lfe-h4,',
'.l-card section .title { color: var(--ld-fg-soft) !important; }',
'.l-card .lfe-h1, .l-card .lfe-h5, .l-card .lfe-h6 { color: var(--ld-fg-heading) !important; }',
'.l-card .lfe-caption, .l-card .lfe-caption time,',
'.l-card .selected-tags .lcolor--grey-3,',
'.l-card .result .count,',
'.l-card .page-bar .total,',
'.l-card .attachments .light-text { color: var(--ld-fg-muted) !important; }',
'/* ★ 记录详情右侧信息行的「标签」(所属题目/评测状态/评测分数/提交时间)→ 白色。',
' 原来和上面那组共用 var(--ld-fg-muted)(灰 rgb(160,160,160)),按要求改为白色。 */',
'.l-card .l-flex-info-row > span:first-child { color: var(--ld-fg) !important; }',
/* 链接:非内联色的才是我们自己的链接 */
'.l-card .lfe-marked a,',
'.l-card .attachments a,',
'.l-card .l-flex-info-row a' + NOT_INLINE_COLOR + ',',
'.l-card .solution-list .row a' + NOT_INLINE_COLOR + ',',
'.l-card .row .title a, .l-card .row .pid a,',
'.l-card .selected-tags a,',
'.l-card .result a.lfe-caption,',
'.l-card .header-container a,',
'.l-card .table .row .username a, .l-card .table .row .title a,',
'footer a { color: var(--ld-link) !important; }',
'.l-card .lfe-marked a:hover, .l-card .attachments a:hover,',
'.l-card .row .title a:hover, .l-card .table .row .username a:hover,',
'.l-card .table .row .title a:hover,',
'.l-card .l-flex-info-row a' + NOT_INLINE_COLOR + ':hover,',
'.l-card .solution-list .row a' + NOT_INLINE_COLOR + ':hover,',
'footer a:hover { color: var(--ld-link-hover) !important; }',
'.l-card .lfe-marked hr, .l-card .l-flex-info-row,',
'.l-card .table .row-wrap, .l-card .table .row,',
'.l-card .list-wrap .row-wrap, .l-card .list-wrap .row {',
' border-color: var(--ld-hairline) !important;',
'}',
'.l-card .lfe-marked :not(pre) > code,',
'.l-card .announcement code, .l-card .bulletin code, .l-card .notice code,',
'.l-card .feed-card-content code, .l-card .markdown-body :not(pre) > code {',
' background: rgba(255, 255, 255, 0.08) !important;',
' color: var(--ld-inline-code) !important;',
' border: none !important;',
'}'
].join('\n'));
/* ---------- 4.4 标题去横线 ------------------------------------------------- */
CSS_PARTS.push([
'/* ★ 去掉正文标题下面自带的横线 */',
'.l-card .lfe-marked h1, .l-card .lfe-marked h2, .l-card .lfe-marked h3,',
'.l-card .lfe-marked h4, .l-card .lfe-marked h5, .l-card .lfe-marked h6,',
'.l-card .lfe-h1, .l-card .lfe-h2, .l-card .lfe-h3,',
'.l-card .lfe-h4, .l-card .lfe-h5, .l-card .lfe-h6 {',
' border-bottom: none !important;',
' padding-bottom: 0 !important;',
' box-shadow: none !important;',
'}'
].join('\n'));
/* ---------- 4.5 代码块(样例框 / 题解 / 预览) ----------------------------- */
CSS_PARTS.push([
'.l-card .io-sample { background: transparent !important; }',
'.l-card .io-sample-block { background: transparent !important; }',
'/* ★ 「输入输出样例」大标题下不要再套框:这两个容器不参与任何边框/阴影,',
' 只有里面的代码框自己有框。 */',
'.l-card .io-sample, .l-card .io-sample-block,',
'.l-card .io-sample > div, .l-card .io-sample-block > div {',
' border: none !important;',
' box-shadow: none !important;',
'}',
'/* ★ 代码显示框:原脚本那套独立深色底 rgba(0,0,0,0.35),比卡片深 */',
'.l-card .io-sample pre, .l-card .io-sample pre.lfe-code,',
'.l-card pre.lfe-code, .l-card .lfe-code,',
'.l-card .lfe-marked pre, .l-card .markdown-body pre,',
'.l-card .preview pre, .l-card .code-block pre {',
' background: var(--ld-layer-2) !important;',
' color: ' + PALETTE.code + ' !important;',
' border: 1px solid var(--ld-hairline) !important;',
' border-radius: ' + RADIUS + ' !important;',
' padding: 1em !important;',
' overflow-x: auto !important;',
' box-sizing: border-box !important;',
' margin: 1em 0 !important;',
'}',
'.l-card .io-sample pre code, .l-card pre.lfe-code code,',
'.l-card .lfe-code code, .l-card .lfe-marked pre code,',
'.l-card .markdown-body pre code, .l-card .preview pre code {',
' background: transparent !important; /* 内部透明,彻底解决双层背景 */',
' border: none !important;',
' padding: 0 !important;',
' color: ' + PALETTE.code + ' !important;',
' display: block !important;',
" font-family: 'Consolas', 'Monaco', 'Courier New', monospace !important;",
'}',
'/* ★ 只覆盖「样例区」代码框的底色:更透,与样例框(0.68)接近,不陷出第三层。',
' 题解页 markdown 代码框 / 提交页 CodeMirror 不在此选择器内,保持 --ld-code-bg 不变。 */',
'.l-card .io-sample pre, .l-card .io-sample pre.lfe-code {',
' background: var(--ld-sample-code-bg) !important;',
'}',
'.l-card .io-sample .lfe-caption, .l-card .io-sample .lfe-caption b {',
' background: transparent !important;',
' color: var(--ld-fg-soft) !important;',
' border-color: transparent !important;',
'}',
'.l-card .io-sample .lfe-caption button {',
' color: var(--ld-primary) !important;',
' border-color: var(--ld-primary) !important;',
' background: transparent !important;',
'}',
'.l-card .io-sample .lfe-caption button:hover { background: rgba(52, 152, 219, 0.15) !important; }'
].join('\n'));
/* ---------- 4.6 复制按钮 ------------------------------------------------ */
CSS_PARTS.push([
'html body button.copy-button, html body .copy-button,',
'html body .lfe-marked button.copy-button,',
'html body [class*="copy"] > button, html body button[class*="copy"] {',
' color: ' + PALETTE.fg + ' !important;',
' fill: ' + PALETTE.fg + ' !important;',
' stroke: none !important;',
' opacity: 1 !important;',
' visibility: visible !important;',
' background: transparent !important;',
' background-color: transparent !important;',
' border: none !important;',
' box-shadow: none !important;',
'}',
'/* hover:只有极淡白底,字/图标保持白色 */',
'html body button.copy-button:hover, html body .copy-button:hover,',
'html body [class*="copy"] > button:hover, html body button[class*="copy"]:hover {',
' color: ' + PALETTE.fg + ' !important;',
' fill: ' + PALETTE.fg + ' !important;',
' background: rgba(255, 255, 255, 0.1) !important;',
' background-color: rgba(255, 255, 255, 0.1) !important;',
' border: none !important;',
'}',
'html body button.copy-button svg, html body button.copy-button path,',
'html body .copy-button svg, html body .copy-button path,',
'html body [class*="copy"] > button svg, html body button[class*="copy"] svg {',
' color: var(--ld-fg) !important;',
' fill: var(--ld-fg) !important;',
' stroke: none !important;',
'}'
].join('\n'));
/* ---------- 4.7 按钮 / 标签 / 输入控件 ------------------------------------ */
CSS_PARTS.push([
'/* ========== 按钮统一样式 ========== */',
'.l-card .button-transparent,',
'.l-card.burger .body button.solid,',
'.l-card button.transparent,',
'.l-card .menu .button {',
' color: var(--ld-fg) !important;',
' border: 1px solid rgba(255, 255, 255, 0.7) !important;',
' background: transparent !important;',
'}',
'.l-card .button-transparent:hover,',
'.l-card.burger .body button.solid:hover,',
'.l-card button.transparent:hover {',
' color: var(--ld-fg) !important;',
' border-color: var(--ld-fg) !important;',
' background: rgba(255, 255, 255, 0.1) !important;',
'}',
'/* 实心按钮:跟随站点主题色。',
' ★ 排除 .lcolor-var-red-3(语义红按钮,如文章编辑页的「删除文章」)——',
' 否则会被强制成蓝底白字无边框,丢掉它的语义红。 */',
'.l-card button.solid:not(.lcolor-var-red-3), .l-card a.solid:not(.lcolor-var-red-3),',
'.l-card .result button.solid:not(.lcolor-var-red-3),',
'.l-card .inquiry-header .solid:not(.lcolor-var-red-3),',
'.l-card .inquiry-header a.solid:not(.lcolor-var-red-3) {',
' background-color: var(--ld-primary) !important;',
' color: var(--ld-fg) !important;',
' border-width: 0 !important;',
' border-style: none !important;',
'}',
'.l-card button.solid:hover, .l-card a.solid:hover,',
'.l-card .result button.solid:hover,',
'.l-card .inquiry-header .solid:hover { background-color: var(--ld-primary-dark) !important; }',
':is(html) body .l-card .right a.solid.l-button,',
':is(html) body .l-card .right button.solid {',
' background-color: transparent !important;',
' color: ' + PALETTE.fg + ' !important;',
' border-width: 0.571429px !important;',
' border-style: solid !important;',
' border-color: rgba(255, 255, 255, 0.7) !important;',
'}',
':is(html) body .l-card .drop, :is(html) body .drop {',
' background-color: var(--ld-surface) !important;',
' border-top-color: var(--ld-hairline) !important;',
' border-right-color: var(--ld-hairline) !important;',
' border-bottom-color: var(--ld-hairline) !important;',
' border-left-color: var(--ld-hairline) !important;',
'}',
':is(html) body .l-card .image-block, :is(html) body .image-block {',
' background-color: var(--ld-surface) !important;',
' border-top-color: var(--ld-hairline) !important;',
' border-right-color: var(--ld-hairline) !important;',
' border-bottom-color: var(--ld-hairline) !important;',
' border-left-color: var(--ld-hairline) !important;',
'}',
':is(html) body .image-block time,',
':is(html) body .image-block span,',
':is(html) body .image-block .lfe-caption {',
' color: var(--ld-fg-muted) !important;',
'}',
'html body .top-bar {',
' /* 用 --ld-surface-hi(#333333) 而不是 --ld-surface(#2a2a2a):',
' 后者与 .theme-page 页面底同色,会让顶栏失去层次(用户反馈)。 */',
' background-color: var(--ld-surface-hi) !important;',
' /* 站点这条 bar 的文字是 rgb(51,51,51) 深色,压暗底后必须同时提亮字色 */',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body .ticket-card .left.row span,',
'html body .l-card .ticket-card .left.row span {',
' background-color: var(--ld-panel) !important;',
' color: var(--ld-fg-soft) !important;',
'}',
'html body div.title {',
' color: ' + PALETTE.fg + ' !important;',
'}',
':is(html) body button.lcolor-var-blue-4 {',
' color: rgb(var(--lcolor--blue-3)) !important;',
' border-top-color: rgb(var(--lcolor--blue-3)) !important;',
' border-right-color: rgb(var(--lcolor--blue-3)) !important;',
' border-bottom-color: rgb(var(--lcolor--blue-3)) !important;',
' border-left-color: rgb(var(--lcolor--blue-3)) !important;',
'}',
'html body .l-card.error-background,',
'html body .error-background,',
'html body .l-card .error-background {',
' background-color: var(--ld-card) !important;',
'}',
'html body .l-card.error-background *,',
'html body .error-background * {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body pre.lfe-marked-original:empty,',
'html body .lfe-marked-original:empty {',
' background-color: transparent !important;',
' border-top-color: transparent !important;',
' border-right-color: transparent !important;',
' border-bottom-color: transparent !important;',
' border-left-color: transparent !important;',
'}',
'html body:has(.error-background) nav.sidebar,',
'html body:has(.error-background) .sidebar.lside,',
'html body:has(.error-background) .user-nav {',
' background-color: var(--ld-surface-hi) !important;',
'}',
'html body:has(.error-background) nav.sidebar span,',
'html body:has(.error-background) nav.sidebar a,',
'html body:has(.error-background) .sidebar.lside span,',
'html body:has(.error-background) .sidebar.lside a,',
'html body:has(.error-background) .user-nav span,',
'html body:has(.error-background) .user-nav a {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body nav.sidebar,',
'html body .sidebar.lside,',
'html body .user-nav {',
' background-color: var(--ld-surface-hi) !important;',
'}',
'html body nav.sidebar :not(svg):not(path):not([style*="color"]):not([class*="lcolor"]),',
'html body .sidebar.lside :not(svg):not(path):not([style*="color"]):not([class*="lcolor"]),',
'html body .user-nav :not(svg):not(path):not([style*="color"]):not([class*="lcolor"]) {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body nav.sidebar a:focus,',
'html body nav.sidebar button:focus,',
'html body .sidebar.lside a:focus,',
'html body .sidebar.lside button:focus,',
'html body .user-nav a:focus,',
'html body .user-nav button:focus,',
'html body nav.sidebar a:focus-visible,',
'html body nav.sidebar button:focus-visible,',
'html body .sidebar.lside a:focus-visible,',
'html body .sidebar.lside button:focus-visible,',
'html body .user-nav a:focus-visible,',
'html body .user-nav button:focus-visible {',
' outline-style: none !important;',
'}',
'html body .l-card .menu-container,',
'html body .menu-container {',
' border-bottom-color: var(--ld-hairline) !important;',
'}',
'html body .l-card .section,',
'html body .section {',
' border-bottom-color: var(--ld-hairline) !important;',
'}',
'html body main.wrapped.lfe-body,',
'html body .wrapper.wrapped,',
'html body .main-container {',
' background-color: var(--ld-surface) !important;',
'}',
'html body .card.message {',
' background-color: var(--ld-card) !important;',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body .card.message *,',
'html body .wrapper.wrapped .header span,',
'html body .wrapper.wrapped .header a,',
'html body .wrapper.wrapped .header .user-nav {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body .wrapper.wrapped .header .user-nav,',
'html body .wrapper.wrapped .header {',
' background-color: transparent !important;',
'}',
'html body .cs-dialog,',
'html body .cs-dialog-header,',
'html body .cs-dialog-body,',
'html body .cs-dialog-footer,',
'html body .cs-dialog-content {',
' background-color: var(--ld-card) !important;',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body .cs-dialog :not(a):not(button):not([class*="lcolor"]):not([class*="token"]):not(svg):not(path) {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body .cs-dialog-container {',
' background-color: rgba(0, 0, 0, 0.5) !important;',
'}',
'/* ★★ 编辑器「设置 / 更多」等其它内联浮层:统一给深色底(teleport 到 body,不带 .l-card) */',
'html body .l-card.container.type-burger,',
'html body .l-card.container {',
' background-color: var(--ld-card) !important;',
' color: ' + PALETTE.fg + ' !important;',
'}',
'/* 工单创建页左侧说明栏的白竖线(div.side-info border-left rgb(232,232,232)) */',
'html body .side-info {',
' border-left-color: var(--ld-hairline) !important;',
'}',
'html body:not(:has(.lfe-body)) {',
' background-color: var(--ld-surface) !important;',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body:not(:has(.lfe-body)) .card,',
'html body:not(:has(.lfe-body)) [class*="dialog"],',
'html body:not(:has(.lfe-body)) [class*="modal"],',
'html body:not(:has(.lfe-body)) [class*="panel"] {',
' background-color: var(--ld-card) !important;',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body:not(:has(.lfe-body)) input,',
'html body:not(:has(.lfe-body)) textarea {',
' background-color: var(--ld-surface) !important;',
' color: ' + PALETTE.fg + ' !important;',
' border-top-color: var(--ld-border) !important;',
' border-right-color: var(--ld-border) !important;',
' border-bottom-color: var(--ld-border) !important;',
' border-left-color: var(--ld-border) !important;',
'}',
'/* ★★ 外链安全拦截页里那个「白框」的真身:
(用户提供的 DOM 片段)。',
' 它不是 input/textarea,而是 ,所以上面那条规则覆盖不到 ——',
' 页面主体已经深色(深灰底/白字/蓝按钮),只有这个 pre 仍是纯白。',
' 这里直接按 id 精准命中(id="url" 是该页专有,不写 .lfe-body 限定,',
' 以防该页结构变体;作用范围极小、无误伤风险)。 */',
'html body pre#url,',
'html body #url {',
' background-color: var(--ld-surface) !important;',
' color: ' + PALETTE.fg + ' !important;',
' border-top-color: var(--ld-border) !important;',
' border-right-color: var(--ld-border) !important;',
' border-bottom-color: var(--ld-border) !important;',
' border-left-color: var(--ld-border) !important;',
'}',
'html body .am-comment,',
'html body .am-comment-main {',
' background-color: transparent !important;',
'}',
'html body .am-comment-hd {',
' background-color: var(--ld-panel) !important;',
' color: ' + PALETTE.fg + ' !important;',
' border-bottom-color: var(--ld-border) !important;',
'}',
'html body .am-comment-bd {',
' background-color: var(--ld-surface) !important;',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body .am-comment-hd :not(a):not([style*="color"]):not([class*="lcolor"]):not(svg):not(path),',
'html body .am-comment-bd :not(a):not([style*="color"]):not([class*="lcolor"]):not(svg):not(path) {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'/* 尾巴:外圈跟随气泡边框(站点蓝),内芯跟随气泡底色 */',
'html body .am-comment-main::before {',
' border-right-color: var(--ld-primary) !important;',
'}',
'html body .am-comment-main::after {',
' border-right-color: var(--ld-surface) !important;',
'}',
'html body:has(.lg-index-content),',
'html body:has(.lg-index-content) .main-container,',
'html body:has(.lg-index-content) main {',
' background-color: var(--ld-surface) !important;',
'}',
'html body:has(.lg-index-content) .lg-article,',
'html body:has(.lg-index-content) .am-panel,',
'html body:has(.lg-index-content) .am-slider,',
'html body:has(.lg-index-content) .am-slider-slide,',
'html body:has(.lg-index-content) .am-slider-desc {',
' background-color: var(--ld-card) !important;',
'}',
'html body:has(.lg-index-content) .am-comment-hd,',
'html body:has(.lg-index-content) .am-comment-bd {',
' background-color: var(--ld-panel) !important;',
'}',
'html body:has(.lg-index-content) input.am-form-field,',
'html body:has(.lg-index-content) .am-form-field,',
'html body:has(.lg-index-content) textarea {',
' background-color: var(--ld-surface) !important;',
' color: ' + PALETTE.fg + ' !important;',
' border-top-color: var(--ld-border) !important;',
' border-right-color: var(--ld-border) !important;',
' border-bottom-color: var(--ld-border) !important;',
' border-left-color: var(--ld-border) !important;',
'}',
'html body:has(.lg-index-content) main :not(a):not(button):not(input):not(textarea):not(select):not([class*="am-btn"]):not([class*="am-panel-"]):not([class*="lg-fg-"]):not([class*="lg-bg-"]) {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'/* SVG 用的是 fill 而非 color,单独处理 */',
'html body:has(.lg-index-content) main svg text,',
'html body:has(.lg-index-content) main text {',
' fill: ' + PALETTE.fg + ' !important;',
'}',
'/* 语义色 .lg-fg-bluedark(rgb(52,73,94) 深蓝,深卡上不可读):保留蓝色相、提亮 */',
'html body:has(.lg-index-content) .lg-fg-bluedark {',
' color: var(--ld-link) !important;',
'}',
'html body .highcharts-tooltip path,',
'html body .highcharts-tooltip > path,',
'html body .highcharts-tooltip path:first-child,',
'html body .highcharts-tooltip path:last-child {',
' fill: var(--ld-surface) !important;',
' stroke: var(--ld-border) !important;',
'}',
'html body .highcharts-tooltip text,',
'html body .highcharts-tooltip tspan {',
' fill: ' + PALETTE.fg + ' !important;',
'}',
'/* 图表自身的网格线 / 轴线:Highcharts 默认是浅灰,深底上刺眼 → 改用 hairline */',
'html body .highcharts-grid-line,',
'html body .highcharts-axis-line,',
'html body .highcharts-tick {',
' stroke: var(--ld-hairline) !important;',
'}',
'html body .highcharts-axis-labels text,',
'html body .highcharts-legend-item text,',
'html body .highcharts-title text,',
'html body .highcharts-subtitle text,',
'html body .highcharts-yaxis-title text,',
'html body .highcharts-xaxis-title text {',
' fill: ' + PALETTE.fg + ' !important;',
'}',
'html body .category-card {',
' /* ★ 不能设 transparent:这几张卡位于页面「云彩背景图」之上,',
' 透明会让亮色背景图透出,白字不可读(实测回归)。给实心深色底。 */',
' background-color: var(--ld-surface) !important;',
' color: ' + PALETTE.fg + ' !important;',
' border-top-color: var(--ld-hairline) !important;',
' border-right-color: var(--ld-hairline) !important;',
' border-bottom-color: var(--ld-hairline) !important;',
' border-left-color: var(--ld-hairline) !important;',
'}',
'html body .category-card.active {',
' background-color: var(--ld-surface-hi) !important;',
' color: ' + PALETTE.fg + ' !important;',
' border-top-color: var(--ld-border) !important;',
' border-right-color: var(--ld-border) !important;',
' border-bottom-color: var(--ld-border) !important;',
' border-left-color: var(--ld-border) !important;',
'}',
'html body .training-card {',
' background-color: var(--ld-surface) !important;',
' border-top-color: var(--ld-hairline) !important;',
' border-right-color: var(--ld-hairline) !important;',
' border-bottom-color: var(--ld-hairline) !important;',
' border-left-color: var(--ld-hairline) !important;',
'}',
'/* ★ 环形进度条的底轨:SVG (.liquid-chart 内,共 18 个)。',
' fill="#fff" 是「呈现属性」,优先级最低,普通 CSS 即可覆盖(无需 !important,仍加上保险)。',
' 改成比卡片底(--ld-surface #2a2a2a)浅一档的 --ld-surface-hi(#333333)。 */',
'html body .liquid-chart circle[fill="#fff"],',
'html body .liquid-chart circle[fill="#FFF"],',
'html body .liquid-chart circle[fill="#ffffff"] {',
' fill: var(--ld-surface-hi) !important;',
'}',
'html body .training-card .card-title,',
'html body .category-card .card-title {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body .training-card .card-desc,',
'html body .category-card .card-desc,',
'html body .training-card span,',
'html body .category-card span {',
' color: var(--ld-fg-muted) !important;',
'}',
'html body main.main h1.title,',
'html body .ticket-banner h1,',
'html body .ticket-banner .title {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'/* 分割线:只改 border-top-color,不动宽度 */',
'html body main.main hr,',
'html body .l-card hr {',
' border-top-color: var(--ld-hairline) !important;',
' border-bottom-color: var(--ld-hairline) !important;',
'}',
'html body .l-card .upload-card {',
' background-color: var(--ld-surface) !important;',
' border-top-color: var(--ld-hairline) !important;',
' border-right-color: var(--ld-hairline) !important;',
' border-bottom-color: var(--ld-hairline) !important;',
' border-left-color: var(--ld-hairline) !important;',
' color: var(--ld-fg-muted) !important;',
'}',
':is(html) body .l-card .btn-actions a.solid:hover,',
':is(html) body .l-card .btn-actions button.solid:hover,',
':is(html) body .l-card .right a.solid.l-button:hover,',
':is(html) body .l-card .right button.solid:hover {',
' background-color: rgba(255, 255, 255, 0.1) !important;',
' color: ' + PALETTE.fg + ' !important;',
' border-color: rgba(255, 255, 255, 0.9) !important;',
'}',
'/* ========== 内联式表单控件 ========== */',
'.l-card .combo-wrapper,',
'.l-card .combo-wrapper.combo,',
'.l-card .combo-wrapper.form-item,',
'.l-card .combo-wrapper.form-item.block-item.combo,',
'.l-card.burger .combo-wrapper.lang-select,',
'.l-card.burger .combo-wrapper.light-black {',
' background-color: var(--ld-surface) !important;',
' border: 1px solid var(--ld-border) !important;',
' color: var(--ld-fg) !important;',
'}',
'.l-card .combo-wrapper .text, .l-card .combo-wrapper .text *:not([class*="lcolor"]):not([style*="color"]),',
'.l-card .combo-wrapper input, .l-card .combo-wrapper input[type="text"],',
'.l-card .combo-wrapper .text input,',
'.l-card.burger .combo-wrapper .text {',
' background-color: transparent !important;',
' color: var(--ld-fg) !important;',
' border-style: none !important;',
' box-shadow: none !important;',
'}',
'.l-card .combo-wrapper .placeholder, .l-card input.search-text::placeholder,',
'.l-card .refined-input input::placeholder { color: var(--ld-fg-faint) !important; }',
'.l-card .combo-wrapper .arrow svg,',
'.l-card .refined-input .east, .l-card .refined-input .search-icon,',
'.l-card .refined-input .west, .l-card .refined-input .west svg { color: var(--ld-fg-soft) !important; }',
'.l-card .combo-wrapper .ruler { background-color: transparent !important; border-color: var(--ld-border) !important; }',
'/* 关键词 / 搜索框:外层浅底 + 内层完全透明,避免深色圆角套娃 */',
'.l-card .refined-input, .l-card .refined-input.search-text {',
' background: rgba(255, 255, 255, 0.06) !important;',
' border: 1px solid var(--ld-hairline) !important;',
' border-radius: 4px !important;',
' box-shadow: none !important;',
' color: var(--ld-fg) !important;',
'}',
'.l-card .refined-input > *, .l-card .refined-input * { background: transparent !important; }',
'.l-card .refined-input input, .l-card .refined-input input.search-text,',
'.l-card input.search-text, .l-card input.scoreboard-search,',
'.l-card .refined-input.scoreboard-search input,',
'.l-card input[placeholder*="UID"], .l-card input[placeholder*="用户名"],',
'.l-card input[placeholder*="关键词"], .l-card input[placeholder*="搜索"],',
'.l-card .tag-select-area .search-box input {',
' background: transparent !important;',
' border: none !important;',
' border-radius: 0 !important;',
' box-shadow: none !important;',
' outline: none !important;',
' color: var(--ld-fg) !important;',
'}',
'.l-card .refined-input.scoreboard-search {',
' background: rgba(255, 255, 255, 0.06) !important;',
' border: 1px solid var(--ld-hairline) !important;',
' border-radius: 4px !important;',
' box-shadow: none !important;',
'}',
'.l-card input[placeholder*="UID"]::placeholder,',
'.l-card input[placeholder*="用户名"]::placeholder,',
'.l-card input[placeholder*="关键词"]::placeholder,',
'.l-card input[placeholder*="搜索"]::placeholder,',
'.l-card .refined-input.scoreboard-search input::placeholder { color: var(--ld-fg-muted) !important; }',
'.l-card button.tag-button:not(.selected), .l-card .toggle-tag:not(.selected),',
'.l-card .tag-select-area .toggle-tag:not(.selected) {',
' background-color: var(--ld-surface) !important;',
' background-image: none !important;',
' border-color: var(--ld-border) !important;',
' border-style: solid !important;',
' border-width: 1px !important;',
' color: var(--ld-fg-soft) !important;',
'}',
'.l-card button.tag-button:not(.selected):hover, .l-card .toggle-tag:not(.selected):hover {',
' background-color: var(--ld-surface-hi) !important;',
' border-color: var(--ld-border-hi) !important;',
' color: var(--ld-fg) !important;',
'}',
'/* 已选中的语义色 chip:不给它换色,悬浮只整体压暗一档(保留色相) */',
'.l-card .toggle-tag.selected:hover { filter: brightness(0.9) !important; }',
':is(html) body .l-card .tag:not(:has(*)):not([style*="background-color"]):hover,',
':is(html) body .l-card [class*="tag"]:not(:has(*)):not([style*="background-color"]):hover,',
':is(html) body .l-card button.tag-button:not(.selected):hover,',
':is(html) body .l-card .toggle-tag:not(.selected):hover {',
' background-color: var(--ld-panel) !important;',
' color: ' + PALETTE.fg + ' !important;',
'}',
':is(html) body .l-card .tag[style*="background-color"]:not(:has(*)):hover,',
':is(html) body .l-card .tag[style*="background-color"]:not(:has(*)):active,',
':is(html) body .l-card [class*="tag"][style*="background-color"]:not(:has(*)):hover,',
':is(html) body .l-card [class*="tag"][style*="background-color"]:not(:has(*)):active {',
' filter: brightness(0.85) !important;',
'}',
'.l-card .search-option label, .l-card .search-option svg { color: var(--ld-fg-soft) !important; }',
'.l-card .tag-select-area .title { color: var(--ld-fg-heading) !important; }',
'.l-card .lfe-marked h1, .l-card .lfe-marked h2, .l-card .lfe-marked h3 { color: var(--ld-fg-heading) !important; }',
'.l-card .lfe-marked blockquote {',
' /* ★ 卡片 alpha × 70%,半透明略深,不是死黑实色 */',
' background: var(--ld-quote) !important;',
' border-left: 4px solid rgba(255, 255, 255, 0.2) !important;',
' color: var(--ld-fg-soft) !important;',
' padding: 0.5em 1em !important;',
' margin: 1em 0 !important;',
'}'
].join('\n'));
/* ---------- 4.8 页内 tab / 菜单 ------------------------------------------- */
CSS_PARTS.push([
'/* ========== 页内 tab / 菜单 ========== */',
'.l-card .menu .entry, .l-card .menu .items li .entry,',
'.l-card .rank-tabs a, .l-card .rank-tabs span { color: var(--ld-fg-soft) !important; }',
'.l-card .menu .entry.selected, .l-card .menu .items li .entry.selected,',
'.l-card .rank-tabs a.active, .l-card .rank-tabs .selected,',
'.l-card .scoreboard-header nav li.selected { color: var(--ld-primary) !important; }'
].join('\n'));
/* ---------- 4.9 浮层:下拉 / Popper / 弹窗 -------------------------------- */
CSS_PARTS.push([
'/* =========================================================',
' ★★★ 下拉框、语言切换等浮层:必须用不透明底色,',
' 半透明会让下面的正文透上来,可读性直接崩掉',
' ========================================================= */',
'html ' + SEL_POPOVER + ' {',
' /* ★ 只用 background-color 长写:background 简写会重置 background-image,',
' 把 popover 里的封面图(内联 background-image)一并清成 none。 */',
' background-color: var(--ld-surface) !important;',
' border: 1px solid var(--ld-border) !important;',
' border-radius: 4px !important;',
' box-shadow: 0 4px 12px var(--ld-shadow-deep) !important;',
' color: var(--ld-code) !important;',
'}',
'html body [class*="lang-select"], html body [class*="language-select"],',
'html body .l-card.burger .combo-wrapper.lang-select,',
'html body .dropdown.shown:has(.dropdown-operations) {',
' /* ★ 同样改长写,避免简写重置 background-image(同类隐患统一处理) */',
' background-color: var(--ld-code-bg) !important;',
'}',
'html body .dropdown ul, html body .v-popper__popper ul,',
'html body .v-popper__inner ul, html body .v-popper--theme-dropdown ul,',
'html body [class*="lang-select"] ul, html body [class*="dropdown"] ul,',
'html body .lfe-dropdown ul { background: transparent !important; }',
'html body .dropdown li, html body .dropdown a, html body .dropdown div,',
'html body .v-popper__popper li, html body .v-popper__popper a, html body .v-popper__popper div,',
'html body .v-popper__inner li, html body .v-popper__inner a, html body .v-popper__inner div,',
'html body .v-popper--theme-dropdown li, html body .v-popper--theme-dropdown a,',
'html body .v-popper--theme-dropdown div,',
'html body [class*="lang-select"] li, html body [class*="lang-select"] a,',
'html body [class*="dropdown"] li, html body [class*="dropdown"] a,',
'html body .lfe-dropdown li, html body .lfe-dropdown a {',
' color: ' + PALETTE.code + ' !important;',
' /* ★ 长写:简写 background 会把 popover 内 div 的 background-image 清成 none */',
' background-color: transparent !important;',
'}',
'html body .dropdown li:hover, html body .dropdown a:hover,',
'html body .v-popper__popper li:hover, html body .v-popper__popper a:hover,',
'html body .v-popper__inner li:hover, html body .v-popper__inner a:hover,',
'html body .v-popper--theme-dropdown li:hover, html body .v-popper--theme-dropdown a:hover,',
'html body [class*="lang-select"] li:hover,',
'html body [class*="dropdown"] li:hover, html body [class*="dropdown"] a:hover,',
'html body .lfe-dropdown li:hover, html body .lfe-dropdown a:hover {',
' background-color: #3a3a3a !important;',
' color: var(--ld-fg) !important;',
'}',
'html body .v-popper__arrow-container .v-popper__arrow-inner,',
'html body .v-popper__arrow-container .v-popper__arrow-outer {',
' border-color: var(--ld-surface) !important;',
' background: var(--ld-surface) !important;',
'}',
'.swal2-popup:not(:has(.swal2-image)),',
'.swal2-popup.swal2-toast,',
'.swal2-popup:has(.swal2-title):not([style*="transparent"]) {',
' background-color: var(--ld-surface-deep) !important;',
' color: var(--ld-fg) !important;',
' border: 1px solid rgba(255, 255, 255, 0.1) !important;',
' box-shadow: 0 4px 20px var(--ld-shadow-deep) !important;',
'}',
'.swal2-title { color: var(--ld-fg) !important; }',
'.swal2-html-container { color: ' + PALETTE.code + ' !important; }',
'.swal2-success-circular-line-left, .swal2-success-circular-line-right,',
'.swal2-success-fix { background-color: var(--ld-surface-deep) !important; }',
'.swal2-icon.swal2-success { border-color: var(--ld-success) !important; color: var(--ld-success) !important; }',
'.swal2-icon.swal2-success [class^=swal2-success-line] { background-color: var(--ld-success) !important; }',
'.swal2-icon.swal2-success .swal2-success-ring { border: 4px solid rgba(165, 220, 134, 0.3) !important; }',
'.swal2-styled.swal2-confirm { background-color: var(--ld-primary) !important; }',
'.swal2-styled.swal2-cancel { background-color: var(--ld-surface-hi) !important; color: var(--ld-fg) !important; }',
'/* 通用模态框 / 遮罩 */',
'.lfe-modal .lfe-modal-body, .lfe-modal .lfe-modal-content, .lfe-dialog,',
'.modal .modal-content, .modal-content, .popup-content {',
' background: var(--ld-surface) !important;',
' color: var(--ld-fg) !important;',
' border: 1px solid var(--ld-hairline) !important;',
'}',
'.lfe-modal .lfe-modal-header, .lfe-modal .lfe-modal-footer {',
' background: transparent !important;',
' border-color: var(--ld-hairline) !important;',
' color: var(--ld-fg) !important;',
'}'
].join('\n'));
/* ---------- 4.10 页脚、列表、分页、进度 ---------------------------------- */
CSS_PARTS.push([
'/* ========== 页脚链接悬停 ========== */',
'footer a:hover { color: var(--ld-link-hover) !important; }',
'/* ========== 列表 / 表格骨架 ========== */',
'.l-card .list-wrap, .l-card .list-wrap.table, .l-card .list-wrap.table.border,',
'.l-card .table, .l-card .table.border {',
' background: transparent !important;',
' border-color: var(--ld-hairline) !important;',
'}',
'.l-card .list .header-wrap, .l-card .list .header,',
'.l-card .list-wrap .header-wrap, .l-card .list-wrap .header,',
'.l-card .table .header-wrap, .l-card .table .header {',
' background: transparent !important;',
' border: none !important;',
' box-shadow: none !important;',
'}',
'.l-card .header-container, .l-card .header-container .sortable,',
'.l-card .header-container span, .l-card .table .header-container .sortable { color: var(--ld-fg-soft) !important; }',
'.l-card .table .header-container .lfe-caption { color: var(--ld-fg-muted) !important; }',
'.l-card .list-wrap .row-wrap, .l-card .list-wrap .row,',
'.l-card .table .row-wrap, .l-card .table .row {',
' background: transparent !important;',
' border-color: var(--ld-hairline-soft) !important;',
'}',
'/* ★ 行 hover 不再在这里统一给背景:表格页保留,列表页完全交给站点原生悬停 */',
'.l-card .table .row:hover { background: rgba(255, 255, 255, 0.06) !important; }',
'/* ★ .list-wrap:not(.table):记录列表容器是 `.list-wrap.table`(同时带两个类),',
' 若不加 :not(.table),这条透明规则会以「同特异性、源码更靠后」压掉上面',
' `.l-card .table .row:hover` 的浅色高亮,导致评测记录行 hover 时背景变空。 */',
'.l-card .list-wrap:not(.table) .row:hover,',
'.l-card.solution-list .row:hover, .l-card.solution-list .row-wrap:hover,',
'.l-card .solution-list .row:hover, .l-card .solution-list .row-wrap:hover {',
' background: transparent !important;',
' background-color: transparent !important;',
'}',
'.l-card .row .pid, .l-card .table .row .rank, .l-card .table .row .user,',
'.l-card .table .row .total { color: var(--ld-fg-soft) !important; }',
'.l-card .table .row [class*="time"], .l-card .table .row .light-text,',
'.l-card .table .row .secondary, .l-card .table .row .total .td-runtime { color: var(--ld-fg-muted) !important; }',
'/* ★ 分数 span 必须排除语义色类 .lcolor--*:站点用 .lcolor--green-3 / red-3 / orange-3',
' 给分数上 AC/WA 语义色,被这条白字规则命中就全变白(丢失绿/红语义)。',
' 收窄后站点自己的 .lcolor--* 规则自然生效 —— 零硬编码,站点换色自动跟随。',
' 容器(.status / .score / .full-score / .total .td-score)不排除,保持 var(--ld-fg)。 */',
'.l-card .table .row .status, .l-card .table .row .status span:not([class*="lcolor"]),',
'.l-card .table .row .score:not([class*="lcolor"]), .l-card .table .row .score span:not([class*="lcolor"]),',
'.l-card .table .row .full-score, .l-card .table .row .full-score *,',
'.l-card .table .row [class*="full-score"],',
'.l-card .table .row .total .td-score { color: var(--ld-fg) !important; }',
'/* ========== 进度框 ========== */',
'.l-card .progress-frame {',
' background: rgba(0, 0, 0, 0.5) !important;',
' border: 1px solid rgba(255, 255, 255, 0.25) !important;',
' box-shadow: none !important;',
' box-sizing: border-box !important;',
' padding: 0 !important;',
'}',
'.l-card .progress-frame > .square { border: none !important; margin: 0 !important; }',
'/* ========== 底部工具条 / 分页 ========== */',
'.l-card .bottom-wrap, .l-card .toolbar {',
' background: transparent !important;',
' border-color: var(--ld-hairline) !important;',
'}',
'.l-card .bottom-wrap.float {',
' background: #383838 !important;',
' border-top: 1px solid rgba(255, 255, 255, 0.1) !important;',
' box-shadow: 0 -4px 12px rgba(0, 0, 0, 0.35) !important;',
'}',
'.l-card .toolbar .btn-checkbox { color: var(--ld-link) !important; }',
'.l-card .page-bar .total strong { color: var(--ld-fg) !important; }',
'.l-card .page-bar button {',
' background: transparent !important;',
' border: 1px solid rgba(255, 255, 255, 0.15) !important;',
' color: var(--ld-fg-soft) !important;',
'}',
'.l-card .page-bar button:hover { border-color: rgba(255, 255, 255, 0.4) !important; color: var(--ld-fg) !important; }',
'.l-card .page-bar button.selected {',
' background: var(--ld-primary) !important;',
' border-color: var(--ld-primary) !important;',
' color: var(--ld-fg) !important;',
'}',
'.l-card .selected-tags .lfe-caption { color: var(--ld-fg-muted) !important; }'
].join('\n'));
/* ---------- 4.10b 比赛列表页(contest/list)------------------------------ */
CSS_PARTS.push([
'/* =========================================================',
' 比赛列表页(原脚本没覆盖这块)',
' ========================================================= */',
'/* ★ 结果计数 .filter-result-count .number 是站点内联色 rgba(0,0,0,0.75)',
' (黑字配白底),在深色卡上几乎不可见,纠正为跟随卡片文字色。',
' 只改计数本身,不动旁边作者名的等级色。 */',
'.l-card .filter-result-count,',
'.l-card .filter-result-count .number,',
'.l-card .result .count .number,',
'.l-card .row .number, .l-card .list-wrap .row .number {',
' color: var(--ld-fg-soft) !important;',
'}',
'.l-card .filter-result-count a, .l-card .filter-result-count strong {',
' color: var(--ld-fg) !important;',
'}',
'.l-card .row .name, .l-card .list-wrap .row .name,',
'.l-card .row .provider-display, .l-card .list-wrap .row .provider-display,',
'.l-card .row .provider, .l-card .list-wrap .row .provider {',
' color: var(--ld-fg-soft) !important;',
'}',
'.l-card .row .icon-status:not([style*="color"]),',
'.l-card .list-wrap .row .icon-status:not([style*="color"]) {',
' color: var(--ld-fg-muted) !important;',
'}',
'/* 比赛类型标签保留站点本身的色底,只保证文字可读 */',
'.l-card .row .tag, .l-card .list-wrap .row .tag { color: var(--ld-fg) !important; }',
'/* ★★★ 比赛列表页的筛选卡片(.l-card.filter-card):',
' 未选中态原来是 rgb(87,87,87) + 透明底,在深色卡上对比度 1.02,整排隐形。',
' 现在改成与「题目列表页 主题库/洛谷/CF/AT 选项卡」同一套设计:',
' 未选中 = 主题蓝文字 + 主题蓝边框 + 透明底 + 3px 圆角 + 1px 8px 内边距;',
' 选中 = 主题蓝实底 + 白字。站点样式带 data-v-* 作用域,所以用 html body 压特异性。 */',
'html body .l-card.filter-card button.option,',
'html body .l-card.filter-card .l-options button.option,',
'html body .l-card.filter-card button[class~="option"],',
'html body .l-card button.option {',
' background: transparent !important;',
' background-color: transparent !important;',
' border: none !important;',
' /* ★ 未选中字色对齐题目列表页:白字(原为 var(--ld-primary) 蓝字) */',
' color: ' + PALETTE.fg + ' !important;',
' border-radius: 3px !important;',
' padding: 1px 8px !important;',
' /* 与题目列表「主题库/洛谷/CF/AT」选项卡逐项对齐。',
' 注意 display 不设:contest 的父级 .l-options 是 flex,flex 子项必然 blockify,',
' 覆盖 display 也无效,且会造成两页无意义的差异。 */',
' font-size: 16px !important;',
' font-weight: 400 !important;',
' line-height: 24px !important;',
' margin: 0 8px 0 0 !important;',
' cursor: pointer !important;',
' transition: 0.3s !important;',
'}',
'html body .l-card.filter-card button.option:hover,',
'html body .l-card button.option:hover {',
' /* ★ hover:极淡白底,不加边框、不改字色(字已是白色) */',
' background: rgba(255, 255, 255, 0.12) !important;',
' background-color: rgba(255, 255, 255, 0.12) !important;',
' border: none !important;',
' color: ' + PALETTE.fg + ' !important;',
' cursor: pointer !important;',
'}',
'/* 选中态:主题蓝实底 + 白字(与题目列表选项卡一致,无边框、cursor default) */',
'html body .l-card.filter-card button.option.active,',
'html body .l-card.filter-card button.option.selected,',
'html body .l-card button.option.active,',
'html body .l-card button.option.selected {',
' background: var(--ld-primary) !important;',
' background-color: var(--ld-primary) !important;',
' border: none !important;',
' color: ' + PALETTE.fg + ' !important;',
' cursor: default !important;',
'}',
'/* 卡片内部的 .row 子容器(.title-row / .left.row / .right.row / .info-row)始终保持透明 */',
'html body .l-card .row .row:hover,',
'html body .l-card .row .row,',
'html body .l-card [class*="title-row"]:hover,',
'html body .l-card [class*="info-row"]:hover {',
' background: transparent !important;',
' background-color: transparent !important;',
'}',
'html body .l-card .row .name:hover, html body .l-card .row .title:hover,',
'html body .l-card .row time:hover, html body .l-card .row .time:hover,',
'html body .l-card .row [class*="time"]:hover,',
'html body .l-card .row .provider-display:hover,',
'html body .l-card .row a:not(.l-button):not(.solid):not([class*="button"]):not([style*="background-color"]):hover,',
'html body .l-card .row span:not(.l-button):not(.solid):not([class*="button"]):not([style*="background-color"]):hover,',
'html body .l-card .list-wrap .row .name:hover,',
'html body .l-card .list-wrap .row [class*="time"]:hover,',
'html body .l-card .list-wrap .row a:not(.l-button):not(.solid):not([class*="button"]):not([style*="background-color"]):hover {',
' background: transparent !important;',
' background-color: transparent !important;',
' box-shadow: none !important;',
'}',
'/* 子元素自身的底色也清掉,避免出现「框里还有框」 */',
'html body .l-card .row .name, html body .l-card .row .title,',
'html body .l-card .row time, html body .l-card .row [class*="time"],',
'html body .l-card .list-wrap .row .name, html body .l-card .list-wrap .row [class*="time"] {',
' background: transparent !important;',
' background-color: transparent !important;',
'}',
'/* 筛选卡的标签文字(比赛分类 / 比赛赛制) */',
'html body .l-card.filter-card .filter-label, html body .l-card.filter .filter-label {',
' color: var(--ld-fg-muted) !important;',
'}',
'/* 筛选卡里可能出现的下拉框 / 复选项也一并跟随 */',
'html body .l-card.filter-card .combo-wrapper { background: ' + PALETTE.surface + ' !important; }',
'/* 列表头 / 分页 / 筛选沿用统一骨架,这里只补比赛页特有的容器 */',
'.l-card .row .name a, .l-card .list-wrap .row .name a { color: var(--ld-link) !important; }',
'.l-card .row .name a:hover, .l-card .list-wrap .row .name a:hover { color: var(--ld-link-hover) !important; }'
].join('\n'));
/* ---------- 4.11 题目列表页 ---------------------------------------------- */
CSS_PARTS.push([
'/* =========================================================',
' 题目列表页',
' ========================================================= */',
'.l-card section .title { color: var(--ld-fg-heading) !important; }',
'.l-card .block-item.category ul,',
'.l-card .block-item.category ul.luogu,',
'.l-card .block-item.category ul.rmj {',
' background: transparent !important;',
' border: none !important;',
' box-shadow: none !important;',
' padding: 0 !important;',
'}',
'.l-card .block-item.category ul li {',
' background: transparent !important;',
' border: none !important;',
' color: var(--ld-fg) !important;',
' opacity: 1 !important;',
'}',
'.l-card .block-item.category ul li:hover {',
' background: rgba(255, 255, 255, 0.1) !important;',
' color: var(--ld-fg) !important;',
'}',
'.l-card .block-item.category ul li.selected {',
' background: var(--ld-primary) !important;',
' color: var(--ld-fg) !important;',
' opacity: 1 !important;',
' border-radius: 3px !important;',
'}',
'.l-card .result .count .number { color: var(--ld-fg) !important; font-weight: bold !important; }',
'/* ★ 最优解高亮:只对带 green-1 背景的 .problem 生效 */',
'.l-card .table .row .problem[style*="green-1"],',
'.l-card .table .row [style*="--lfe-color--green-1"] {',
' background-color: rgba(83, 196, 26, 0.12) !important;',
'}',
'/* 当前用户高亮的纠偏放在常驻样式表里(见 CSS_FIXES),关闭深色后也要生效 */'
].join('\n'));
/* ---------- 4.12 题解页 ------------------------------------------------- */
CSS_PARTS.push([
'/* =========================================================',
' 题解页面',
' ========================================================= */',
'/* ★ 取消鼠标悬停在题解上的整个文本框亮起效果(规则已在 4.10 统一定义,此处不重复) */',
'.l-card.solution-list .header nav ul li { color: var(--ld-fg-soft) !important; }',
'.l-card.solution-list .header nav ul li.selected { color: var(--ld-primary) !important; }',
'.l-card.solution-list .header b { color: var(--ld-fg) !important; }',
'.l-card.solution-list .lfe-caption, .l-card.solution-list .lfe-caption time { color: var(--ld-fg-muted) !important; }',
'/* ★ 题解底部吸附操作栏 */',
'.l-card .float.operations {',
' background: var(--ld-surface-deep) !important;',
' border-top: 1px solid rgba(255, 255, 255, 0.15) !important;',
' box-shadow: 0 -4px 12px var(--ld-shadow-deep) !important;',
' padding: 10px 16px !important;',
' z-index: 100 !important;',
'}',
'.l-card .float.operations .button { color: var(--ld-fg-soft) !important; fill: var(--ld-fg-soft) !important; }',
'.l-card .float.operations .button:hover { color: var(--ld-fg) !important; fill: var(--ld-fg) !important; }',
'.l-card .float.operations .thumb-up.active,',
'.l-card .float.operations .thumb-up.voted,',
'.l-card .float.operations .thumb-up.enable,',
'.l-card .operations .thumb-up.active, .l-card .operations .thumb-up.voted,',
'.l-card .operations .thumb-up.enable { color: var(--ld-primary) !important; fill: var(--ld-primary) !important; }',
'.l-card .float.operations .thumb-up.active:hover,',
'.l-card .float.operations .thumb-up.voted:hover,',
'.l-card .float.operations .thumb-up.enable:hover { color: var(--ld-primary-soft) !important; fill: var(--ld-primary-soft) !important; }',
'/* ★ 题解 / 文章正文:文字全部白色。',
' 注意实际类名是 .lfe-marked-wrap,不能只写 .lfe-marked;',
' :not([style*="color"]) 用来放行用户名/等级标识的内联色。 */',
'.l-card .lfe-marked, .l-card .lfe-marked-wrap, .l-card .marked,',
'.l-card .lfe-marked p, .l-card .lfe-marked-wrap p, .l-card .marked p,',
'.l-card .lfe-marked li, .l-card .lfe-marked-wrap li, .l-card .marked li,',
'.l-card .lfe-marked strong, .l-card .lfe-marked-wrap strong,',
'.l-card .lfe-marked em, .l-card .lfe-marked-wrap em,',
'.l-card .lfe-marked td, .l-card .lfe-marked-wrap td,',
'.l-card .lfe-marked th, .l-card .lfe-marked-wrap th,',
'.l-card .lfe-marked h1, .l-card .lfe-marked h2, .l-card .lfe-marked h3,',
'.l-card .lfe-marked h4, .l-card .lfe-marked h5, .l-card .lfe-marked h6,',
'.l-card .lfe-marked-wrap h1, .l-card .lfe-marked-wrap h2, .l-card .lfe-marked-wrap h3,',
'.l-card .solution-article, .l-card .article-content, .l-card .markdown-body {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body main.main > div:not([class]):has(> .article-content) {',
' background-color: var(--ld-card) !important;',
'}',
'/* =========================================================',
' 文章页(/article/*)专项:这些元素全都在 .l-card 之外,',
' 所以脚本里那批 `.l-card …` 规则一律够不着,必须用 main.main 作用域。',
' ========================================================= */',
'/* ① 文章页不可读文字 → 浅色(实测均为站点浅色主题的深字) */',
'html body main.main .article-banner h1.title {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body main.main .article-banner .label {',
' color: var(--ld-fg-muted) !important;',
'}',
'html body main.main .article-banner .label + * {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body main.main .article-comment h3.lfe-h3.section-title,',
'html body main.main .article-comment h4.lfe-h4 {',
' color: ' + PALETTE.fg + ' !important;',
'}',
'html body main.main .comment-filter-line > span {',
' color: var(--ld-fg-muted) !important;',
'}',
'html body main.main .article-content .actions {',
' background-color: transparent !important;',
'}',
'html body .l-card.reply-item .meta {',
' background-color: var(--ld-panel) !important;',
'}',
'/* ★ 评论/回复里的「回复于 xxx」时间文字:站点原值 rgba(0,0,0,0.5)(浅色主题的',
' 半透明黑),落在深色底上几乎不可见,而脚本从未覆盖它。',
' 用 .time 类(不是 time 标签)统一修 —— 横幅里「发布时间」的值是裸