From 2de0ee8e302a39bcf67950129f2d7a7ed5ec1e14 Mon Sep 17 00:00:00 2001
From: Linus Rath <139418639+rathlinus@users.noreply.github.com>
Date: Sat, 31 Oct 2026 02:20:40 +0100
Subject: [PATCH] fix: keep tag text readable on unread, selected and hovered
rows
---
app/globals.css | 11 +++
stores/__tests__/keyword-palette-fill.test.ts | 54 ++++++++++++
.../__tests__/settings-store-keywords.test.ts | 2 +-
stores/settings-store.ts | 84 ++++++++++---------
4 files changed, 110 insertions(+), 41 deletions(-)
create mode 100644 stores/__tests__/keyword-palette-fill.test.ts
diff --git a/app/globals.css b/app/globals.css
index 0297c65ce..01c1fbcc1 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -171,6 +171,17 @@
}
}
+/* A tag lozenge's tint (KEYWORD_PALETTE fill): the hue at 10%, laid over the
+ page background rather than over whatever is behind the tag. A
+ see-through bg-amber-500/10 took on the row's colour, so on an unread,
+ selected or hovered row the tag text fell below 4.5:1. On the plain page
+ it looks the same as before. */
+@utility tag-fill-* {
+ --tag-fill: --alpha(--value(--color-*) / 10%);
+ background-color: var(--color-background);
+ background-image: linear-gradient(var(--tag-fill), var(--tag-fill));
+}
+
/* The default border colour. In the base layer, so a border colour utility
(border-primary, border-transparent, border-destructive, border-input)
diff --git a/stores/__tests__/keyword-palette-fill.test.ts b/stores/__tests__/keyword-palette-fill.test.ts
new file mode 100644
index 000000000..d691538e6
--- /dev/null
+++ b/stores/__tests__/keyword-palette-fill.test.ts
@@ -0,0 +1,54 @@
+import { describe, it, expect, beforeAll } from 'vitest';
+import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
+import os from 'os';
+import path from 'path';
+import type { Root } from 'postcss';
+import { KEYWORD_PALETTE } from '../settings-store';
+
+/**
+ * A tag lozenge sits on list rows that change colour: unread, selected,
+ * hovered. A see-through fill took that colour on, and an amber tag's text
+ * fell below 4.5:1 on an unread row (the a11y guard's color-contrast).
+ * Build globals.css with Tailwind to see what each fill actually compiles to.
+ */
+let root: Root;
+
+beforeAll(async () => {
+ const postcss = (await import('postcss')).default;
+ const tailwind = (await import('@tailwindcss/postcss')).default;
+ const file = path.join(process.cwd(), 'app', 'globals.css');
+ // Scan a folder holding only the palette's fills.
+ const base = mkdtempSync(path.join(os.tmpdir(), 'tag-fill-'));
+ try {
+ const fills = Object.values(KEYWORD_PALETTE).map((color) => color.fill).join(' ');
+ writeFileSync(path.join(base, 'fills.html'), ``);
+ root = (await postcss([tailwind({ base })]).process(readFileSync(file, 'utf8'), { from: file })).root;
+ } finally {
+ rmSync(base, { recursive: true, force: true });
+ }
+}, 60_000);
+
+/** The values `prop` takes in the class's rule, fallbacks included. */
+function values(cls: string, prop: string): string[] {
+ const found: string[] = [];
+ root.walkRules(`.${cls.replace(/\//g, '\\/')}`, (rule) => {
+ rule.walkDecls(prop, (decl) => {
+ found.push(decl.value);
+ });
+ });
+ return found;
+}
+
+describe('KEYWORD_PALETTE fills', () => {
+ it('paint the tint over the page background, so the row behind a tag cannot lower its contrast', () => {
+ const seeThrough = Object.entries(KEYWORD_PALETTE)
+ .filter(([, color]) => {
+ const base = values(color.fill, 'background-color');
+ return base.length === 0
+ || base.some((v) => v !== 'var(--color-background)')
+ || values(color.fill, 'background-image').length === 0;
+ })
+ .map(([key, color]) => `${key}: ${color.fill} -> ${values(color.fill, 'background-color').join(' | ') || 'no background'}`);
+ expect(seeThrough).toEqual([]);
+ });
+});
diff --git a/stores/__tests__/settings-store-keywords.test.ts b/stores/__tests__/settings-store-keywords.test.ts
index 407475431..b804ef625 100644
--- a/stores/__tests__/settings-store-keywords.test.ts
+++ b/stores/__tests__/settings-store-keywords.test.ts
@@ -75,7 +75,7 @@ describe('settings-store keywords', () => {
// at runtime and each has to carry its own utility prefix.
Object.values(KEYWORD_PALETTE).forEach((entry) => {
expect(entry.dot).toMatch(/^bg-/);
- expect(entry.fill).toMatch(/^bg-/);
+ expect(entry.fill).toMatch(/^tag-fill-/);
expect(entry.border).toMatch(/^border-/);
expect(entry.text).toMatch(/^text-.* dark:text-/);
expect(entry.rowTint).toMatch(/^bg-.* dark:bg-/);
diff --git a/stores/settings-store.ts b/stores/settings-store.ts
index 8c9a9d591..395397c3a 100644
--- a/stores/settings-store.ts
+++ b/stores/settings-store.ts
@@ -423,7 +423,11 @@ export interface KeywordColor {
dot: string;
/** The same solid colour as `dot`, for glyphs that take a text colour. */
icon: string;
- /** Lozenge background. */
+ /**
+ * Lozenge background. Opaque (tag-fill-*, app/globals.css) wherever `text`
+ * is a hue: a see-through fill takes on the row's colour, and the text's
+ * contrast with it.
+ */
fill: string;
/** Lozenge border. */
border: string;
@@ -445,47 +449,47 @@ export interface KeywordColor {
*/
export const KEYWORD_PALETTE: Record = {
// light
- 'red-light': { dot: 'bg-red-300', icon: 'text-red-300', fill: 'bg-red-300/10', border: 'border-red-300/30', text: 'text-red-600 dark:text-red-200', rowTint: 'bg-red-50/60 dark:bg-red-950/20' },
- 'orange-light': { dot: 'bg-orange-300', icon: 'text-orange-300', fill: 'bg-orange-300/10', border: 'border-orange-300/30', text: 'text-orange-600 dark:text-orange-200', rowTint: 'bg-orange-50/60 dark:bg-orange-950/20' },
- 'amber-light': { dot: 'bg-amber-300', icon: 'text-amber-300', fill: 'bg-amber-300/10', border: 'border-amber-300/30', text: 'text-amber-600 dark:text-amber-200', rowTint: 'bg-amber-50/60 dark:bg-amber-950/20' },
- 'yellow-light': { dot: 'bg-yellow-300', icon: 'text-yellow-300', fill: 'bg-yellow-300/10', border: 'border-yellow-300/30', text: 'text-yellow-600 dark:text-yellow-200', rowTint: 'bg-yellow-50/60 dark:bg-yellow-950/20' },
- 'lime-light': { dot: 'bg-lime-300', icon: 'text-lime-300', fill: 'bg-lime-300/10', border: 'border-lime-300/30', text: 'text-lime-600 dark:text-lime-200', rowTint: 'bg-lime-50/60 dark:bg-lime-950/20' },
- 'green-light': { dot: 'bg-green-300', icon: 'text-green-300', fill: 'bg-green-300/10', border: 'border-green-300/30', text: 'text-green-600 dark:text-green-200', rowTint: 'bg-green-50/60 dark:bg-green-950/20' },
- 'teal-light': { dot: 'bg-teal-300', icon: 'text-teal-300', fill: 'bg-teal-300/10', border: 'border-teal-300/30', text: 'text-teal-600 dark:text-teal-200', rowTint: 'bg-teal-50/60 dark:bg-teal-950/20' },
- 'cyan-light': { dot: 'bg-cyan-300', icon: 'text-cyan-300', fill: 'bg-cyan-300/10', border: 'border-cyan-300/30', text: 'text-cyan-600 dark:text-cyan-200', rowTint: 'bg-cyan-50/60 dark:bg-cyan-950/20' },
- 'blue-light': { dot: 'bg-blue-300', icon: 'text-blue-300', fill: 'bg-blue-300/10', border: 'border-blue-300/30', text: 'text-blue-600 dark:text-blue-200', rowTint: 'bg-blue-50/60 dark:bg-blue-950/20' },
- 'indigo-light': { dot: 'bg-indigo-300', icon: 'text-indigo-300', fill: 'bg-indigo-300/10', border: 'border-indigo-300/30', text: 'text-indigo-600 dark:text-indigo-200', rowTint: 'bg-indigo-50/60 dark:bg-indigo-950/20' },
- 'purple-light': { dot: 'bg-purple-300', icon: 'text-purple-300', fill: 'bg-purple-300/10', border: 'border-purple-300/30', text: 'text-purple-600 dark:text-purple-200', rowTint: 'bg-purple-50/60 dark:bg-purple-950/20' },
- 'pink-light': { dot: 'bg-pink-300', icon: 'text-pink-300', fill: 'bg-pink-300/10', border: 'border-pink-300/30', text: 'text-pink-600 dark:text-pink-200', rowTint: 'bg-pink-50/60 dark:bg-pink-950/20' },
- 'gray-light': { dot: 'bg-gray-300', icon: 'text-gray-300', fill: 'bg-gray-300/10', border: 'border-gray-300/30', text: 'text-gray-600 dark:text-gray-200', rowTint: 'bg-gray-50/60 dark:bg-gray-950/20' },
+ 'red-light': { dot: 'bg-red-300', icon: 'text-red-300', fill: 'tag-fill-red-300', border: 'border-red-300/30', text: 'text-red-600 dark:text-red-200', rowTint: 'bg-red-50/60 dark:bg-red-950/20' },
+ 'orange-light': { dot: 'bg-orange-300', icon: 'text-orange-300', fill: 'tag-fill-orange-300', border: 'border-orange-300/30', text: 'text-orange-600 dark:text-orange-200', rowTint: 'bg-orange-50/60 dark:bg-orange-950/20' },
+ 'amber-light': { dot: 'bg-amber-300', icon: 'text-amber-300', fill: 'tag-fill-amber-300', border: 'border-amber-300/30', text: 'text-amber-600 dark:text-amber-200', rowTint: 'bg-amber-50/60 dark:bg-amber-950/20' },
+ 'yellow-light': { dot: 'bg-yellow-300', icon: 'text-yellow-300', fill: 'tag-fill-yellow-300', border: 'border-yellow-300/30', text: 'text-yellow-600 dark:text-yellow-200', rowTint: 'bg-yellow-50/60 dark:bg-yellow-950/20' },
+ 'lime-light': { dot: 'bg-lime-300', icon: 'text-lime-300', fill: 'tag-fill-lime-300', border: 'border-lime-300/30', text: 'text-lime-600 dark:text-lime-200', rowTint: 'bg-lime-50/60 dark:bg-lime-950/20' },
+ 'green-light': { dot: 'bg-green-300', icon: 'text-green-300', fill: 'tag-fill-green-300', border: 'border-green-300/30', text: 'text-green-600 dark:text-green-200', rowTint: 'bg-green-50/60 dark:bg-green-950/20' },
+ 'teal-light': { dot: 'bg-teal-300', icon: 'text-teal-300', fill: 'tag-fill-teal-300', border: 'border-teal-300/30', text: 'text-teal-600 dark:text-teal-200', rowTint: 'bg-teal-50/60 dark:bg-teal-950/20' },
+ 'cyan-light': { dot: 'bg-cyan-300', icon: 'text-cyan-300', fill: 'tag-fill-cyan-300', border: 'border-cyan-300/30', text: 'text-cyan-600 dark:text-cyan-200', rowTint: 'bg-cyan-50/60 dark:bg-cyan-950/20' },
+ 'blue-light': { dot: 'bg-blue-300', icon: 'text-blue-300', fill: 'tag-fill-blue-300', border: 'border-blue-300/30', text: 'text-blue-600 dark:text-blue-200', rowTint: 'bg-blue-50/60 dark:bg-blue-950/20' },
+ 'indigo-light': { dot: 'bg-indigo-300', icon: 'text-indigo-300', fill: 'tag-fill-indigo-300', border: 'border-indigo-300/30', text: 'text-indigo-600 dark:text-indigo-200', rowTint: 'bg-indigo-50/60 dark:bg-indigo-950/20' },
+ 'purple-light': { dot: 'bg-purple-300', icon: 'text-purple-300', fill: 'tag-fill-purple-300', border: 'border-purple-300/30', text: 'text-purple-600 dark:text-purple-200', rowTint: 'bg-purple-50/60 dark:bg-purple-950/20' },
+ 'pink-light': { dot: 'bg-pink-300', icon: 'text-pink-300', fill: 'tag-fill-pink-300', border: 'border-pink-300/30', text: 'text-pink-600 dark:text-pink-200', rowTint: 'bg-pink-50/60 dark:bg-pink-950/20' },
+ 'gray-light': { dot: 'bg-gray-300', icon: 'text-gray-300', fill: 'tag-fill-gray-300', border: 'border-gray-300/30', text: 'text-gray-600 dark:text-gray-200', rowTint: 'bg-gray-50/60 dark:bg-gray-950/20' },
// base
- red: { dot: 'bg-red-500', icon: 'text-red-500', fill: 'bg-red-500/10', border: 'border-red-500/30', text: 'text-red-700 dark:text-red-300', rowTint: 'bg-red-50 dark:bg-red-950/30' },
- orange: { dot: 'bg-orange-500', icon: 'text-orange-500', fill: 'bg-orange-500/10', border: 'border-orange-500/30', text: 'text-orange-700 dark:text-orange-300', rowTint: 'bg-orange-50 dark:bg-orange-950/30' },
- amber: { dot: 'bg-amber-500', icon: 'text-amber-500', fill: 'bg-amber-500/10', border: 'border-amber-500/30', text: 'text-amber-700 dark:text-amber-300', rowTint: 'bg-amber-50 dark:bg-amber-950/30' },
- yellow: { dot: 'bg-yellow-500', icon: 'text-yellow-500', fill: 'bg-yellow-500/10', border: 'border-yellow-500/30', text: 'text-yellow-700 dark:text-yellow-300', rowTint: 'bg-yellow-50 dark:bg-yellow-950/30' },
- lime: { dot: 'bg-lime-500', icon: 'text-lime-500', fill: 'bg-lime-500/10', border: 'border-lime-500/30', text: 'text-lime-700 dark:text-lime-300', rowTint: 'bg-lime-50 dark:bg-lime-950/30' },
- green: { dot: 'bg-green-500', icon: 'text-green-500', fill: 'bg-green-500/10', border: 'border-green-500/30', text: 'text-green-700 dark:text-green-300', rowTint: 'bg-green-50 dark:bg-green-950/30' },
- teal: { dot: 'bg-teal-500', icon: 'text-teal-500', fill: 'bg-teal-500/10', border: 'border-teal-500/30', text: 'text-teal-700 dark:text-teal-300', rowTint: 'bg-teal-50 dark:bg-teal-950/30' },
- cyan: { dot: 'bg-cyan-500', icon: 'text-cyan-500', fill: 'bg-cyan-500/10', border: 'border-cyan-500/30', text: 'text-cyan-700 dark:text-cyan-300', rowTint: 'bg-cyan-50 dark:bg-cyan-950/30' },
- blue: { dot: 'bg-blue-500', icon: 'text-blue-500', fill: 'bg-blue-500/10', border: 'border-blue-500/30', text: 'text-blue-700 dark:text-blue-300', rowTint: 'bg-blue-50 dark:bg-blue-950/30' },
- indigo: { dot: 'bg-indigo-500', icon: 'text-indigo-500', fill: 'bg-indigo-500/10', border: 'border-indigo-500/30', text: 'text-indigo-700 dark:text-indigo-300', rowTint: 'bg-indigo-50 dark:bg-indigo-950/30' },
- purple: { dot: 'bg-purple-500', icon: 'text-purple-500', fill: 'bg-purple-500/10', border: 'border-purple-500/30', text: 'text-purple-700 dark:text-purple-300', rowTint: 'bg-purple-50 dark:bg-purple-950/30' },
- pink: { dot: 'bg-pink-500', icon: 'text-pink-500', fill: 'bg-pink-500/10', border: 'border-pink-500/30', text: 'text-pink-700 dark:text-pink-300', rowTint: 'bg-pink-50 dark:bg-pink-950/30' },
- gray: { dot: 'bg-gray-500', icon: 'text-gray-500', fill: 'bg-gray-500/10', border: 'border-gray-500/30', text: 'text-gray-700 dark:text-gray-300', rowTint: 'bg-gray-50 dark:bg-gray-950/30' },
+ red: { dot: 'bg-red-500', icon: 'text-red-500', fill: 'tag-fill-red-500', border: 'border-red-500/30', text: 'text-red-700 dark:text-red-300', rowTint: 'bg-red-50 dark:bg-red-950/30' },
+ orange: { dot: 'bg-orange-500', icon: 'text-orange-500', fill: 'tag-fill-orange-500', border: 'border-orange-500/30', text: 'text-orange-700 dark:text-orange-300', rowTint: 'bg-orange-50 dark:bg-orange-950/30' },
+ amber: { dot: 'bg-amber-500', icon: 'text-amber-500', fill: 'tag-fill-amber-500', border: 'border-amber-500/30', text: 'text-amber-700 dark:text-amber-300', rowTint: 'bg-amber-50 dark:bg-amber-950/30' },
+ yellow: { dot: 'bg-yellow-500', icon: 'text-yellow-500', fill: 'tag-fill-yellow-500', border: 'border-yellow-500/30', text: 'text-yellow-700 dark:text-yellow-300', rowTint: 'bg-yellow-50 dark:bg-yellow-950/30' },
+ lime: { dot: 'bg-lime-500', icon: 'text-lime-500', fill: 'tag-fill-lime-500', border: 'border-lime-500/30', text: 'text-lime-700 dark:text-lime-300', rowTint: 'bg-lime-50 dark:bg-lime-950/30' },
+ green: { dot: 'bg-green-500', icon: 'text-green-500', fill: 'tag-fill-green-500', border: 'border-green-500/30', text: 'text-green-700 dark:text-green-300', rowTint: 'bg-green-50 dark:bg-green-950/30' },
+ teal: { dot: 'bg-teal-500', icon: 'text-teal-500', fill: 'tag-fill-teal-500', border: 'border-teal-500/30', text: 'text-teal-700 dark:text-teal-300', rowTint: 'bg-teal-50 dark:bg-teal-950/30' },
+ cyan: { dot: 'bg-cyan-500', icon: 'text-cyan-500', fill: 'tag-fill-cyan-500', border: 'border-cyan-500/30', text: 'text-cyan-700 dark:text-cyan-300', rowTint: 'bg-cyan-50 dark:bg-cyan-950/30' },
+ blue: { dot: 'bg-blue-500', icon: 'text-blue-500', fill: 'tag-fill-blue-500', border: 'border-blue-500/30', text: 'text-blue-700 dark:text-blue-300', rowTint: 'bg-blue-50 dark:bg-blue-950/30' },
+ indigo: { dot: 'bg-indigo-500', icon: 'text-indigo-500', fill: 'tag-fill-indigo-500', border: 'border-indigo-500/30', text: 'text-indigo-700 dark:text-indigo-300', rowTint: 'bg-indigo-50 dark:bg-indigo-950/30' },
+ purple: { dot: 'bg-purple-500', icon: 'text-purple-500', fill: 'tag-fill-purple-500', border: 'border-purple-500/30', text: 'text-purple-700 dark:text-purple-300', rowTint: 'bg-purple-50 dark:bg-purple-950/30' },
+ pink: { dot: 'bg-pink-500', icon: 'text-pink-500', fill: 'tag-fill-pink-500', border: 'border-pink-500/30', text: 'text-pink-700 dark:text-pink-300', rowTint: 'bg-pink-50 dark:bg-pink-950/30' },
+ gray: { dot: 'bg-gray-500', icon: 'text-gray-500', fill: 'tag-fill-gray-500', border: 'border-gray-500/30', text: 'text-gray-700 dark:text-gray-300', rowTint: 'bg-gray-50 dark:bg-gray-950/30' },
// dark
- 'red-dark': { dot: 'bg-red-700', icon: 'text-red-700', fill: 'bg-red-700/10', border: 'border-red-700/30', text: 'text-red-800 dark:text-red-400', rowTint: 'bg-red-100 dark:bg-red-950/50' },
- 'orange-dark': { dot: 'bg-orange-700', icon: 'text-orange-700', fill: 'bg-orange-700/10', border: 'border-orange-700/30', text: 'text-orange-800 dark:text-orange-400', rowTint: 'bg-orange-100 dark:bg-orange-950/50' },
- 'amber-dark': { dot: 'bg-amber-700', icon: 'text-amber-700', fill: 'bg-amber-700/10', border: 'border-amber-700/30', text: 'text-amber-800 dark:text-amber-400', rowTint: 'bg-amber-100 dark:bg-amber-950/50' },
- 'yellow-dark': { dot: 'bg-yellow-700', icon: 'text-yellow-700', fill: 'bg-yellow-700/10', border: 'border-yellow-700/30', text: 'text-yellow-800 dark:text-yellow-400', rowTint: 'bg-yellow-100 dark:bg-yellow-950/50' },
- 'lime-dark': { dot: 'bg-lime-700', icon: 'text-lime-700', fill: 'bg-lime-700/10', border: 'border-lime-700/30', text: 'text-lime-800 dark:text-lime-400', rowTint: 'bg-lime-100 dark:bg-lime-950/50' },
- 'green-dark': { dot: 'bg-green-700', icon: 'text-green-700', fill: 'bg-green-700/10', border: 'border-green-700/30', text: 'text-green-800 dark:text-green-400', rowTint: 'bg-green-100 dark:bg-green-950/50' },
- 'teal-dark': { dot: 'bg-teal-700', icon: 'text-teal-700', fill: 'bg-teal-700/10', border: 'border-teal-700/30', text: 'text-teal-800 dark:text-teal-400', rowTint: 'bg-teal-100 dark:bg-teal-950/50' },
- 'cyan-dark': { dot: 'bg-cyan-700', icon: 'text-cyan-700', fill: 'bg-cyan-700/10', border: 'border-cyan-700/30', text: 'text-cyan-800 dark:text-cyan-400', rowTint: 'bg-cyan-100 dark:bg-cyan-950/50' },
- 'blue-dark': { dot: 'bg-blue-700', icon: 'text-blue-700', fill: 'bg-blue-700/10', border: 'border-blue-700/30', text: 'text-blue-800 dark:text-blue-400', rowTint: 'bg-blue-100 dark:bg-blue-950/50' },
- 'indigo-dark': { dot: 'bg-indigo-700', icon: 'text-indigo-700', fill: 'bg-indigo-700/10', border: 'border-indigo-700/30', text: 'text-indigo-800 dark:text-indigo-400', rowTint: 'bg-indigo-100 dark:bg-indigo-950/50' },
- 'purple-dark': { dot: 'bg-purple-700', icon: 'text-purple-700', fill: 'bg-purple-700/10', border: 'border-purple-700/30', text: 'text-purple-800 dark:text-purple-400', rowTint: 'bg-purple-100 dark:bg-purple-950/50' },
- 'pink-dark': { dot: 'bg-pink-700', icon: 'text-pink-700', fill: 'bg-pink-700/10', border: 'border-pink-700/30', text: 'text-pink-800 dark:text-pink-400', rowTint: 'bg-pink-100 dark:bg-pink-950/50' },
- 'gray-dark': { dot: 'bg-gray-700', icon: 'text-gray-700', fill: 'bg-gray-700/10', border: 'border-gray-700/30', text: 'text-gray-800 dark:text-gray-400', rowTint: 'bg-gray-100 dark:bg-gray-950/50' },
+ 'red-dark': { dot: 'bg-red-700', icon: 'text-red-700', fill: 'tag-fill-red-700', border: 'border-red-700/30', text: 'text-red-800 dark:text-red-400', rowTint: 'bg-red-100 dark:bg-red-950/50' },
+ 'orange-dark': { dot: 'bg-orange-700', icon: 'text-orange-700', fill: 'tag-fill-orange-700', border: 'border-orange-700/30', text: 'text-orange-800 dark:text-orange-400', rowTint: 'bg-orange-100 dark:bg-orange-950/50' },
+ 'amber-dark': { dot: 'bg-amber-700', icon: 'text-amber-700', fill: 'tag-fill-amber-700', border: 'border-amber-700/30', text: 'text-amber-800 dark:text-amber-400', rowTint: 'bg-amber-100 dark:bg-amber-950/50' },
+ 'yellow-dark': { dot: 'bg-yellow-700', icon: 'text-yellow-700', fill: 'tag-fill-yellow-700', border: 'border-yellow-700/30', text: 'text-yellow-800 dark:text-yellow-400', rowTint: 'bg-yellow-100 dark:bg-yellow-950/50' },
+ 'lime-dark': { dot: 'bg-lime-700', icon: 'text-lime-700', fill: 'tag-fill-lime-700', border: 'border-lime-700/30', text: 'text-lime-800 dark:text-lime-400', rowTint: 'bg-lime-100 dark:bg-lime-950/50' },
+ 'green-dark': { dot: 'bg-green-700', icon: 'text-green-700', fill: 'tag-fill-green-700', border: 'border-green-700/30', text: 'text-green-800 dark:text-green-400', rowTint: 'bg-green-100 dark:bg-green-950/50' },
+ 'teal-dark': { dot: 'bg-teal-700', icon: 'text-teal-700', fill: 'tag-fill-teal-700', border: 'border-teal-700/30', text: 'text-teal-800 dark:text-teal-400', rowTint: 'bg-teal-100 dark:bg-teal-950/50' },
+ 'cyan-dark': { dot: 'bg-cyan-700', icon: 'text-cyan-700', fill: 'tag-fill-cyan-700', border: 'border-cyan-700/30', text: 'text-cyan-800 dark:text-cyan-400', rowTint: 'bg-cyan-100 dark:bg-cyan-950/50' },
+ 'blue-dark': { dot: 'bg-blue-700', icon: 'text-blue-700', fill: 'tag-fill-blue-700', border: 'border-blue-700/30', text: 'text-blue-800 dark:text-blue-400', rowTint: 'bg-blue-100 dark:bg-blue-950/50' },
+ 'indigo-dark': { dot: 'bg-indigo-700', icon: 'text-indigo-700', fill: 'tag-fill-indigo-700', border: 'border-indigo-700/30', text: 'text-indigo-800 dark:text-indigo-400', rowTint: 'bg-indigo-100 dark:bg-indigo-950/50' },
+ 'purple-dark': { dot: 'bg-purple-700', icon: 'text-purple-700', fill: 'tag-fill-purple-700', border: 'border-purple-700/30', text: 'text-purple-800 dark:text-purple-400', rowTint: 'bg-purple-100 dark:bg-purple-950/50' },
+ 'pink-dark': { dot: 'bg-pink-700', icon: 'text-pink-700', fill: 'tag-fill-pink-700', border: 'border-pink-700/30', text: 'text-pink-800 dark:text-pink-400', rowTint: 'bg-pink-100 dark:bg-pink-950/50' },
+ 'gray-dark': { dot: 'bg-gray-700', icon: 'text-gray-700', fill: 'tag-fill-gray-700', border: 'border-gray-700/30', text: 'text-gray-800 dark:text-gray-400', rowTint: 'bg-gray-100 dark:bg-gray-950/50' },
} as const;
/** Palette laid out as the settings picker shows it: lighter, base, darker. */