diff --git a/.gitignore b/.gitignore index 89fdabd..221f352 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ dist/*.zip .vscode CLAUDE.local.md CLAUDE.md +.codegraph/ diff --git a/extension/background-notify.test.js b/extension/background-notify.test.js new file mode 100644 index 0000000..eae8094 --- /dev/null +++ b/extension/background-notify.test.js @@ -0,0 +1,111 @@ +'use strict'; + +const test = require('node:test'); +const assert = require('node:assert/strict'); +const path = require('node:path'); + +const BACKGROUND_PATH = path.join(__dirname, 'background.js'); + +// background.js registers listeners at top level and caches its module, so we +// flush the cache and re-evaluate it for each scenario. +function loadBackground(chrome) { + global.chrome = chrome; + delete require.cache[require.resolve(BACKGROUND_PATH)]; + require(BACKGROUND_PATH); +} + +function buildChrome() { + const captured = {}; + const state = { + sendMessageCalls: [], + warnCalls: [], + }; + + const chrome = { + runtime: { + id: 'test-ext-id', + getURL: (p) => `chrome-extension://test-ext-id/${p}`, + onInstalled: { addListener: () => {} }, + onStartup: { addListener: () => {} }, + sendMessage: async () => {}, + }, + action: { + setBadgeText: async () => {}, + }, + tabs: { + query: async () => [], + remove: async () => {}, + onCreated: { addListener: (cb) => { captured.onCreated = cb; } }, + onRemoved: { addListener: (cb) => { captured.onRemoved = cb; } }, + onUpdated: { addListener: (cb) => { captured.onUpdated = cb; } }, + }, + storage: { + local: { get: async () => ({}) }, + }, + }; + + return { chrome, captured, state }; +} + +test('tab events broadcast via chrome.runtime.sendMessage, not content-script channel', async () => { + const { chrome, captured, state } = buildChrome(); + chrome.runtime.sendMessage = async (msg) => { + state.sendMessageCalls.push(msg); + }; + loadBackground(chrome); + assert.ok(captured.onCreated, 'background should register a tabs.onCreated listener'); + + await captured.onCreated({ id: 99 }); + + assert.strictEqual(state.sendMessageCalls.length, 1); + assert.deepStrictEqual(state.sendMessageCalls[0], { + action: 'tabs-changed', + source: 'tabs.onCreated', + triggerTabId: 99, + }); + + await captured.onRemoved(42); + const last = state.sendMessageCalls[state.sendMessageCalls.length - 1]; + assert.deepStrictEqual(last, { + action: 'tabs-changed', + source: 'tabs.onRemoved', + triggerTabId: 42, + }); +}); + +test('"Receiving end does not exist" rejection is swallowed silently', async () => { + const { chrome, captured, state } = buildChrome(); + chrome.runtime.sendMessage = async () => { + throw new Error('Could not establish connection. Receiving end does not exist.'); + }; + + const originalWarn = console.warn; + console.warn = (...args) => { state.warnCalls.push(args); }; + try { + loadBackground(chrome); + await captured.onCreated({ id: 7 }); + } finally { + console.warn = originalWarn; + } + + assert.strictEqual(state.warnCalls.length, 0); +}); + +test('non-connection errors from sendMessage are surfaced via console.warn', async () => { + const { chrome, captured, state } = buildChrome(); + chrome.runtime.sendMessage = async () => { + throw new Error('unexpected broadcast failure'); + }; + + const originalWarn = console.warn; + console.warn = (...args) => { state.warnCalls.push(args); }; + try { + loadBackground(chrome); + await captured.onCreated({ id: 7 }); + } finally { + console.warn = originalWarn; + } + + assert.strictEqual(state.warnCalls.length, 1); + assert.match(state.warnCalls[0].join(' '), /unexpected broadcast failure/); +}); diff --git a/extension/background.js b/extension/background.js index 5583249..69e0300 100644 --- a/extension/background.js +++ b/extension/background.js @@ -6,114 +6,97 @@ */ const TAB_HARBOR_BG_DEBUG = false; -if (TAB_HARBOR_BG_DEBUG) console.log('[tab-harbor bg] Service worker loaded, registering event listeners...'); +if (TAB_HARBOR_BG_DEBUG) + console.log( + "[tab-harbor bg] Service worker loaded, registering event listeners...", + ); // ─── Auto-close duplicate new tabs ─────────────────────────────────────────── function getNewTabUrls() { return new Set([ - chrome.runtime.getURL('index.html'), - chrome.runtime.getURL('extension/index.html'), + chrome.runtime.getURL("index.html"), + chrome.runtime.getURL("extension/index.html"), ]); } function isNewTabBlank(tab, newTabUrls) { - const knownNewTabUrls = newTabUrls instanceof Set - ? newTabUrls - : new Set(Array.isArray(newTabUrls) ? newTabUrls : [newTabUrls]); - const url = tab?.url || ''; - const pendingUrl = tab?.pendingUrl || ''; - if (pendingUrl && !knownNewTabUrls.has(pendingUrl) && pendingUrl !== 'chrome://newtab/') { + const knownNewTabUrls = + newTabUrls instanceof Set + ? newTabUrls + : new Set(Array.isArray(newTabUrls) ? newTabUrls : [newTabUrls]); + const url = tab?.url || ""; + const pendingUrl = tab?.pendingUrl || ""; + if ( + pendingUrl && + !knownNewTabUrls.has(pendingUrl) && + pendingUrl !== "chrome://newtab/" + ) { return false; } return ( - url === 'chrome://newtab/' || + url === "chrome://newtab/" || knownNewTabUrls.has(url) || - pendingUrl === 'chrome://newtab/' || + pendingUrl === "chrome://newtab/" || knownNewTabUrls.has(pendingUrl) || - url === '' || - (tab.status === 'loading' && !url) + url === "" || + (tab.status === "loading" && !url) ); } async function closeDuplicateNewTabs() { try { - const stored = await chrome.storage.local.get('themePreferences'); + const stored = await chrome.storage.local.get("themePreferences"); const prefs = stored.themePreferences || {}; if (prefs.closeDuplicateNewTabsEnabled !== true) return; const newTabUrls = getNewTabUrls(); const allTabs = await chrome.tabs.query({}); - const blankTabs = allTabs.filter(tab => isNewTabBlank(tab, newTabUrls)); + const blankTabs = allTabs.filter((tab) => isNewTabBlank(tab, newTabUrls)); if (blankTabs.length <= 1) return; // Keep the active tab; if none is active, keep the one with the largest id (newest) - const activeTab = blankTabs.find(tab => tab.active); - const toKeep = activeTab || blankTabs.reduce((a, b) => (a.id > b.id ? a : b)); - const toClose = blankTabs.filter(tab => tab.id !== toKeep.id).map(tab => tab.id); + const activeTab = blankTabs.find((tab) => tab.active); + const toKeep = + activeTab || blankTabs.reduce((a, b) => (a.id > b.id ? a : b)); + const toClose = blankTabs + .filter((tab) => tab.id !== toKeep.id) + .map((tab) => tab.id); if (toClose.length > 0) await chrome.tabs.remove(toClose); } catch (err) { - console.warn('[tab-harbor bg] closeDuplicateNewTabs error:', err.message); + console.warn("[tab-harbor bg] closeDuplicateNewTabs error:", err.message); } } async function updateBadge() { try { - await chrome.action.setBadgeText({ text: '' }); + await chrome.action.setBadgeText({ text: "" }); } catch { - chrome.action.setBadgeText({ text: '' }); + chrome.action.setBadgeText({ text: "" }); } } -function getTabHarborDashboardUrls() { - const extensionId = chrome.runtime.id; - return new Set([ - `chrome-extension://${extensionId}/index.html`, - `chrome-extension://${extensionId}/extension/index.html`, - ]); -} - // ─── Event listeners ────────────────────────────────────────────────────────── // Notify Tab Harbor pages when tabs change so they can refresh async function notifyTabHarborPages(eventMeta = {}) { - try { - // Find all Tab Harbor dashboard pages - const dashboardUrls = getTabHarborDashboardUrls(); + const message = { + action: "tabs-changed", + source: eventMeta.source || "tabs.changed", + triggerTabId: eventMeta.triggerTabId ?? null, + }; - // Query all tabs and filter manually for more reliable matching - const allTabs = await chrome.tabs.query({}); - - const dashboardTabs = allTabs.filter(tab => { - if (!tab.url) return false; - // Tab Harbor can appear as either: - // 1. chrome-extension://EXTENSION_ID/index.html (direct access) - // 2. chrome-extension://EXTENSION_ID/extension/index.html (root manifest entry) - // 3. chrome://newtab/ with title "Tab Harbor" (new tab override) - return ( - dashboardUrls.has(tab.url) || - (tab.url === 'chrome://newtab/' && tab.title === 'Tab Harbor') + try { + await chrome.runtime.sendMessage(message); + } catch (err) { + if (err?.message && !err.message.includes("Receiving end does not exist")) { + console.warn( + "[tab-harbor bg] Error notifying Tab Harbor pages:", + err.message, ); - }); - - if (dashboardTabs.length === 0) return; - - for (const tab of dashboardTabs) { - try { - await chrome.tabs.sendMessage(tab.id, { - action: 'tabs-changed', - source: eventMeta.source || 'tabs.changed', - triggerTabId: eventMeta.triggerTabId ?? null, - }); - } catch (err) { - // Tab might be closed or not ready, ignore - console.warn(`[tab-harbor bg] Failed to notify tab ${tab.id}:`, err.message); - } } - } catch (err) { - console.warn('[tab-harbor bg] Error in notifyTabHarborPages:', err); } } @@ -130,20 +113,20 @@ chrome.runtime.onStartup.addListener(() => { // Update badge and notify Tab Harbor pages whenever a tab is opened chrome.tabs.onCreated.addListener((tab) => { updateBadge(); - notifyTabHarborPages({ source: 'tabs.onCreated', triggerTabId: tab?.id }); + notifyTabHarborPages({ source: "tabs.onCreated", triggerTabId: tab?.id }); closeDuplicateNewTabs(); }); // Update badge and notify Tab Harbor pages whenever a tab is closed chrome.tabs.onRemoved.addListener((tabId) => { updateBadge(); - notifyTabHarborPages({ source: 'tabs.onRemoved', triggerTabId: tabId }); + notifyTabHarborPages({ source: "tabs.onRemoved", triggerTabId: tabId }); }); // Update badge and notify Tab Harbor pages when a tab's URL changes (e.g. navigating to/from chrome://) chrome.tabs.onUpdated.addListener((tabId) => { updateBadge(); - notifyTabHarborPages({ source: 'tabs.onUpdated', triggerTabId: tabId }); + notifyTabHarborPages({ source: "tabs.onUpdated", triggerTabId: tabId }); }); // ─── Initial run ───────────────────────────────────────────────────────────── diff --git a/extension/config-sync.js b/extension/config-sync.js new file mode 100644 index 0000000..4c0fdd5 --- /dev/null +++ b/extension/config-sync.js @@ -0,0 +1,100 @@ +'use strict'; + +(function attachTabHarborConfigSync(globalScope) { + const { + normalizeQuickShortcuts: apiNormalizeQuickShortcuts, + } = globalScope.TabOutThemeControls || {}; + + const { + normalizeSavedTabSessions: apiNormalizeSavedTabSessions, + } = globalScope.TabHarborTabSessions || {}; + + const CONFIG_VERSION = 1; + const STORAGE_KEYS = ['themePreferences', 'quickShortcuts', 'savedTabSessions']; + + function isValidConfigObject(value) { + return value !== null && typeof value === 'object' && !Array.isArray(value); + } + + async function exportConfig() { + const data = await chrome.storage.local.get(STORAGE_KEYS); + const config = { + version: CONFIG_VERSION, + exportedAt: new Date().toISOString(), + }; + for (const key of STORAGE_KEYS) { + config[key] = key in data ? data[key] : null; + } + if (Array.isArray(config.quickShortcuts)) { + config.quickShortcuts = config.quickShortcuts.map(({ icon, iconKind, ...rest }) => rest); + } + return JSON.stringify(config, null, 2); + } + + function validateImportData(parsed) { + if (!isValidConfigObject(parsed)) { + throw new Error('Invalid config: root must be an object'); + } + const hasKey = STORAGE_KEYS.some(key => key in parsed); + if (!hasKey) { + throw new Error('Invalid config: missing recognized data keys'); + } + if (parsed.quickShortcuts != null && !Array.isArray(parsed.quickShortcuts)) { + throw new Error('Invalid config: quickShortcuts must be an array'); + } + if (parsed.savedTabSessions != null && !Array.isArray(parsed.savedTabSessions)) { + throw new Error('Invalid config: savedTabSessions must be an array'); + } + } + + async function importConfig(jsonString) { + let parsed; + try { + parsed = JSON.parse(jsonString); + } catch { + throw new Error('Invalid file: not valid JSON'); + } + + validateImportData(parsed); + + const storagePayload = {}; + + if (isValidConfigObject(parsed.themePreferences)) { + storagePayload.themePreferences = parsed.themePreferences; + } + + if (Array.isArray(parsed.quickShortcuts)) { + const stripped = parsed.quickShortcuts.map(({ icon, iconKind, ...rest }) => rest); + storagePayload.quickShortcuts = apiNormalizeQuickShortcuts + ? apiNormalizeQuickShortcuts(stripped) + : stripped; + } + + if (Array.isArray(parsed.savedTabSessions)) { + storagePayload.savedTabSessions = apiNormalizeSavedTabSessions + ? apiNormalizeSavedTabSessions(parsed.savedTabSessions) + : parsed.savedTabSessions; + } + + if (Object.keys(storagePayload).length === 0) { + throw new Error('Invalid config: no valid data to import'); + } + + await chrome.storage.local.set(storagePayload); + + return { importedKeys: Object.keys(storagePayload) }; + } + + const api = { + CONFIG_VERSION, + STORAGE_KEYS, + exportConfig, + importConfig, + }; + + if (typeof module !== 'undefined' && module.exports) { + module.exports = api; + } + + globalScope.TabHarborConfigSync = api; +})(typeof globalThis !== 'undefined' ? globalThis : window); diff --git a/extension/config-sync.test.js b/extension/config-sync.test.js new file mode 100644 index 0000000..7542cca --- /dev/null +++ b/extension/config-sync.test.js @@ -0,0 +1,222 @@ +'use strict'; + +const test = require('node:test'); +const assert = require('node:assert/strict'); + +const { + exportConfig, + importConfig, + CONFIG_VERSION, + STORAGE_KEYS, +} = require('./config-sync.js'); + +function createMockStorage(initial = {}) { + const store = { ...initial }; + return { + store, + chrome: { + storage: { + local: { + get: async (keys) => { + const result = {}; + for (const key of keys) { + if (key in store) result[key] = store[key]; + } + return result; + }, + set: async (payload) => { + Object.assign(store, payload); + }, + }, + }, + }, + }; +} + +async function withMockStorage(initial, fn) { + const mock = createMockStorage(initial); + const originalChrome = mock.chrome; + globalThis.chrome = originalChrome; + try { + await fn(mock.store); + } finally { + delete globalThis.chrome; + } +} + +test('exportConfig returns JSON with version, exportedAt, and all three keys', async () => { + const initial = { + themePreferences: { mode: 'dark', paletteId: 'sage' }, + quickShortcuts: [{ id: 's1', url: 'https://example.com', label: 'Example' }], + savedTabSessions: [], + }; + + await withMockStorage(initial, async () => { + const json = await exportConfig(); + const parsed = JSON.parse(json); + + assert.equal(parsed.version, CONFIG_VERSION); + assert.ok(typeof parsed.exportedAt === 'string'); + assert.deepEqual(parsed.themePreferences, initial.themePreferences); + assert.deepEqual(parsed.quickShortcuts, initial.quickShortcuts); + assert.deepEqual(parsed.savedTabSessions, initial.savedTabSessions); + }); +}); + +test('exportConfig strips icon/iconKind from quickShortcuts', async () => { + const initial = { + quickShortcuts: [ + { id: 's1', url: 'https://example.com', label: 'Example', icon: 'data:image/png;base64,abc', iconKind: 'image' }, + ], + }; + + await withMockStorage(initial, async () => { + const json = await exportConfig(); + const parsed = JSON.parse(json); + + assert.equal(parsed.quickShortcuts.length, 1); + assert.ok(!('icon' in parsed.quickShortcuts[0])); + assert.ok(!('iconKind' in parsed.quickShortcuts[0])); + assert.equal(parsed.quickShortcuts[0].url, 'https://example.com'); + }); +}); + +test('exportConfig works with empty/missing data', async () => { + await withMockStorage({}, async () => { + const json = await exportConfig(); + const parsed = JSON.parse(json); + + assert.equal(parsed.version, CONFIG_VERSION); + assert.ok('themePreferences' in parsed); + assert.ok('quickShortcuts' in parsed); + assert.ok('savedTabSessions' in parsed); + }); +}); + +test('importConfig writes valid data to storage', async () => { + const incoming = { + themePreferences: { mode: 'light', paletteId: 'mist' }, + quickShortcuts: [{ id: 's2', url: 'https://test.dev', label: 'Test' }], + savedTabSessions: [{ + id: 'tab-session-123', + name: 'My tabs', + savedAt: '2026-01-01T00:00:00.000Z', + source: 'manual', + tabs: [{ url: 'https://example.com', title: 'Example' }], + groups: [], + }], + }; + const jsonString = JSON.stringify(incoming); + + await withMockStorage({}, async (store) => { + const result = await importConfig(jsonString); + + assert.deepEqual(result.importedKeys.sort(), ['quickShortcuts', 'savedTabSessions', 'themePreferences']); + assert.ok(store.themePreferences); + assert.ok(Array.isArray(store.quickShortcuts)); + assert.ok(Array.isArray(store.savedTabSessions)); + }); +}); + +test('importConfig rejects invalid JSON', async () => { + await withMockStorage({}, async () => { + await assert.rejects( + importConfig('{ broken json'), + /not valid JSON/, + ); + }); +}); + +test('importConfig strips icon/iconKind from quickShortcuts', async () => { + const incoming = { + quickShortcuts: [ + { id: 's1', url: 'https://example.com', label: 'Example', icon: 'data:image/png;base64,abc', iconKind: 'image' }, + { id: 's2', url: 'https://test.dev', label: 'Test', icon: '🔥', iconKind: 'glyph' }, + ], + }; + + await withMockStorage({}, async (store) => { + await importConfig(JSON.stringify(incoming)); + + assert.equal(store.quickShortcuts.length, 2); + for (const shortcut of store.quickShortcuts) { + assert.ok(!('icon' in shortcut)); + assert.ok(!('iconKind' in shortcut)); + } + assert.equal(store.quickShortcuts[0].url, 'https://example.com'); + assert.equal(store.quickShortcuts[1].label, 'Test'); + }); +}); + +test('importConfig treats null values as absent (skips them)', async () => { + const incoming = { + themePreferences: null, + quickShortcuts: null, + savedTabSessions: [{ id: 's1', name: 'Test', savedAt: '2026-01-01T00:00:00.000Z', source: 'manual', tabs: [{ url: 'https://example.com', title: 'Example' }], groups: [] }], + }; + + await withMockStorage({}, async (store) => { + const result = await importConfig(JSON.stringify(incoming)); + + assert.deepEqual(result.importedKeys, ['savedTabSessions']); + assert.ok(!('themePreferences' in store)); + assert.ok(!('quickShortcuts' in store)); + assert.ok(Array.isArray(store.savedTabSessions)); + }); +}); + +test('importConfig rejects non-object root', async () => { + await withMockStorage({}, async () => { + await assert.rejects(importConfig('[1,2,3]'), /root must be an object/); + await assert.rejects(importConfig('"string"'), /root must be an object/); + await assert.rejects(importConfig('42'), /root must be an object/); + }); +}); + +test('importConfig rejects object with no recognized keys', async () => { + await withMockStorage({}, async () => { + await assert.rejects( + importConfig(JSON.stringify({ foo: 'bar', baz: 123 })), + /missing recognized data keys/, + ); + }); +}); + +test('importConfig rejects wrong types for known keys', async () => { + await withMockStorage({}, async () => { + await assert.rejects( + importConfig(JSON.stringify({ quickShortcuts: 'not-an-array' })), + /quickShortcuts must be an array/, + ); + await assert.rejects( + importConfig(JSON.stringify({ savedTabSessions: { bad: true } })), + /savedTabSessions must be an array/, + ); + }); +}); + +test('importConfig does not corrupt existing data on failure', async () => { + const initial = { + themePreferences: { mode: 'dark', paletteId: 'paper' }, + }; + + await withMockStorage(initial, async (store) => { + await assert.rejects(importConfig('not json')); + assert.deepEqual(store.themePreferences, initial.themePreferences); + }); +}); + +test('importConfig skips keys not present in the file', async () => { + const incoming = { + themePreferences: { mode: 'system', paletteId: 'blush' }, + }; + + await withMockStorage({}, async (store) => { + const result = await importConfig(JSON.stringify(incoming)); + + assert.deepEqual(result.importedKeys, ['themePreferences']); + assert.deepEqual(store.themePreferences, incoming.themePreferences); + assert.ok(!('quickShortcuts' in store)); + assert.ok(!('savedTabSessions' in store)); + }); +}); diff --git a/extension/dashboard-runtime.js b/extension/dashboard-runtime.js index 07abf5a..ad26b29 100644 --- a/extension/dashboard-runtime.js +++ b/extension/dashboard-runtime.js @@ -3004,12 +3004,72 @@ function renderWorkspaceThemeTools() { ${runtimeT ? runtimeT('closeDuplicateNewTabsLabel') : 'Auto-close duplicate new tabs'} +
+
${runtimeT ? runtimeT('settingsExportImport') : 'Export & import'}
+
+ + +
+
+ `; } +async function handleExportConfig() { + const configSync = globalThis.TabHarborConfigSync; + if (!configSync) { + showToast('Config sync unavailable'); + return; + } + try { + const json = await configSync.exportConfig(); + const blob = new Blob([json], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const stamp = new Date().toISOString().replace(/[:.]/g, '-'); + const a = document.createElement('a'); + a.href = url; + a.download = `tab-harbor-config-${stamp}.json`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + setThemeMenuOpen(false, { restoreFocus: true }); + showToast(runtimeT ? runtimeT('toastConfigExported') : 'Config exported'); + } catch (err) { + console.error('[tab-harbor] Export failed:', err); + showToast(runtimeT ? runtimeT('toastConfigExportFailed') : 'Export failed'); + } +} + +async function handleConfigImportInput(inputEl) { + const configSync = globalThis.TabHarborConfigSync; + if (!configSync) { + showToast('Config sync unavailable'); + return; + } + const file = inputEl.files?.[0]; + if (!file) return; + try { + const text = await file.text(); + const result = await configSync.importConfig(text); + await loadThemePreferences(); + await renderQuickShortcuts(); + if (document.body.classList.contains('showing-saved-tabs-page')) { + await globalThis.TabHarborSessionManager?.renderSavedTabsPage?.(); + } + setThemeMenuOpen(false, { restoreFocus: true }); + showToast(runtimeT + ? runtimeT('toastConfigImported', { keys: result.importedKeys.length }) + : `Imported ${result.importedKeys.length} setting${result.importedKeys.length !== 1 ? 's' : ''}`); + } catch (err) { + console.error('[tab-harbor] Import failed:', err); + showToast(err?.message || (runtimeT ? runtimeT('toastConfigImportFailed') : 'Import failed')); + } +} + function renderGroupNavArea(groups) { return `
@@ -3234,7 +3294,6 @@ async function buildDomainGroups(realTabs = getRealTabs()) { } if (landingTabs.length > 0) { - groupMap.__landing_pages__ = undefined; groupMap['__landing-pages__'] = { domain: '__landing-pages__', tabs: landingTabs }; } @@ -3506,6 +3565,18 @@ document.addEventListener('click', async (e) => { return; } + if (action === 'export-config') { + e.preventDefault(); + await handleExportConfig(); + return; + } + + if (action === 'import-config') { + e.preventDefault(); + document.getElementById('configImportInput')?.click(); + return; + } + if (action === 'select-language') { const language = actionEl.dataset.language || 'auto'; if (runtimeSetLanguagePreference) { @@ -4532,6 +4603,12 @@ document.addEventListener('change', async (e) => { return; } + if (e.target.id === 'configImportInput') { + await handleConfigImportInput(e.target); + e.target.value = ''; + return; + } + if (e.target.id !== 'themeBackgroundInput') return; const file = e.target.files?.[0]; diff --git a/extension/i18n.js b/extension/i18n.js index 766f0db..c029a2a 100644 --- a/extension/i18n.js +++ b/extension/i18n.js @@ -177,6 +177,13 @@ savedSessionNavDisplayModeName: 'Group name', sleepControlLabel: 'Manual sleep control', closeDuplicateNewTabsLabel: 'Auto-close duplicate new tabs', + settingsExportImport: 'Backup', + settingsExport: 'Export', + settingsImport: 'Import', + toastConfigExported: 'Config exported', + toastConfigExportFailed: 'Could not export config', + toastConfigImported: 'Imported {keys} settings', + toastConfigImportFailed: 'Could not import config', sleepAllTabsButton: 'Sleep all tabs in group', deleteSessionButton: 'Delete session', sessionPickerTitle: 'Choose what to save', @@ -350,6 +357,13 @@ savedSessionNavDisplayModeName: '分组名称', sleepControlLabel: '手动休眠控制', closeDuplicateNewTabsLabel: '自动关闭重复新标签页', + settingsExportImport: '备份', + settingsExport: '导出', + settingsImport: '导入', + toastConfigExported: '配置已导出', + toastConfigExportFailed: '导出配置失败', + toastConfigImported: '已导入 {keys} 项设置', + toastConfigImportFailed: '导入配置失败', sleepAllTabsButton: '休眠组内全部标签页', deleteSessionButton: '删除会话', sessionPickerTitle: '选择要保存的内容', diff --git a/extension/index.html b/extension/index.html index b34533f..bddb898 100644 --- a/extension/index.html +++ b/extension/index.html @@ -374,6 +374,7 @@

Edit shortcut

+ diff --git a/extension/manifest.json b/extension/manifest.json index bf6a807..6efc2d2 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,9 +1,16 @@ { "manifest_version": 3, "name": "Tab Harbor", - "version": "1.1.1", + "version": "1.1.2", "description": "A new tab dashboard for organizing open tabs, quick links, todos, and saved tab sessions in one calm workspace.", - "permissions": ["tabs", "storage", "search", "clipboardRead", "tabGroups", "favicon"], + "permissions": [ + "tabs", + "storage", + "search", + "clipboardRead", + "tabGroups", + "favicon" + ], "chrome_url_overrides": { "newtab": "index.html" }, "background": { "service_worker": "background.js" }, "action": { diff --git a/extension/style.css b/extension/style.css index 8ca42b1..c5bd018 100644 --- a/extension/style.css +++ b/extension/style.css @@ -5,1396 +5,1703 @@ ============================================================ */ :root { - --ink: #1a1613; - --paper: #f8f5f0; - --warm-gray: #e8e2da; - --muted: #9a918a; - --accent-amber: #c8713a; - --accent-sage: #5a7a62; - --accent-slate: #5a6b7a; - --accent-rose: #b35a5a; - --workspace-accent: #8a653f; - --workspace-accent-soft: #f2e7db; - --workspace-accent-border: #d4b396; - --workspace-accent-contrast: #fffaf5; - --status-active: #3d7a4a; - --status-cooling: #b8892e; - --status-abandoned: #b35a5a; - --card-bg: #fffdf9; - --shadow: rgba(26, 22, 19, 0.06); - --page-custom-background: none; - --theme-accent-soft: color-mix(in srgb, var(--accent-amber) 10%, var(--card-bg) 90%); - --theme-accent-muted: color-mix(in srgb, var(--accent-amber) 18%, var(--warm-gray) 82%); - --theme-accent-strong: color-mix(in srgb, var(--accent-amber) 72%, var(--ink) 28%); - --theme-control-hover: color-mix(in srgb, var(--ink) 8%, transparent); - --custom-surface-opacity: 14%; - --custom-border-opacity: 14%; - --custom-badge-opacity: 4%; - --custom-fallback-opacity: 5%; - --ui-scale: 1; - --shortcut-scale: 1; - --ui-font-8: 8px; - --ui-font-9: 9px; - --ui-font-10: 10px; - --ui-font-11: 11px; - --ui-font-12: 12px; - --ui-font-13: 13px; - --ui-font-14: 14px; - --ui-font-15: 15px; - --ui-font-16: 16px; - --ui-font-17: 17px; - --ui-font-18: 18px; - --ui-font-20: 20px; - --ui-font-22: 22px; - --ui-font-24: 24px; - --ui-font-28: 28px; - --ui-font-40: 40px; - --quick-shortcut-card-size: 76px; - --quick-shortcut-shell-size: 40px; - --quick-shortcut-icon-wrap-size: 40px; - --quick-shortcut-icon-size: 22px; - --quick-shortcut-label-size: 11px; - --floating-surface-opacity: clamp(82%, calc(var(--custom-surface-opacity) + 54%), 94%); - --floating-border-opacity: clamp(30%, calc(var(--custom-border-opacity) + 18%), 64%); - --panel-surface-opacity: 92%; - --panel-card-opacity: clamp(74%, calc(var(--custom-surface-opacity) + 48%), 94%); - --drawer-trigger-surface: color-mix(in srgb, var(--card-bg) 94%, var(--paper) 6%); - --drawer-trigger-surface-hover: color-mix(in srgb, var(--card-bg) 88%, var(--workspace-accent-soft) 12%); - --drawer-trigger-border: color-mix(in srgb, var(--warm-gray) 64%, var(--workspace-accent-border) 36%); - --drawer-trigger-border-hover: color-mix(in srgb, var(--warm-gray) 36%, var(--workspace-accent-border) 64%); - --drawer-trigger-icon: color-mix(in srgb, var(--ink) 78%, var(--muted) 22%); - --tooltip-surface: color-mix(in srgb, var(--workspace-accent-soft) 32%, var(--card-bg) 68%); - --tooltip-border: color-mix(in srgb, var(--workspace-accent-border) 72%, var(--warm-gray) 28%); - --tooltip-text: var(--workspace-chip-text); - --banner-action-bg: var(--workspace-accent); - --banner-action-bg-hover: color-mix(in srgb, var(--workspace-accent) 82%, var(--ink) 18%); - --banner-action-text: var(--workspace-accent-contrast); - --workspace-chip-bg: color-mix(in srgb, var(--workspace-accent-soft) 66%, var(--card-bg) 34%); - --workspace-chip-bg-strong: color-mix(in srgb, var(--workspace-accent-soft) 84%, var(--card-bg) 16%); - --workspace-chip-text: var(--workspace-accent); - --workspace-chip-border: color-mix(in srgb, var(--workspace-accent-border) 78%, var(--card-bg) 22%); - --drawer-tab-idle: color-mix(in srgb, var(--muted) 76%, var(--workspace-chip-text) 24%); - --drawer-tab-hover: var(--workspace-chip-text); - --drawer-tab-pressed: color-mix(in srgb, var(--workspace-chip-text) 84%, var(--ink) 16%); - --drawer-tab-underline-hover: color-mix(in srgb, var(--workspace-accent-border) 64%, transparent); - --drawer-tab-underline-active: color-mix(in srgb, var(--workspace-accent-border) 72%, transparent); - --drawer-tab-underline-pressed: color-mix(in srgb, var(--workspace-accent-border) 78%, transparent); - --focus-ring: color-mix(in srgb, var(--workspace-accent) 56%, white 44%); - --focus-ring-shadow: 0 0 0 3px color-mix(in srgb, var(--workspace-accent-soft) 82%, transparent); -} - -* { margin: 0; padding: 0; box-sizing: border-box; } + --ink: #1a1613; + --paper: #f8f5f0; + --warm-gray: #e8e2da; + --muted: #9a918a; + --accent-amber: #c8713a; + --accent-sage: #5a7a62; + --accent-slate: #5a6b7a; + --accent-rose: #b35a5a; + --workspace-accent: #8a653f; + --workspace-accent-soft: #f2e7db; + --workspace-accent-border: #d4b396; + --workspace-accent-contrast: #fffaf5; + --status-active: #3d7a4a; + --status-cooling: #b8892e; + --status-abandoned: #b35a5a; + --card-bg: #fffdf9; + --shadow: rgba(26, 22, 19, 0.06); + --page-custom-background: none; + --theme-accent-soft: color-mix( + in srgb, + var(--accent-amber) 10%, + var(--card-bg) 90% + ); + --theme-accent-muted: color-mix( + in srgb, + var(--accent-amber) 18%, + var(--warm-gray) 82% + ); + --theme-accent-strong: color-mix( + in srgb, + var(--accent-amber) 72%, + var(--ink) 28% + ); + --theme-control-hover: color-mix(in srgb, var(--ink) 8%, transparent); + --custom-surface-opacity: 14%; + --custom-border-opacity: 14%; + --custom-badge-opacity: 4%; + --custom-fallback-opacity: 5%; + --ui-scale: 1; + --shortcut-scale: 1; + --ui-font-8: 8px; + --ui-font-9: 9px; + --ui-font-10: 10px; + --ui-font-11: 11px; + --ui-font-12: 12px; + --ui-font-13: 13px; + --ui-font-14: 14px; + --ui-font-15: 15px; + --ui-font-16: 16px; + --ui-font-17: 17px; + --ui-font-18: 18px; + --ui-font-20: 20px; + --ui-font-22: 22px; + --ui-font-24: 24px; + --ui-font-28: 28px; + --ui-font-40: 40px; + --quick-shortcut-card-size: 76px; + --quick-shortcut-shell-size: 40px; + --quick-shortcut-icon-wrap-size: 40px; + --quick-shortcut-icon-size: 22px; + --quick-shortcut-label-size: 11px; + --floating-surface-opacity: clamp( + 82%, + calc(var(--custom-surface-opacity) + 54%), + 94% + ); + --floating-border-opacity: clamp( + 30%, + calc(var(--custom-border-opacity) + 18%), + 64% + ); + --panel-surface-opacity: 92%; + --panel-card-opacity: clamp( + 74%, + calc(var(--custom-surface-opacity) + 48%), + 94% + ); + --drawer-trigger-surface: color-mix( + in srgb, + var(--card-bg) 94%, + var(--paper) 6% + ); + --drawer-trigger-surface-hover: color-mix( + in srgb, + var(--card-bg) 88%, + var(--workspace-accent-soft) 12% + ); + --drawer-trigger-border: color-mix( + in srgb, + var(--warm-gray) 64%, + var(--workspace-accent-border) 36% + ); + --drawer-trigger-border-hover: color-mix( + in srgb, + var(--warm-gray) 36%, + var(--workspace-accent-border) 64% + ); + --drawer-trigger-icon: color-mix(in srgb, var(--ink) 78%, var(--muted) 22%); + --tooltip-surface: color-mix( + in srgb, + var(--workspace-accent-soft) 32%, + var(--card-bg) 68% + ); + --tooltip-border: color-mix( + in srgb, + var(--workspace-accent-border) 72%, + var(--warm-gray) 28% + ); + --tooltip-text: var(--workspace-chip-text); + --banner-action-bg: var(--workspace-accent); + --banner-action-bg-hover: color-mix( + in srgb, + var(--workspace-accent) 82%, + var(--ink) 18% + ); + --banner-action-text: var(--workspace-accent-contrast); + --workspace-chip-bg: color-mix( + in srgb, + var(--workspace-accent-soft) 66%, + var(--card-bg) 34% + ); + --workspace-chip-bg-strong: color-mix( + in srgb, + var(--workspace-accent-soft) 84%, + var(--card-bg) 16% + ); + --workspace-chip-text: var(--workspace-accent); + --workspace-chip-border: color-mix( + in srgb, + var(--workspace-accent-border) 78%, + var(--card-bg) 22% + ); + --drawer-tab-idle: color-mix( + in srgb, + var(--muted) 76%, + var(--workspace-chip-text) 24% + ); + --drawer-tab-hover: var(--workspace-chip-text); + --drawer-tab-pressed: color-mix( + in srgb, + var(--workspace-chip-text) 84%, + var(--ink) 16% + ); + --drawer-tab-underline-hover: color-mix( + in srgb, + var(--workspace-accent-border) 64%, + transparent + ); + --drawer-tab-underline-active: color-mix( + in srgb, + var(--workspace-accent-border) 72%, + transparent + ); + --drawer-tab-underline-pressed: color-mix( + in srgb, + var(--workspace-accent-border) 78%, + transparent + ); + --focus-ring: color-mix(in srgb, var(--workspace-accent) 56%, white 44%); + --focus-ring-shadow: 0 0 0 3px + color-mix(in srgb, var(--workspace-accent-soft) 82%, transparent); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} body { - font-family: 'Public Sans', sans-serif; - font-size: var(--ui-font-14); - background-color: var(--paper); - background-image: var(--page-custom-background); - background-size: cover; - background-position: center; - background-repeat: no-repeat; - background-attachment: fixed; - color: var(--ink); - min-height: 100vh; - -webkit-font-smoothing: antialiased; - position: relative; + font-family: "Public Sans", sans-serif; + font-size: var(--ui-font-14); + background-color: var(--paper); + background-image: var(--page-custom-background); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + background-attachment: fixed; + color: var(--ink); + min-height: 100vh; + -webkit-font-smoothing: antialiased; + position: relative; } /* Subtle paper texture */ body::before { - content: ''; - position: fixed; - inset: 0; - background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.03'/%3E%3C/svg%3E"); - pointer-events: none; - z-index: 1; + content: ""; + position: fixed; + inset: 0; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.03'/%3E%3C/svg%3E"); + pointer-events: none; + z-index: 1; } body.theme-tone-dark::before { - opacity: 0.5; + opacity: 0.5; } .container { - position: relative; - z-index: 2; - max-width: 1180px; - margin: 0 auto; - padding: 40px 32px 72px; + position: relative; + z-index: 2; + max-width: 1180px; + margin: 0 auto; + padding: 40px 32px 72px; } /* When the saved-for-later sidebar is open, expand the container so the main column and right rail have enough room */ .container:has(.dashboard-columns) { - max-width: 1260px; + max-width: 1260px; } /* ---- Header ---- */ .page-header { - display: flex; - justify-content: stretch; - align-items: flex-start; - margin-bottom: 0; - padding: 8px 0 0; - border: none; - border-radius: 0; - background: transparent; - box-shadow: none; - text-align: left; + display: flex; + justify-content: stretch; + align-items: flex-start; + margin-bottom: 0; + padding: 8px 0 0; + border: none; + border-radius: 0; + background: transparent; + box-shadow: none; + text-align: left; } .header-left { - display: flex; - flex-direction: column; - align-items: flex-start; - width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + width: 100%; } .header-title-row { - display: flex; - align-items: center; - justify-content: flex-start; - gap: 18px; - width: 100%; - flex-wrap: nowrap; + display: flex; + align-items: center; + justify-content: flex-start; + gap: 18px; + width: 100%; + flex-wrap: nowrap; } .header-left h1 { - font-family: 'Libre Caslon Display', serif; - font-weight: 400; - font-size: 40px; - font-size: var(--ui-font-40); - letter-spacing: -0.02em; - color: var(--ink); - margin-bottom: 0; - white-space: nowrap; - line-height: 1; + font-family: "Libre Caslon Display", serif; + font-weight: 400; + font-size: 40px; + font-size: var(--ui-font-40); + letter-spacing: -0.02em; + color: var(--ink); + margin-bottom: 0; + white-space: nowrap; + line-height: 1; } .header-left .date { - font-size: 10px; - font-size: var(--ui-font-10); - color: var(--muted); - font-weight: 600; - letter-spacing: 0.18em; - text-transform: uppercase; - white-space: nowrap; - line-height: 1; - transform: translateY(1px); + font-size: 10px; + font-size: var(--ui-font-10); + color: var(--muted); + font-weight: 600; + letter-spacing: 0.18em; + text-transform: uppercase; + white-space: nowrap; + line-height: 1; + transform: translateY(1px); } .hitokoto { - margin-top: 10px; - font-family: 'Libre Caslon Display', serif; - font-size: 14px; - font-size: var(--ui-font-14); - line-height: 1.6; - color: color-mix(in srgb, var(--muted) 85%, var(--ink) 15%); - max-width: 520px; + margin-top: 10px; + font-family: "Libre Caslon Display", serif; + font-size: 14px; + font-size: var(--ui-font-14); + line-height: 1.6; + color: color-mix(in srgb, var(--muted) 85%, var(--ink) 15%); + max-width: 520px; } .hitokoto-text { - font-style: italic; + font-style: italic; } .hitokoto-from { - font-size: 12px; - font-size: var(--ui-font-12); - color: var(--muted); - font-style: normal; - white-space: nowrap; + font-size: 12px; + font-size: var(--ui-font-12); + color: var(--muted); + font-style: normal; + white-space: nowrap; } .header-search { - margin-top: 14px; - width: 100%; - align-self: stretch; + margin-top: 14px; + width: 100%; + align-self: stretch; } .header-search-label { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; } .header-search-shell { - display: flex; - align-items: center; - gap: 10px; - width: 100%; - border-radius: 999px; - padding: 0 14px; - min-height: 48px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) calc(var(--custom-border-opacity) + 40%), var(--warm-gray) 38%); - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 74%), transparent); - box-shadow: 0 10px 22px color-mix(in srgb, var(--workspace-accent) 5%, transparent); - transition: border-color 0.18s ease, box-shadow 0.18s ease, background 0.18s ease; + display: flex; + align-items: center; + gap: 10px; + width: 100%; + border-radius: 999px; + padding: 0 14px; + min-height: 48px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) + calc(var(--custom-border-opacity) + 40%), + var(--warm-gray) 38% + ); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 74%), + transparent + ); + box-shadow: 0 10px 22px + color-mix(in srgb, var(--workspace-accent) 5%, transparent); + transition: + border-color 0.18s ease, + box-shadow 0.18s ease, + background 0.18s ease; } .header-search-shell:focus-within { - border-color: var(--workspace-accent-border); - box-shadow: 0 14px 28px color-mix(in srgb, var(--workspace-accent) 14%, transparent); - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 78%), var(--workspace-accent-soft) 4%); + border-color: var(--workspace-accent-border); + box-shadow: 0 14px 28px + color-mix(in srgb, var(--workspace-accent) 14%, transparent); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 78%), + var(--workspace-accent-soft) 4% + ); } .header-search-icon { - width: 16px; - height: 16px; - color: var(--workspace-accent); - flex-shrink: 0; + width: 16px; + height: 16px; + color: var(--workspace-accent); + flex-shrink: 0; } .header-search-input { - width: 100%; - border: none; - outline: none; - background: transparent; - color: var(--ink); - font: inherit; - font-size: 15px; - font-size: var(--ui-font-15); + width: 100%; + border: none; + outline: none; + background: transparent; + color: var(--ink); + font: inherit; + font-size: 15px; + font-size: var(--ui-font-15); } .header-search-input::placeholder { - color: color-mix(in srgb, var(--muted) 88%, var(--workspace-accent) 12%); + color: color-mix(in srgb, var(--muted) 88%, var(--workspace-accent) 12%); } .quick-tabs { - margin-top: 14px; - width: 100%; - align-self: stretch; + margin-top: 14px; + width: 100%; + align-self: stretch; } .quick-tabs-grid { - display: grid; - grid-template-columns: repeat(auto-fill, var(--quick-shortcut-card-size)); - justify-content: flex-start; - align-items: flex-start; - gap: 12px 10px; - width: 100%; + display: grid; + grid-template-columns: repeat(auto-fill, var(--quick-shortcut-card-size)); + justify-content: flex-start; + align-items: flex-start; + gap: 12px 10px; + width: 100%; } .quick-shortcut-card { - position: relative; - width: var(--quick-shortcut-card-size); - flex: 0 0 var(--quick-shortcut-card-size); - border: none; - transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.22s ease; - will-change: transform; + position: relative; + width: var(--quick-shortcut-card-size); + flex: 0 0 var(--quick-shortcut-card-size); + border: none; + transition: + transform 0.28s cubic-bezier(0.22, 1, 0.36, 1), + opacity 0.22s ease; + will-change: transform; } .quick-shortcut-open { - border: none; - border-radius: 0; - background: transparent; - color: var(--ink); - min-height: 0; - padding: 0; - display: grid; - grid-template-rows: var(--quick-shortcut-shell-size) auto; - justify-items: center; - align-content: start; - gap: 6px; - text-align: center; - cursor: pointer; - transition: transform 0.24s cubic-bezier(0.22, 1, 0.36, 1), color 0.18s ease; - width: 100%; - -webkit-user-drag: none; - user-select: none; + border: none; + border-radius: 0; + background: transparent; + color: var(--ink); + min-height: 0; + padding: 0; + display: grid; + grid-template-rows: var(--quick-shortcut-shell-size) auto; + justify-items: center; + align-content: start; + gap: 6px; + text-align: center; + cursor: pointer; + transition: + transform 0.24s cubic-bezier(0.22, 1, 0.36, 1), + color 0.18s ease; + width: 100%; + -webkit-user-drag: none; + user-select: none; } .quick-shortcut-open:hover, .quick-shortcut-open:focus-visible { - transform: translateY(-1px); - color: var(--theme-accent-strong); + transform: translateY(-1px); + color: var(--theme-accent-strong); } .quick-shortcut-card.is-add { - color: var(--muted); + color: var(--muted); } .quick-shortcut-remove { - position: absolute; - top: -2px; - right: 0; - width: 18px; - height: 18px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 16%, var(--warm-gray) 84%); - border-radius: 999px; - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 82%), var(--paper) 18%); - color: var(--muted); - display: inline-flex; - align-items: center; - justify-content: center; - opacity: 0; - pointer-events: none; - box-shadow: 0 3px 8px color-mix(in srgb, var(--ink) 6%, transparent); - transform: translateY(2px) scale(0.92); - transition: - opacity 0.18s ease, - color 0.18s ease, - background 0.18s ease, - border-color 0.18s ease, - box-shadow 0.18s ease, - transform 0.18s ease; + position: absolute; + top: -2px; + right: 0; + width: 18px; + height: 18px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 16%, + var(--warm-gray) 84% + ); + border-radius: 999px; + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 82%), + var(--paper) 18% + ); + color: var(--muted); + display: inline-flex; + align-items: center; + justify-content: center; + opacity: 0; + pointer-events: none; + box-shadow: 0 3px 8px color-mix(in srgb, var(--ink) 6%, transparent); + transform: translateY(2px) scale(0.92); + transition: + opacity 0.18s ease, + color 0.18s ease, + background 0.18s ease, + border-color 0.18s ease, + box-shadow 0.18s ease, + transform 0.18s ease; } .quick-shortcut-edit { - position: absolute; - top: -2px; - left: 0; - width: 18px; - height: 18px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 16%, var(--warm-gray) 84%); - border-radius: 999px; - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 82%), var(--paper) 18%); - color: var(--muted); - display: inline-flex; - align-items: center; - justify-content: center; - opacity: 0; - pointer-events: none; - box-shadow: 0 3px 8px color-mix(in srgb, var(--ink) 6%, transparent); - transform: translateY(2px) scale(0.92); - transition: - opacity 0.18s ease, - color 0.18s ease, - background 0.18s ease, - border-color 0.18s ease, - box-shadow 0.18s ease, - transform 0.18s ease; + position: absolute; + top: -2px; + left: 0; + width: 18px; + height: 18px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 16%, + var(--warm-gray) 84% + ); + border-radius: 999px; + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 82%), + var(--paper) 18% + ); + color: var(--muted); + display: inline-flex; + align-items: center; + justify-content: center; + opacity: 0; + pointer-events: none; + box-shadow: 0 3px 8px color-mix(in srgb, var(--ink) 6%, transparent); + transform: translateY(2px) scale(0.92); + transition: + opacity 0.18s ease, + color 0.18s ease, + background 0.18s ease, + border-color 0.18s ease, + box-shadow 0.18s ease, + transform 0.18s ease; } .quick-shortcut-card:hover .quick-shortcut-edit, .quick-shortcut-card:hover .quick-shortcut-remove, .quick-shortcut-card:focus-within .quick-shortcut-edit, .quick-shortcut-card:focus-within .quick-shortcut-remove { - opacity: 1; - pointer-events: auto; - transform: translateY(0) scale(1); + opacity: 1; + pointer-events: auto; + transform: translateY(0) scale(1); } .quick-shortcut-edit:hover, .quick-shortcut-edit:focus-visible { - border-color: color-mix(in srgb, var(--workspace-accent-border) 38%, transparent); - background: color-mix(in srgb, var(--workspace-accent-soft) 58%, var(--card-bg) 42%); - color: color-mix(in srgb, var(--workspace-chip-text) 90%, var(--ink) 10%); - box-shadow: 0 7px 14px color-mix(in srgb, var(--workspace-accent) 12%, transparent); + border-color: color-mix( + in srgb, + var(--workspace-accent-border) 38%, + transparent + ); + background: color-mix( + in srgb, + var(--workspace-accent-soft) 58%, + var(--card-bg) 42% + ); + color: color-mix(in srgb, var(--workspace-chip-text) 90%, var(--ink) 10%); + box-shadow: 0 7px 14px + color-mix(in srgb, var(--workspace-accent) 12%, transparent); } .quick-shortcut-edit:active { - transform: translateY(1px) scale(0.97); - box-shadow: 0 3px 8px color-mix(in srgb, var(--workspace-accent) 8%, transparent); + transform: translateY(1px) scale(0.97); + box-shadow: 0 3px 8px + color-mix(in srgb, var(--workspace-accent) 8%, transparent); } .quick-shortcut-remove:hover, .quick-shortcut-remove:focus-visible { - border-color: color-mix(in srgb, var(--status-abandoned) 24%, transparent); - background: color-mix(in srgb, var(--status-abandoned) 12%, var(--card-bg) 88%); - color: color-mix(in srgb, var(--status-abandoned) 92%, var(--ink) 8%); - box-shadow: 0 7px 14px color-mix(in srgb, var(--status-abandoned) 14%, transparent); + border-color: color-mix(in srgb, var(--status-abandoned) 24%, transparent); + background: color-mix( + in srgb, + var(--status-abandoned) 12%, + var(--card-bg) 88% + ); + color: color-mix(in srgb, var(--status-abandoned) 92%, var(--ink) 8%); + box-shadow: 0 7px 14px + color-mix(in srgb, var(--status-abandoned) 14%, transparent); } .quick-shortcut-remove:active { - transform: translateY(1px) scale(0.97); - box-shadow: 0 3px 8px color-mix(in srgb, var(--status-abandoned) 10%, transparent); + transform: translateY(1px) scale(0.97); + box-shadow: 0 3px 8px + color-mix(in srgb, var(--status-abandoned) 10%, transparent); } .quick-shortcut-edit svg, .quick-shortcut-remove svg { - width: 9px; - height: 9px; + width: 9px; + height: 9px; } .quick-shortcut-icon-wrap { - width: var(--quick-shortcut-icon-wrap-size); - height: var(--quick-shortcut-icon-wrap-size); - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 12px; - border: none; - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 24%), transparent); - flex-shrink: 0; - transition: background 0.16s ease, color 0.16s ease, box-shadow 0.16s ease; + width: var(--quick-shortcut-icon-wrap-size); + height: var(--quick-shortcut-icon-wrap-size); + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 12px; + border: none; + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 24%), + transparent + ); + flex-shrink: 0; + transition: + background 0.16s ease, + color 0.16s ease, + box-shadow 0.16s ease; } .quick-shortcut-open:hover .quick-shortcut-icon-wrap, .quick-shortcut-open:focus-visible .quick-shortcut-icon-wrap { - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 18%), var(--workspace-accent-soft) 14%); - box-shadow: 0 4px 10px color-mix(in srgb, var(--workspace-accent) 6%, transparent); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 18%), + var(--workspace-accent-soft) 14% + ); + box-shadow: 0 4px 10px + color-mix(in srgb, var(--workspace-accent) 6%, transparent); } .quick-shortcut-icon { - width: var(--quick-shortcut-icon-size); - height: var(--quick-shortcut-icon-size); - border-radius: 6px; - object-fit: cover; + width: var(--quick-shortcut-icon-size); + height: var(--quick-shortcut-icon-size); + border-radius: 6px; + object-fit: cover; } .quick-shortcut-icon-custom { - object-fit: contain; + object-fit: contain; } .quick-shortcut-custom-glyph { - width: var(--quick-shortcut-icon-size); - height: var(--quick-shortcut-icon-size); - display: inline-flex; - align-items: center; - justify-content: center; - font-size: calc(var(--quick-shortcut-icon-size) * 0.86); - line-height: 1; + width: var(--quick-shortcut-icon-size); + height: var(--quick-shortcut-icon-size); + display: inline-flex; + align-items: center; + justify-content: center; + font-size: calc(var(--quick-shortcut-icon-size) * 0.86); + line-height: 1; } .quick-shortcut-fallback { - width: var(--quick-shortcut-icon-size); - height: var(--quick-shortcut-icon-size); - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 999px; - background: var(--theme-accent-soft); - color: var(--theme-accent-strong); - font-size: 10px; - font-size: calc(var(--quick-shortcut-label-size) * 0.91); - font-weight: 700; - letter-spacing: 0.05em; + width: var(--quick-shortcut-icon-size); + height: var(--quick-shortcut-icon-size); + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 999px; + background: var(--theme-accent-soft); + color: var(--theme-accent-strong); + font-size: 10px; + font-size: calc(var(--quick-shortcut-label-size) * 0.91); + font-weight: 700; + letter-spacing: 0.05em; } .quick-shortcut-label { - font-size: 11px; - font-size: var(--quick-shortcut-label-size); - line-height: 1.45; - color: color-mix(in srgb, var(--ink) 82%, var(--muted) 18%); - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; - max-width: 100%; + font-size: 11px; + font-size: var(--quick-shortcut-label-size); + line-height: 1.45; + color: color-mix(in srgb, var(--ink) 82%, var(--muted) 18%); + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + max-width: 100%; } .quick-shortcut-card.is-add .quick-shortcut-icon-wrap { - background: color-mix(in srgb, var(--workspace-accent-soft) 72%, var(--paper) 28%); - color: var(--workspace-chip-text); - box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--workspace-accent-border) 30%, transparent); + background: color-mix( + in srgb, + var(--workspace-accent-soft) 72%, + var(--paper) 28% + ); + color: var(--workspace-chip-text); + box-shadow: inset 0 0 0 1px + color-mix(in srgb, var(--workspace-accent-border) 30%, transparent); } .quick-shortcut-card.is-add .quick-shortcut-label { - visibility: visible; + visibility: visible; } body.quick-shortcut-list-dragging { - cursor: grabbing; - user-select: none; + cursor: grabbing; + user-select: none; } body.quick-shortcut-list-dragging .quick-shortcut-open { - cursor: grabbing; + cursor: grabbing; } .quick-shortcut-card.is-drag-ghost { - position: fixed; - left: var(--drag-left, 0); - top: var(--drag-top, 0); - width: var(--drag-width, auto); - height: var(--drag-height, auto); - z-index: 120; - pointer-events: none; - opacity: 1; - display: block; - visibility: visible; + position: fixed; + left: var(--drag-left, 0); + top: var(--drag-top, 0); + width: var(--drag-width, auto); + height: var(--drag-height, auto); + z-index: 120; + pointer-events: none; + opacity: 1; + display: block; + visibility: visible; } .quick-shortcut-card.is-drag-ghost .quick-shortcut-open { - transform: none; - transition: none; - color: var(--ink); - opacity: 1; - visibility: visible; + transform: none; + transition: none; + color: var(--ink); + opacity: 1; + visibility: visible; } .quick-shortcut-card.is-drag-ghost .quick-shortcut-icon-wrap { - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 22%), var(--workspace-accent-soft) 16%); - box-shadow: 0 12px 22px color-mix(in srgb, var(--ink) 10%, transparent); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 22%), + var(--workspace-accent-soft) 16% + ); + box-shadow: 0 12px 22px color-mix(in srgb, var(--ink) 10%, transparent); } .quick-shortcut-card.is-drag-ghost .quick-shortcut-label { - color: var(--ink); + color: var(--ink); } .quick-shortcut-card.is-drag-ghost .quick-shortcut-edit, .quick-shortcut-card.is-drag-ghost .quick-shortcut-remove { - display: none; + display: none; } .quick-shortcut-slot { - width: var(--quick-shortcut-card-size); - flex: 0 0 var(--quick-shortcut-card-size); - min-height: calc(var(--quick-shortcut-shell-size) + 16px); - pointer-events: none; + width: var(--quick-shortcut-card-size); + flex: 0 0 var(--quick-shortcut-card-size); + min-height: calc(var(--quick-shortcut-shell-size) + 16px); + pointer-events: none; } .header-theme-trigger { - border: none; - background: transparent; - color: color-mix(in srgb, var(--ink) 78%, var(--muted) 22%); - border-radius: 999px; - padding: 4px; - display: inline-flex; - align-items: center; - cursor: pointer; - transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease; - position: relative; + border: none; + background: transparent; + color: color-mix(in srgb, var(--ink) 78%, var(--muted) 22%); + border-radius: 999px; + padding: 4px; + display: inline-flex; + align-items: center; + cursor: pointer; + transition: + background 0.15s ease, + color 0.15s ease, + transform 0.15s ease; + position: relative; } .header-theme-trigger:hover, .header-theme-trigger[aria-expanded="true"] { - background: var(--theme-control-hover); - color: var(--theme-accent-strong); + background: var(--theme-control-hover); + color: var(--theme-accent-strong); } .header-theme-trigger svg { - width: 18px; - height: 18px; + width: 18px; + height: 18px; } .header-theme-trigger::after { - content: attr(data-tooltip); - position: absolute; - right: 0; - bottom: calc(100% + 8px); - transform: translateY(2px); - background: var(--tooltip-surface); - color: var(--tooltip-text); - border: 1px solid var(--tooltip-border); - padding: 5px 8px; - border-radius: 6px; - font-size: 11px; - font-weight: 500; - letter-spacing: 0.2px; - white-space: nowrap; - box-shadow: none; - backdrop-filter: blur(10px); - opacity: 0; - pointer-events: none; - transition: opacity 0.06s ease, transform 0.06s ease; - z-index: 20; + content: attr(data-tooltip); + position: absolute; + right: 0; + bottom: calc(100% + 8px); + transform: translateY(2px); + background: var(--tooltip-surface); + color: var(--tooltip-text); + border: 1px solid var(--tooltip-border); + padding: 5px 8px; + border-radius: 6px; + font-size: 11px; + font-weight: 500; + letter-spacing: 0.2px; + white-space: nowrap; + box-shadow: none; + backdrop-filter: blur(10px); + opacity: 0; + pointer-events: none; + transition: + opacity 0.06s ease, + transform 0.06s ease; + z-index: 20; } .header-theme-trigger:hover::after, .header-theme-trigger:focus-visible::after { - opacity: 1; - transform: translateY(0); + opacity: 1; + transform: translateY(0); } .theme-menu[hidden] { - display: none !important; + display: none !important; } .theme-menu { - position: absolute; - top: calc(100% + 10px); - right: 0; - width: 320px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) calc(var(--custom-border-opacity) + 6%), var(--warm-gray) 32%); - border-radius: 18px; - background: color-mix(in srgb, var(--card-bg) var(--panel-card-opacity), transparent); - box-shadow: 0 16px 30px color-mix(in srgb, var(--workspace-accent) 10%, transparent); - padding: 16px; - display: flex; - flex-direction: column; - gap: 0; - z-index: 30; - backdrop-filter: blur(10px); + position: absolute; + top: calc(100% + 10px); + right: 0; + width: 320px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) + calc(var(--custom-border-opacity) + 6%), + var(--warm-gray) 32% + ); + border-radius: 18px; + background: color-mix( + in srgb, + var(--card-bg) var(--panel-card-opacity), + transparent + ); + box-shadow: 0 16px 30px + color-mix(in srgb, var(--workspace-accent) 10%, transparent); + padding: 16px; + display: flex; + flex-direction: column; + gap: 0; + z-index: 30; + backdrop-filter: blur(10px); } .theme-menu-section { - display: flex; - flex-direction: column; - gap: 12px; + display: flex; + flex-direction: column; + gap: 12px; } .theme-menu-section + .theme-menu-section { - margin-top: 14px; - padding-top: 14px; - border-top: 1px solid color-mix(in srgb, var(--workspace-accent-border) 18%, transparent); + margin-top: 14px; + padding-top: 14px; + border-top: 1px solid + color-mix(in srgb, var(--workspace-accent-border) 18%, transparent); } .theme-menu-tabs { - display: flex; - align-items: center; - justify-content: flex-start; - gap: 18px; - margin-bottom: 16px; - padding-bottom: 10px; - border-bottom: 1px solid color-mix(in srgb, var(--workspace-accent-border) 18%, transparent); + display: flex; + align-items: center; + justify-content: flex-start; + gap: 18px; + margin-bottom: 16px; + padding-bottom: 10px; + border-bottom: 1px solid + color-mix(in srgb, var(--workspace-accent-border) 18%, transparent); } .theme-menu-tab { - border: none; - border-radius: 0; - background: transparent; - color: color-mix(in srgb, var(--muted) 74%, var(--ink) 26%); - min-height: auto; - padding: 0 0 3px; - font-family: 'Public Sans', sans-serif; - font-size: 12px; - font-size: var(--ui-font-12); - font-weight: 700; - cursor: pointer; - transition: color 0.15s ease; + border: none; + border-radius: 0; + background: transparent; + color: color-mix(in srgb, var(--muted) 74%, var(--ink) 26%); + min-height: auto; + padding: 0 0 3px; + font-family: "Public Sans", sans-serif; + font-size: 12px; + font-size: var(--ui-font-12); + font-weight: 700; + cursor: pointer; + transition: color 0.15s ease; } .theme-menu-tab:hover { - color: var(--ink); + color: var(--ink); } .theme-menu-tab.is-active { - color: var(--theme-accent-strong); - text-decoration: underline; - text-underline-offset: 0.28em; - text-decoration-thickness: 1px; - text-decoration-color: color-mix(in srgb, var(--workspace-accent-border) 68%, transparent); + color: var(--theme-accent-strong); + text-decoration: underline; + text-underline-offset: 0.28em; + text-decoration-thickness: 1px; + text-decoration-color: color-mix( + in srgb, + var(--workspace-accent-border) 68%, + transparent + ); } .theme-menu-panel[hidden] { - display: none; + display: none; } .theme-menu-row { - display: flex; - align-items: center; - justify-content: space-between; - gap: 10px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; } .theme-menu-row-inline-choices { - align-items: flex-start; + align-items: flex-start; } .theme-menu-row-inline-range { - align-items: center; + align-items: center; } .theme-menu-label { - font-size: 10px; - font-size: var(--ui-font-10); - letter-spacing: 0.16em; - text-transform: uppercase; - color: var(--muted); - font-weight: 700; - padding-left: 2px; - flex: 0 0 auto; - padding-top: 4px; + font-size: 10px; + font-size: var(--ui-font-10); + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--muted); + font-weight: 700; + padding-left: 2px; + flex: 0 0 auto; + padding-top: 4px; } .theme-range-value { - font-size: 11px; - font-size: var(--ui-font-11); - color: var(--ink); - font-weight: 600; - flex: 0 0 auto; - min-width: 30px; - text-align: right; + font-size: 11px; + font-size: var(--ui-font-11); + color: var(--ink); + font-weight: 600; + flex: 0 0 auto; + min-width: 30px; + text-align: right; } .theme-range { - width: 100%; - flex: 1 1 auto; - appearance: none; - -webkit-appearance: none; - height: 4px; - border-radius: 999px; - background: color-mix(in srgb, var(--workspace-accent-border) 36%, var(--warm-gray) 64%); - outline: none; + width: 100%; + flex: 1 1 auto; + appearance: none; + -webkit-appearance: none; + height: 4px; + border-radius: 999px; + background: color-mix( + in srgb, + var(--workspace-accent-border) 36%, + var(--warm-gray) 64% + ); + outline: none; } .theme-range::-webkit-slider-thumb { - -webkit-appearance: none; - width: 14px; - height: 14px; - border-radius: 999px; - border: none; - background: var(--theme-accent-strong); - box-shadow: 0 2px 6px color-mix(in srgb, var(--workspace-accent) 20%, transparent); - cursor: pointer; + -webkit-appearance: none; + width: 14px; + height: 14px; + border-radius: 999px; + border: none; + background: var(--theme-accent-strong); + box-shadow: 0 2px 6px + color-mix(in srgb, var(--workspace-accent) 20%, transparent); + cursor: pointer; } .theme-range::-moz-range-thumb { - width: 14px; - height: 14px; - border-radius: 999px; - border: none; - background: var(--theme-accent-strong); - box-shadow: 0 2px 6px color-mix(in srgb, var(--workspace-accent) 20%, transparent); - cursor: pointer; + width: 14px; + height: 14px; + border-radius: 999px; + border: none; + background: var(--theme-accent-strong); + box-shadow: 0 2px 6px + color-mix(in srgb, var(--workspace-accent) 20%, transparent); + cursor: pointer; } .theme-mode-options { - display: flex; - flex: 1 1 auto; - justify-content: flex-end; - flex-wrap: wrap; - gap: 10px 14px; + display: flex; + flex: 1 1 auto; + justify-content: flex-end; + flex-wrap: wrap; + gap: 10px 14px; } .theme-mode-option { - border: none; - background: transparent; - color: color-mix(in srgb, var(--muted) 74%, var(--ink) 26%); - min-height: auto; - padding: 2px 0; - font-family: 'Public Sans', sans-serif; - font-size: 12px; - font-size: var(--ui-font-12); - font-weight: 600; - cursor: pointer; - transition: color 0.15s ease, opacity 0.15s ease; + border: none; + background: transparent; + color: color-mix(in srgb, var(--muted) 74%, var(--ink) 26%); + min-height: auto; + padding: 2px 0; + font-family: "Public Sans", sans-serif; + font-size: 12px; + font-size: var(--ui-font-12); + font-weight: 600; + cursor: pointer; + transition: + color 0.15s ease, + opacity 0.15s ease; } .theme-mode-option:hover { - color: var(--ink); + color: var(--ink); } .theme-mode-option.is-active { - color: var(--theme-accent-strong); - text-decoration: underline; - text-underline-offset: 0.24em; - text-decoration-thickness: 1px; - text-decoration-color: color-mix(in srgb, var(--workspace-accent-border) 68%, transparent); + color: var(--theme-accent-strong); + text-decoration: underline; + text-underline-offset: 0.24em; + text-decoration-thickness: 1px; + text-decoration-color: color-mix( + in srgb, + var(--workspace-accent-border) 68%, + transparent + ); } .theme-options { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); - grid-auto-rows: 1fr; - gap: 8px 10px; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); + grid-auto-rows: 1fr; + gap: 8px 10px; } .theme-option { - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) calc(var(--custom-border-opacity) + 4%), var(--warm-gray) 38%); - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 56%), transparent); - color: var(--ink); - border-radius: 14px; - padding: 6px 10px; - display: grid; - grid-template-columns: minmax(0, 1fr) auto; - align-items: center; - gap: 8px; - min-height: 44px; - cursor: pointer; - transition: border-color 0.15s ease, background 0.15s ease, transform 0.15s ease, color 0.15s ease; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) + calc(var(--custom-border-opacity) + 4%), + var(--warm-gray) 38% + ); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 56%), + transparent + ); + color: var(--ink); + border-radius: 14px; + padding: 6px 10px; + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + align-items: center; + gap: 8px; + min-height: 44px; + cursor: pointer; + transition: + border-color 0.15s ease, + background 0.15s ease, + transform 0.15s ease, + color 0.15s ease; } .theme-option:hover { - transform: translateY(-1px); - border-color: var(--theme-accent-muted); + transform: translateY(-1px); + border-color: var(--theme-accent-muted); } .theme-option.is-active { - border-color: color-mix(in srgb, var(--accent-amber) 32%, var(--warm-gray) 68%); - background: var(--theme-accent-soft); + border-color: color-mix( + in srgb, + var(--accent-amber) 32%, + var(--warm-gray) 68% + ); + background: var(--theme-accent-soft); } .theme-option-main { - display: flex; - align-items: center; - gap: 7px; - flex: 1 1 auto; - min-width: 0; + display: flex; + align-items: center; + gap: 7px; + flex: 1 1 auto; + min-width: 0; } .theme-option-main > span:last-child { - display: flex; - flex-direction: column; - align-items: flex-start; - min-width: 0; + display: flex; + flex-direction: column; + align-items: flex-start; + min-width: 0; } .theme-option-swatch { - width: 24px; - height: 14px; - border-radius: 999px; - background: linear-gradient(90deg, var(--theme-paper) 0 50%, var(--theme-accent) 50% 100%); - /*border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 24%, transparent);*/ - box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--card-bg) 26%, transparent); + width: 24px; + height: 14px; + border-radius: 999px; + background: linear-gradient( + 90deg, + var(--theme-paper) 0 50%, + var(--theme-accent) 50% 100% + ); + /*border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 24%, transparent);*/ + box-shadow: inset 0 0 0 1px + color-mix(in srgb, var(--card-bg) 26%, transparent); } .theme-option-name { - font-size: 12px; - font-size: var(--ui-font-12); - font-weight: 600; - white-space: nowrap; + font-size: 12px; + font-size: var(--ui-font-12); + font-weight: 600; + white-space: nowrap; } .theme-option-meta { - display: none; + display: none; } .theme-option-check { - width: 14px; - height: 14px; - border-radius: 999px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 34%, var(--warm-gray) 66%); - display: inline-flex; - align-items: center; - justify-content: center; - color: transparent; - transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease; + width: 14px; + height: 14px; + border-radius: 999px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 34%, + var(--warm-gray) 66% + ); + display: inline-flex; + align-items: center; + justify-content: center; + color: transparent; + transition: + border-color 0.15s ease, + background 0.15s ease, + color 0.15s ease; } .theme-option.is-active .theme-option-check { - border-color: var(--theme-accent-muted); - background: var(--theme-accent-soft); - color: var(--theme-accent-strong); + border-color: var(--theme-accent-muted); + background: var(--theme-accent-soft); + color: var(--theme-accent-strong); } .theme-option-check svg { - width: 8px; - height: 8px; + width: 8px; + height: 8px; } body.theme-tone-dark .header-search-shell { - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 60%), transparent); - border-color: color-mix(in srgb, var(--workspace-accent-border) calc(var(--custom-border-opacity) + 20%), var(--warm-gray) 48%); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 60%), + transparent + ); + border-color: color-mix( + in srgb, + var(--workspace-accent-border) calc(var(--custom-border-opacity) + 20%), + var(--warm-gray) 48% + ); } body.theme-tone-dark .quick-shortcut-icon-wrap { - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 18%), transparent); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 18%), + transparent + ); } body.theme-tone-dark .theme-menu { - background: var(--card-bg); - border-color: var(--warm-gray); + background: var(--card-bg); + border-color: var(--warm-gray); } body.theme-tone-dark .deferred-shell { - background: var(--card-bg); - border-color: var(--warm-gray); + background: var(--card-bg); + border-color: var(--warm-gray); } .theme-menu-actions { - display: flex; - gap: 10px; + display: flex; + gap: 10px; } .theme-menu-action { - border: none; - background: color-mix(in srgb, var(--workspace-accent-soft) 26%, transparent); - color: var(--ink); - border-radius: 12px; - padding: 8px 12px; - font-family: 'Public Sans', sans-serif; - font-size: 12px; - font-weight: 600; - cursor: pointer; - transition: background 0.15s ease, color 0.15s ease; - min-height: 36px; - flex: 1 1 0; + border: none; + background: color-mix( + in srgb, + var(--workspace-accent-soft) 26%, + transparent + ); + color: var(--ink); + border-radius: 12px; + padding: 8px 12px; + font-family: "Public Sans", sans-serif; + font-size: 12px; + font-weight: 600; + cursor: pointer; + transition: + background 0.15s ease, + color 0.15s ease; + min-height: 36px; + flex: 1 1 0; } .theme-menu-action:hover { - background: var(--theme-accent-soft); - color: var(--theme-accent-strong); + background: var(--theme-accent-soft); + color: var(--theme-accent-strong); } .theme-menu-action.is-secondary { - background: transparent; - color: var(--muted); + background: transparent; + color: var(--muted); } .theme-menu-action.is-secondary:hover { - background: color-mix(in srgb, var(--workspace-accent-soft) 18%, transparent); - color: var(--ink); + background: color-mix( + in srgb, + var(--workspace-accent-soft) 18%, + transparent + ); + color: var(--ink); } /* ---- Chrome tab groups toggle ---- */ .theme-menu-toggle-label { - display: flex; - align-items: center; - gap: 10px; - cursor: pointer; - user-select: none; - -webkit-user-select: none; + display: flex; + align-items: center; + gap: 10px; + cursor: pointer; + user-select: none; + -webkit-user-select: none; } .theme-menu-toggle-label input[type="checkbox"] { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - white-space: nowrap; - border: 0; + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; } -.theme-menu-toggle-label input[type="checkbox"]:focus-visible + .theme-menu-toggle-slider { - outline: 2px solid var(--focus-ring); - outline-offset: 3px; - box-shadow: var(--focus-ring-shadow); +.theme-menu-toggle-label + input[type="checkbox"]:focus-visible + + .theme-menu-toggle-slider { + outline: 2px solid var(--focus-ring); + outline-offset: 3px; + box-shadow: var(--focus-ring-shadow); } .theme-menu-toggle-slider { - position: relative; - width: 36px; - height: 20px; - flex-shrink: 0; - border-radius: 999px; - background: color-mix(in srgb, var(--warm-gray) 60%, var(--muted) 40%); - transition: background 0.2s ease; + position: relative; + width: 36px; + height: 20px; + flex-shrink: 0; + border-radius: 999px; + background: color-mix(in srgb, var(--warm-gray) 60%, var(--muted) 40%); + transition: background 0.2s ease; } .theme-menu-toggle-slider::after { - content: ''; - position: absolute; - top: 2px; - left: 2px; - width: 16px; - height: 16px; - border-radius: 999px; - background: var(--card-bg); - transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1); - box-shadow: 0 1px 3px color-mix(in srgb, var(--ink) 20%, transparent); + content: ""; + position: absolute; + top: 2px; + left: 2px; + width: 16px; + height: 16px; + border-radius: 999px; + background: var(--card-bg); + transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1); + box-shadow: 0 1px 3px color-mix(in srgb, var(--ink) 20%, transparent); } -.theme-menu-toggle-label input[type="checkbox"]:checked + .theme-menu-toggle-slider { - background: var(--workspace-accent); +.theme-menu-toggle-label + input[type="checkbox"]:checked + + .theme-menu-toggle-slider { + background: var(--workspace-accent); } -.theme-menu-toggle-label input[type="checkbox"]:checked + .theme-menu-toggle-slider::after { - transform: translateX(16px); +.theme-menu-toggle-label + input[type="checkbox"]:checked + + .theme-menu-toggle-slider::after { + transform: translateX(16px); } .theme-menu-toggle-label .theme-menu-label { - cursor: pointer; + cursor: pointer; } .theme-menu-toggle-text { - padding-top: 0; - flex: 1 1 auto; + padding-top: 0; + flex: 1 1 auto; } .theme-menu-toggle-button-row { - cursor: default; + cursor: default; } .theme-menu-toggle-button-row .theme-toggle-switch { - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 40%, transparent); + border: 1px solid + color-mix(in srgb, var(--workspace-accent-border) 40%, transparent); } .theme-menu-toggle-button-row .theme-menu-label { - cursor: default; + cursor: default; } /* ---- Language options ---- */ .theme-language-options { - display: flex; - flex: 1 1 auto; - justify-content: flex-end; - flex-wrap: wrap; - gap: 10px 14px; + display: flex; + flex: 1 1 auto; + justify-content: flex-end; + flex-wrap: wrap; + gap: 10px 14px; } .theme-language-option { - flex: 0 0 auto; - border: none; - background: transparent; - color: color-mix(in srgb, var(--muted) 74%, var(--ink) 26%); - padding: 2px 0; - font-family: 'Public Sans', sans-serif; - font-size: 12px; - font-weight: 600; - cursor: pointer; - transition: color 0.15s ease, opacity 0.15s ease; - min-height: auto; - text-align: center; + flex: 0 0 auto; + border: none; + background: transparent; + color: color-mix(in srgb, var(--muted) 74%, var(--ink) 26%); + padding: 2px 0; + font-family: "Public Sans", sans-serif; + font-size: 12px; + font-weight: 600; + cursor: pointer; + transition: + color 0.15s ease, + opacity 0.15s ease; + min-height: auto; + text-align: center; } .theme-language-option:hover { - color: var(--ink); + color: var(--ink); } .theme-language-option.is-active { - color: var(--theme-accent-strong); - text-decoration: underline; - text-underline-offset: 0.24em; - text-decoration-thickness: 1px; - text-decoration-color: color-mix(in srgb, var(--workspace-accent-border) 68%, transparent); + color: var(--theme-accent-strong); + text-decoration: underline; + text-underline-offset: 0.24em; + text-decoration-thickness: 1px; + text-decoration-color: color-mix( + in srgb, + var(--workspace-accent-border) 68%, + transparent + ); } /* ---- Tab cleanup banner ---- */ .theme-toggle-switch { - position: relative; - width: 36px; - height: 20px; - border-radius: 999px; - background: color-mix(in srgb, var(--workspace-accent-border) 40%, var(--warm-gray) 60%); - border: none; - cursor: pointer; - transition: background 0.2s ease; - flex-shrink: 0; - padding: 0; + position: relative; + width: 36px; + height: 20px; + border-radius: 999px; + background: color-mix( + in srgb, + var(--workspace-accent-border) 40%, + var(--warm-gray) 60% + ); + border: none; + cursor: pointer; + transition: background 0.2s ease; + flex-shrink: 0; + padding: 0; } .theme-toggle-switch::after { - content: ''; - position: absolute; - top: 1.5px; - left: 1.5px; - width: 16px; - height: 16px; - border-radius: 999px; - background: var(--card-bg); - transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1); - box-shadow: 0 1px 3px color-mix(in srgb, var(--ink) 20%, transparent); + content: ""; + position: absolute; + top: 1px; + left: 1.5px; + width: 16px; + height: 16px; + border-radius: 999px; + background: var(--card-bg); + transition: transform 0.2s cubic-bezier(0.22, 1, 0.36, 1); + box-shadow: 0 1px 3px color-mix(in srgb, var(--ink) 20%, transparent); } .theme-toggle-switch.is-active { - background: var(--accent-sage); + background: var(--accent-sage); } .theme-toggle-switch.is-active::after { - transform: translateX(16px); + transform: translateX(16px); } .tab-cleanup-banner { - background: linear-gradient( - 135deg, - color-mix(in srgb, var(--theme-accent-soft) 56%, var(--card-bg) 44%), - color-mix(in srgb, var(--theme-accent-soft) 86%, var(--card-bg) 14%) - ); - border: 1px solid var(--theme-accent-muted); - border-radius: 8px; - padding: 16px 24px; - display: flex; - align-items: center; - justify-content: space-between; - margin-bottom: 16px; - box-shadow: 0 10px 26px color-mix(in srgb, var(--ink) 7%, transparent); + background: linear-gradient( + 135deg, + color-mix(in srgb, var(--theme-accent-soft) 56%, var(--card-bg) 44%), + color-mix(in srgb, var(--theme-accent-soft) 86%, var(--card-bg) 14%) + ); + border: 1px solid var(--theme-accent-muted); + border-radius: 8px; + padding: 16px 24px; + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 16px; + box-shadow: 0 10px 26px color-mix(in srgb, var(--ink) 7%, transparent); } .tab-cleanup-left { - display: flex; - align-items: center; - gap: 16px; + display: flex; + align-items: center; + gap: 16px; } .tab-cleanup-icon { - width: 36px; - height: 36px; - border-radius: 50%; - background: color-mix(in srgb, var(--theme-accent-soft) 82%, var(--card-bg) 18%); - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; + width: 36px; + height: 36px; + border-radius: 50%; + background: color-mix( + in srgb, + var(--theme-accent-soft) 82%, + var(--card-bg) 18% + ); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; } .tab-cleanup-icon svg { - width: 18px; - height: 18px; - color: var(--theme-accent-strong); + width: 18px; + height: 18px; + color: var(--theme-accent-strong); } .tab-cleanup-text { - font-size: 13px; - color: var(--ink); - line-height: 1.5; + font-size: 13px; + color: var(--ink); + line-height: 1.5; } .tab-cleanup-text strong { - font-weight: 600; + font-weight: 600; } .tab-cleanup-btn { - font-family: 'Public Sans', sans-serif; - font-size: 12px; - font-weight: 600; - padding: 8px 20px; - border-radius: 6px; - border: none; - background: var(--banner-action-bg); - color: var(--banner-action-text); - cursor: pointer; - transition: all 0.2s; - white-space: nowrap; - min-height: 36px; + font-family: "Public Sans", sans-serif; + font-size: 12px; + font-weight: 600; + padding: 8px 20px; + border-radius: 6px; + border: none; + background: var(--banner-action-bg); + color: var(--banner-action-text); + cursor: pointer; + transition: all 0.2s; + white-space: nowrap; + min-height: 36px; } .tab-cleanup-btn:hover { - background: var(--banner-action-bg-hover); - transform: translateY(-1px); + background: var(--banner-action-bg-hover); + transform: translateY(-1px); } /* ---- Nudge banner ---- */ .nudge-banner { - background: linear-gradient(135deg, rgba(179, 90, 90, 0.04), rgba(179, 90, 90, 0.08)); - border: 1px solid rgba(179, 90, 90, 0.15); - border-radius: 8px; - padding: 16px 24px; - display: flex; - align-items: center; - gap: 16px; - margin-bottom: 40px; + background: linear-gradient( + 135deg, + rgba(179, 90, 90, 0.04), + rgba(179, 90, 90, 0.08) + ); + border: 1px solid rgba(179, 90, 90, 0.15); + border-radius: 8px; + padding: 16px 24px; + display: flex; + align-items: center; + gap: 16px; + margin-bottom: 40px; } .nudge-icon { - width: 36px; - height: 36px; - border-radius: 50%; - background: rgba(179, 90, 90, 0.1); - display: flex; - align-items: center; - justify-content: center; - flex-shrink: 0; + width: 36px; + height: 36px; + border-radius: 50%; + background: rgba(179, 90, 90, 0.1); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; } .nudge-icon svg { - width: 18px; - height: 18px; - color: var(--status-abandoned); + width: 18px; + height: 18px; + color: var(--status-abandoned); } .nudge-text { - font-size: 13px; - color: var(--ink); - line-height: 1.5; + font-size: 13px; + color: var(--ink); + line-height: 1.5; } .nudge-text strong { - font-weight: 600; + font-weight: 600; } /* ---- Section Headers ---- */ .section-header { - display: flex; - align-items: center; - gap: 12px; - margin-bottom: 16px; - margin-top: 0; - flex-wrap: wrap; + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 16px; + margin-top: 0; + flex-wrap: wrap; } .section-header h2 { - font-family: 'Public Sans', sans-serif; - font-weight: 700; - font-size: 11px; - font-size: var(--ui-font-11); - letter-spacing: 0.18em; - text-transform: uppercase; - color: color-mix(in srgb, var(--workspace-chip-text) 72%, var(--muted) 28%); - white-space: nowrap; + font-family: "Public Sans", sans-serif; + font-weight: 700; + font-size: 11px; + font-size: var(--ui-font-11); + letter-spacing: 0.18em; + text-transform: uppercase; + color: color-mix(in srgb, var(--workspace-chip-text) 72%, var(--muted) 28%); + white-space: nowrap; } #openTabsSection .section-header h2, .saved-sessions-section .section-header h2 { - width: 13ch; - flex: 0 0 13ch; + width: 13ch; + flex: 0 0 13ch; } #openTabsSection .section-count, .saved-sessions-section .section-count { - width: 96px; - flex: 0 0 96px; - justify-content: flex-end; + width: 96px; + flex: 0 0 96px; + justify-content: flex-end; } .section-line { - flex: 1; - height: 1px; - background: var(--warm-gray); + flex: 1; + height: 1px; + background: var(--warm-gray); } .section-count { - display: inline-flex; - align-items: center; - gap: 6px; - font-size: 12px; - font-size: var(--ui-font-12); - color: var(--workspace-chip-text); - font-weight: 500; - letter-spacing: 0.02em; - white-space: nowrap; + display: inline-flex; + align-items: center; + gap: 6px; + font-size: 12px; + font-size: var(--ui-font-12); + color: var(--workspace-chip-text); + font-weight: 500; + letter-spacing: 0.02em; + white-space: nowrap; } .group-nav { - display: flex; - align-items: stretch; - gap: 12px; - flex-wrap: wrap; - margin-bottom: 14px; + display: flex; + align-items: stretch; + gap: 12px; + flex-wrap: wrap; + margin-bottom: 14px; } .group-nav-wide { - width: 100%; - min-height: 40px; - margin-bottom: 18px; - justify-content: flex-start; - flex-wrap: nowrap; - align-items: center; - gap: 14px; + width: 100%; + min-height: 40px; + margin-bottom: 18px; + justify-content: flex-start; + flex-wrap: nowrap; + align-items: center; + gap: 14px; } .group-nav-list { - display: flex; - align-items: center; - gap: 10px; - flex-wrap: nowrap; - flex: 1; - min-width: 0; - min-height: 40px; - overflow-x: auto; - overflow-y: hidden; - scrollbar-width: none; + display: flex; + align-items: center; + gap: 10px; + flex-wrap: nowrap; + flex: 1; + min-width: 0; + min-height: 40px; + overflow-x: auto; + overflow-y: hidden; + scrollbar-width: none; } .group-nav-list::-webkit-scrollbar { - display: none; + display: none; } .group-nav-tools { - position: relative; - display: flex; - align-items: center; - gap: 16px; - flex: 0 0 auto; + position: relative; + display: flex; + align-items: center; + gap: 16px; + flex: 0 0 auto; } .group-nav-placeholder { - width: 34px; - height: 34px; - flex: 0 0 34px; - border-radius: 999px; - opacity: 0; - pointer-events: none; + width: 34px; + height: 34px; + flex: 0 0 34px; + border-radius: 999px; + opacity: 0; + pointer-events: none; } .group-nav-button { - width: 40px; - height: 40px; - border-radius: 999px; - border: 1px solid color-mix(in srgb, var(--warm-gray) 70%, var(--workspace-accent-border) 30%); - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 64%), transparent); - display: inline-flex; - align-items: center; - justify-content: center; - cursor: grab; - overflow: visible; - position: relative; - transition: transform 0.24s cubic-bezier(0.22, 1, 0.36, 1), border-color 0.18s ease, box-shadow 0.24s cubic-bezier(0.22, 1, 0.36, 1); - will-change: transform; + width: 40px; + height: 40px; + border-radius: 999px; + border: 1px solid + color-mix( + in srgb, + var(--warm-gray) 70%, + var(--workspace-accent-border) 30% + ); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 64%), + transparent + ); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: grab; + overflow: visible; + position: relative; + transition: + transform 0.24s cubic-bezier(0.22, 1, 0.36, 1), + border-color 0.18s ease, + box-shadow 0.24s cubic-bezier(0.22, 1, 0.36, 1); + will-change: transform; } .group-nav-button, .group-nav-button * { - -webkit-user-drag: none; + -webkit-user-drag: none; } .group-nav-button.is-dragging { - position: fixed; - left: var(--drag-left, 0); - top: var(--drag-top, 0); - z-index: 120; - opacity: 1; - transform: scale(1.04); - border-color: var(--theme-accent-muted); - box-shadow: 0 12px 24px color-mix(in srgb, var(--workspace-accent) 14%, transparent); - pointer-events: none; - transition: none; + position: fixed; + left: var(--drag-left, 0); + top: var(--drag-top, 0); + z-index: 120; + opacity: 1; + transform: scale(1.04); + border-color: var(--theme-accent-muted); + box-shadow: 0 12px 24px + color-mix(in srgb, var(--workspace-accent) 14%, transparent); + pointer-events: none; + transition: none; } .group-nav-button:hover { - transform: translateY(-1px); - border-color: var(--theme-accent-muted); - box-shadow: none; + transform: translateY(-1px); + border-color: var(--theme-accent-muted); + box-shadow: none; } .group-nav-button::after { - content: attr(data-tooltip); - position: absolute; - bottom: calc(100% + 8px); - background: var(--tooltip-surface); - color: var(--tooltip-text); - border: 1px solid var(--tooltip-border); - padding: 5px 8px; - border-radius: 6px; - font-size: 11px; - font-weight: 500; - letter-spacing: 0.2px; - white-space: nowrap; - box-shadow: none; - backdrop-filter: blur(10px); - opacity: 0; - pointer-events: none; - transition: opacity 0.06s ease, transform 0.06s ease; - z-index: 20; + content: attr(data-tooltip); + position: absolute; + bottom: calc(100% + 8px); + background: var(--tooltip-surface); + color: var(--tooltip-text); + border: 1px solid var(--tooltip-border); + padding: 5px 8px; + border-radius: 6px; + font-size: 11px; + font-weight: 500; + letter-spacing: 0.2px; + white-space: nowrap; + box-shadow: none; + backdrop-filter: blur(10px); + opacity: 0; + pointer-events: none; + transition: + opacity 0.06s ease, + transform 0.06s ease; + z-index: 20; } .group-nav-button::after { - left: 50%; - transform: translate(-50%, 2px); + left: 50%; + transform: translate(-50%, 2px); } .group-nav-button:hover::after, .group-nav-button:focus-visible::after { - opacity: 1; - transform: translate(-50%, 0); + opacity: 1; + transform: translate(-50%, 0); } .group-nav-icon, .group-nav-fallback { - width: 20px; - height: 20px; + width: 20px; + height: 20px; } .group-nav-fallback { - display: inline-flex; - align-items: center; - justify-content: center; - font-size: 9px; - font-weight: 700; - color: var(--theme-accent-strong); - letter-spacing: 0.3px; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 9px; + font-weight: 700; + color: var(--theme-accent-strong); + letter-spacing: 0.3px; } body.group-dragging { - user-select: none; + user-select: none; } body.group-dragging .group-nav-button { - cursor: grabbing; + cursor: grabbing; } /* ---- Mission Cards ---- */ .missions { - display: flex; - flex-direction: column; - gap: 12px; - margin-bottom: 32px; + display: flex; + flex-direction: column; + gap: 12px; + margin-bottom: 32px; } .mission-card { - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 68%), transparent); - border: 1px solid color-mix(in srgb, var(--warm-gray) calc(var(--custom-border-opacity) + 56%), var(--workspace-accent-border) 26%); - border-radius: 16px; - padding: 14px 16px; - display: flex; - flex-direction: column; - gap: 8px; - transition: box-shadow 0.25s ease, transform 0.25s ease, opacity 0.3s ease; - cursor: pointer; - position: relative; - overflow: visible; - break-inside: avoid; - margin-bottom: 0; - box-shadow: 0 14px 28px color-mix(in srgb, var(--workspace-accent) 6%, transparent); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 68%), + transparent + ); + border: 1px solid + color-mix( + in srgb, + var(--warm-gray) calc(var(--custom-border-opacity) + 56%), + var(--workspace-accent-border) 26% + ); + border-radius: 16px; + padding: 14px 16px; + display: flex; + flex-direction: column; + gap: 8px; + transition: + box-shadow 0.25s ease, + transform 0.25s ease, + opacity 0.3s ease; + cursor: pointer; + position: relative; + overflow: visible; + break-inside: avoid; + margin-bottom: 0; + box-shadow: 0 14px 28px + color-mix(in srgb, var(--workspace-accent) 6%, transparent); } /* Colored top border instead of side bar for grid cards */ @@ -1408,488 +1715,533 @@ body.group-dragging .group-nav-button { /* background: var(--warm-gray);*/ /*}*/ -.mission-card.has-active-bar::before { background: var(--status-active); } -.mission-card.has-amber-bar::before { background: var(--accent-amber); } -.mission-card.has-neutral-bar::before { background: var(--warm-gray); } +.mission-card.has-active-bar::before { + background: var(--status-active); +} +.mission-card.has-amber-bar::before { + background: var(--accent-amber); +} +.mission-card.has-neutral-bar::before { + background: var(--warm-gray); +} .mission-card:hover { - box-shadow: 0 16px 30px color-mix(in srgb, var(--workspace-accent) 12%, transparent); - transform: translateY(-1px); + box-shadow: 0 16px 30px + color-mix(in srgb, var(--workspace-accent) 12%, transparent); + transform: translateY(-1px); } /* Closing animation — card scales down and fades out */ .mission-card.closing { - opacity: 0; - transform: scale(0.9); - transition: opacity 0.25s ease, transform 0.25s ease; - pointer-events: none; + opacity: 0; + transform: scale(0.9); + transition: + opacity 0.25s ease, + transform 0.25s ease; + pointer-events: none; } .mission-card.collapsed { - display: none !important; + display: none !important; } /* Old side status bar — hidden, replaced by top border via ::before */ .status-bar { - display: none; + display: none; } .mission-content { - min-width: 0; + min-width: 0; } /* Hide the right-side meta (page count) — info is already in the badge */ .mission-meta { - display: none; + display: none; } .mission-top { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 10px; - margin-bottom: 4px; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 10px; + margin-bottom: 4px; } .mission-actions { - display: inline-flex; - align-items: center; - gap: 2px; - flex: 0 0 auto; + display: inline-flex; + align-items: center; + gap: 2px; + flex: 0 0 auto; } .mission-heading { - display: flex; - align-items: center; - gap: 8px; - flex: 1; - min-width: 0; - flex-wrap: wrap; + display: flex; + align-items: center; + gap: 8px; + flex: 1; + min-width: 0; + flex-wrap: wrap; } .mission-title-wrap { - display: inline-flex; - align-items: center; - gap: 6px; - min-width: 0; + display: inline-flex; + align-items: center; + gap: 6px; + min-width: 0; } .mission-name { - font-weight: 600; - font-size: 15px; - font-size: var(--ui-font-15); - color: var(--ink); - letter-spacing: -0.01em; + font-weight: 600; + font-size: 15px; + font-size: var(--ui-font-15); + color: var(--ink); + letter-spacing: -0.01em; } .mission-rename-trigger { - border: none; - padding: 0; - background: transparent; - text-align: left; - cursor: pointer; - min-width: 0; + border: none; + padding: 0; + background: transparent; + text-align: left; + cursor: pointer; + min-width: 0; } .mission-rename-trigger:hover .mission-name, .mission-rename-trigger:focus-visible .mission-name { - color: color-mix(in srgb, var(--ink) 88%, var(--theme-accent-strong) 12%); + color: color-mix(in srgb, var(--ink) 88%, var(--theme-accent-strong) 12%); } .mission-rename-trigger:focus-visible { - outline: none; + outline: none; } .mission-rename-form { - display: inline-flex; - align-items: center; - min-width: min(520px, 100%); - width: min(520px, 100%); - max-width: 100%; + display: inline-flex; + align-items: center; + min-width: min(520px, 100%); + width: min(520px, 100%); + max-width: 100%; } .mission-rename-input { - min-width: 280px; - width: 100%; - height: 38px; - padding: 0 14px; - border-radius: 8px; - border: 1px solid color-mix(in srgb, var(--workspace-chip-border) 72%, var(--ink) 28%); - background: color-mix(in srgb, var(--card-bg) 94%, var(--theme-accent-soft) 6%); - color: var(--ink); - font: 600 15px/1.2 'Public Sans', sans-serif; - font-size: var(--ui-font-15); + min-width: 280px; + width: 100%; + height: 38px; + padding: 0 14px; + border-radius: 8px; + border: 1px solid + color-mix(in srgb, var(--workspace-chip-border) 72%, var(--ink) 28%); + background: color-mix( + in srgb, + var(--card-bg) 94%, + var(--theme-accent-soft) 6% + ); + color: var(--ink); + font: + 600 15px/1.2 "Public Sans", + sans-serif; + font-size: var(--ui-font-15); } .mission-rename-input:focus { - outline: none; - border-color: var(--theme-accent-muted); - box-shadow: 0 0 0 3px color-mix(in srgb, var(--theme-accent-soft) 55%, transparent); + outline: none; + border-color: var(--theme-accent-muted); + box-shadow: 0 0 0 3px + color-mix(in srgb, var(--theme-accent-soft) 55%, transparent); } .mission-tag { - font-size: 10px; - font-size: var(--ui-font-10); - text-transform: uppercase; - letter-spacing: 1px; - font-weight: 600; - padding: 2px 8px; - border-radius: 3px; + font-size: 10px; + font-size: var(--ui-font-10); + text-transform: uppercase; + letter-spacing: 1px; + font-weight: 600; + padding: 2px 8px; + border-radius: 3px; } .mission-tag.active { - color: var(--status-active); - background: rgba(61, 122, 74, 0.08); + color: var(--status-active); + background: rgba(61, 122, 74, 0.08); } .mission-tag.cooling { - color: var(--status-cooling); - background: rgba(184, 137, 46, 0.08); + color: var(--status-cooling); + background: rgba(184, 137, 46, 0.08); } .mission-tag.abandoned { - color: var(--status-abandoned); - background: rgba(179, 90, 90, 0.08); + color: var(--status-abandoned); + background: rgba(179, 90, 90, 0.08); } /* Tab indicator badge — shows how many Chrome tabs are still open for this mission */ .duplicate-count-badge { - display: inline-flex; - align-items: center; - font-size: 10px; - font-size: var(--ui-font-10); - font-weight: 600; - color: var(--workspace-chip-text); - background: var(--workspace-chip-bg-strong); - border: 1px solid var(--workspace-chip-border); - padding: 2px 6px; - border-radius: 3px; + display: inline-flex; + align-items: center; + font-size: 10px; + font-size: var(--ui-font-10); + font-weight: 600; + color: var(--workspace-chip-text); + background: var(--workspace-chip-bg-strong); + border: 1px solid var(--workspace-chip-border); + padding: 2px 6px; + border-radius: 3px; } .mission-summary { - font-size: 12px; - font-size: var(--ui-font-12); - color: var(--muted); - line-height: 1.55; - margin-bottom: 8px; + font-size: 12px; + font-size: var(--ui-font-12); + color: var(--muted); + line-height: 1.55; + margin-bottom: 8px; } .mission-pages { - display: flex; - flex-direction: column; - gap: 0; - transition: all 0.3s ease-out; + display: flex; + flex-direction: column; + gap: 0; + transition: all 0.3s ease-out; } .mission-card.is-drop-target { - box-shadow: 0 18px 34px color-mix(in srgb, var(--workspace-accent) 14%, transparent); + box-shadow: 0 18px 34px + color-mix(in srgb, var(--workspace-accent) 14%, transparent); } .mission-card.is-drop-target .mission-pages { - background: color-mix(in srgb, var(--workspace-accent-soft) 20%, transparent); - border-radius: 12px; + background: color-mix( + in srgb, + var(--workspace-accent-soft) 20%, + transparent + ); + border-radius: 12px; } /* Smooth height transition when chips are removed */ .mission-pages .page-chip { - transition: opacity 0.2s ease, transform 0.2s ease, margin 0.3s ease-out; + transition: + opacity 0.2s ease, + transform 0.2s ease, + margin 0.3s ease-out; } /* ---- Tab row — each tab is a full-width row with favicon, title, and actions ---- */ .page-chip { - font-size: 13px; - font-size: var(--ui-font-13); - color: var(--ink); - background: transparent; - padding: 8px 2px; - border-radius: 0; - border: none; - border-bottom: 1px solid rgba(154, 145, 138, 0.12); - position: relative; - display: flex; - align-items: center; - gap: 8px; - line-height: 1.4; + font-size: 13px; + font-size: var(--ui-font-13); + color: var(--ink); + background: transparent; + padding: 8px 2px; + border-radius: 0; + border: none; + border-bottom: 1px solid rgba(154, 145, 138, 0.12); + position: relative; + display: flex; + align-items: center; + gap: 8px; + line-height: 1.4; } .page-chip > .chip-reorder-handle { - flex-shrink: 0; - margin-left: 1px; - width: 30px; - height: 30px; + flex-shrink: 0; + margin-left: 1px; + width: 30px; + height: 30px; } .page-chip:last-child, .page-chip-overflow { - border-bottom: none; + border-bottom: none; } /* Favicon */ .chip-favicon { - width: 14px; - height: 14px; - flex-shrink: 0; - border-radius: 2px; + width: 14px; + height: 14px; + flex-shrink: 0; + border-radius: 2px; } .chip-favicon-fallback, .inline-favicon-fallback { - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - border-radius: 999px; - background: color-mix(in srgb, var(--accent-amber) var(--custom-fallback-opacity), transparent); - color: var(--accent-amber); - font-size: 9px; - font-weight: 700; - letter-spacing: 0.3px; + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + border-radius: 999px; + background: color-mix( + in srgb, + var(--accent-amber) var(--custom-fallback-opacity), + transparent + ); + color: var(--accent-amber); + font-size: 9px; + font-weight: 700; + letter-spacing: 0.3px; } .chip-favicon-fallback { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .inline-favicon-fallback { - width: 14px; - height: 14px; - vertical-align: -2px; - margin-right: 4px; + width: 14px; + height: 14px; + vertical-align: -2px; + margin-right: 4px; } /* Title text — wraps naturally, no truncation */ .chip-text { - flex: 1; - min-width: 0; - /* Show up to 2 lines, then ellipsis */ - display: -webkit-box; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; - overflow: hidden; + flex: 1; + min-width: 0; + /* Show up to 2 lines, then ellipsis */ + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; } /* Duplicate badge */ .chip-dupe-badge { - color: var(--accent-amber); - font-weight: 600; + color: var(--accent-amber); + font-weight: 600; } /* Duplicate border highlight */ .chip-has-dupes { - border-color: rgba(200, 113, 58, 0.25); + border-color: rgba(200, 113, 58, 0.25); } /* Action buttons grouped on the right */ .chip-actions { - display: flex; - align-items: center; - gap: 4px; - flex-shrink: 0; - margin-left: auto; + display: flex; + align-items: center; + gap: 4px; + flex-shrink: 0; + margin-left: auto; } .chip-reorder-handle { - opacity: 1; - color: color-mix(in srgb, var(--ink) 84%, var(--muted) 16%); + opacity: 1; + color: color-mix(in srgb, var(--ink) 84%, var(--muted) 16%); } .chip-reorder-handle:hover { - opacity: 1; - color: var(--ink); + opacity: 1; + color: var(--ink); } /* ---- Chip action buttons (save + close) ---- */ .chip-action { - display: inline-flex; - align-items: center; - justify-content: center; - background: none; - border: none; - color: var(--muted); - cursor: pointer; - width: 28px; - height: 28px; - padding: 0; - border-radius: 4px; - opacity: 0.48; - transition: opacity 0.15s, color 0.15s, background 0.15s; - flex-shrink: 0; - position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + background: none; + border: none; + color: var(--muted); + cursor: pointer; + width: 28px; + height: 28px; + padding: 0; + border-radius: 4px; + opacity: 0.48; + transition: + opacity 0.15s, + color 0.15s, + background 0.15s; + flex-shrink: 0; + position: relative; } .chip-action svg { - width: 13px; - height: 13px; + width: 13px; + height: 13px; } .chip-action:hover { - opacity: 1; - background: rgba(154, 145, 138, 0.1); + opacity: 1; + background: rgba(154, 145, 138, 0.1); } .chip-save:hover { - color: var(--accent-sage); - background: rgba(90, 122, 98, 0.08); + color: var(--accent-sage); + background: rgba(90, 122, 98, 0.08); } .chip-session-save:hover { - color: var(--workspace-chip-text); - background: color-mix(in srgb, var(--workspace-accent-soft) 54%, transparent); + color: var(--workspace-chip-text); + background: color-mix( + in srgb, + var(--workspace-accent-soft) 54%, + transparent + ); } .chip-close:hover { - color: var(--status-abandoned); - background: rgba(179, 90, 90, 0.08); + color: var(--status-abandoned); + background: rgba(179, 90, 90, 0.08); } - .chip-discard:hover { - color: var(--muted); - background: rgba(114, 107, 203, 0.08); + color: var(--muted); + background: rgba(114, 107, 203, 0.08); } /* ---- Discarded (sleeping) tab state ---- */ .page-chip--discarded { - opacity: 0.6; + opacity: 0.6; } .page-chip--discarded .chip-text { - text-decoration: line-through; + text-decoration: line-through; } .group-action-icon { - display: inline-flex; - align-items: center; - justify-content: center; - width: 30px; - height: 30px; - padding: 0; - border: none; - background: transparent; - color: color-mix(in srgb, var(--muted) 86%, var(--ink) 14%); - cursor: pointer; - transition: color 0.15s ease, opacity 0.15s ease; - position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + width: 30px; + height: 30px; + padding: 0; + border: none; + background: transparent; + color: color-mix(in srgb, var(--muted) 86%, var(--ink) 14%); + cursor: pointer; + transition: + color 0.15s ease, + opacity 0.15s ease; + position: relative; } .group-action-icon svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .group-action-icon:hover { - color: var(--ink); - opacity: 1; + color: var(--ink); + opacity: 1; } .group-action-icon.group-action-close:hover { - color: var(--status-abandoned); + color: var(--status-abandoned); } .page-chip.clickable { - cursor: pointer; - transition: background 0.15s ease; + cursor: pointer; + transition: background 0.15s ease; } .page-chip.clickable:hover { - background: color-mix(in srgb, var(--workspace-accent-soft) 36%, transparent); + background: color-mix( + in srgb, + var(--workspace-accent-soft) 36%, + transparent + ); } /* "+N more" overflow chip */ .page-chip-overflow { - font-size: 11px; - font-size: var(--ui-font-11); - color: var(--muted); - padding: 4px 2px; + font-size: 11px; + font-size: var(--ui-font-11); + color: var(--muted); + padding: 4px 2px; } /* mission-meta hidden — see above */ .mission-time { - font-size: 12px; - font-size: var(--ui-font-12); - color: var(--muted); - margin-bottom: 4px; + font-size: 12px; + font-size: var(--ui-font-12); + color: var(--muted); + margin-bottom: 4px; } .mission-page-count { - font-size: 20px; - font-size: var(--ui-font-20); - font-family: 'Libre Caslon Display', serif; - font-weight: 300; - color: var(--ink); - line-height: 1; + font-size: 20px; + font-size: var(--ui-font-20); + font-family: "Libre Caslon Display", serif; + font-weight: 300; + color: var(--ink); + line-height: 1; } .mission-page-label { - font-size: 10px; - font-size: var(--ui-font-10); - color: var(--muted); - text-transform: uppercase; - letter-spacing: 1px; + font-size: 10px; + font-size: var(--ui-font-10); + color: var(--muted); + text-transform: uppercase; + letter-spacing: 1px; } /* ---- Actions row ---- */ .actions { - display: flex; - gap: 8px; - margin-top: 8px; - flex-wrap: wrap; + display: flex; + gap: 8px; + margin-top: 8px; + flex-wrap: wrap; } .section-icon-action { - display: inline-flex; - align-items: center; - justify-content: center; - width: 30px; - height: 30px; - padding: 0; - border: none; - background: transparent; - color: color-mix(in srgb, var(--muted) 82%, var(--ink) 18%); - cursor: pointer; - transition: color 0.15s ease, opacity 0.15s ease; - position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + width: 30px; + height: 30px; + padding: 0; + border: none; + background: transparent; + color: color-mix(in srgb, var(--muted) 82%, var(--ink) 18%); + cursor: pointer; + transition: + color 0.15s ease, + opacity 0.15s ease; + position: relative; } .section-icon-action svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .section-icon-action:hover { - color: var(--ink); + color: var(--ink); } .section-icon-action-close:hover { - color: var(--status-abandoned); + color: var(--status-abandoned); } .chip-action[data-tooltip]::after, .group-action-icon[data-tooltip]::after, .section-icon-action[data-tooltip]::after, .todo-action-btn[data-tooltip]::after { - content: attr(data-tooltip); - position: absolute; - left: 50%; - bottom: calc(100% + 8px); - transform: translate(-50%, 2px); - background: var(--tooltip-surface); - color: var(--tooltip-text); - border: 1px solid var(--tooltip-border); - padding: 5px 8px; - border-radius: 6px; - font-size: 11px; - font-weight: 500; - letter-spacing: 0.2px; - white-space: nowrap; - box-shadow: 0 8px 24px color-mix(in srgb, var(--ink) 16%, transparent); - backdrop-filter: blur(10px); - opacity: 0; - pointer-events: none; - transition: opacity 0.06s ease, transform 0.06s ease; - z-index: 20; + content: attr(data-tooltip); + position: absolute; + left: 50%; + bottom: calc(100% + 8px); + transform: translate(-50%, 2px); + background: var(--tooltip-surface); + color: var(--tooltip-text); + border: 1px solid var(--tooltip-border); + padding: 5px 8px; + border-radius: 6px; + font-size: 11px; + font-weight: 500; + letter-spacing: 0.2px; + white-space: nowrap; + box-shadow: 0 8px 24px color-mix(in srgb, var(--ink) 16%, transparent); + backdrop-filter: blur(10px); + opacity: 0; + pointer-events: none; + transition: + opacity 0.06s ease, + transform 0.06s ease; + z-index: 20; } .chip-action[data-tooltip]:hover::after, @@ -1900,1218 +2252,1382 @@ body.group-dragging .group-nav-button { .section-icon-action[data-tooltip]:focus-visible::after, .todo-action-btn[data-tooltip]:hover::after, .todo-action-btn[data-tooltip]:focus-visible::after { - opacity: 1; - transform: translate(-50%, 0); + opacity: 1; + transform: translate(-50%, 0); } .action-btn { - font-size: 11px; - font-size: var(--ui-font-11); - font-family: 'Public Sans', sans-serif; - font-weight: 600; - padding: 6px 12px; - border-radius: 999px; - border: 1px solid color-mix(in srgb, var(--warm-gray) 72%, var(--workspace-accent-border) 28%); - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 66%), transparent); - color: color-mix(in srgb, var(--ink) 70%, var(--muted) 30%); - cursor: pointer; - transition: all 0.2s; - display: inline-flex; - align-items: center; - gap: 5px; - min-height: 34px; + font-size: 11px; + font-size: var(--ui-font-11); + font-family: "Public Sans", sans-serif; + font-weight: 600; + padding: 6px 12px; + border-radius: 999px; + border: 1px solid + color-mix( + in srgb, + var(--warm-gray) 72%, + var(--workspace-accent-border) 28% + ); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 66%), + transparent + ); + color: color-mix(in srgb, var(--ink) 70%, var(--muted) 30%); + cursor: pointer; + transition: all 0.2s; + display: inline-flex; + align-items: center; + gap: 5px; + min-height: 34px; } .action-btn:hover { - border-color: var(--ink); - color: var(--ink); + border-color: var(--ink); + color: var(--ink); } .action-btn svg { - width: 10px; - height: 10px; + width: 10px; + height: 10px; } .action-btn.primary { - background: var(--ink); - color: var(--paper); - border-color: var(--ink); + background: var(--ink); + color: var(--paper); + border-color: var(--ink); } .action-btn.primary:hover { - opacity: 0.85; + opacity: 0.85; } .action-btn.close-tabs { - border-color: var(--workspace-chip-border); - color: var(--workspace-chip-text); - background: color-mix(in srgb, var(--workspace-chip-bg) 92%, var(--card-bg) 8%); - border-radius: 8px; - min-height: 28px; - padding: 4px 10px; + border-color: var(--workspace-chip-border); + color: var(--workspace-chip-text); + background: color-mix( + in srgb, + var(--workspace-chip-bg) 92%, + var(--card-bg) 8% + ); + border-radius: 8px; + min-height: 28px; + padding: 4px 10px; } .action-btn.close-tabs:hover { - background: var(--workspace-chip-bg-strong); - border-color: var(--workspace-accent-border); + background: var(--workspace-chip-bg-strong); + border-color: var(--workspace-accent-border); } .action-btn.save-tabs { - border-color: rgba(90, 122, 98, 0.3); - color: var(--accent-sage); - background: rgba(90, 122, 98, 0.04); + border-color: rgba(90, 122, 98, 0.3); + color: var(--accent-sage); + background: rgba(90, 122, 98, 0.04); } .action-btn.save-tabs:hover { - background: rgba(90, 122, 98, 0.1); - border-color: var(--accent-sage); + background: rgba(90, 122, 98, 0.1); + border-color: var(--accent-sage); } .action-btn.danger { - color: var(--status-abandoned); + color: var(--status-abandoned); } .action-btn.danger:hover { - border-color: var(--status-abandoned); - color: var(--status-abandoned); + border-color: var(--status-abandoned); + color: var(--status-abandoned); } /* ---- Workspace pages + saved tab sessions ---- */ .workspace-page-switch { - display: inline-flex; - align-items: center; - gap: 14px; - margin: 0; - padding: 0; - border: none; - border-radius: 0; - background: transparent; + display: inline-flex; + align-items: center; + gap: 14px; + margin: 0; + padding: 0; + border: none; + border-radius: 0; + background: transparent; } .workspace-page-switch-btn { - min-height: 24px; - padding: 0; - border: none; - border-radius: 0; - background: transparent; - color: color-mix(in srgb, var(--muted) 82%, var(--ink) 18%); - cursor: pointer; - font-family: 'Public Sans', sans-serif; - font-size: var(--ui-font-12); - font-weight: 600; - transition: color 0.15s ease, text-decoration-color 0.15s ease; - text-decoration: underline; - text-decoration-thickness: 1px; - text-underline-offset: 0.32em; - text-decoration-color: transparent; + min-height: 24px; + padding: 0; + border: none; + border-radius: 0; + background: transparent; + color: color-mix(in srgb, var(--muted) 82%, var(--ink) 18%); + cursor: pointer; + font-family: "Public Sans", sans-serif; + font-size: var(--ui-font-12); + font-weight: 600; + transition: + color 0.15s ease, + text-decoration-color 0.15s ease; + text-decoration: underline; + text-decoration-thickness: 1px; + text-underline-offset: 0.32em; + text-decoration-color: transparent; } .workspace-page-switch-btn:hover { - color: var(--ink); + color: var(--ink); } .workspace-page-switch-btn.is-active { - color: var(--workspace-chip-text); - text-decoration-color: color-mix(in srgb, var(--workspace-accent-border) 72%, transparent); + color: var(--workspace-chip-text); + text-decoration-color: color-mix( + in srgb, + var(--workspace-accent-border) 72%, + transparent + ); } .workspace-page-switch-inline { - justify-content: flex-end; + justify-content: flex-end; } .workspace-page[hidden] { - display: none !important; + display: none !important; } .saved-tabs-page-header { - display: flex; - flex-direction: column; - gap: 14px; - margin: 0 0 28px; - padding-bottom: 18px; - border-bottom: 1px solid color-mix(in srgb, var(--warm-gray) 58%, transparent); + display: flex; + flex-direction: column; + gap: 14px; + margin: 0 0 28px; + padding-bottom: 18px; + border-bottom: 1px solid + color-mix(in srgb, var(--warm-gray) 58%, transparent); } .saved-tabs-page-toolbar { - display: flex; - justify-content: flex-end; - min-height: 40px; + display: flex; + justify-content: flex-end; + min-height: 40px; } .saved-tabs-page-heading { - min-width: 0; + min-width: 0; } .saved-tabs-page-title { - font-family: 'Libre Caslon Display', serif; - font-size: var(--ui-font-40); - font-weight: 400; - line-height: 1; - color: var(--ink); + font-family: "Libre Caslon Display", serif; + font-size: var(--ui-font-40); + font-weight: 400; + line-height: 1; + color: var(--ink); } .saved-tabs-page-subtitle, .session-picker-subtitle { - max-width: 560px; - margin-top: 8px; - color: color-mix(in srgb, var(--muted) 88%, var(--ink) 12%); - font-size: var(--ui-font-13); - line-height: 1.55; + max-width: 560px; + margin-top: 8px; + color: color-mix(in srgb, var(--muted) 88%, var(--ink) 12%); + font-size: var(--ui-font-13); + line-height: 1.55; } .saved-tabs-page-actions { - display: flex; - align-items: center; - gap: 16px; - justify-content: flex-end; - min-height: 40px; + display: flex; + align-items: center; + gap: 16px; + justify-content: flex-end; + min-height: 40px; } .workspace-tool-spacer { - width: 26px; - height: 26px; - flex: 0 0 26px; - visibility: hidden; - pointer-events: none; + width: 26px; + height: 26px; + flex: 0 0 26px; + visibility: hidden; + pointer-events: none; } .session-picker { - margin: 0 0 30px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 34%, var(--warm-gray) 66%); - border-radius: 8px; - background: color-mix(in srgb, var(--card-bg) calc(var(--panel-card-opacity)), transparent); - box-shadow: 0 14px 34px color-mix(in srgb, var(--shadow) 72%, transparent); - overflow: hidden; + margin: 0 0 30px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 34%, + var(--warm-gray) 66% + ); + border-radius: 8px; + background: color-mix( + in srgb, + var(--card-bg) calc(var(--panel-card-opacity)), + transparent + ); + box-shadow: 0 14px 34px color-mix(in srgb, var(--shadow) 72%, transparent); + overflow: hidden; } .session-picker[hidden] { - display: none !important; + display: none !important; } .session-picker-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 12px; - padding: 16px 18px 14px; - border-bottom: 1px solid color-mix(in srgb, var(--warm-gray) 54%, transparent); + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; + padding: 16px 18px 14px; + border-bottom: 1px solid + color-mix(in srgb, var(--warm-gray) 54%, transparent); } .session-picker-title { - color: var(--ink); - font-size: var(--ui-font-16); - font-weight: 600; - line-height: 1.25; + color: var(--ink); + font-size: var(--ui-font-16); + font-weight: 600; + line-height: 1.25; } .session-picker-list { - display: flex; - flex-direction: column; - max-height: min(58vh, 560px); - overflow: auto; + display: flex; + flex-direction: column; + max-height: min(58vh, 560px); + overflow: auto; } .session-picker-group { - border-bottom: 1px solid color-mix(in srgb, var(--warm-gray) 45%, transparent); + border-bottom: 1px solid + color-mix(in srgb, var(--warm-gray) 45%, transparent); } .session-picker-group:last-child { - border-bottom: none; + border-bottom: none; } .session-picker-group-header, .session-picker-tab-row { - display: grid; - align-items: center; - column-gap: 10px; - cursor: pointer; + display: grid; + align-items: center; + column-gap: 10px; + cursor: pointer; } .session-picker-group-header { - grid-template-columns: 18px minmax(0, 1fr) auto; - min-height: 44px; - padding: 10px 18px; - background: color-mix(in srgb, var(--workspace-chip-bg) 34%, transparent); + grid-template-columns: 18px minmax(0, 1fr) auto; + min-height: 44px; + padding: 10px 18px; + background: color-mix(in srgb, var(--workspace-chip-bg) 34%, transparent); } .session-picker-tabs { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } .session-picker-tab-row { - grid-template-columns: 18px minmax(0, 1.25fr) minmax(160px, 0.9fr); - min-height: 42px; - padding: 8px 18px; - border-top: 1px solid color-mix(in srgb, var(--warm-gray) 28%, transparent); + grid-template-columns: 18px minmax(0, 1.25fr) minmax(160px, 0.9fr); + min-height: 42px; + padding: 8px 18px; + border-top: 1px solid color-mix(in srgb, var(--warm-gray) 28%, transparent); } .session-picker-tab-row:hover { - background: color-mix(in srgb, var(--workspace-chip-bg) 24%, transparent); + background: color-mix(in srgb, var(--workspace-chip-bg) 24%, transparent); } .session-picker input[type="checkbox"] { - appearance: none; - -webkit-appearance: none; - width: 16px; - height: 16px; - margin: 0; - border: 1px solid color-mix(in srgb, var(--muted) 62%, var(--warm-gray) 38%); - border-radius: 4px; - background: color-mix(in srgb, var(--card-bg) 92%, transparent); - cursor: pointer; - position: relative; + appearance: none; + -webkit-appearance: none; + width: 16px; + height: 16px; + margin: 0; + border: 1px solid color-mix(in srgb, var(--muted) 62%, var(--warm-gray) 38%); + border-radius: 4px; + background: color-mix(in srgb, var(--card-bg) 92%, transparent); + cursor: pointer; + position: relative; } .session-picker input[type="checkbox"]:checked { - background: var(--accent-sage); - border-color: var(--accent-sage); + background: var(--accent-sage); + border-color: var(--accent-sage); } .session-picker input[type="checkbox"]:checked::after { - content: ''; - position: absolute; - left: 4px; - top: 1px; - width: 4px; - height: 8px; - border: solid var(--workspace-accent-contrast); - border-width: 0 2px 2px 0; - transform: rotate(45deg); + content: ""; + position: absolute; + left: 4px; + top: 1px; + width: 4px; + height: 8px; + border: solid var(--workspace-accent-contrast); + border-width: 0 2px 2px 0; + transform: rotate(45deg); } .session-picker input[type="checkbox"]:indeterminate { - background: color-mix(in srgb, var(--accent-sage) 72%, var(--card-bg) 28%); - border-color: var(--accent-sage); + background: color-mix(in srgb, var(--accent-sage) 72%, var(--card-bg) 28%); + border-color: var(--accent-sage); } .session-picker input[type="checkbox"]:indeterminate::after { - content: ''; - position: absolute; - left: 3px; - right: 3px; - top: 7px; - height: 2px; - border-radius: 999px; - background: var(--workspace-accent-contrast); + content: ""; + position: absolute; + left: 3px; + right: 3px; + top: 7px; + height: 2px; + border-radius: 999px; + background: var(--workspace-accent-contrast); } .session-picker-group-title, .session-picker-tab-title { - min-width: 0; - color: var(--ink); - font-size: var(--ui-font-13); - line-height: 1.35; + min-width: 0; + color: var(--ink); + font-size: var(--ui-font-13); + line-height: 1.35; } .session-picker-group-title { - font-weight: 600; + font-weight: 600; } .session-picker-group-count, .session-picker-tab-url { - color: var(--muted); - font-size: var(--ui-font-11); - line-height: 1.35; + color: var(--muted); + font-size: var(--ui-font-11); + line-height: 1.35; } .session-picker-tab-title { - display: inline-flex; - align-items: center; - gap: 8px; + display: inline-flex; + align-items: center; + gap: 8px; } .session-picker-tab-title img, .saved-session-tab-chip img { - width: 16px; - height: 16px; - border-radius: 4px; - flex-shrink: 0; + width: 16px; + height: 16px; + border-radius: 4px; + flex-shrink: 0; } .session-picker-tab-title > span:last-child, .session-picker-tab-url { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .session-picker-footer { - display: flex; - align-items: center; - gap: 8px; - padding: 11px 18px; - border-top: 1px solid color-mix(in srgb, var(--workspace-accent-border) 20%, transparent); - background: color-mix(in srgb, var(--card-bg) 74%, var(--paper) 26%); + display: flex; + align-items: center; + gap: 8px; + padding: 11px 18px; + border-top: 1px solid + color-mix(in srgb, var(--workspace-accent-border) 20%, transparent); + background: color-mix(in srgb, var(--card-bg) 74%, var(--paper) 26%); } .session-picker-count { - flex: 1; - color: var(--muted); - font-size: var(--ui-font-12); + flex: 1; + color: var(--muted); + font-size: var(--ui-font-12); } .session-picker-save-mode { - display: inline-flex; - align-items: center; - gap: 2px; - padding: 2px; - border: 1px solid color-mix(in srgb, var(--warm-gray) 62%, transparent); - border-radius: 8px; - background: color-mix(in srgb, var(--workspace-chip-bg) 38%, transparent); + display: inline-flex; + align-items: center; + gap: 2px; + padding: 2px; + border: 1px solid color-mix(in srgb, var(--warm-gray) 62%, transparent); + border-radius: 8px; + background: color-mix(in srgb, var(--workspace-chip-bg) 38%, transparent); } .session-picker-mode-button { - min-height: 28px; - padding: 4px 10px; - border: none; - border-radius: 6px; - background: transparent; - color: var(--muted); - cursor: pointer; - font-family: 'Public Sans', sans-serif; - font-size: var(--ui-font-12); - font-weight: 600; + min-height: 28px; + padding: 4px 10px; + border: none; + border-radius: 6px; + background: transparent; + color: var(--muted); + cursor: pointer; + font-family: "Public Sans", sans-serif; + font-size: var(--ui-font-12); + font-weight: 600; } .session-picker-mode-button:hover:not(:disabled), .session-picker-mode-button.is-active { - background: color-mix(in srgb, var(--card-bg) 92%, transparent); - color: var(--ink); + background: color-mix(in srgb, var(--card-bg) 92%, transparent); + color: var(--ink); } .session-picker-mode-button:disabled { - cursor: not-allowed; - opacity: 0.48; + cursor: not-allowed; + opacity: 0.48; } .session-picker-name-input, .session-picker-target-select { - min-height: 32px; - width: min(220px, 28vw); - max-width: 220px; - border: 1px solid color-mix(in srgb, var(--warm-gray) 66%, transparent); - border-radius: 8px; - background: color-mix(in srgb, var(--card-bg) 88%, transparent); - color: var(--ink); - font-family: 'Public Sans', sans-serif; - font-size: var(--ui-font-12); - padding: 5px 28px 5px 9px; + min-height: 32px; + width: min(220px, 28vw); + max-width: 220px; + border: 1px solid color-mix(in srgb, var(--warm-gray) 66%, transparent); + border-radius: 8px; + background: color-mix(in srgb, var(--card-bg) 88%, transparent); + color: var(--ink); + font-family: "Public Sans", sans-serif; + font-size: var(--ui-font-12); + padding: 5px 28px 5px 9px; } .session-picker-name-input { - padding-right: 9px; + padding-right: 9px; } .session-picker-name-input::placeholder { - color: color-mix(in srgb, var(--muted) 82%, transparent); + color: color-mix(in srgb, var(--muted) 82%, transparent); } .session-picker-name-input:focus { - border-color: var(--workspace-accent-border); - outline: none; - box-shadow: 0 0 0 3px color-mix(in srgb, var(--workspace-accent-soft) 62%, transparent); + border-color: var(--workspace-accent-border); + outline: none; + box-shadow: 0 0 0 3px + color-mix(in srgb, var(--workspace-accent-soft) 62%, transparent); } .session-picker-target-select:disabled { - color: var(--muted); - opacity: 0.55; + color: var(--muted); + opacity: 0.55; } .session-picker .action-btn:disabled { - cursor: not-allowed; - opacity: 0.52; + cursor: not-allowed; + opacity: 0.52; } .saved-sessions-section { - display: flex; - flex-direction: column; - gap: 14px; + display: flex; + flex-direction: column; + gap: 14px; } .saved-tabs-header-spacer { - visibility: hidden; - pointer-events: none; - min-height: 0; - margin: 0; - padding: 0; + visibility: hidden; + pointer-events: none; + min-height: 0; + margin: 0; + padding: 0; } .saved-sessions-list { - display: flex; - flex-direction: column; - gap: 12px; + display: flex; + flex-direction: column; + gap: 12px; } .saved-session-card { - display: block; - padding: 16px 18px; - border: 1px solid color-mix(in srgb, var(--warm-gray) 62%, var(--workspace-accent-border) 18%); - border-radius: 8px; - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 70%), transparent); - box-shadow: 0 10px 24px color-mix(in srgb, var(--shadow) 58%, transparent); + display: block; + padding: 16px 18px; + border: 1px solid + color-mix( + in srgb, + var(--warm-gray) 62%, + var(--workspace-accent-border) 18% + ); + border-radius: 8px; + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 70%), + transparent + ); + box-shadow: 0 10px 24px color-mix(in srgb, var(--shadow) 58%, transparent); } .saved-session-main { - min-width: 0; + min-width: 0; } .saved-session-top { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 10px; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 10px; } .saved-session-heading { - display: flex; - align-items: baseline; - gap: 10px; - flex-wrap: wrap; - flex: 1; - min-width: 0; + display: flex; + align-items: baseline; + gap: 10px; + flex-wrap: wrap; + flex: 1; + min-width: 0; } .saved-session-heading span { - color: var(--muted); - font-size: var(--ui-font-11); + color: var(--muted); + font-size: var(--ui-font-11); } .saved-session-card .mission-name { - font-size: 17px; - line-height: 1.3; + font-size: 17px; + line-height: 1.3; } .saved-session-count-tools { - display: inline-flex; - align-items: center; - justify-content: flex-end; - gap: 10px; - min-width: 0; + display: inline-flex; + align-items: center; + justify-content: flex-end; + gap: 10px; + min-width: 0; } .saved-session-count-text { - white-space: nowrap; + white-space: nowrap; } .saved-session-settings-wrap { - position: relative; - display: inline-flex; - align-items: center; - flex: 0 0 auto; + position: relative; + display: inline-flex; + align-items: center; + flex: 0 0 auto; } .saved-session-settings-trigger { - width: 26px; - height: 26px; - padding: 3px; - color: color-mix(in srgb, var(--muted) 82%, var(--ink) 18%); + width: 26px; + height: 26px; + padding: 3px; + color: color-mix(in srgb, var(--muted) 82%, var(--ink) 18%); } .saved-session-settings-trigger svg { - width: 16px; - height: 16px; + width: 16px; + height: 16px; } .saved-session-settings-menu { - top: calc(100% + 8px); - right: 0; - left: auto; - width: 248px; + top: calc(100% + 8px); + right: 0; + left: auto; + width: 248px; } .saved-session-settings-select { - width: 100%; - min-height: 34px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 28%, var(--warm-gray) 72%); - border-radius: 10px; - background: color-mix(in srgb, var(--card-bg) 92%, transparent); - color: var(--ink); - padding: 0 10px; - font-family: 'Public Sans', sans-serif; - font-size: var(--ui-font-12); + width: 100%; + min-height: 34px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 28%, + var(--warm-gray) 72% + ); + border-radius: 10px; + background: color-mix(in srgb, var(--card-bg) 92%, transparent); + color: var(--ink); + padding: 0 10px; + font-family: "Public Sans", sans-serif; + font-size: var(--ui-font-12); } .saved-session-settings-select:focus-visible { - outline: 2px solid var(--focus-ring); - outline-offset: 2px; - box-shadow: var(--focus-ring-shadow); + outline: 2px solid var(--focus-ring); + outline-offset: 2px; + box-shadow: var(--focus-ring-shadow); } .saved-session-nav-button.is-name-mode { - width: auto; - max-width: 220px; - min-width: 0; - height: auto; - min-height: 24px; - padding: 0 4px; - border: none; - border-radius: 0; - background: transparent; - box-shadow: none; - justify-content: flex-start; - color: color-mix(in srgb, var(--muted) 82%, var(--ink) 18%); - transition: color 0.15s ease, text-decoration-color 0.15s ease, transform 0.15s ease; - text-decoration: underline; - text-decoration-thickness: 1px; - text-underline-offset: 0.32em; - text-decoration-color: transparent; + width: auto; + max-width: 220px; + min-width: 0; + height: auto; + min-height: 24px; + padding: 0 4px; + border: none; + border-radius: 0; + background: transparent; + box-shadow: none; + justify-content: flex-start; + color: color-mix(in srgb, var(--muted) 82%, var(--ink) 18%); + transition: + color 0.15s ease, + text-decoration-color 0.15s ease, + transform 0.15s ease; + text-decoration: underline; + text-decoration-thickness: 1px; + text-underline-offset: 0.32em; + text-decoration-color: transparent; } .saved-session-nav-button.is-name-mode:hover, .saved-session-nav-button.is-name-mode:focus-visible { - border: none; - background: transparent; - box-shadow: none; - color: var(--ink); - text-decoration-color: color-mix(in srgb, var(--workspace-accent-border) 64%, transparent); + border: none; + background: transparent; + box-shadow: none; + color: var(--ink); + text-decoration-color: color-mix( + in srgb, + var(--workspace-accent-border) 64%, + transparent + ); } .saved-session-nav-label { - display: block; - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-size: var(--ui-font-12); - font-weight: 500; - letter-spacing: 0.01em; + display: block; + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: var(--ui-font-12); + font-weight: 500; + letter-spacing: 0.01em; } .saved-session-preview { - display: flex; - flex-direction: column; - gap: 0; - margin-top: 12px; + display: flex; + flex-direction: column; + gap: 0; + margin-top: 12px; } .saved-session-card.is-collapsed .saved-session-preview { - display: none; + display: none; } .saved-session-card.is-collapsed { - padding-top: 8px; - padding-bottom: 8px; + padding-top: 8px; + padding-bottom: 8px; } .saved-session-card.is-collapsed .saved-session-top { - align-items: center; - gap: 6px; + align-items: center; + gap: 6px; } .saved-session-card.is-collapsed .saved-session-heading { - gap: 6px; + gap: 6px; } .saved-session-card.is-collapsed .mission-actions { - gap: 0; + gap: 0; } .saved-session-tab-list { - display: flex; - flex-direction: column; - gap: 0; + display: flex; + flex-direction: column; + gap: 0; } .saved-session-tab-row { - position: relative; - display: grid; - grid-template-columns: auto minmax(0, 1fr) auto; - align-items: center; - column-gap: 8px; - row-gap: 2px; - padding: 8px 2px; - border-bottom: 1px solid rgba(154, 145, 138, 0.12); - transition: opacity 0.2s ease, transform 0.2s ease; - cursor: pointer; + position: relative; + display: grid; + grid-template-columns: auto minmax(0, 1fr) auto; + align-items: center; + column-gap: 8px; + row-gap: 2px; + padding: 8px 2px; + border-bottom: 1px solid rgba(154, 145, 138, 0.12); + transition: + opacity 0.2s ease, + transform 0.2s ease; + cursor: pointer; } .saved-session-tab-row:last-child { - border-bottom: none; + border-bottom: none; } .saved-session-tab-row.is-dragging { - position: fixed; - left: var(--drag-left, 0); - top: var(--drag-top, 0); - width: var(--drag-width, auto); - z-index: 120; - pointer-events: none; - background: color-mix(in srgb, var(--card-bg) 94%, var(--paper) 6%); - box-shadow: 0 12px 24px color-mix(in srgb, var(--ink) 10%, transparent); - border-radius: 8px; - border-bottom: none; + position: fixed; + left: var(--drag-left, 0); + top: var(--drag-top, 0); + width: var(--drag-width, auto); + z-index: 120; + pointer-events: none; + background: color-mix(in srgb, var(--card-bg) 94%, var(--paper) 6%); + box-shadow: 0 12px 24px color-mix(in srgb, var(--ink) 10%, transparent); + border-radius: 8px; + border-bottom: none; } .saved-session-tab-placeholder { - height: 44px; - border-radius: 8px; - background: color-mix(in srgb, var(--workspace-accent-soft) 28%, transparent); - border: 1px dashed color-mix(in srgb, var(--workspace-accent-border) 48%, transparent); + height: 44px; + border-radius: 8px; + background: color-mix( + in srgb, + var(--workspace-accent-soft) 28%, + transparent + ); + border: 1px dashed + color-mix(in srgb, var(--workspace-accent-border) 48%, transparent); } .saved-session-new-slot { - display: flex; - align-items: center; - min-height: 24px; - pointer-events: none; + display: flex; + align-items: center; + min-height: 24px; + pointer-events: none; } .saved-session-new-slot-line { - width: 100%; - border-top: 2px dashed color-mix(in srgb, var(--workspace-accent-border) 60%, var(--warm-gray) 40%); - opacity: 0.9; + width: 100%; + border-top: 2px dashed + color-mix( + in srgb, + var(--workspace-accent-border) 60%, + var(--warm-gray) 40% + ); + opacity: 0.9; } .saved-session-reorder-handle { - flex-shrink: 0; - width: 30px; - height: 30px; + flex-shrink: 0; + width: 30px; + height: 30px; } .saved-session-tab-main { - min-width: 0; - display: inline-flex; - align-items: center; - gap: 6px; + min-width: 0; + display: inline-flex; + align-items: center; + gap: 6px; } .saved-session-tab-main img { - width: 16px; - height: 16px; - border-radius: 4px; - flex-shrink: 0; + width: 16px; + height: 16px; + border-radius: 4px; + flex-shrink: 0; } .saved-session-tab-title { - min-width: 0; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - color: color-mix(in srgb, var(--ink) 78%, var(--muted) 22%); - font-size: var(--ui-font-12); + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: color-mix(in srgb, var(--ink) 78%, var(--muted) 22%); + font-size: var(--ui-font-12); } .saved-session-tab-url { - grid-column: 2 / 3; - min-width: 0; - color: var(--muted); - font-size: var(--ui-font-11); - line-height: 1.35; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + grid-column: 2 / 3; + min-width: 0; + color: var(--muted); + font-size: var(--ui-font-11); + line-height: 1.35; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .saved-session-actions { - display: inline-flex; - align-items: center; - gap: 6px; + display: inline-flex; + align-items: center; + gap: 6px; } .saved-session-restore svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .saved-session-collapse svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .saved-session-collapse::after { - content: none; - display: none; + content: none; + display: none; } .saved-sessions-empty { - padding: 34px 16px; - text-align: center; - color: var(--muted); - font-family: 'Libre Caslon Display', serif; - font-size: var(--ui-font-18); - line-height: 1.45; + padding: 34px 16px; + text-align: center; + color: var(--muted); + font-family: "Libre Caslon Display", serif; + font-size: var(--ui-font-18); + line-height: 1.45; } /* ---- Toast notification ---- */ .toast { - position: fixed; - bottom: 32px; - left: 50%; - transform: translateX(-50%) translateY(80px); - background: var(--ink); - color: var(--paper); - font-family: 'Public Sans', sans-serif; - font-size: 13px; - font-weight: 500; - padding: 12px 24px; - border-radius: 8px; - box-shadow: 0 8px 32px rgba(0,0,0,0.2); - z-index: 100; - opacity: 0; - transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1); - pointer-events: none; - display: flex; - align-items: center; - gap: 8px; + position: fixed; + bottom: 32px; + left: 50%; + transform: translateX(-50%) translateY(80px); + background: var(--ink); + color: var(--paper); + font-family: "Public Sans", sans-serif; + font-size: 13px; + font-weight: 500; + padding: 12px 24px; + border-radius: 8px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2); + z-index: 100; + opacity: 0; + transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1); + pointer-events: none; + display: flex; + align-items: center; + gap: 8px; } .toast.visible { - opacity: 1; - transform: translateX(-50%) translateY(0); - pointer-events: auto; + opacity: 1; + transform: translateX(-50%) translateY(0); + pointer-events: auto; } .toast svg { - width: 16px; - height: 16px; - color: var(--status-active); + width: 16px; + height: 16px; + color: var(--status-active); } -.toast-action[hidden] { display: none !important; } +.toast-action[hidden] { + display: none !important; +} .toast-action { - background: transparent; - border: none; - color: var(--accent-amber); - font: inherit; - font-size: 13px; - font-weight: 600; - cursor: pointer; - padding: 0; - text-decoration: underline; - text-underline-offset: 2px; + background: transparent; + border: none; + color: var(--accent-amber); + font: inherit; + font-size: 13px; + font-weight: 600; + cursor: pointer; + padding: 0; + text-decoration: underline; + text-underline-offset: 2px; } -.toast-action:hover { color: var(--paper); } +.toast-action:hover { + color: var(--paper); +} .shortcut-editor-backdrop[hidden], .shortcut-editor[hidden] { - display: none !important; + display: none !important; } .shortcut-editor-backdrop { - position: fixed; - inset: 0; - background: color-mix(in srgb, var(--ink) 8%, transparent); - z-index: 109; + position: fixed; + inset: 0; + background: color-mix(in srgb, var(--ink) 8%, transparent); + z-index: 109; } .shortcut-editor { - position: fixed; - inset: auto 88px 24px auto; - width: min(360px, calc(100vw - 32px)); - z-index: 110; + position: fixed; + inset: auto 88px 24px auto; + width: min(360px, calc(100vw - 32px)); + z-index: 110; } .shortcut-editor-form { - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) calc(var(--custom-border-opacity) + 10%), var(--warm-gray) 30%); - border-radius: 20px; - background: color-mix(in srgb, var(--card-bg) var(--panel-card-opacity), transparent); - box-shadow: 0 20px 42px color-mix(in srgb, var(--workspace-accent) 14%, transparent); - padding: 18px 18px 18px 18px; - display: flex; - flex-direction: column; - gap: 14px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) + calc(var(--custom-border-opacity) + 10%), + var(--warm-gray) 30% + ); + border-radius: 20px; + background: color-mix( + in srgb, + var(--card-bg) var(--panel-card-opacity), + transparent + ); + box-shadow: 0 20px 42px + color-mix(in srgb, var(--workspace-accent) 14%, transparent); + padding: 18px 18px 18px 18px; + display: flex; + flex-direction: column; + gap: 14px; } .shortcut-editor-header { - display: flex; - align-items: flex-start; - justify-content: space-between; - gap: 16px; + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; } .shortcut-editor-header-main { - display: flex; - align-items: center; - gap: 10px; - min-width: 0; + display: flex; + align-items: center; + gap: 10px; + min-width: 0; } .shortcut-editor-title { - font-family: 'Libre Caslon Display', serif; - font-size: 24px; - font-weight: 400; - line-height: 1.05; - color: var(--ink); + font-family: "Libre Caslon Display", serif; + font-size: 24px; + font-weight: 400; + line-height: 1.05; + color: var(--ink); } -.shortcut-editor-back[hidden] { display: none !important; } -.shortcut-editor-back { display: none; } +.shortcut-editor-back[hidden] { + display: none !important; +} +.shortcut-editor-back { + display: none; +} .shortcut-editor-close { - width: 32px; - height: 32px; - border: none; - border-radius: 999px; - background: transparent; - color: var(--muted); - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; + width: 32px; + height: 32px; + border: none; + border-radius: 999px; + background: transparent; + color: var(--muted); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; } .shortcut-editor-close svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .shortcut-editor-field { - display: flex; - flex-direction: column; - gap: 6px; + display: flex; + flex-direction: column; + gap: 6px; } .shortcut-editor-field-inline { - margin-top: 2px; + margin-top: 2px; } .shortcut-editor-inline-field { - display: grid; - grid-template-columns: auto minmax(0, 1fr); - align-items: center; - gap: 10px; + display: grid; + grid-template-columns: auto minmax(0, 1fr); + align-items: center; + gap: 10px; } .shortcut-editor-label { - font-size: 10px; - letter-spacing: 0.16em; - text-transform: uppercase; - color: var(--muted); - font-weight: 700; + font-size: 10px; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--muted); + font-weight: 700; } .shortcut-editor-input { - width: 100%; - min-height: 40px; - border-radius: 12px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 26%, var(--warm-gray) 74%); - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 74%), transparent); - color: var(--ink); - font: inherit; - padding: 0 12px; + width: 100%; + min-height: 40px; + border-radius: 12px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 26%, + var(--warm-gray) 74% + ); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 74%), + transparent + ); + color: var(--ink); + font: inherit; + padding: 0 12px; } .shortcut-editor-textarea { - min-height: 110px; - resize: vertical; - padding: 10px 12px; - line-height: 1.45; + min-height: 110px; + resize: vertical; + padding: 10px 12px; + line-height: 1.45; } .shortcut-editor-emoji-input { - max-width: 120px; + max-width: 120px; } .shortcut-editor-section { - display: flex; - flex-direction: column; - gap: 12px; + display: flex; + flex-direction: column; + gap: 12px; } .shortcut-editor-mode-stage { - min-height: 152px; + min-height: 152px; } .shortcut-editor-source-row { - display: flex; - align-items: center; - gap: 14px; + display: flex; + align-items: center; + gap: 14px; } .shortcut-editor-source-segments { - display: inline-flex; - align-items: center; - gap: 4px; - padding: 3px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 18%, var(--warm-gray) 82%); - border-radius: 12px; - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 70%), transparent); - flex: 1 1 auto; - min-width: 0; + display: inline-flex; + align-items: center; + gap: 4px; + padding: 3px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 18%, + var(--warm-gray) 82% + ); + border-radius: 12px; + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 70%), + transparent + ); + flex: 1 1 auto; + min-width: 0; } .shortcut-editor-source-chip { - display: inline-flex; - align-items: center; - justify-content: center; - border: none; - background: transparent; - color: color-mix(in srgb, var(--muted) 74%, var(--workspace-chip-text) 26%); - border-radius: 9px; - min-height: 34px; - padding: 0 11px; - flex: 1 1 0; - font: inherit; - font-size: 11px; - font-weight: 600; - cursor: pointer; - transition: color 0.15s ease, background 0.15s ease; + display: inline-flex; + align-items: center; + justify-content: center; + border: none; + background: transparent; + color: color-mix(in srgb, var(--muted) 74%, var(--workspace-chip-text) 26%); + border-radius: 9px; + min-height: 34px; + padding: 0 11px; + flex: 1 1 0; + font: inherit; + font-size: 11px; + font-weight: 600; + cursor: pointer; + transition: + color 0.15s ease, + background 0.15s ease; } .shortcut-editor-source-chip:hover { - color: var(--workspace-chip-text); - background: color-mix(in srgb, var(--workspace-chip-bg) 54%, transparent); + color: var(--workspace-chip-text); + background: color-mix(in srgb, var(--workspace-chip-bg) 54%, transparent); } .shortcut-editor-source-chip[aria-pressed="true"] { - color: var(--workspace-chip-text); - background: color-mix(in srgb, var(--workspace-chip-bg) 88%, var(--card-bg) 12%); + color: var(--workspace-chip-text); + background: color-mix( + in srgb, + var(--workspace-chip-bg) 88%, + var(--card-bg) 12% + ); } .shortcut-editor-mode-group[hidden] { - display: none !important; + display: none !important; } .shortcut-editor-mode-group { - width: 100%; + width: 100%; } .shortcut-editor-mode-note { - font-size: 11px; - color: var(--muted); - line-height: 1.45; + font-size: 11px; + color: var(--muted); + line-height: 1.45; } .shortcut-editor-row { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; } .shortcut-editor-clear { - border: none; - background: transparent; - color: var(--workspace-chip-text); - font-size: 11px; - font-family: 'Public Sans', sans-serif; - font-weight: 600; - cursor: pointer; - padding: 0; - text-decoration: underline; - text-underline-offset: 2px; + border: none; + background: transparent; + color: var(--workspace-chip-text); + font-size: 11px; + font-family: "Public Sans", sans-serif; + font-weight: 600; + cursor: pointer; + padding: 0; + text-decoration: underline; + text-underline-offset: 2px; } .shortcut-editor-preview-wrap { - display: flex; - align-items: center; - gap: 12px; + display: flex; + align-items: center; + gap: 12px; } .shortcut-editor-preview { - width: 40px; - height: 40px; - border-radius: 10px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 10%, var(--warm-gray) 90%); - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 66%), transparent); - display: inline-flex; - align-items: center; - justify-content: center; - overflow: hidden; - flex-shrink: 0; + width: 40px; + height: 40px; + border-radius: 10px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 10%, + var(--warm-gray) 90% + ); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 66%), + transparent + ); + display: inline-flex; + align-items: center; + justify-content: center; + overflow: hidden; + flex-shrink: 0; } .shortcut-editor-field, .shortcut-editor-source-row, .shortcut-editor-mode-stage, .shortcut-editor-footer { - width: 100%; + width: 100%; } .shortcut-editor-preview img { - width: 22px; - height: 22px; - object-fit: contain; + width: 22px; + height: 22px; + object-fit: contain; } .shortcut-editor-preview-fallback { - width: 22px; - height: 22px; - display: inline-flex; - align-items: center; - justify-content: center; - border-radius: 999px; - background: var(--theme-accent-soft); - color: var(--theme-accent-strong); - font-size: 11px; - font-weight: 700; + width: 22px; + height: 22px; + display: inline-flex; + align-items: center; + justify-content: center; + border-radius: 999px; + background: var(--theme-accent-soft); + color: var(--theme-accent-strong); + font-size: 11px; + font-weight: 700; } .shortcut-editor-preview-glyph { - font-size: 20px; - line-height: 1; + font-size: 20px; + line-height: 1; } .shortcut-editor-emoji-chip { - width: 32px; - height: 32px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 22%, var(--warm-gray) 78%); - border-radius: 999px; - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 72%), transparent); - display: inline-flex; - align-items: center; - justify-content: center; - font-size: 17px; - line-height: 1; - cursor: pointer; + width: 32px; + height: 32px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 22%, + var(--warm-gray) 78% + ); + border-radius: 999px; + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 72%), + transparent + ); + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 17px; + line-height: 1; + cursor: pointer; } .shortcut-editor-preview-copy { - display: flex; - flex-direction: column; - gap: 4px; - min-width: 0; + display: flex; + flex-direction: column; + gap: 4px; + min-width: 0; } .shortcut-editor-preview-title { - font-size: 13px; - color: var(--ink); - font-weight: 600; + font-size: 13px; + color: var(--ink); + font-weight: 600; } .shortcut-editor-preview-meta { - font-size: 11px; - color: var(--muted); - line-height: 1.45; + font-size: 11px; + color: var(--muted); + line-height: 1.45; } .shortcut-editor-actions-row, .shortcut-editor-footer { - display: flex; - gap: 10px; + display: flex; + gap: 10px; } .shortcut-editor-footer { - margin-top: 2px; + margin-top: 2px; } .back-to-top { - position: fixed; - left: 24px; - bottom: 28px; - width: 42px; - height: 42px; - border-radius: 999px; - border: 1px solid color-mix(in srgb, var(--warm-gray) var(--floating-border-opacity), transparent); - background: color-mix(in srgb, var(--card-bg) var(--floating-surface-opacity), transparent); - color: var(--accent-amber); - box-shadow: 0 10px 24px rgba(26, 22, 19, 0.12); - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; - opacity: 0; - pointer-events: none; - transform: translateY(8px); - transition: opacity 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease, background 0.18s ease, border-color 0.18s ease; - z-index: 95; - backdrop-filter: blur(10px) saturate(1.02); + position: fixed; + left: 24px; + bottom: 28px; + width: 42px; + height: 42px; + border-radius: 999px; + border: 1px solid + color-mix( + in srgb, + var(--warm-gray) var(--floating-border-opacity), + transparent + ); + background: color-mix( + in srgb, + var(--card-bg) var(--floating-surface-opacity), + transparent + ); + color: var(--accent-amber); + box-shadow: 0 10px 24px rgba(26, 22, 19, 0.12); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + opacity: 0; + pointer-events: none; + transform: translateY(8px); + transition: + opacity 0.18s ease, + transform 0.18s ease, + box-shadow 0.18s ease, + background 0.18s ease, + border-color 0.18s ease; + z-index: 95; + backdrop-filter: blur(10px) saturate(1.02); } .back-to-top.visible { - opacity: 1; - pointer-events: auto; - transform: translateY(0); + opacity: 1; + pointer-events: auto; + transform: translateY(0); } .back-to-top:hover { - background: color-mix(in srgb, var(--card-bg) calc(var(--floating-surface-opacity) + 8%), transparent); - box-shadow: 0 14px 28px rgba(26, 22, 19, 0.16); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--floating-surface-opacity) + 8%), + transparent + ); + box-shadow: 0 14px 28px rgba(26, 22, 19, 0.16); } .back-to-top svg { - width: 18px; - height: 18px; + width: 18px; + height: 18px; } /* ---- Footer ---- */ footer { - margin-top: 48px; - padding-top: 20px; - border-top: 1px solid var(--warm-gray); - display: flex; - justify-content: space-between; - align-items: flex-end; - gap: 16px; - flex-wrap: wrap; + margin-top: 48px; + padding-top: 20px; + border-top: 1px solid var(--warm-gray); + display: flex; + justify-content: space-between; + align-items: flex-end; + gap: 16px; + flex-wrap: wrap; } .footer-stats { - display: flex; - gap: 32px; + display: flex; + gap: 32px; } .stat { - text-align: center; + text-align: center; } .stat-num { - font-family: 'Libre Caslon Display', serif; - font-size: 28px; - font-weight: 300; - color: var(--ink); - line-height: 1; - transition: all 0.3s; + font-family: "Libre Caslon Display", serif; + font-size: 28px; + font-weight: 300; + color: var(--ink); + line-height: 1; + transition: all 0.3s; } .stat-label { - font-size: 10px; - text-transform: uppercase; - letter-spacing: 1.5px; - color: var(--muted); - margin-top: 4px; + font-size: 10px; + text-transform: uppercase; + letter-spacing: 1.5px; + color: var(--muted); + margin-top: 4px; } .last-refresh { - font-size: 11px; - color: var(--muted); + font-size: 11px; + color: var(--muted); } .footer-credit { - color: var(--muted); + color: var(--muted); } .footer-credit-link { - color: inherit; - text-decoration: underline; - text-underline-offset: 2px; - transition: color 0.18s ease; + color: inherit; + text-decoration: underline; + text-underline-offset: 2px; + transition: color 0.18s ease; } .footer-credit-link:hover, .footer-credit-link:focus-visible { - color: var(--theme-accent-strong); + color: var(--theme-accent-strong); } .refresh-btn { - font-family: 'Public Sans', sans-serif; - font-size: 11px; - font-weight: 500; - color: var(--accent-amber); - background: none; - border: none; - cursor: pointer; - text-decoration: underline; - text-underline-offset: 2px; + font-family: "Public Sans", sans-serif; + font-size: 11px; + font-weight: 500; + color: var(--accent-amber); + background: none; + border: none; + cursor: pointer; + text-decoration: underline; + text-underline-offset: 2px; } /* ---- Animations ---- */ @keyframes fadeUp { - from { opacity: 0; transform: translateY(12px); } - to { opacity: 1; transform: translateY(0); } + from { + opacity: 0; + transform: translateY(12px); + } + to { + opacity: 1; + transform: translateY(0); + } } -body.entry-animations-enabled header { animation: fadeUp 0.5s ease both; } -body.entry-animations-enabled .tab-cleanup-banner { animation: fadeUp 0.5s ease 0.1s both; } -body.entry-animations-enabled .nudge-banner { animation: fadeUp 0.5s ease 0.15s both; } -body.entry-animations-enabled .active-section .section-header { animation: fadeUp 0.5s ease 0.2s both; } -body.entry-animations-enabled .abandoned-section .section-header { animation: fadeUp 0.5s ease 0.45s both; } -body.entry-animations-enabled footer { animation: fadeUp 0.5s ease 0.65s both; } -body.entry-animations-enabled .deferred-column .section-header { animation: fadeUp 0.5s ease 0.1s both; } - +body.entry-animations-enabled header { + animation: fadeUp 0.5s ease both; +} +body.entry-animations-enabled .tab-cleanup-banner { + animation: fadeUp 0.5s ease 0.1s both; +} +body.entry-animations-enabled .nudge-banner { + animation: fadeUp 0.5s ease 0.15s both; +} +body.entry-animations-enabled .active-section .section-header { + animation: fadeUp 0.5s ease 0.2s both; +} +body.entry-animations-enabled .abandoned-section .section-header { + animation: fadeUp 0.5s ease 0.45s both; +} +body.entry-animations-enabled footer { + animation: fadeUp 0.5s ease 0.65s both; +} +body.entry-animations-enabled .deferred-column .section-header { + animation: fadeUp 0.5s ease 0.1s both; +} /* ================================================================ STATIC DEFAULT VIEW — new elements added for "AI on demand" @@ -3119,13 +3635,13 @@ body.entry-animations-enabled .deferred-column .section-header { animation: fade /* ---- Neutral status bar (domain-grouped cards, no AI color) ---- */ .status-bar.neutral { - background: var(--warm-gray); + background: var(--warm-gray); } /* ---- "Domain" tag on static domain cards ---- */ .mission-tag.neutral { - color: var(--muted); - background: rgba(154, 145, 138, 0.1); + color: var(--muted); + background: rgba(154, 145, 138, 0.1); } /* ================================================================ @@ -3135,70 +3651,76 @@ body.entry-animations-enabled .deferred-column .section-header { animation: fade ================================================================ */ .missions-empty-state { - /* Takes the full width — spans all columns */ - column-span: all; + /* Takes the full width — spans all columns */ + column-span: all; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 12px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 12px; - padding: 56px 24px; - text-align: center; + padding: 56px 24px; + text-align: center; - animation: fadeUp 0.5s ease both; + animation: fadeUp 0.5s ease both; } /* CSS-drawn checkmark in a glowing circle */ .empty-checkmark { - width: 56px; - height: 56px; - border-radius: 50%; - background: rgba(90, 122, 98, 0.1); - border: 1.5px solid rgba(90, 122, 98, 0.3); - - /* Soft sage glow */ - box-shadow: 0 0 0 8px rgba(90, 122, 98, 0.05), - 0 0 0 16px rgba(90, 122, 98, 0.03); - - display: flex; - align-items: center; - justify-content: center; + width: 56px; + height: 56px; + border-radius: 50%; + background: rgba(90, 122, 98, 0.1); + border: 1.5px solid rgba(90, 122, 98, 0.3); + + /* Soft sage glow */ + box-shadow: + 0 0 0 8px rgba(90, 122, 98, 0.05), + 0 0 0 16px rgba(90, 122, 98, 0.03); + + display: flex; + align-items: center; + justify-content: center; - /* Pop in with a gentle scale animation */ - animation: checkPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s both; + /* Pop in with a gentle scale animation */ + animation: checkPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) 0.1s both; } .empty-checkmark svg { - width: 26px; - height: 26px; - color: var(--accent-sage); - stroke-width: 2.5; + width: 26px; + height: 26px; + color: var(--accent-sage); + stroke-width: 2.5; } @keyframes checkPop { - from { transform: scale(0.6); opacity: 0; } - to { transform: scale(1); opacity: 1; } + from { + transform: scale(0.6); + opacity: 0; + } + to { + transform: scale(1); + opacity: 1; + } } .empty-title { - font-family: 'Libre Caslon Display', serif; - font-size: 20px; - font-weight: 400; - font-style: italic; - color: var(--ink); - letter-spacing: -0.3px; + font-family: "Libre Caslon Display", serif; + font-size: 20px; + font-weight: 400; + font-style: italic; + color: var(--ink); + letter-spacing: -0.3px; } .empty-subtitle { - font-size: 13px; - color: var(--muted); - font-weight: 400; - letter-spacing: 0.3px; + font-size: 13px; + color: var(--muted); + font-weight: 400; + letter-spacing: 0.3px; } - /* ================================================================ UPDATE BANNER Appears at the very top of the page when a new version is available. @@ -3208,1562 +3730,1734 @@ body.entry-animations-enabled .deferred-column .section-header { animation: fade ================================================================ */ .update-banner { - /* Thin bar — sits above the header, below the container's top padding */ - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; + /* Thin bar — sits above the header, below the container's top padding */ + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; - /* Sage green tint — matches accent-sage but very light */ - background: linear-gradient(135deg, rgba(90, 122, 98, 0.05), rgba(90, 122, 98, 0.10)); - border: 1px solid rgba(90, 122, 98, 0.22); - border-radius: 8px; - padding: 10px 16px; + /* Sage green tint — matches accent-sage but very light */ + background: linear-gradient( + 135deg, + rgba(90, 122, 98, 0.05), + rgba(90, 122, 98, 0.1) + ); + border: 1px solid rgba(90, 122, 98, 0.22); + border-radius: 8px; + padding: 10px 16px; - /* Push the header down slightly */ - margin-bottom: 24px; + /* Push the header down slightly */ + margin-bottom: 24px; - /* Slide in from above when it appears */ - animation: bannerSlideIn 0.35s cubic-bezier(0.16, 1, 0.3, 1) both; + /* Slide in from above when it appears */ + animation: bannerSlideIn 0.35s cubic-bezier(0.16, 1, 0.3, 1) both; } @keyframes bannerSlideIn { - from { opacity: 0; transform: translateY(-8px); } - to { opacity: 1; transform: translateY(0); } + from { + opacity: 0; + transform: translateY(-8px); + } + to { + opacity: 1; + transform: translateY(0); + } } /* Left cluster: icon + text */ .update-banner-left { - display: flex; - align-items: center; - gap: 10px; - flex: 1; - min-width: 0; /* prevents text overflow from breaking layout */ + display: flex; + align-items: center; + gap: 10px; + flex: 1; + min-width: 0; /* prevents text overflow from breaking layout */ } .update-banner-icon { - width: 16px; - height: 16px; - color: var(--accent-sage); - flex-shrink: 0; - opacity: 0.85; + width: 16px; + height: 16px; + color: var(--accent-sage); + flex-shrink: 0; + opacity: 0.85; } .update-banner-text { - font-size: 13px; - font-size: var(--ui-font-13); - color: var(--ink); - font-weight: 400; - line-height: 1.4; - opacity: 0.85; + font-size: 13px; + font-size: var(--ui-font-13); + color: var(--ink); + font-weight: 400; + line-height: 1.4; + opacity: 0.85; } /* Right cluster: action button + dismiss X */ .update-banner-right { - display: flex; - align-items: center; - gap: 8px; - flex-shrink: 0; + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; } /* "Update now" button — small, filled, sage green */ .update-banner-btn { - font-family: 'Public Sans', sans-serif; - font-size: 12px; - font-size: var(--ui-font-12); - font-weight: 500; - color: #fff; - background: var(--accent-sage); - border: none; - border-radius: 5px; - padding: 5px 12px; - cursor: pointer; - letter-spacing: 0.2px; - transition: background 0.2s, opacity 0.2s; - white-space: nowrap; + font-family: "Public Sans", sans-serif; + font-size: 12px; + font-size: var(--ui-font-12); + font-weight: 500; + color: #fff; + background: var(--accent-sage); + border: none; + border-radius: 5px; + padding: 5px 12px; + cursor: pointer; + letter-spacing: 0.2px; + transition: + background 0.2s, + opacity 0.2s; + white-space: nowrap; } .update-banner-btn:hover { - background: #4a6952; /* slightly darker sage */ + background: #4a6952; /* slightly darker sage */ } .update-banner-btn:disabled { - opacity: 0.55; - cursor: not-allowed; + opacity: 0.55; + cursor: not-allowed; } /* Dismiss X button — minimal, icon-only */ .update-banner-dismiss { - display: flex; - align-items: center; - justify-content: center; - width: 24px; - height: 24px; - border: none; - background: transparent; - cursor: pointer; - border-radius: 4px; - color: var(--muted); - transition: background 0.15s, color 0.15s; - padding: 0; - flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + width: 24px; + height: 24px; + border: none; + background: transparent; + cursor: pointer; + border-radius: 4px; + color: var(--muted); + transition: + background 0.15s, + color 0.15s; + padding: 0; + flex-shrink: 0; } .update-banner-dismiss:hover { - background: rgba(26, 22, 19, 0.06); - color: var(--ink); + background: rgba(26, 22, 19, 0.06); + color: var(--ink); } .update-banner-dismiss svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } - /* ================================================================ SAVED FOR LATER — Checklist Column + Archive ================================================================ */ /* ---- Two-column layout ---- */ .dashboard-columns { - display: grid; - grid-template-columns: minmax(0, 1.35fr) minmax(320px, 0.95fr); - column-gap: 40px; - row-gap: 24px; - align-items: flex-start; - justify-content: space-between; + display: grid; + grid-template-columns: minmax(0, 1.35fr) minmax(320px, 0.95fr); + column-gap: 40px; + row-gap: 24px; + align-items: flex-start; + justify-content: space-between; } .dashboard-columns .active-section { - grid-column: 1; - grid-row: 1 / span 2; - min-width: 0; - width: 100%; + grid-column: 1; + grid-row: 1 / span 2; + min-width: 0; + width: 100%; } .dashboard-columns .page-header { - grid-column: 2; - grid-row: 1; + grid-column: 2; + grid-row: 1; } .drawer-trigger-stack { - position: fixed; - right: 0; - top: 50%; - display: flex; - flex-direction: column; - gap: 10px; - z-index: 92; + position: fixed; + right: 0; + top: 50%; + display: flex; + flex-direction: column; + gap: 10px; + z-index: 92; } .deferred-trigger { - position: relative; - width: 42px; - height: 42px; - border: 1px solid var(--drawer-trigger-border); - border-right: none; - border-radius: 11px 0 0 11px; - background: var(--drawer-trigger-surface); - color: var(--drawer-trigger-icon); - box-shadow: 0 8px 18px color-mix(in srgb, var(--workspace-accent) 10%, transparent); - padding: 0; - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease, background 0.18s ease, color 0.18s ease; + position: relative; + width: 42px; + height: 42px; + border: 1px solid var(--drawer-trigger-border); + border-right: none; + border-radius: 11px 0 0 11px; + background: var(--drawer-trigger-surface); + color: var(--drawer-trigger-icon); + box-shadow: 0 8px 18px + color-mix(in srgb, var(--workspace-accent) 10%, transparent); + padding: 0; + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: + transform 0.18s ease, + box-shadow 0.18s ease, + border-color 0.18s ease, + background 0.18s ease, + color 0.18s ease; } .deferred-trigger:hover { - transform: translateX(-2px); - background: var(--drawer-trigger-surface-hover); - border-color: var(--drawer-trigger-border-hover); - box-shadow: 0 12px 22px color-mix(in srgb, var(--workspace-accent) 16%, transparent); + transform: translateX(-2px); + background: var(--drawer-trigger-surface-hover); + border-color: var(--drawer-trigger-border-hover); + box-shadow: 0 12px 22px + color-mix(in srgb, var(--workspace-accent) 16%, transparent); } .deferred-trigger-icon { - width: 18px; - height: 18px; - flex-shrink: 0; + width: 18px; + height: 18px; + flex-shrink: 0; } .deferred-trigger[aria-expanded="true"] { - background: color-mix(in srgb, var(--card-bg) 86%, var(--workspace-accent-soft) 14%); - border-color: var(--drawer-trigger-border-hover); - box-shadow: 0 18px 30px color-mix(in srgb, var(--workspace-accent) 18%, transparent); + background: color-mix( + in srgb, + var(--card-bg) 86%, + var(--workspace-accent-soft) 14% + ); + border-color: var(--drawer-trigger-border-hover); + box-shadow: 0 18px 30px + color-mix(in srgb, var(--workspace-accent) 18%, transparent); } .todo-trigger { - position: relative; - min-width: 42px; + position: relative; + min-width: 42px; } .deferred-overlay { - position: fixed; - inset: 0; - background: rgba(26, 22, 19, 0.01); - opacity: 0; - pointer-events: none; - transition: opacity 0.2s ease; - z-index: 90; + position: fixed; + inset: 0; + background: rgba(26, 22, 19, 0.01); + opacity: 0; + pointer-events: none; + transition: opacity 0.2s ease; + z-index: 90; } .deferred-overlay.visible { - opacity: 1; - pointer-events: auto; + opacity: 1; + pointer-events: auto; } /* Right drawer — overlay on desktop, full-screen on mobile */ .deferred-column { - position: fixed; - top: 20px; - right: 20px; - bottom: 20px; - width: min(392px, calc(100vw - 40px)); - padding: 0; - background: transparent; - opacity: 0; - pointer-events: none; - transform: translateX(24px); - transition: opacity 0.22s ease, transform 0.22s ease; - z-index: 91; + position: fixed; + top: 20px; + right: 20px; + bottom: 20px; + width: min(392px, calc(100vw - 40px)); + padding: 0; + background: transparent; + opacity: 0; + pointer-events: none; + transform: translateX(24px); + transition: + opacity 0.22s ease, + transform 0.22s ease; + z-index: 91; } .deferred-column.open { - opacity: 1; - pointer-events: auto; - transform: translateX(0); + opacity: 1; + pointer-events: auto; + transform: translateX(0); } .deferred-shell { - height: 100%; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) calc(var(--custom-border-opacity) + 18%), var(--warm-gray) 26%); - border-radius: 18px; - background: color-mix(in srgb, var(--card-bg) var(--panel-card-opacity), transparent); - box-shadow: 0 20px 38px color-mix(in srgb, var(--workspace-accent) 16%, transparent); - padding: 24px 22px 22px; - overflow-y: auto; - backdrop-filter: blur(10px); + height: 100%; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) + calc(var(--custom-border-opacity) + 18%), + var(--warm-gray) 26% + ); + border-radius: 18px; + background: color-mix( + in srgb, + var(--card-bg) var(--panel-card-opacity), + transparent + ); + box-shadow: 0 20px 38px + color-mix(in srgb, var(--workspace-accent) 16%, transparent); + padding: 24px 22px 22px; + overflow-y: auto; + backdrop-filter: blur(10px); } .drawer-panel { - display: none; + display: none; } .drawer-panel.is-active { - display: block; + display: block; } .deferred-header { - padding-bottom: 8px; - animation: none !important; + padding-bottom: 8px; + animation: none !important; } .drawer-title-switch { - display: inline-flex; - align-items: center; - gap: 12px; - flex-shrink: 0; + display: inline-flex; + align-items: center; + gap: 12px; + flex-shrink: 0; } .drawer-title-btn { - border: none; - background: transparent; - padding: 0 0 2px; - font-family: 'Libre Caslon Display', serif; - font-weight: 400; - font-size: 22px; - font-size: var(--ui-font-22); - line-height: 1.02; - color: var(--drawer-tab-idle); - cursor: pointer; - text-decoration: underline; - text-decoration-color: transparent; - text-decoration-thickness: 1px; - text-underline-offset: 5px; - transition: color 0.15s ease, opacity 0.15s ease, text-decoration-color 0.15s ease; + border: none; + background: transparent; + padding: 0 0 2px; + font-family: "Libre Caslon Display", serif; + font-weight: 400; + font-size: 22px; + font-size: var(--ui-font-22); + line-height: 1.02; + color: var(--drawer-tab-idle); + cursor: pointer; + text-decoration: underline; + text-decoration-color: transparent; + text-decoration-thickness: 1px; + text-underline-offset: 5px; + transition: + color 0.15s ease, + opacity 0.15s ease, + text-decoration-color 0.15s ease; } .drawer-title-btn.is-active, .drawer-title-btn[aria-selected="true"] { - color: var(--ink); - text-decoration-color: var(--drawer-tab-underline-active); + color: var(--ink); + text-decoration-color: var(--drawer-tab-underline-active); } .drawer-title-btn:not(.is-active):hover, .drawer-title-btn[aria-selected="false"]:hover { - color: var(--drawer-tab-hover); - text-decoration-color: var(--drawer-tab-underline-hover); + color: var(--drawer-tab-hover); + text-decoration-color: var(--drawer-tab-underline-hover); } .drawer-title-btn:not(.is-active):active, .drawer-title-btn[aria-selected="false"]:active { - color: var(--drawer-tab-pressed); - text-decoration-color: var(--drawer-tab-underline-pressed); + color: var(--drawer-tab-pressed); + text-decoration-color: var(--drawer-tab-underline-pressed); } .drawer-header-actions { - display: flex; - align-items: center; - gap: 8px; + display: flex; + align-items: center; + gap: 8px; } .drawer-icon-btn { - width: 32px; - height: 32px; - border: none; - background: transparent; - color: var(--muted); - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; - border-radius: 999px; - transition: color 0.15s ease, background 0.15s ease, opacity 0.15s ease; - opacity: 0.7; + width: 32px; + height: 32px; + border: none; + background: transparent; + color: var(--muted); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + border-radius: 999px; + transition: + color 0.15s ease, + background 0.15s ease, + opacity 0.15s ease; + opacity: 0.7; } .drawer-icon-btn:hover { - color: var(--accent-amber); - background: rgba(200, 113, 58, 0.08); - opacity: 1; + color: var(--accent-amber); + background: rgba(200, 113, 58, 0.08); + opacity: 1; } .drawer-icon-btn svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .mission-card.group-nav-target, .saved-session-card.group-nav-target { - box-shadow: 0 0 0 2px rgba(200, 113, 58, 0.18), 0 10px 24px rgba(26, 22, 19, 0.08); + box-shadow: + 0 0 0 2px rgba(200, 113, 58, 0.18), + 0 10px 24px rgba(26, 22, 19, 0.08); } /* On narrow screens, stack vertically */ @media (max-width: 960px) { - .dashboard-columns { - grid-template-columns: 1fr; - row-gap: 20px; - } - .dashboard-columns .active-section, - .dashboard-columns .page-header { - grid-column: 1; - grid-row: auto; - } - .page-header { - justify-content: flex-start; - text-align: left; - padding: 20px 18px; - } - .header-left { - align-items: flex-start; - } - .header-title-row { - justify-content: flex-start; - gap: 12px; - } - .hitokoto { - max-width: 100%; - } - .quick-tabs-grid { - gap: 12px 10px; - } - .theme-menu { - width: min(320px, calc(100vw - 32px)); - } - .saved-tabs-page-header, - .saved-session-card { - grid-template-columns: 1fr; - } - .saved-tabs-page-header { - flex-direction: column; - gap: 14px; - } - .saved-tabs-page-actions, - .saved-session-actions { - justify-content: flex-start; - } - .session-picker-tab-row { - grid-template-columns: 18px minmax(0, 1fr); - row-gap: 3px; - } - .session-picker-tab-url { - grid-column: 2; - min-width: 0; - } - .deferred-trigger { - min-width: 44px; - width: 44px; - min-height: 44px; - height: 44px; - border-radius: 999px; - padding: 0; - justify-content: center; - } - .drawer-trigger-stack { - right: 12px; - top: auto; - bottom: 24px; - gap: 8px; - } - .deferred-trigger:hover { - transform: translateY(-1px); - } - .deferred-column { - inset: 0; - width: 100%; - transform: translateY(20px); - } - .deferred-column.open { - transform: translateY(0); - } - .deferred-shell { - border-radius: 0; - padding: 18px 16px 20px; - } - .group-nav { - gap: 6px; - } - .group-nav-button { - width: 30px; - height: 30px; - } - .back-to-top { - left: 18px; - bottom: 20px; - width: 44px; - height: 44px; - } - .drawer-icon-btn, - .archive-item-delete, - .deferred-action-btn, - .drawer-reorder-handle { - width: 36px; - height: 36px; - } + .dashboard-columns { + grid-template-columns: 1fr; + row-gap: 20px; + } + .dashboard-columns .active-section, + .dashboard-columns .page-header { + grid-column: 1; + grid-row: auto; + } + .page-header { + justify-content: flex-start; + text-align: left; + padding: 20px 18px; + } + .header-left { + align-items: flex-start; + } + .header-title-row { + justify-content: flex-start; + gap: 12px; + } + .hitokoto { + max-width: 100%; + } + .quick-tabs-grid { + gap: 12px 10px; + } + .theme-menu { + width: min(320px, calc(100vw - 32px)); + } + .saved-tabs-page-header, + .saved-session-card { + grid-template-columns: 1fr; + } + .saved-tabs-page-header { + flex-direction: column; + gap: 14px; + } + .saved-tabs-page-actions, + .saved-session-actions { + justify-content: flex-start; + } + .session-picker-tab-row { + grid-template-columns: 18px minmax(0, 1fr); + row-gap: 3px; + } + .session-picker-tab-url { + grid-column: 2; + min-width: 0; + } + .deferred-trigger { + min-width: 44px; + width: 44px; + min-height: 44px; + height: 44px; + border-radius: 999px; + padding: 0; + justify-content: center; + } + .drawer-trigger-stack { + right: 12px; + top: auto; + bottom: 24px; + gap: 8px; + } + .deferred-trigger:hover { + transform: translateY(-1px); + } + .deferred-column { + inset: 0; + width: 100%; + transform: translateY(20px); + } + .deferred-column.open { + transform: translateY(0); + } + .deferred-shell { + border-radius: 0; + padding: 18px 16px 20px; + } + .group-nav { + gap: 6px; + } + .group-nav-button { + width: 30px; + height: 30px; + } + .back-to-top { + left: 18px; + bottom: 20px; + width: 44px; + height: 44px; + } + .drawer-icon-btn, + .archive-item-delete, + .deferred-action-btn, + .drawer-reorder-handle { + width: 36px; + height: 36px; + } } /* ---- Checklist items ---- */ .deferred-item { - display: flex; - align-items: flex-start; - gap: 12px; - padding: 12px 0; - border-bottom: 1px solid rgba(154, 145, 138, 0.12); - animation: fadeUp 0.3s ease both; - position: relative; + display: flex; + align-items: flex-start; + gap: 12px; + padding: 12px 0; + border-bottom: 1px solid rgba(154, 145, 138, 0.12); + animation: fadeUp 0.3s ease both; + position: relative; } .deferred-item:last-child { - border-bottom: none; + border-bottom: none; } /* Custom checkbox */ .deferred-checkbox { - appearance: none; - -webkit-appearance: none; - width: 18px; - height: 18px; - border: 2px solid var(--warm-gray); - border-radius: 4px; - cursor: pointer; - flex-shrink: 0; - margin-top: 1px; - transition: all 0.2s; - position: relative; + appearance: none; + -webkit-appearance: none; + width: 18px; + height: 18px; + border: 2px solid var(--warm-gray); + border-radius: 4px; + cursor: pointer; + flex-shrink: 0; + margin-top: 1px; + transition: all 0.2s; + position: relative; } .deferred-checkbox:hover { - border-color: var(--accent-sage); + border-color: var(--accent-sage); } .deferred-checkbox:checked { - background: var(--accent-sage); - border-color: var(--accent-sage); + background: var(--accent-sage); + border-color: var(--accent-sage); } /* Checkmark inside the checkbox */ .deferred-checkbox:checked::after { - content: ''; - position: absolute; - top: 2px; - left: 5px; - width: 4px; - height: 8px; - border: solid white; - border-width: 0 2px 2px 0; - transform: rotate(45deg); + content: ""; + position: absolute; + top: 2px; + left: 5px; + width: 4px; + height: 8px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); } /* Item content (title, domain, time) */ .deferred-info { - flex: 1; - min-width: 0; + flex: 1; + min-width: 0; } .deferred-title { - font-size: 14px; - font-size: var(--ui-font-14); - line-height: 1.45; - color: var(--ink); - text-decoration: none; - display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - transition: color 0.15s; + font-size: 14px; + font-size: var(--ui-font-14); + line-height: 1.45; + color: var(--ink); + text-decoration: none; + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + transition: color 0.15s; } .deferred-title:hover { - color: var(--accent-amber); + color: var(--accent-amber); } .deferred-meta { - font-size: 11px; - font-size: var(--ui-font-11); - color: var(--muted); - margin-top: 2px; - display: flex; - gap: 8px; + font-size: 11px; + font-size: var(--ui-font-11); + color: var(--muted); + margin-top: 2px; + display: flex; + gap: 8px; } .deferred-actions { - display: flex; - align-items: center; - gap: 4px; - flex-shrink: 0; + display: flex; + align-items: center; + gap: 4px; + flex-shrink: 0; } .drawer-reorder-handle { - width: 28px; - height: 28px; - border: none; - background: transparent; - color: color-mix(in srgb, var(--ink) 86%, var(--muted) 14%); - display: inline-flex; - align-items: center; - justify-content: center; - cursor: grab; - border-radius: 999px; - opacity: 1; - box-shadow: none; - transition: opacity 0.15s ease, color 0.15s ease, background 0.15s ease; + width: 28px; + height: 28px; + border: none; + background: transparent; + color: color-mix(in srgb, var(--ink) 86%, var(--muted) 14%); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: grab; + border-radius: 999px; + opacity: 1; + box-shadow: none; + transition: + opacity 0.15s ease, + color 0.15s ease, + background 0.15s ease; } .drawer-reorder-handle:hover { - opacity: 1; - color: var(--ink); - background: rgba(154, 145, 138, 0.08); + opacity: 1; + color: var(--ink); + background: rgba(154, 145, 138, 0.08); } .drawer-reorder-handle:active { - cursor: grabbing; + cursor: grabbing; } .drawer-reorder-handle svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .todo-reorder-handle { - width: 30px; - height: 30px; - color: color-mix(in srgb, var(--ink) 84%, var(--muted) 16%); + width: 30px; + height: 30px; + color: color-mix(in srgb, var(--ink) 84%, var(--muted) 16%); } .todo-reorder-handle:hover, .todo-reorder-handle:focus-visible { - color: var(--ink); - background: color-mix(in srgb, var(--workspace-chip-bg) 76%, transparent); + color: var(--ink); + background: color-mix(in srgb, var(--workspace-chip-bg) 76%, transparent); } .todo-reorder-handle svg { - width: 16px; - height: 16px; + width: 16px; + height: 16px; } body.drawer-list-dragging { - cursor: grabbing; - user-select: none; + cursor: grabbing; + user-select: none; } body.drawer-list-dragging .drawer-reorder-handle { - cursor: grabbing; + cursor: grabbing; } body.page-chip-list-dragging { - cursor: grabbing; - user-select: none; + cursor: grabbing; + user-select: none; } body.page-chip-list-dragging .chip-reorder-handle { - cursor: grabbing; + cursor: grabbing; } body.page-chip-drag-armed, body.page-chip-drag-armed * { - user-select: none; - -webkit-user-select: none; + user-select: none; + -webkit-user-select: none; } body.page-chip-drop-new-group .main-content { - outline: none; + outline: none; } .mission-drop-new-group-slot { - grid-column: 1 / -1; - display: flex; - align-items: center; - min-height: 24px; - pointer-events: none; + grid-column: 1 / -1; + display: flex; + align-items: center; + min-height: 24px; + pointer-events: none; } .mission-drop-new-group-line { - width: 100%; - border-top: 2px dashed color-mix(in srgb, var(--workspace-accent-border) 60%, var(--warm-gray) 40%); - opacity: 0.9; + width: 100%; + border-top: 2px dashed + color-mix( + in srgb, + var(--workspace-accent-border) 60%, + var(--warm-gray) 40% + ); + opacity: 0.9; } .page-chip.is-dragging { - position: fixed; - left: var(--drag-left, 0); - top: var(--drag-top, 0); - width: var(--drag-width, auto); - z-index: 120; - pointer-events: none; - opacity: 0; + position: fixed; + left: var(--drag-left, 0); + top: var(--drag-top, 0); + width: var(--drag-width, auto); + z-index: 120; + pointer-events: none; + opacity: 0; } .chip-reorder-placeholder { - border: 1px dashed rgba(154, 145, 138, 0.28); - border-radius: 12px; - background: rgba(248, 245, 240, 0.72); - margin: 4px 0; + border: 1px dashed rgba(154, 145, 138, 0.28); + border-radius: 12px; + background: rgba(248, 245, 240, 0.72); + margin: 4px 0; } .todo-item.is-dragging { - position: fixed; - left: var(--drag-left, 0); - top: var(--drag-top, 0); - width: var(--drag-width, auto); - z-index: 120; - pointer-events: none; - border-bottom-color: transparent; - border-radius: 12px; - background: rgba(255, 253, 249, 0.96); - box-shadow: 0 18px 34px rgba(26, 22, 19, 0.16); + position: fixed; + left: var(--drag-left, 0); + top: var(--drag-top, 0); + width: var(--drag-width, auto); + z-index: 120; + pointer-events: none; + border-bottom-color: transparent; + border-radius: 12px; + background: rgba(255, 253, 249, 0.96); + box-shadow: 0 18px 34px rgba(26, 22, 19, 0.16); } .drawer-reorder-placeholder { - border: 1px dashed rgba(154, 145, 138, 0.28); - border-radius: 12px; - background: rgba(248, 245, 240, 0.72); - margin: 4px 0; + border: 1px dashed rgba(154, 145, 138, 0.28); + border-radius: 12px; + background: rgba(248, 245, 240, 0.72); + margin: 4px 0; } .deferred-action-btn { - background: none; - border: none; - color: var(--muted); - cursor: pointer; - width: 28px; - height: 28px; - padding: 0; - opacity: 0.35; - border-radius: 999px; - transition: opacity 0.15s ease, color 0.15s ease, background 0.15s ease; + background: none; + border: none; + color: var(--muted); + cursor: pointer; + width: 28px; + height: 28px; + padding: 0; + opacity: 0.35; + border-radius: 999px; + transition: + opacity 0.15s ease, + color 0.15s ease, + background 0.15s ease; } .deferred-action-btn svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .deferred-action-btn:hover { - opacity: 1; + opacity: 1; } .deferred-restore:hover { - color: var(--accent-sage); - background: rgba(90, 122, 98, 0.08); + color: var(--accent-sage); + background: rgba(90, 122, 98, 0.08); } /* Checked-off item — strikethrough + faded */ .deferred-item.checked .deferred-title { - text-decoration: line-through; - color: var(--muted); + text-decoration: line-through; + color: var(--muted); } .deferred-item.checked .deferred-meta { - opacity: 0.5; + opacity: 0.5; } /* Dismiss (X) button */ .deferred-dismiss { - background: none; - border: none; - color: var(--muted); - cursor: pointer; - padding: 2px; - opacity: 0.3; - transition: opacity 0.15s, color 0.15s; - flex-shrink: 0; - margin-top: 1px; + background: none; + border: none; + color: var(--muted); + cursor: pointer; + padding: 2px; + opacity: 0.3; + transition: + opacity 0.15s, + color 0.15s; + flex-shrink: 0; + margin-top: 1px; } .deferred-dismiss svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .deferred-dismiss:hover { - opacity: 1; - color: var(--status-abandoned); + opacity: 1; + color: var(--status-abandoned); } /* Slide-out animation for items being removed */ .deferred-item.removing { - opacity: 0; - transform: translateX(20px); - transition: opacity 0.3s ease, transform 0.3s ease; + opacity: 0; + transform: translateX(20px); + transition: + opacity 0.3s ease, + transform 0.3s ease; } /* ---- Empty state ---- */ .deferred-empty { - font-size: 13px; - font-size: var(--ui-font-13); - color: var(--muted); - font-style: italic; - padding: 24px 0; - text-align: center; + font-size: 13px; + font-size: var(--ui-font-13); + color: var(--muted); + font-style: italic; + padding: 24px 0; + text-align: center; } /* ---- Archive section ---- */ .deferred-archive { - margin-top: 16px; - padding-top: 12px; - border-top: 1px solid var(--warm-gray); + margin-top: 16px; + padding-top: 12px; + border-top: 1px solid var(--warm-gray); } .archive-header-row { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; } .archive-toggle { - font-family: 'Public Sans', sans-serif; - font-size: 12px; - font-size: var(--ui-font-12); - font-weight: 500; - color: var(--muted); - background: none; - border: none; - cursor: pointer; - display: flex; - align-items: center; - gap: 6px; - padding: 4px 0; - width: auto; - text-align: left; - transition: color 0.15s; + font-family: "Public Sans", sans-serif; + font-size: 12px; + font-size: var(--ui-font-12); + font-weight: 500; + color: var(--muted); + background: none; + border: none; + cursor: pointer; + display: flex; + align-items: center; + gap: 6px; + padding: 4px 0; + width: auto; + text-align: left; + transition: color 0.15s; } .archive-toggle:hover { - color: var(--ink); + color: var(--ink); } .archive-chevron { - width: 14px; - height: 14px; - transition: transform 0.2s; + width: 14px; + height: 14px; + transition: transform 0.2s; } .archive-toggle.open .archive-chevron { - transform: rotate(180deg); + transform: rotate(180deg); } .archive-count { - font-size: 11px; - font-size: var(--ui-font-11); - color: var(--muted); - opacity: 0.7; + font-size: 11px; + font-size: var(--ui-font-11); + color: var(--muted); + opacity: 0.7; } .archive-body { - padding-top: 12px; + padding-top: 12px; } .archive-search { - font-family: 'Public Sans', sans-serif; - font-size: 12px; - font-size: var(--ui-font-12); - width: 100%; - padding: 8px 12px; - border: 1px solid var(--warm-gray); - border-radius: 6px; - background: color-mix(in srgb, var(--card-bg) var(--panel-card-opacity), transparent); - color: var(--ink); - outline: none; - transition: border-color 0.2s; - margin-bottom: 12px; + font-family: "Public Sans", sans-serif; + font-size: 12px; + font-size: var(--ui-font-12); + width: 100%; + padding: 8px 12px; + border: 1px solid var(--warm-gray); + border-radius: 6px; + background: color-mix( + in srgb, + var(--card-bg) var(--panel-card-opacity), + transparent + ); + color: var(--ink); + outline: none; + transition: border-color 0.2s; + margin-bottom: 12px; } .archive-search:focus { - border-color: var(--accent-amber); + border-color: var(--accent-amber); } .archive-search::placeholder { - color: var(--muted); + color: var(--muted); } .archive-clear-btn { - border: none; - background: transparent; - color: var(--workspace-chip-text); - font-size: 11px; - font-size: var(--ui-font-11); - font-family: 'Public Sans', sans-serif; - font-weight: 600; - cursor: pointer; - padding: 0; - text-decoration: underline; - text-underline-offset: 2px; - flex-shrink: 0; + border: none; + background: transparent; + color: var(--workspace-chip-text); + font-size: 11px; + font-size: var(--ui-font-11); + font-family: "Public Sans", sans-serif; + font-weight: 600; + cursor: pointer; + padding: 0; + text-decoration: underline; + text-underline-offset: 2px; + flex-shrink: 0; } .archive-item { - display: flex; - align-items: center; - gap: 8px; - padding: 6px 0; - border-bottom: 1px solid rgba(154, 145, 138, 0.08); + display: flex; + align-items: center; + gap: 8px; + padding: 6px 0; + border-bottom: 1px solid rgba(154, 145, 138, 0.08); } .archive-item:last-child { - border-bottom: none; + border-bottom: none; } .archive-item-main { - flex: 1; - min-width: 0; + flex: 1; + min-width: 0; } .archive-item-title { - font-size: 12px; - font-size: var(--ui-font-12); - color: var(--muted); - text-decoration: none; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - flex: 1; - min-width: 0; - transition: color 0.15s; + font-size: 12px; + font-size: var(--ui-font-12); + color: var(--muted); + text-decoration: none; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; + min-width: 0; + transition: color 0.15s; } .archive-item-title:hover { - color: var(--ink); + color: var(--ink); } .archive-item-date { - font-size: 10px; - font-size: var(--ui-font-10); - color: var(--muted); - opacity: 0.6; - flex-shrink: 0; + font-size: 10px; + font-size: var(--ui-font-10); + color: var(--muted); + opacity: 0.6; + flex-shrink: 0; } .archive-item-delete { - width: 32px; - height: 32px; - border-radius: 999px; - border: none; - background: transparent; - color: var(--muted); - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; - opacity: 0.45; - transition: opacity 0.15s ease, color 0.15s ease, background 0.15s ease; + width: 32px; + height: 32px; + border-radius: 999px; + border: none; + background: transparent; + color: var(--muted); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + opacity: 0.45; + transition: + opacity 0.15s ease, + color 0.15s ease, + background 0.15s ease; } .archive-item-delete:hover { - opacity: 1; - color: var(--status-abandoned); - background: rgba(179, 90, 90, 0.08); + opacity: 1; + color: var(--status-abandoned); + background: rgba(179, 90, 90, 0.08); } .archive-item-delete svg { - width: 13px; - height: 13px; + width: 13px; + height: 13px; } .todo-header { - align-items: center; + align-items: center; } .todo-new-btn { - border: none; - background: transparent; - color: var(--accent-amber); - font-size: 18px; - font-family: 'Public Sans', sans-serif; - font-weight: 600; - line-height: 1; - padding: 0; - cursor: pointer; + border: none; + background: transparent; + color: var(--accent-amber); + font-size: 18px; + font-family: "Public Sans", sans-serif; + font-weight: 600; + line-height: 1; + padding: 0; + cursor: pointer; } .saved-search-wrap, .todo-search-wrap { - margin-bottom: 12px; + margin-bottom: 12px; } .todo-list { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } .todo-item { - display: flex; - align-items: flex-start; - gap: 12px; - padding: 12px 0; - border-bottom: 1px solid rgba(154, 145, 138, 0.12); - position: relative; + display: flex; + align-items: flex-start; + gap: 12px; + padding: 12px 0; + border-bottom: 1px solid rgba(154, 145, 138, 0.12); + position: relative; } .todo-checkbox { - appearance: none; - -webkit-appearance: none; - width: 18px; - height: 18px; - border: 2px solid var(--warm-gray); - border-radius: 4px; - cursor: pointer; - flex-shrink: 0; - margin-top: 1px; - position: relative; + appearance: none; + -webkit-appearance: none; + width: 18px; + height: 18px; + border: 2px solid var(--warm-gray); + border-radius: 4px; + cursor: pointer; + flex-shrink: 0; + margin-top: 1px; + position: relative; } .todo-checkbox:checked { - background: var(--accent-sage); - border-color: var(--accent-sage); + background: var(--accent-sage); + border-color: var(--accent-sage); } .todo-checkbox:checked::after { - content: ''; - position: absolute; - top: 2px; - left: 5px; - width: 4px; - height: 8px; - border: solid white; - border-width: 0 2px 2px 0; - transform: rotate(45deg); + content: ""; + position: absolute; + top: 2px; + left: 5px; + width: 4px; + height: 8px; + border: solid white; + border-width: 0 2px 2px 0; + transform: rotate(45deg); } .todo-main { - flex: 1; - min-width: 0; - border: none; - background: transparent; - color: var(--ink); - text-align: left; - cursor: pointer; - display: flex; - flex-direction: column; - gap: 4px; - padding: 0; + flex: 1; + min-width: 0; + border: none; + background: transparent; + color: var(--ink); + text-align: left; + cursor: pointer; + display: flex; + flex-direction: column; + gap: 4px; + padding: 0; } .todo-actions { - display: flex; - align-items: center; - flex-shrink: 0; - gap: 4px; + display: flex; + align-items: center; + flex-shrink: 0; + gap: 4px; } .todo-action-btn { - width: 28px; - height: 28px; - border: 1px solid transparent; - border-radius: 8px; - background: transparent; - color: var(--muted); - cursor: pointer; - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; - position: relative; - transition: color 160ms ease, background 160ms ease, border-color 160ms ease; + width: 28px; + height: 28px; + border: 1px solid transparent; + border-radius: 8px; + background: transparent; + color: var(--muted); + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + position: relative; + transition: + color 160ms ease, + background 160ms ease, + border-color 160ms ease; } .todo-action-btn:hover, .todo-action-btn:focus-visible { - color: var(--ink); - background: color-mix(in srgb, var(--workspace-chip-bg) 82%, transparent); - border-color: color-mix(in srgb, var(--workspace-accent-border) 34%, transparent); + color: var(--ink); + background: color-mix(in srgb, var(--workspace-chip-bg) 82%, transparent); + border-color: color-mix( + in srgb, + var(--workspace-accent-border) 34%, + transparent + ); } .todo-action-btn.todo-delete:hover, .todo-action-btn.todo-delete:focus-visible { - color: var(--accent-amber); + color: var(--accent-amber); } .todo-action-btn svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } .todo-title { - font-size: 14px; - font-size: var(--ui-font-14); - font-weight: 400; - line-height: 1.45; - color: inherit; + font-size: 14px; + font-size: var(--ui-font-14); + font-weight: 400; + line-height: 1.45; + color: inherit; } .todo-meta, .todo-detail-meta { - font-size: 11px; - font-size: var(--ui-font-11); - color: var(--muted); + font-size: 11px; + font-size: var(--ui-font-11); + color: var(--muted); } .todo-detail { - display: flex; - flex-direction: column; - gap: 12px; + display: flex; + flex-direction: column; + gap: 12px; } .todo-back-btn { - border: none; - background: transparent; - color: var(--accent-amber); - font-size: 12px; - font-family: 'Public Sans', sans-serif; - font-weight: 600; - padding: 0; - display: inline-flex; - align-items: center; - gap: 6px; - cursor: pointer; + border: none; + background: transparent; + color: var(--accent-amber); + font-size: 12px; + font-family: "Public Sans", sans-serif; + font-weight: 600; + padding: 0; + display: inline-flex; + align-items: center; + gap: 6px; + cursor: pointer; } .todo-back-btn svg { - width: 14px; - height: 14px; + width: 14px; + height: 14px; } :is( - .action-btn, - .archive-clear-btn, - .archive-item-delete, - .archive-search, - .archive-toggle, - .back-to-top, - .chip-action, - .deferred-action-btn, - .deferred-checkbox, - .deferred-trigger, - .drawer-icon-btn, - .drawer-reorder-handle, - .drawer-title-btn, - .group-action-icon, - .group-nav-button, - .header-search-input, - .header-theme-trigger, - .section-icon-action, - .move-menu-btn, - .quick-shortcut-open, - .quick-shortcut-remove, - .tab-cleanup-btn, - .theme-language-option, - .theme-menu-action, - .theme-option, - .theme-range, - .todo-editor-input, - .todo-back-btn, - .todo-action-btn, - .todo-checkbox, - .todo-main, - .workspace-page-switch-btn + .action-btn, + .archive-clear-btn, + .archive-item-delete, + .archive-search, + .archive-toggle, + .back-to-top, + .chip-action, + .deferred-action-btn, + .deferred-checkbox, + .deferred-trigger, + .drawer-icon-btn, + .drawer-reorder-handle, + .drawer-title-btn, + .group-action-icon, + .group-nav-button, + .header-search-input, + .header-theme-trigger, + .section-icon-action, + .move-menu-btn, + .quick-shortcut-open, + .quick-shortcut-remove, + .tab-cleanup-btn, + .theme-language-option, + .theme-menu-action, + .theme-option, + .theme-range, + .todo-editor-input, + .todo-back-btn, + .todo-action-btn, + .todo-checkbox, + .todo-main, + .workspace-page-switch-btn ):focus-visible { - outline: 2px solid var(--focus-ring); - outline-offset: 2px; - box-shadow: var(--focus-ring-shadow); + outline: 2px solid var(--focus-ring); + outline-offset: 2px; + box-shadow: var(--focus-ring-shadow); } .quick-shortcut-remove:focus-visible, .header-search-input:focus-visible, .archive-search:focus-visible, .theme-range:focus-visible { - outline-offset: 3px; + outline-offset: 3px; } .header-search-input:focus-visible { - outline: none; - box-shadow: none; + outline: none; + box-shadow: none; } .todo-editor-view { - margin: 2px 0 14px; + margin: 2px 0 14px; } .todo-editor-form { - display: flex; - flex-direction: column; - gap: 12px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 22%, var(--warm-gray) 78%); - border-radius: 12px; - background: color-mix(in srgb, var(--card-bg) 94%, var(--paper) 6%); - padding: 14px; + display: flex; + flex-direction: column; + gap: 12px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 22%, + var(--warm-gray) 78% + ); + border-radius: 12px; + background: color-mix(in srgb, var(--card-bg) 94%, var(--paper) 6%); + padding: 14px; } .todo-editor-head { - display: flex; - align-items: center; - justify-content: space-between; - gap: 10px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; } .todo-editor-head h3 { - margin: 0; - color: var(--ink); - font-size: 15px; - font-size: var(--ui-font-15); - line-height: 1.25; - font-weight: 650; + margin: 0; + color: var(--ink); + font-size: 15px; + font-size: var(--ui-font-15); + line-height: 1.25; + font-weight: 650; } .todo-editor-field { - display: grid; - gap: 6px; + display: grid; + gap: 6px; } .todo-editor-label { - font-size: 10px; - font-size: var(--ui-font-10); - letter-spacing: 0.12em; - text-transform: uppercase; - color: var(--muted); - font-weight: 700; + font-size: 10px; + font-size: var(--ui-font-10); + letter-spacing: 0.12em; + text-transform: uppercase; + color: var(--muted); + font-weight: 700; } .todo-editor-input { - width: 100%; - min-height: 40px; - border-radius: 10px; - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) 24%, var(--warm-gray) 76%); - background: color-mix(in srgb, var(--card-bg) calc(var(--custom-surface-opacity) + 74%), transparent); - color: var(--ink); - font: inherit; - padding: 0 12px; - outline: none; - transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease; + width: 100%; + min-height: 40px; + border-radius: 10px; + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) 24%, + var(--warm-gray) 76% + ); + background: color-mix( + in srgb, + var(--card-bg) calc(var(--custom-surface-opacity) + 74%), + transparent + ); + color: var(--ink); + font: inherit; + padding: 0 12px; + outline: none; + transition: + border-color 160ms ease, + box-shadow 160ms ease, + background 160ms ease; } .todo-editor-input:focus { - border-color: color-mix(in srgb, var(--accent-amber) 54%, var(--workspace-accent-border) 46%); - box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent-amber) 18%, transparent); + border-color: color-mix( + in srgb, + var(--accent-amber) 54%, + var(--workspace-accent-border) 46% + ); + box-shadow: inset 0 0 0 1px + color-mix(in srgb, var(--accent-amber) 18%, transparent); } .todo-editor-input::placeholder { - color: color-mix(in srgb, var(--muted) 78%, transparent); + color: color-mix(in srgb, var(--muted) 78%, transparent); } .todo-editor-textarea { - min-height: 104px; - resize: vertical; - padding: 10px 12px; - line-height: 1.5; + min-height: 104px; + resize: vertical; + padding: 10px 12px; + line-height: 1.5; } .todo-editor-error { - min-height: 16px; - color: var(--accent-amber); - font-size: 11px; - font-size: var(--ui-font-11); - line-height: 1.35; + min-height: 16px; + color: var(--accent-amber); + font-size: 11px; + font-size: var(--ui-font-11); + line-height: 1.35; } .todo-editor-actions { - display: flex; - align-items: center; - justify-content: flex-end; - gap: 8px; + display: flex; + align-items: center; + justify-content: flex-end; + gap: 8px; } .todo-detail-card { - border: 1px solid rgba(154, 145, 138, 0.12); - border-radius: 12px; - background: color-mix(in srgb, var(--card-bg) 96%, var(--paper) 4%); - padding: 16px; + border: 1px solid rgba(154, 145, 138, 0.12); + border-radius: 12px; + background: color-mix(in srgb, var(--card-bg) 96%, var(--paper) 4%); + padding: 16px; } .todo-detail-card h3 { - font-size: 15px; - margin-bottom: 8px; + font-size: 15px; + margin-bottom: 8px; } .todo-detail-card p { - font-size: 13px; - color: var(--ink); - line-height: 1.6; - margin-bottom: 12px; + font-size: 13px; + color: var(--ink); + line-height: 1.6; + margin-bottom: 12px; } .todo-detail-actions { - display: flex; - align-items: center; - gap: 6px; - margin-top: 12px; + display: flex; + align-items: center; + gap: 6px; + margin-top: 12px; } /* ---- Tab Picker Popover ---- */ -.tab-picker-backdrop[hidden] { display: none !important; } +.tab-picker-backdrop[hidden] { + display: none !important; +} .tab-picker-backdrop { - position: fixed; - inset: 0; - background: color-mix(in srgb, var(--ink) 6%, transparent); - z-index: 108; + position: fixed; + inset: 0; + background: color-mix(in srgb, var(--ink) 6%, transparent); + z-index: 108; } -.tab-picker[hidden] { display: none !important; } +.tab-picker[hidden] { + display: none !important; +} .tab-picker { - position: fixed; - bottom: 24px; - right: 24px; - width: 320px; - max-height: min(480px, calc(100vh - 80px)); - border: 1px solid color-mix(in srgb, var(--workspace-accent-border) calc(var(--custom-border-opacity) + 8%), var(--warm-gray) 28%); - border-radius: 18px; - background: color-mix(in srgb, var(--card-bg) var(--panel-card-opacity), transparent); - box-shadow: 0 20px 42px color-mix(in srgb, var(--workspace-accent) 14%, transparent); - display: flex; - flex-direction: column; - overflow: hidden; - z-index: 109; + position: fixed; + bottom: 24px; + right: 24px; + width: 320px; + max-height: min(480px, calc(100vh - 80px)); + border: 1px solid + color-mix( + in srgb, + var(--workspace-accent-border) + calc(var(--custom-border-opacity) + 8%), + var(--warm-gray) 28% + ); + border-radius: 18px; + background: color-mix( + in srgb, + var(--card-bg) var(--panel-card-opacity), + transparent + ); + box-shadow: 0 20px 42px + color-mix(in srgb, var(--workspace-accent) 14%, transparent); + display: flex; + flex-direction: column; + overflow: hidden; + z-index: 109; } .tab-picker-header { - display: flex; - align-items: center; - justify-content: space-between; - gap: 12px; - padding: 10px 16px 8px; - flex-shrink: 0; + display: flex; + align-items: center; + justify-content: space-between; + gap: 12px; + padding: 10px 16px 8px; + flex-shrink: 0; } .tab-picker-close { - width: 28px; - height: 28px; - border: none; - border-radius: 999px; - background: transparent; - color: var(--muted); - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; - transition: background 0.15s, color 0.15s; + width: 28px; + height: 28px; + border: none; + border-radius: 999px; + background: transparent; + color: var(--muted); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: + background 0.15s, + color 0.15s; } .tab-picker-close:hover { - background: rgba(154, 145, 138, 0.12); - color: var(--ink); + background: rgba(154, 145, 138, 0.12); + color: var(--ink); } -.tab-picker-close svg { width: 14px; height: 14px; } +.tab-picker-close svg { + width: 14px; + height: 14px; +} .tab-picker-view-switch { - margin: 0; - flex: 1; - min-width: 0; + margin: 0; + flex: 1; + min-width: 0; } .tab-picker-view-switch .drawer-title-btn { - font-size: 16px; - font-size: var(--ui-font-16); - line-height: 1.05; - white-space: nowrap; - flex: 1 1 0; - text-align: center; + font-size: 16px; + font-size: var(--ui-font-16); + line-height: 1.05; + white-space: nowrap; + flex: 1 1 0; + text-align: center; } .tab-picker-search-wrap { - display: flex; - align-items: center; - gap: 8px; - padding: 0 14px 10px; - flex-shrink: 0; + display: flex; + align-items: center; + gap: 8px; + padding: 0 14px 10px; + flex-shrink: 0; } .tab-picker-search-wrap[hidden], .tab-picker-list[hidden], .tab-picker-editor-host[hidden] { - display: none !important; + display: none !important; } .tab-picker-search-icon { - width: 14px; - height: 14px; - color: var(--muted); - flex-shrink: 0; + width: 14px; + height: 14px; + color: var(--muted); + flex-shrink: 0; } .tab-picker-search { - flex: 1; - border: none; - background: transparent; - color: var(--ink); - font: inherit; - font-size: 13px; - font-size: var(--ui-font-13); - outline: none; + flex: 1; + border: none; + background: transparent; + color: var(--ink); + font: inherit; + font-size: 13px; + font-size: var(--ui-font-13); + outline: none; } -.tab-picker-search::placeholder { color: var(--muted); } +.tab-picker-search::placeholder { + color: var(--muted); +} .tab-picker-list { - flex: 1; - overflow-y: auto; - overscroll-behavior: contain; - padding: 2px 6px 4px; - scrollbar-width: thin; - scrollbar-color: var(--warm-gray) transparent; + flex: 1; + overflow-y: auto; + overscroll-behavior: contain; + padding: 2px 6px 4px; + scrollbar-width: thin; + scrollbar-color: var(--warm-gray) transparent; } .tab-picker-editor-host { - flex: 1; - padding: 0 14px 14px; + flex: 1; + padding: 0 14px 14px; } .shortcut-editor-form.is-tab-picker-pane { - border: none; - border-radius: 0; - background: transparent; - box-shadow: none; - padding: 0 0 4px; - gap: 12px; + border: none; + border-radius: 0; + background: transparent; + box-shadow: none; + padding: 0 0 4px; + gap: 12px; } .shortcut-editor-form.is-tab-picker-pane .shortcut-editor-header { - display: none; + display: none; } -.tab-picker-list::-webkit-scrollbar { width: 4px; } -.tab-picker-list::-webkit-scrollbar-track { background: transparent; } +.tab-picker-list::-webkit-scrollbar { + width: 4px; +} +.tab-picker-list::-webkit-scrollbar-track { + background: transparent; +} .tab-picker-list::-webkit-scrollbar-thumb { - background: var(--warm-gray); - border-radius: 999px; + background: var(--warm-gray); + border-radius: 999px; } .tab-picker-group-label { - font-size: 10px; - font-weight: 700; - letter-spacing: 0.14em; - text-transform: uppercase; - color: var(--muted); - padding: 8px 10px 4px; - position: sticky; - top: 0; - background: color-mix(in srgb, var(--card-bg) var(--panel-card-opacity), transparent); - z-index: 1; + font-size: 10px; + font-weight: 700; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--muted); + padding: 8px 10px 4px; + position: sticky; + top: 0; + background: color-mix( + in srgb, + var(--card-bg) var(--panel-card-opacity), + transparent + ); + z-index: 1; } .tab-picker-row { - display: flex; - align-items: center; - gap: 8px; - padding: 6px 10px; - border-radius: 10px; - cursor: pointer; - transition: background 0.12s ease; + display: flex; + align-items: center; + gap: 8px; + padding: 6px 10px; + border-radius: 10px; + cursor: pointer; + transition: background 0.12s ease; } -.tab-picker-row:hover { background: color-mix(in srgb, var(--workspace-accent-soft) 48%, transparent); } -.tab-picker-row.is-selected { background: color-mix(in srgb, var(--workspace-accent-soft) 36%, transparent); } -.tab-picker-row:focus-visible { outline: 2px solid var(--workspace-chip-text); outline-offset: 1px; } +.tab-picker-row:hover { + background: color-mix( + in srgb, + var(--workspace-accent-soft) 48%, + transparent + ); +} +.tab-picker-row.is-selected { + background: color-mix( + in srgb, + var(--workspace-accent-soft) 36%, + transparent + ); +} +.tab-picker-row:focus-visible { + outline: 2px solid var(--workspace-chip-text); + outline-offset: 1px; +} .tab-picker-checkbox { - appearance: none; - -webkit-appearance: none; - width: 16px; - height: 16px; - border: 1.5px solid var(--warm-gray); - border-radius: 4px; - flex-shrink: 0; - cursor: pointer; - transition: border-color 0.12s, background 0.12s; - position: relative; + appearance: none; + -webkit-appearance: none; + width: 16px; + height: 16px; + border: 1.5px solid var(--warm-gray); + border-radius: 4px; + flex-shrink: 0; + cursor: pointer; + transition: + border-color 0.12s, + background 0.12s; + position: relative; } .tab-picker-checkbox:checked { - background: var(--workspace-chip-text); - border-color: var(--workspace-chip-text); + background: var(--workspace-chip-text); + border-color: var(--workspace-chip-text); } .tab-picker-checkbox:checked::after { - content: ''; - position: absolute; - top: 1px; - left: 4px; - width: 5px; - height: 8px; - border: 1.5px solid white; - border-top: none; - border-left: none; - transform: rotate(45deg); + content: ""; + position: absolute; + top: 1px; + left: 4px; + width: 5px; + height: 8px; + border: 1.5px solid white; + border-top: none; + border-left: none; + transform: rotate(45deg); } .tab-picker-favicon { - width: 16px; - height: 16px; - border-radius: 3px; - flex-shrink: 0; - object-fit: contain; + width: 16px; + height: 16px; + border-radius: 3px; + flex-shrink: 0; + object-fit: contain; } .tab-picker-favicon-fallback { - width: 16px; - height: 16px; - border-radius: 999px; - background: var(--theme-accent-soft); - color: var(--theme-accent-strong); - font-size: 8px; - font-weight: 700; - display: inline-flex; - align-items: center; - justify-content: center; - flex-shrink: 0; + width: 16px; + height: 16px; + border-radius: 999px; + background: var(--theme-accent-soft); + color: var(--theme-accent-strong); + font-size: 8px; + font-weight: 700; + display: inline-flex; + align-items: center; + justify-content: center; + flex-shrink: 0; } .tab-picker-tab-title { - flex: 1; - min-width: 0; - font-size: 12px; - color: var(--ink); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + flex: 1; + min-width: 0; + font-size: 12px; + color: var(--ink); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .tab-picker-add-btn { - width: 24px; - height: 24px; - border: none; - border-radius: 999px; - background: color-mix(in srgb, var(--workspace-accent-soft) 56%, var(--card-bg) 44%); - color: var(--workspace-chip-text); - display: inline-flex; - align-items: center; - justify-content: center; - cursor: pointer; - flex-shrink: 0; - opacity: 0; - transition: opacity 0.12s, background 0.12s, transform 0.12s; + width: 24px; + height: 24px; + border: none; + border-radius: 999px; + background: color-mix( + in srgb, + var(--workspace-accent-soft) 56%, + var(--card-bg) 44% + ); + color: var(--workspace-chip-text); + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + flex-shrink: 0; + opacity: 0; + transition: + opacity 0.12s, + background 0.12s, + transform 0.12s; } .tab-picker-row:hover .tab-picker-add-btn, -.tab-picker-add-btn:focus-visible { opacity: 1; } +.tab-picker-add-btn:focus-visible { + opacity: 1; +} .tab-picker-add-btn:hover { - background: var(--workspace-chip-bg-strong); - transform: scale(1.08); + background: var(--workspace-chip-bg-strong); + transform: scale(1.08); } -.tab-picker-add-btn:active { transform: scale(0.96); } -.tab-picker-add-btn svg { width: 12px; height: 12px; } +.tab-picker-add-btn:active { + transform: scale(0.96); +} +.tab-picker-add-btn svg { + width: 12px; + height: 12px; +} .tab-picker-added-icon { - width: 24px; - height: 24px; - color: var(--accent-sage); - flex-shrink: 0; - opacity: 0.7; + width: 24px; + height: 24px; + color: var(--accent-sage); + flex-shrink: 0; + opacity: 0.7; } .tab-picker-empty { - padding: 32px 16px; - text-align: center; - font-size: 13px; - color: var(--muted); - font-style: italic; + padding: 32px 16px; + text-align: center; + font-size: 13px; + color: var(--muted); + font-style: italic; } -.tab-picker-footer[hidden] { display: none !important; } +.tab-picker-footer[hidden] { + display: none !important; +} .tab-picker-footer { - display: flex; - align-items: center; - gap: 8px; - padding: 10px 14px; - border-top: 1px solid color-mix(in srgb, var(--workspace-accent-border) 16%, transparent); - flex-shrink: 0; + display: flex; + align-items: center; + gap: 8px; + padding: 10px 14px; + border-top: 1px solid + color-mix(in srgb, var(--workspace-accent-border) 16%, transparent); + flex-shrink: 0; } .tab-picker-footer-count { - flex: 1; - font-size: 12px; - color: var(--muted); + flex: 1; + font-size: 12px; + color: var(--muted); } .tab-picker-footer-add { - font-family: 'Public Sans', sans-serif; - font-size: 12px; - font-weight: 600; - border: none; - background: var(--workspace-chip-text); - color: var(--workspace-accent-contrast); - border-radius: 999px; - padding: 6px 14px; - cursor: pointer; - transition: background 0.15s, transform 0.12s; - min-height: 32px; -} - -.tab-picker-footer-add:hover { background: var(--banner-action-bg-hover); } -.tab-picker-footer-add:active { transform: scale(0.97); } + font-family: "Public Sans", sans-serif; + font-size: 12px; + font-weight: 600; + border: none; + background: var(--workspace-chip-text); + color: var(--workspace-accent-contrast); + border-radius: 999px; + padding: 6px 14px; + cursor: pointer; + transition: + background 0.15s, + transform 0.12s; + min-height: 32px; +} + +.tab-picker-footer-add:hover { + background: var(--banner-action-bg-hover); +} +.tab-picker-footer-add:active { + transform: scale(0.97); +} .tab-picker-footer-clear { - font-family: 'Public Sans', sans-serif; - font-size: 12px; - font-weight: 500; - border: none; - background: transparent; - color: var(--muted); - cursor: pointer; - padding: 6px 8px; - border-radius: 6px; - transition: color 0.15s, background 0.15s; + font-family: "Public Sans", sans-serif; + font-size: 12px; + font-weight: 500; + border: none; + background: transparent; + color: var(--muted); + cursor: pointer; + padding: 6px 8px; + border-radius: 6px; + transition: + color 0.15s, + background 0.15s; } -.tab-picker-footer-clear:hover { color: var(--ink); background: rgba(154, 145, 138, 0.1); } +.tab-picker-footer-clear:hover { + color: var(--ink); + background: rgba(154, 145, 138, 0.1); +} @media (prefers-reduced-motion: reduce) { - *, - *::before, - *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - scroll-behavior: auto !important; - } - - .deferred-column, - .deferred-trigger, - .group-nav-button, - .mission-card, - .page-chip, - .quick-shortcut-open { - transform: none !important; - } + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } + + .deferred-column, + .deferred-trigger, + .group-nav-button, + .mission-card, + .page-chip, + .quick-shortcut-open { + transform: none !important; + } } diff --git a/extension/ui-regression.test.js b/extension/ui-regression.test.js index 7a70d54..0308a54 100644 --- a/extension/ui-regression.test.js +++ b/extension/ui-regression.test.js @@ -345,7 +345,7 @@ test('optional local config is loaded safely before app mount', () => { }); test('background keeps the toolbar badge empty', () => { - assert.match(backgroundJs, /await chrome\.action\.setBadgeText\(\{\s*text:\s*''\s*\}\)/); + assert.match(backgroundJs, /await chrome\.action\.setBadgeText\(\{\s*text:\s*["']{2}\s*\}\)/); assert.doesNotMatch(backgroundJs, /String\(count\)/); }); @@ -1056,13 +1056,16 @@ test('dynamic animation styles are generated by JavaScript instead of hardcoded test('dashboard auto-refreshes when tabs change via background message', () => { const bgJs = fs.readFileSync(path.join(__dirname, 'background.js'), 'utf8'); - // Background should notify Tab Harbor pages + // Background should broadcast tab changes via chrome.runtime.sendMessage + // (the dashboard is an extension page, NOT a content script — sendMessage + // to a content script would always fail with "Receiving end does not exist"). assert.match(bgJs, /notifyTabHarborPages/); - assert.match(bgJs, /chrome\.tabs\.sendMessage/); - assert.match(bgJs, /action:\s*'tabs-changed'/); + assert.match(bgJs, /chrome\.runtime\.sendMessage/); + assert.doesNotMatch(bgJs, /chrome\.tabs\.sendMessage/); + assert.match(bgJs, /action:\s*["']tabs-changed["']/); assert.match(bgJs, /triggerTabId/); - assert.match(bgJs, /source:\s*'tabs\.onCreated'/); - assert.match(bgJs, /source:\s*'tabs\.onUpdated'/); + assert.match(bgJs, /source:\s*["']tabs\.onCreated["']/); + assert.match(bgJs, /source:\s*["']tabs\.onUpdated["']/); assert.match(bgJs, /chrome\.tabs\.onCreated\.addListener/); assert.match(bgJs, /chrome\.tabs\.onRemoved\.addListener/);