refactor(theme): the accent was hand-written 16 times — now derived
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / integration (push) Successful in 29s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Successful in 59s
CI & Build / Build & push image (push) Successful in 43s

`rgba(91, 74, 138, …)` is Scribe's accent in decimal. It appears sixteen times
across five files at ten different opacities, plus once as #5B4A8A. Change the
accent in the design system and none of them would have moved — which is the
precise failure the token system exists to prevent, hiding in a notation that
does not look like a colour constant.

Now `color-mix(in srgb, var(--color-primary) N%, transparent)`, so every one
follows the accent. The design system already uses this form for its own tints
(--fs-accent-soft, -faint, -wash), so this is the established idiom rather than
a new one.

The CI literal count barely moves (45 -> 44) because its regex matches #hex and
fifteen of these were rgba(). Worth stating plainly: **the count was never the
goal, and the check is blind to this whole class.** An rgba triple is a colour
literal in every sense that matters and the report does not see it.

Not touched: the badge palette in KnowledgeView (#7A6DA8, #fbbf24, #818cf8 for
note/task/plan) and the remaining greys. Those are genuine unmade decisions —
what colour IS a plan badge — not drift, and inventing tokens for them would be
deciding by implementation.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UaYUaouG9jjhATyuxCKrQs
This commit is contained in:
2026-08-03 11:53:54 -04:00
co-authored by Claude Opus 5
parent bd60d679d9
commit c34454b840
5 changed files with 16 additions and 16 deletions
+3 -3
View File
@@ -129,7 +129,7 @@ router.afterEach(() => {
<style scoped> <style scoped>
.app-header { .app-header {
background: linear-gradient(180deg, var(--color-surface), var(--color-bg)); background: linear-gradient(180deg, var(--color-surface), var(--color-bg));
border-bottom: 1px solid rgba(91, 74, 138, 0.18); border-bottom: 1px solid color-mix(in srgb, var(--color-primary) 18%, transparent);
position: relative; position: relative;
} }
.nav { .nav {
@@ -197,8 +197,8 @@ router.afterEach(() => {
.nav-link.router-link-active { .nav-link.router-link-active {
color: var(--color-primary-solid); color: var(--color-primary-solid);
font-weight: 500; font-weight: 500;
background: rgba(91, 74, 138, 0.25); background: color-mix(in srgb, var(--color-primary) 25%, transparent);
box-shadow: 0 0 16px rgba(91, 74, 138, 0.3); box-shadow: 0 0 16px color-mix(in srgb, var(--color-primary) 30%, transparent);
} }
/* Status indicator */ /* Status indicator */
+3 -3
View File
@@ -64,11 +64,11 @@ function goEdit() {
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
background: var(--color-bg-card); background: var(--color-bg-card);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(91, 74, 138, 0.06); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px color-mix(in srgb, var(--color-primary) 6%, transparent);
transition: box-shadow 0.2s, transform 0.18s ease; transition: box-shadow 0.2s, transform 0.18s ease;
} }
.note-card:hover { .note-card:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(91, 74, 138, 0.14); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px color-mix(in srgb, var(--color-primary) 14.0%, transparent);
transform: translateY(-2px); transform: translateY(-2px);
} }
@@ -89,7 +89,7 @@ function goEdit() {
} }
.note-card.compact:hover { .note-card.compact:hover {
box-shadow: none; box-shadow: none;
background: rgba(91, 74, 138, 0.04); background: color-mix(in srgb, var(--color-primary) 4%, transparent);
transform: none; transform: none;
} }
.note-title-compact { .note-title-compact {
+2 -2
View File
@@ -112,11 +112,11 @@ function isOverdue(): boolean {
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
background: var(--color-bg-card); background: var(--color-bg-card);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(91, 74, 138, 0.06); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px color-mix(in srgb, var(--color-primary) 6%, transparent);
transition: box-shadow 0.2s, transform 0.18s ease; transition: box-shadow 0.2s, transform 0.18s ease;
} }
.task-card:hover { .task-card:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(91, 74, 138, 0.14); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px color-mix(in srgb, var(--color-primary) 14.0%, transparent);
transform: translateY(-2px); transform: translateY(-2px);
} }
+7 -7
View File
@@ -548,7 +548,7 @@ onUnmounted(() => {
content: '· · ·'; content: '· · ·';
display: block; display: block;
text-align: center; text-align: center;
color: rgba(91, 74, 138, 0.3); color: color-mix(in srgb, var(--color-primary) 30%, transparent);
font-size: 0.9rem; font-size: 0.9rem;
letter-spacing: 0.4em; letter-spacing: 0.4em;
padding: 4px 0 12px; padding: 4px 0 12px;
@@ -662,7 +662,7 @@ onUnmounted(() => {
flex-shrink: 0; flex-shrink: 0;
} }
.filter-btn.active .filter-count { .filter-btn.active .filter-count {
background: rgba(91, 74, 138, 0.2); background: color-mix(in srgb, var(--color-primary) 20%, transparent);
color: var(--color-primary); color: var(--color-primary);
} }
.filter-tag { font-size: 0.78rem; } .filter-tag { font-size: 0.78rem; }
@@ -749,12 +749,12 @@ onUnmounted(() => {
} }
.k-card:hover { .k-card:hover {
transform: translateY(-2px); transform: translateY(-2px);
box-shadow: 0 8px 28px rgba(91, 74, 138, 0.25), 0 2px 8px rgba(0, 0, 0, 0.3); box-shadow: 0 8px 28px color-mix(in srgb, var(--color-primary) 25%, transparent), 0 2px 8px rgba(0, 0, 0, 0.3);
border-color: rgba(91, 74, 138, 0.35); border-color: color-mix(in srgb, var(--color-primary) 35%, transparent);
} }
/* Type-specific card DNA */ /* Type-specific card DNA */
.k-card--note { border-color: rgba(91, 74, 138, 0.20); } .k-card--note { border-color: color-mix(in srgb, var(--color-primary) 20%, transparent); }
.k-card--task { border-color: rgba(212, 160, 23, 0.18); } .k-card--task { border-color: rgba(212, 160, 23, 0.18); }
/* Top gradient bars */ /* Top gradient bars */
@@ -769,7 +769,7 @@ onUnmounted(() => {
} }
.k-card--note::before { .k-card--note::before {
right: 0; right: 0;
background: linear-gradient(90deg, #5B4A8A, #7A6DA8); background: linear-gradient(90deg, var(--color-primary), #7A6DA8);
} }
.k-card--task::before { .k-card--task::before {
right: 0; right: 0;
@@ -788,7 +788,7 @@ onUnmounted(() => {
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.04em; letter-spacing: 0.04em;
} }
.badge--note { background: rgba(91, 74, 138,0.15); color: #7A6DA8; } .badge--note { background: color-mix(in srgb, var(--color-primary) 15%, transparent); color: #7A6DA8; }
.badge--task { background: rgba(212,160,23,0.15); color: #fbbf24; } .badge--task { background: rgba(212,160,23,0.15); color: #fbbf24; }
.badge--plan { background: rgba(99,102,241,0.18); color: #818cf8; } .badge--plan { background: rgba(99,102,241,0.18); color: #818cf8; }
+1 -1
View File
@@ -2404,7 +2404,7 @@ function formatUserDate(iso: string): string {
} }
.sidebar-item.active { .sidebar-item.active {
color: var(--color-primary); color: var(--color-primary);
background: rgba(91, 74, 138, 0.08); background: color-mix(in srgb, var(--color-primary) 8%, transparent);
border-left-color: var(--color-primary); border-left-color: var(--color-primary);
font-weight: 500; font-weight: 500;
} }