Add theme options and timed agent dividers

This commit is contained in:
shiyue
2026-06-14 12:16:37 +08:00
parent 382c5accb7
commit 3a4006b7d3
6 changed files with 883 additions and 19 deletions

View File

@@ -21,6 +21,14 @@ Keep this managed block so 'trellis update' can refresh the instructions.
<!-- TRELLIS:END -->
## 常用运维命令
重启 cc-web 服务:
```bash
pm2 restart ccweb --update-env
```
## Codex App / hapi 对齐经验
以下约定来自本项目对 `/home/hdzx/2026/hapi` 中 Codex app-server 接入方式的对比结果。后续如果继续维护 `codexapp`,默认按这些约定实现,避免再走偏到“看起来能跑、但拿不到原生协作能力”的分叉路径。

View File

@@ -256,6 +256,26 @@ function createAgentRuntime(deps) {
return JSON.stringify(truncateObj(item, 1200));
}
function formatAgentMessageDividerTime(date = new Date()) {
const pad = (value) => String(value).padStart(2, '0');
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
}
function createAgentMessageDivider() {
const time = formatAgentMessageDividerTime();
return `<div class="agent-message-divider" data-divider-time="${time}"><span>${time}</span></div>`;
}
function hasAgentMessageBoundaryAtEnd(text) {
return /\n\s*(?:---|\*\*\*|___)\s*$/.test(text)
|| /(?:^|\n)\s*<div\s+class=["']agent-message-divider["'][\s\S]*?<\/div>\s*$/.test(text);
}
function hasAgentMessageBoundaryAtStart(text) {
return /^\s*(?:---|\*\*\*|___)\s*\n/.test(text)
|| /^\s*<div\s+class=["']agent-message-divider["'][\s\S]*?<\/div>\s*/.test(text);
}
function sendRuntime(entry, sessionId, payload) {
wsSend(entry.ws, { ...payload, sessionId });
}
@@ -266,9 +286,9 @@ function createAgentRuntime(deps) {
const currentText = entry.fullText || '';
const hasExistingText = /\S/.test(currentText);
const hasVisualBoundary = /\n\s*(?:---|\*\*\*|___)\s*$/.test(currentText) || /^\s*(?:---|\*\*\*|___)\s*\n/.test(nextText);
const hasVisualBoundary = hasAgentMessageBoundaryAtEnd(currentText) || hasAgentMessageBoundaryAtStart(nextText);
const separator = hasExistingText && !hasVisualBoundary
? (/\n\s*$/.test(currentText) ? '\n---\n\n' : '\n\n---\n\n')
? (/\n\s*$/.test(currentText) ? `\n${createAgentMessageDivider()}\n\n` : `\n\n${createAgentMessageDivider()}\n\n`)
: '';
const chunk = separator + nextText;
entry.fullText += chunk;

View File

@@ -18,6 +18,26 @@ function createCodexAppRuntime(deps = {}) {
wsSend(entry.ws, { ...payload, sessionId });
}
function formatAgentMessageDividerTime(date = new Date()) {
const pad = (value) => String(value).padStart(2, '0');
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
}
function createAgentMessageDivider() {
const time = formatAgentMessageDividerTime();
return `<div class="agent-message-divider" data-divider-time="${time}"><span>${time}</span></div>`;
}
function hasAgentMessageBoundaryAtEnd(text) {
return /\n\s*(?:---|\*\*\*|___)\s*$/.test(text)
|| /(?:^|\n)\s*<div\s+class=["']agent-message-divider["'][\s\S]*?<\/div>\s*$/.test(text);
}
function hasAgentMessageBoundaryAtStart(text) {
return /^\s*(?:---|\*\*\*|___)\s*\n/.test(text)
|| /^\s*<div\s+class=["']agent-message-divider["'][\s\S]*?<\/div>\s*/.test(text);
}
function itemKind(item) {
switch (item?.type) {
case 'commandExecution':
@@ -263,8 +283,8 @@ function createCodexAppRuntime(deps = {}) {
if (entry.agentMessageItems?.get(itemId)) return '';
const currentText = entry.fullText || '';
if (!/\S/.test(currentText)) return '';
const hasVisualBoundary = /\n\s*(?:---|\*\*\*|___)\s*$/.test(currentText) || /^\s*(?:---|\*\*\*|___)\s*\n/.test(String(nextText || ''));
return hasVisualBoundary ? '' : '\n\n---\n\n';
const hasVisualBoundary = hasAgentMessageBoundaryAtEnd(currentText) || hasAgentMessageBoundaryAtStart(String(nextText || ''));
return hasVisualBoundary ? '' : `\n\n${createAgentMessageDivider()}\n\n`;
}
function updateToolResult(entry, sessionId, itemId, result, done = false, patch = {}) {

View File

@@ -2,10 +2,11 @@
(function () {
'use strict';
const ASSET_VERSION = '20260613-codexapp-tools2';
const ASSET_VERSION = '20260614-divider-time-selectfix';
const WS_URL = `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/ws`;
const RENDER_DEBOUNCE = 100;
const COMPOSER_SUGGESTION_DEBOUNCE = 120;
const DIVIDER_TIME_STORAGE_KEY = 'cc-web-show-divider-time';
const SLASH_COMMANDS = [
{ cmd: '/clear', desc: '清除当前会话' },
@@ -73,6 +74,42 @@
desc: '更明亮的留白和更克制的棕色强调,像编辑台一样安静。',
swatches: ['#f6f1e8', '#efe8dc', '#8b5e3c', '#2f4b45'],
},
{
value: 'sage',
label: 'Sage Console',
desc: '清透鼠尾草绿与石墨文字,适合长时间工作流。',
swatches: ['#f5f8f2', '#e6efdf', '#2f6f64', '#557ba3'],
},
{
value: 'ink',
label: 'Ink Focus',
desc: '浅灰纸面配靛蓝重点,信息密度更高也更冷静。',
swatches: ['#f6f7fb', '#e8edf5', '#3f5fb5', '#3f8f73'],
},
{
value: 'dawn',
label: 'Dawn Studio',
desc: '晨光米白配珊瑚红,保留温度但比暖纸更轻。',
swatches: ['#fff7f2', '#f3e8e1', '#b5524d', '#4f8a6b'],
},
{
value: 'carbon',
label: 'Carbon Mint',
desc: '石墨黑底配薄荷绿重点,夜间使用更稳。',
swatches: ['#0f1314', '#202829', '#67d8b2', '#9fb7ff'],
},
{
value: 'nocturne',
label: 'Nocturne Teal',
desc: '深海青黑配电光蓝,适合高专注会话。',
swatches: ['#081417', '#142b31', '#5ecdf5', '#f0c36a'],
},
{
value: 'cinder',
label: 'Cinder Rose',
desc: '炭黑底配低饱和玫瑰色,暗色里保留一点温度。',
swatches: ['#151112', '#2a2022', '#e68193', '#67c587'],
},
];
// --- State ---
@@ -98,6 +135,7 @@
let currentModel = 'opus';
let currentAgent = AGENT_LABELS[localStorage.getItem('cc-web-agent')] ? localStorage.getItem('cc-web-agent') : DEFAULT_AGENT;
let currentTheme = (document.documentElement.dataset.theme || localStorage.getItem('cc-web-theme') || 'washi');
let showAgentDividerTime = localStorage.getItem(DIVIDER_TIME_STORAGE_KEY) !== '0';
let codexConfigCache = null;
let loadedHistorySessionId = null;
let activeSessionLoad = null;
@@ -123,6 +161,7 @@
let noteDraftSeq = 0;
const pendingNotesByTarget = new Map();
const userMessageIndex = new Map();
document.documentElement.dataset.dividerTime = showAgentDividerTime ? 'show' : 'hide';
// --- DOM ---
const $ = (sel) => document.querySelector(sel);
@@ -447,6 +486,26 @@
refreshThemeSummaries();
}
function getDividerTimeSummary() {
return showAgentDividerTime ? '显示时间' : '不显示时间';
}
function refreshDividerTimeControls(root = document) {
root.querySelectorAll('[data-divider-time-summary]').forEach((node) => {
node.textContent = getDividerTimeSummary();
});
root.querySelectorAll('[data-divider-time-toggle]').forEach((node) => {
node.checked = showAgentDividerTime;
});
}
function applyDividerTimePreference(visible) {
showAgentDividerTime = !!visible;
document.documentElement.dataset.dividerTime = showAgentDividerTime ? 'show' : 'hide';
localStorage.setItem(DIVIDER_TIME_STORAGE_KEY, showAgentDividerTime ? '1' : '0');
refreshDividerTimeControls();
}
function buildThemePickerHtml(options = {}) {
const { showSectionTitle = true } = options;
return `
@@ -476,7 +535,7 @@
});
}
function buildThemeEntryHtml() {
function buildAppearanceSettingsHtml() {
return `
<div class="settings-section-title">外观</div>
<button class="settings-nav-card" type="button" data-open-theme-page>
@@ -486,9 +545,34 @@
</span>
<span class="settings-nav-card-arrow" aria-hidden="true"></span>
</button>
<label class="settings-toggle-row">
<span class="settings-toggle-copy">
<span class="settings-toggle-title">分隔线时间</span>
<span class="settings-toggle-meta">当前:<span data-divider-time-summary>${escapeHtml(getDividerTimeSummary())}</span></span>
</span>
<span class="settings-switch">
<input type="checkbox" data-divider-time-toggle ${showAgentDividerTime ? 'checked' : ''}>
<span class="settings-switch-track" aria-hidden="true">
<span class="settings-switch-thumb"></span>
</span>
</span>
</label>
`;
}
function mountAppearanceSettings(panel) {
const themePageBtn = panel.querySelector('[data-open-theme-page]');
if (themePageBtn) themePageBtn.addEventListener('click', openThemeSubpage);
const dividerTimeToggle = panel.querySelector('[data-divider-time-toggle]');
if (dividerTimeToggle) {
dividerTimeToggle.checked = showAgentDividerTime;
dividerTimeToggle.addEventListener('change', () => {
applyDividerTimePreference(dividerTimeToggle.checked);
});
}
refreshDividerTimeControls(panel);
}
function buildNotifyEntryHtml(config) {
const provider = config?.provider || 'off';
const providerLabel = PROVIDER_OPTIONS.find(o => o.value === provider)?.label || '关闭';
@@ -4319,7 +4403,7 @@
${title}
<div style="font-size:0.9em;color:var(--text-primary);margin-bottom:20px;line-height:1.7;word-break:break-word;white-space:pre-line">${escapeHtml(options.message || '')}</div>
<div style="display:flex;flex-direction:column;gap:8px">
<button id="simple-confirm-ok" style="width:100%;padding:10px;border:none;border-radius:10px;background:var(--accent);color:#fff;font-size:0.95em;font-weight:600;cursor:pointer;font-family:inherit">${escapeHtml(confirmText)}</button>
<button id="simple-confirm-ok" style="width:100%;padding:10px;border:none;border-radius:10px;background:var(--accent);color:var(--accent-ink, #fff);font-size:0.95em;font-weight:600;cursor:pointer;font-family:inherit">${escapeHtml(confirmText)}</button>
<button id="simple-confirm-cancel" style="width:100%;padding:9px;border:none;border-radius:10px;background:transparent;color:var(--text-muted);font-size:0.85em;cursor:pointer;font-family:inherit">${escapeHtml(cancelText)}</button>
</div>
`;
@@ -4355,7 +4439,7 @@
box.innerHTML = `
<div style="font-size:0.9em;color:var(--text-primary);margin-bottom:20px;line-height:1.7">${escapeHtml(getDeleteConfirmMessage(agent))}</div>
<div style="display:flex;flex-direction:column;gap:8px">
<button id="del-confirm-ok" style="width:100%;padding:10px;border:none;border-radius:10px;background:var(--accent);color:#fff;font-size:0.95em;font-weight:600;cursor:pointer;font-family:inherit">确认删除</button>
<button id="del-confirm-ok" style="width:100%;padding:10px;border:none;border-radius:10px;background:var(--accent);color:var(--accent-ink, #fff);font-size:0.95em;font-weight:600;cursor:pointer;font-family:inherit">确认删除</button>
<button id="del-confirm-skip" style="width:100%;padding:9px;border:1px solid var(--border-color);border-radius:10px;background:var(--bg-tertiary);color:var(--text-secondary);font-size:0.85em;cursor:pointer;font-family:inherit">确认且不再提示</button>
<button id="del-confirm-cancel" style="width:100%;padding:9px;border:none;border-radius:10px;background:transparent;color:var(--text-muted);font-size:0.85em;cursor:pointer;font-family:inherit">取消</button>
</div>
@@ -4588,7 +4672,7 @@
if (!currentSessionId || chatTitle.contentEditable === 'true') return;
const originalText = chatTitle.textContent;
chatTitle.contentEditable = 'true';
chatTitle.style.background = '#fff';
chatTitle.style.background = 'var(--surface-strong)';
chatTitle.style.outline = '1px solid var(--accent)';
chatTitle.style.borderRadius = '6px';
chatTitle.style.padding = '2px 8px';
@@ -5647,7 +5731,7 @@
<div class="settings-divider"></div>
${buildThemeEntryHtml()}
${buildAppearanceSettingsHtml()}
<div class="settings-divider"></div>
@@ -5665,8 +5749,7 @@
overlay.appendChild(panel);
document.body.appendChild(overlay);
const themePageBtn = panel.querySelector('[data-open-theme-page]');
if (themePageBtn) themePageBtn.addEventListener('click', openThemeSubpage);
mountAppearanceSettings(panel);
const notifyPageBtn = panel.querySelector('[data-open-notify-page]');
if (notifyPageBtn) notifyPageBtn.addEventListener('click', openNotifySubpage);
@@ -5934,7 +6017,7 @@
<div class="settings-divider"></div>
${buildThemeEntryHtml()}
${buildAppearanceSettingsHtml()}
<div class="settings-divider"></div>
@@ -5952,8 +6035,7 @@
overlay.appendChild(panel);
document.body.appendChild(overlay);
const themePageBtn = panel.querySelector('[data-open-theme-page]');
if (themePageBtn) themePageBtn.addEventListener('click', openThemeSubpage);
mountAppearanceSettings(panel);
const notifyPageBtn2 = panel.querySelector('[data-open-notify-page]');
if (notifyPageBtn2) notifyPageBtn2.addEventListener('click', openNotifySubpage);

View File

@@ -9,10 +9,12 @@
<script>
(function () {
var theme = localStorage.getItem('cc-web-theme') || 'washi';
var dividerTime = localStorage.getItem('cc-web-show-divider-time') === '0' ? 'hide' : 'show';
document.documentElement.dataset.theme = theme;
document.documentElement.dataset.dividerTime = dividerTime;
})();
</script>
<link rel="stylesheet" href="style.css?v=20260613-codexapp-tools2">
<link rel="stylesheet" href="style.css?v=20260614-divider-time-selectfix">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css">
</head>
<body>
@@ -147,6 +149,6 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.1/marked.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script src="app.js?v=20260613-codexapp-tools2"></script>
<script src="app.js?v=20260614-divider-time-selectfix"></script>
</body>
</html>

View File

@@ -39,6 +39,8 @@
--shadow-strong: 0 8px 32px rgba(45, 31, 20, 0.08);
--theme-card-bg: rgba(255, 249, 242, 0.72);
--theme-card-border: rgba(221, 208, 192, 0.92);
--theme-card-hover-border: rgba(192, 85, 58, 0.32);
--theme-card-active-ring: rgba(192, 85, 58, 0.12);
--loading-overlay-layer-a: rgba(250, 246, 240, 0.76);
--loading-overlay-layer-b: rgba(233, 224, 212, 0.82);
--loading-overlay-scrim: rgba(45, 31, 20, 0.18);
@@ -84,6 +86,8 @@ html[data-theme='coolvibe'] {
--shadow-strong: 0 18px 40px rgba(9, 54, 69, 0.12);
--theme-card-bg: rgba(255, 255, 255, 0.88);
--theme-card-border: rgba(207, 224, 230, 0.96);
--theme-card-hover-border: rgba(8, 145, 178, 0.32);
--theme-card-active-ring: rgba(8, 145, 178, 0.14);
--loading-overlay-layer-a: rgba(241, 251, 253, 0.78);
--loading-overlay-layer-b: rgba(219, 239, 244, 0.84);
--loading-overlay-scrim: rgba(10, 52, 67, 0.16);
@@ -354,6 +358,8 @@ html[data-theme='editorial'] {
--shadow-strong: 0 14px 36px rgba(50, 32, 20, 0.1);
--theme-card-bg: rgba(255, 252, 246, 0.88);
--theme-card-border: rgba(216, 204, 186, 0.96);
--theme-card-hover-border: rgba(139, 94, 60, 0.32);
--theme-card-active-ring: rgba(139, 94, 60, 0.12);
--loading-overlay-layer-a: rgba(247, 241, 231, 0.8);
--loading-overlay-layer-b: rgba(230, 219, 203, 0.84);
--loading-overlay-scrim: rgba(46, 36, 27, 0.16);
@@ -366,6 +372,379 @@ html[data-theme='editorial'] {
--loading-bar-fill: linear-gradient(90deg, #8b5e3c, #c59470, #8b5e3c);
}
html[data-theme='sage'] {
--bg-primary: #f5f8f2;
--bg-secondary: #edf3e8;
--bg-tertiary: #dce8d6;
--bg-bubble-user: #2f6f64;
--bg-bubble-assistant: #fbfdf8;
--text-primary: #18231f;
--text-secondary: #50635c;
--text-muted: #7d9088;
--border-color: #cad9ce;
--accent: #2f6f64;
--accent-hover: #24584f;
--accent-light: rgba(47, 111, 100, 0.13);
--success: #5c8a4e;
--danger: #b65b55;
--info: #557ba3;
--note-accent: #557ba3;
--note-accent-hover: #416380;
--note-bg: rgba(85, 123, 163, 0.1);
--note-bg-strong: rgba(85, 123, 163, 0.16);
--note-border: rgba(85, 123, 163, 0.24);
--scrollbar-thumb: #aec4b7;
--page-background:
radial-gradient(circle at top left, rgba(47, 111, 100, 0.1), transparent 38%),
linear-gradient(180deg, #f9fbf5, #eef5ea 48%, #f5f8f2);
--login-background:
linear-gradient(135deg, #f9fbf5 0%, #edf4e8 52%, #dfe9d9 100%);
--surface-strong: #fffefb;
--shadow-strong: 0 14px 36px rgba(32, 64, 54, 0.11);
--theme-card-bg: rgba(255, 254, 251, 0.86);
--theme-card-border: rgba(202, 217, 206, 0.96);
--theme-card-hover-border: rgba(47, 111, 100, 0.32);
--theme-card-active-ring: rgba(47, 111, 100, 0.13);
--loading-overlay-layer-a: rgba(245, 248, 242, 0.8);
--loading-overlay-layer-b: rgba(220, 232, 214, 0.84);
--loading-overlay-scrim: rgba(24, 35, 31, 0.16);
--loading-card-bg: linear-gradient(180deg, rgba(255, 254, 251, 0.98), rgba(239, 246, 234, 0.96));
--loading-card-border: rgba(47, 111, 100, 0.17);
--loading-card-shadow: 0 24px 60px rgba(32, 64, 54, 0.14), inset 0 1px 0 rgba(255, 255, 255, 0.82);
--loading-badge-bg: rgba(47, 111, 100, 0.12);
--loading-badge-text: #2f6f64;
--loading-bar-bg: rgba(202, 217, 206, 0.92);
--loading-bar-fill: linear-gradient(90deg, #2f6f64, #6aa889, #2f6f64);
}
html[data-theme='ink'] {
--bg-primary: #f6f7fb;
--bg-secondary: #eef1f7;
--bg-tertiary: #dde3ef;
--bg-bubble-user: #3f5fb5;
--bg-bubble-assistant: #ffffff;
--text-primary: #171923;
--text-secondary: #515b6d;
--text-muted: #7b8495;
--border-color: #d2d8e6;
--accent: #3f5fb5;
--accent-hover: #324d93;
--accent-light: rgba(63, 95, 181, 0.12);
--success: #3f8f73;
--danger: #c35062;
--info: #456aa6;
--note-accent: #3f8f73;
--note-accent-hover: #2f6e58;
--note-bg: rgba(63, 143, 115, 0.1);
--note-bg-strong: rgba(63, 143, 115, 0.16);
--note-border: rgba(63, 143, 115, 0.24);
--scrollbar-thumb: #b5bfd3;
--page-background:
radial-gradient(circle at top right, rgba(63, 95, 181, 0.1), transparent 36%),
linear-gradient(180deg, #fbfcff, #eef1f7 48%, #f6f7fb);
--login-background:
linear-gradient(135deg, #fbfcff 0%, #eef1f7 52%, #e3e8f3 100%);
--surface-strong: #ffffff;
--shadow-strong: 0 16px 38px rgba(31, 42, 72, 0.11);
--theme-card-bg: rgba(255, 255, 255, 0.88);
--theme-card-border: rgba(210, 216, 230, 0.96);
--theme-card-hover-border: rgba(63, 95, 181, 0.32);
--theme-card-active-ring: rgba(63, 95, 181, 0.13);
--loading-overlay-layer-a: rgba(246, 247, 251, 0.8);
--loading-overlay-layer-b: rgba(221, 227, 239, 0.84);
--loading-overlay-scrim: rgba(23, 25, 35, 0.16);
--loading-card-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.98), rgba(241, 244, 250, 0.96));
--loading-card-border: rgba(63, 95, 181, 0.17);
--loading-card-shadow: 0 24px 60px rgba(31, 42, 72, 0.14), inset 0 1px 0 rgba(255, 255, 255, 0.84);
--loading-badge-bg: rgba(63, 95, 181, 0.12);
--loading-badge-text: #3f5fb5;
--loading-bar-bg: rgba(210, 216, 230, 0.92);
--loading-bar-fill: linear-gradient(90deg, #3f5fb5, #6e86d6, #3f5fb5);
}
html[data-theme='dawn'] {
--bg-primary: #fff7f2;
--bg-secondary: #f6ede7;
--bg-tertiary: #eadbd2;
--bg-bubble-user: #b5524d;
--bg-bubble-assistant: #fffaf6;
--text-primary: #2b2220;
--text-secondary: #665753;
--text-muted: #947f79;
--border-color: #decac0;
--accent: #b5524d;
--accent-hover: #94403d;
--accent-light: rgba(181, 82, 77, 0.13);
--success: #4f8a6b;
--danger: #ba4e58;
--info: #597da5;
--note-accent: #4f8a6b;
--note-accent-hover: #3c6b52;
--note-bg: rgba(79, 138, 107, 0.1);
--note-bg-strong: rgba(79, 138, 107, 0.16);
--note-border: rgba(79, 138, 107, 0.24);
--scrollbar-thumb: #cdb6ad;
--page-background:
radial-gradient(circle at top left, rgba(181, 82, 77, 0.08), transparent 36%),
linear-gradient(180deg, #fffaf6, #f7ede6 48%, #fff7f2);
--login-background:
linear-gradient(135deg, #fffaf6 0%, #f6ebe4 52%, #eadbd2 100%);
--surface-strong: #ffffff;
--shadow-strong: 0 14px 36px rgba(86, 47, 42, 0.11);
--theme-card-bg: rgba(255, 250, 246, 0.88);
--theme-card-border: rgba(222, 202, 192, 0.96);
--theme-card-hover-border: rgba(181, 82, 77, 0.32);
--theme-card-active-ring: rgba(181, 82, 77, 0.13);
--loading-overlay-layer-a: rgba(255, 247, 242, 0.8);
--loading-overlay-layer-b: rgba(234, 219, 210, 0.84);
--loading-overlay-scrim: rgba(43, 34, 32, 0.16);
--loading-card-bg: linear-gradient(180deg, rgba(255, 250, 246, 0.98), rgba(247, 237, 230, 0.96));
--loading-card-border: rgba(181, 82, 77, 0.17);
--loading-card-shadow: 0 24px 60px rgba(86, 47, 42, 0.14), inset 0 1px 0 rgba(255, 255, 255, 0.82);
--loading-badge-bg: rgba(181, 82, 77, 0.12);
--loading-badge-text: #b5524d;
--loading-bar-bg: rgba(222, 202, 192, 0.92);
--loading-bar-fill: linear-gradient(90deg, #b5524d, #de8f7a, #b5524d);
}
html[data-theme='carbon'] {
color-scheme: dark;
--bg-primary: #0f1314;
--bg-secondary: #151a1b;
--bg-tertiary: #202829;
--bg-bubble-user: #247b66;
--bg-bubble-assistant: #171d1e;
--text-primary: #edf5ef;
--text-secondary: #b7c7c0;
--text-muted: #82938b;
--border-color: #2b3836;
--accent: #67d8b2;
--accent-hover: #52c69f;
--accent-light: rgba(103, 216, 178, 0.16);
--success: #74c989;
--danger: #ff7b73;
--info: #9fb7ff;
--note-accent: #9fb7ff;
--note-accent-hover: #bdcbff;
--note-bg: rgba(159, 183, 255, 0.12);
--note-bg-strong: rgba(159, 183, 255, 0.18);
--note-border: rgba(159, 183, 255, 0.28);
--scrollbar-thumb: #41514f;
--page-background:
radial-gradient(circle at top left, rgba(103, 216, 178, 0.12), transparent 34%),
linear-gradient(180deg, #111819, #0f1314 50%, #0b0e0f);
--login-background:
radial-gradient(circle at top, rgba(103, 216, 178, 0.13), transparent 38%),
linear-gradient(135deg, #111819 0%, #0f1314 54%, #0a0c0d 100%);
--surface-strong: #171d1e;
--shadow-strong: 0 22px 54px rgba(0, 0, 0, 0.38);
--theme-card-bg: rgba(23, 29, 30, 0.9);
--theme-card-border: rgba(75, 96, 92, 0.74);
--theme-card-hover-border: rgba(103, 216, 178, 0.38);
--theme-card-active-ring: rgba(103, 216, 178, 0.18);
--loading-overlay-layer-a: rgba(15, 19, 20, 0.86);
--loading-overlay-layer-b: rgba(32, 40, 41, 0.82);
--loading-overlay-scrim: rgba(0, 0, 0, 0.34);
--loading-card-bg: linear-gradient(180deg, rgba(25, 32, 33, 0.98), rgba(17, 23, 24, 0.96));
--loading-card-border: rgba(103, 216, 178, 0.2);
--loading-card-shadow: 0 28px 70px rgba(0, 0, 0, 0.44), inset 0 1px 0 rgba(255, 255, 255, 0.05);
--loading-badge-bg: rgba(103, 216, 178, 0.14);
--loading-badge-text: #86e8c6;
--loading-bar-bg: rgba(65, 81, 79, 0.92);
--loading-bar-fill: linear-gradient(90deg, #67d8b2, #9fb7ff, #67d8b2);
--accent-ink: #071512;
--dark-panel-bg: rgba(23, 29, 30, 0.96);
--dark-panel-soft: rgba(28, 36, 37, 0.92);
--dark-shadow-soft: 0 14px 32px rgba(0, 0, 0, 0.28);
}
html[data-theme='nocturne'] {
color-scheme: dark;
--bg-primary: #081417;
--bg-secondary: #0d1d22;
--bg-tertiary: #142b31;
--bg-bubble-user: #116f92;
--bg-bubble-assistant: #0f2025;
--text-primary: #edf8fa;
--text-secondary: #b1c8cf;
--text-muted: #76929b;
--border-color: #263c43;
--accent: #5ecdf5;
--accent-hover: #45b9e4;
--accent-light: rgba(94, 205, 245, 0.15);
--success: #67d9a4;
--danger: #fb7185;
--info: #8fb9ff;
--note-accent: #f0c36a;
--note-accent-hover: #ffd57d;
--note-bg: rgba(240, 195, 106, 0.12);
--note-bg-strong: rgba(240, 195, 106, 0.18);
--note-border: rgba(240, 195, 106, 0.28);
--scrollbar-thumb: #39525a;
--page-background:
radial-gradient(circle at top right, rgba(94, 205, 245, 0.12), transparent 34%),
linear-gradient(180deg, #0b1b20, #081417 52%, #050b0d);
--login-background:
radial-gradient(circle at center, rgba(94, 205, 245, 0.12), transparent 38%),
linear-gradient(135deg, #0b1b20 0%, #081417 55%, #050b0d 100%);
--surface-strong: #0f2025;
--shadow-strong: 0 22px 54px rgba(0, 0, 0, 0.4);
--theme-card-bg: rgba(15, 32, 37, 0.9);
--theme-card-border: rgba(55, 84, 93, 0.76);
--theme-card-hover-border: rgba(94, 205, 245, 0.38);
--theme-card-active-ring: rgba(94, 205, 245, 0.18);
--loading-overlay-layer-a: rgba(8, 20, 23, 0.86);
--loading-overlay-layer-b: rgba(20, 43, 49, 0.82);
--loading-overlay-scrim: rgba(0, 0, 0, 0.35);
--loading-card-bg: linear-gradient(180deg, rgba(16, 34, 39, 0.98), rgba(9, 22, 26, 0.96));
--loading-card-border: rgba(94, 205, 245, 0.2);
--loading-card-shadow: 0 28px 70px rgba(0, 0, 0, 0.46), inset 0 1px 0 rgba(255, 255, 255, 0.05);
--loading-badge-bg: rgba(94, 205, 245, 0.14);
--loading-badge-text: #7ddcff;
--loading-bar-bg: rgba(57, 82, 90, 0.92);
--loading-bar-fill: linear-gradient(90deg, #5ecdf5, #f0c36a, #5ecdf5);
--accent-ink: #041216;
--dark-panel-bg: rgba(15, 32, 37, 0.96);
--dark-panel-soft: rgba(19, 42, 48, 0.92);
--dark-shadow-soft: 0 14px 32px rgba(0, 0, 0, 0.3);
}
html[data-theme='cinder'] {
color-scheme: dark;
--bg-primary: #151112;
--bg-secondary: #1f1719;
--bg-tertiary: #2a2022;
--bg-bubble-user: #9f4051;
--bg-bubble-assistant: #21191b;
--text-primary: #f6eeee;
--text-secondary: #cbb9bb;
--text-muted: #927e82;
--border-color: #3d2d31;
--accent: #e68193;
--accent-hover: #d36c7f;
--accent-light: rgba(230, 129, 147, 0.16);
--success: #67c587;
--danger: #ff7b86;
--info: #8eb4e8;
--note-accent: #67c587;
--note-accent-hover: #83d99d;
--note-bg: rgba(103, 197, 135, 0.12);
--note-bg-strong: rgba(103, 197, 135, 0.18);
--note-border: rgba(103, 197, 135, 0.28);
--scrollbar-thumb: #584148;
--page-background:
radial-gradient(circle at top left, rgba(230, 129, 147, 0.11), transparent 34%),
linear-gradient(180deg, #1c1517, #151112 52%, #0d0a0b);
--login-background:
radial-gradient(circle at top, rgba(230, 129, 147, 0.13), transparent 38%),
linear-gradient(135deg, #1c1517 0%, #151112 55%, #0d0a0b 100%);
--surface-strong: #21191b;
--shadow-strong: 0 22px 54px rgba(0, 0, 0, 0.4);
--theme-card-bg: rgba(33, 25, 27, 0.9);
--theme-card-border: rgba(83, 61, 67, 0.76);
--theme-card-hover-border: rgba(230, 129, 147, 0.38);
--theme-card-active-ring: rgba(230, 129, 147, 0.18);
--loading-overlay-layer-a: rgba(21, 17, 18, 0.86);
--loading-overlay-layer-b: rgba(42, 32, 34, 0.82);
--loading-overlay-scrim: rgba(0, 0, 0, 0.35);
--loading-card-bg: linear-gradient(180deg, rgba(35, 27, 29, 0.98), rgba(23, 18, 19, 0.96));
--loading-card-border: rgba(230, 129, 147, 0.2);
--loading-card-shadow: 0 28px 70px rgba(0, 0, 0, 0.46), inset 0 1px 0 rgba(255, 255, 255, 0.05);
--loading-badge-bg: rgba(230, 129, 147, 0.14);
--loading-badge-text: #f09aaa;
--loading-bar-bg: rgba(88, 65, 72, 0.92);
--loading-bar-fill: linear-gradient(90deg, #e68193, #67c587, #e68193);
--accent-ink: #1b0f12;
--dark-panel-bg: rgba(33, 25, 27, 0.96);
--dark-panel-soft: rgba(41, 31, 34, 0.92);
--dark-shadow-soft: 0 14px 32px rgba(0, 0, 0, 0.3);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .login-box,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-panel,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-panel,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .option-picker,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-agent-menu,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .new-chat-dropdown,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .cmd-menu {
background: var(--dark-panel-bg);
border-color: var(--border-color);
box-shadow: var(--shadow-strong);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .sidebar {
background: linear-gradient(180deg, var(--bg-secondary), var(--bg-primary));
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-main {
background: var(--page-background);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .sidebar-header,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .sidebar-footer,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-header,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .input-area {
background: rgba(0, 0, 0, 0.14);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .agent-switch,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .input-wrapper,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .attachment-chip,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg-attachment-card,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-nav-card,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-toggle-row,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-select,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-text-input,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-field input,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-select,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .session-item-edit-input {
background: var(--dark-panel-soft);
border-color: var(--border-color);
color: var(--text-primary);
box-shadow: var(--dark-shadow-soft);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .agent-switch-btn:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-agent-btn:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .attach-btn:hover {
background: var(--accent-light);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .agent-switch-btn.active,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .login-logo,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .new-chat-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .send-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-actions .btn-save,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .fc-submit-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-btn-primary {
color: var(--accent-ink);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-agent-btn {
border-color: var(--border-color);
color: var(--text-primary);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg.assistant .msg-bubble,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-content {
background: var(--bg-bubble-assistant);
border-color: var(--border-color);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg-attachment-thumb {
background: linear-gradient(180deg, var(--bg-tertiary), var(--bg-secondary));
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .attachment-tray-note,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-content.reasoning,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-content.collab-agent-content,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-content.command,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-content.file-change {
background: var(--dark-panel-soft);
color: var(--text-primary);
border-color: var(--border-color);
}
/* === Reset === */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
@@ -1620,6 +1999,35 @@ body.session-loading-active {
border-top: 1px solid rgba(122, 104, 82, 0.22);
margin: 10px 0 11px;
}
.msg-bubble .agent-message-divider {
display: flex;
align-items: center;
gap: 10px;
margin: 10px 0 11px;
color: var(--text-muted);
font-size: 11px;
line-height: 1;
white-space: nowrap;
}
.msg-bubble .agent-message-divider::before,
.msg-bubble .agent-message-divider::after {
content: '';
flex: 1 1 auto;
height: 1px;
background: rgba(122, 104, 82, 0.22);
}
.msg-bubble .agent-message-divider span {
flex: 0 0 auto;
color: var(--text-muted);
font-family: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
font-size: 11px;
}
html[data-divider-time='hide'] .msg-bubble .agent-message-divider {
gap: 0;
}
html[data-divider-time='hide'] .msg-bubble .agent-message-divider span {
display: none;
}
.msg-bubble ul, .msg-bubble ol { margin: 4px 0 8px 20px; }
.msg-bubble li { margin-bottom: 2px; }
.msg-bubble h1, .msg-bubble h2, .msg-bubble h3, .msg-bubble h4 {
@@ -2863,6 +3271,77 @@ body.session-loading-active {
line-height: 1;
flex-shrink: 0;
}
.settings-toggle-row {
width: 100%;
margin-top: 10px;
padding: 14px 16px;
border: 1px solid var(--border-color);
border-radius: 14px;
background: var(--theme-card-bg);
display: flex;
align-items: center;
justify-content: space-between;
gap: 14px;
cursor: pointer;
}
.settings-toggle-copy {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.settings-toggle-title {
font-size: 14px;
font-weight: 700;
color: var(--text-primary);
}
.settings-toggle-meta {
font-size: 12px;
color: var(--text-secondary);
}
.settings-switch {
position: relative;
flex: 0 0 auto;
width: 42px;
height: 24px;
}
.settings-switch input {
position: absolute;
inset: 0;
opacity: 0;
cursor: pointer;
}
.settings-switch-track {
position: absolute;
inset: 0;
border-radius: 999px;
background: var(--bg-tertiary);
border: 1px solid var(--border-color);
transition: background 0.18s ease, border-color 0.18s ease;
}
.settings-switch-thumb {
position: absolute;
top: 3px;
left: 3px;
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--surface-strong);
box-shadow: 0 2px 6px rgba(45, 31, 20, 0.18);
transition: transform 0.18s ease, background 0.18s ease;
}
.settings-switch input:checked + .settings-switch-track {
background: var(--accent);
border-color: var(--accent);
}
.settings-switch input:checked + .settings-switch-track .settings-switch-thumb {
transform: translateX(18px);
background: var(--accent-ink, #fff);
}
.settings-switch input:focus-visible + .settings-switch-track {
outline: 2px solid var(--accent-light);
outline-offset: 2px;
}
.settings-subpage-panel {
max-width: 460px;
}
@@ -2884,11 +3363,11 @@ body.session-loading-active {
}
.theme-card:hover {
transform: translateY(-2px);
border-color: rgba(192, 85, 58, 0.32);
border-color: var(--theme-card-hover-border);
}
.theme-card.active {
border-color: var(--accent);
box-shadow: 0 0 0 2px rgba(192, 85, 58, 0.12);
box-shadow: 0 0 0 2px var(--theme-card-active-ring);
}
.theme-card-preview {
display: grid;
@@ -4016,3 +4495,256 @@ html[data-theme='coolvibe'] .settings-back:hover {
flex-direction: column;
}
}
/* === Dark Theme Completion Layer === */
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) body {
background: var(--page-background);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .login-overlay {
background: var(--login-background);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-overlay,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .force-change-overlay,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-overlay,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .sidebar-overlay {
background: rgba(0, 0, 0, 0.58);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .login-box,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .force-change-panel,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-panel,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-panel,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .option-picker,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-agent-menu,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .cmd-menu,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .new-chat-dropdown,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .user-outline-panel {
background: var(--dark-panel-bg);
border-color: var(--border-color);
box-shadow: var(--shadow-strong);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .sidebar {
background: linear-gradient(180deg, var(--bg-secondary), var(--bg-primary));
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-main {
background: var(--page-background);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .sidebar-header,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .sidebar-footer,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-header,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .input-area,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-header,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-footer {
background: rgba(0, 0, 0, 0.16);
border-color: var(--border-color);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .agent-switch,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .session-list-empty,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .session-project-header,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .session-project-create,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-agent-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .mode-select,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-cwd,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .user-outline-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .user-outline-item,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-back,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-nav-card,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-toggle-row,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .theme-card,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-field input,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-select,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .force-change-form input,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-select,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-text-input,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .codex-user-input-text,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .input-wrapper,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .attachment-chip,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .attachment-chip.uploading,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg-attachment-card,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .ask-question-card,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .ask-option-preview,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .ask-option-item,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .codex-user-input-option,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-quick-pick,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-toolbar-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-mobile-back,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-path,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-pane,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-preview-content,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-prompt,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-item,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-thread-chip,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .todo-list-container {
background: var(--dark-panel-soft);
border-color: var(--border-color);
color: var(--text-primary);
box-shadow: none;
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-select,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .mode-select {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23b7c7c0'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-size: 10px 6px;
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-select {
background-position: right 12px center;
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .mode-select {
background-position: right 8px center;
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .session-project-count,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .session-item-pin-badge,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .cmd-item-kind,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .import-item-tag,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-item-icon {
background: var(--accent-light);
border-color: var(--theme-card-hover-border);
color: var(--accent);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-item.directory .file-browser-item-icon {
background: var(--note-bg);
border-color: var(--note-border);
color: var(--note-accent);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .session-item:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .session-item-btn:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .chat-title:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .menu-btn:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-btn:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-close-btn:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .option-picker-item:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .cmd-item:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .cmd-item.active,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-item:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .user-outline-item:hover {
background: var(--accent-light);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .session-item.active,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .option-picker-item.active,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .ask-option-item.ask-option-selected,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .file-browser-item.active {
background: var(--accent-light);
border-color: var(--accent);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .new-chat-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .new-chat-arrow,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .send-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-actions .btn-save,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .fc-submit-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .modal-btn-primary,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .import-item-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .agent-switch-btn.active {
color: var(--accent-ink);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .note-mode-btn,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .send-btn.note-send {
color: var(--bg-primary);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg.assistant .msg-bubble,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg.user.cross-conversation .msg-bubble,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg.user.cross-conversation-reply .msg-bubble {
background: var(--bg-bubble-assistant);
border-color: var(--border-color);
color: var(--text-primary);
box-shadow: var(--dark-shadow-soft);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .cross-conversation-id-btn {
background: var(--dark-panel-soft);
border-color: var(--border-color);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg-attachment-card.is-expired,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .msg-attachment-thumb,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .attachment-preview-stage,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .code-preview-pane {
background: linear-gradient(180deg, var(--bg-tertiary), var(--bg-secondary));
border-color: var(--border-color);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .attachment-preview-stage.is-ready,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .attachment-preview-image {
background: #050708;
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .pending-note .note-bubble,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .attachment-tray-note,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-inline-note,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-inline-note.warning,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .agent-context-card {
background: var(--note-bg);
border-color: var(--note-border);
color: var(--text-secondary);
box-shadow: none;
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .settings-inline-note code,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-code {
background: rgba(0, 0, 0, 0.22);
color: var(--text-primary);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-group {
background: var(--dark-panel-bg);
border-color: var(--border-color);
box-shadow: none;
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call.codex-command,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call.codex-collab-agent-tool-call {
background: var(--dark-panel-bg);
border-color: var(--note-border);
box-shadow: none;
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call summary,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-group-summary {
background: var(--dark-panel-soft);
color: var(--text-secondary);
border-color: var(--border-color);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call summary:hover,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-group-summary:hover {
background: var(--accent-light);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-content,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-content.reasoning,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-content.collab-agent-content,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-content.command,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-content.file-change,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-group-inner,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .ask-user-question {
background: var(--bg-bubble-assistant);
color: var(--text-primary);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .tool-call-state,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .session-item-status,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-overall-status,
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .collab-agent-item-status {
background: rgba(255, 255, 255, 0.08);
border: 1px solid var(--border-color);
}
:is(html[data-theme='carbon'], html[data-theme='nocturne'], html[data-theme='cinder']) .theme-card-swatch {
border-color: rgba(255, 255, 255, 0.16);
}