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() {
+
+
`;
}
+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/);