feat(design): foundation pass — dusty violet palette, warm parchment light, Inter + JetBrains Mono

Applies the FabledSword + Scribe iteration palette to theme.css end to
end: indigo (#7c3aed) → dusty violet (#5B4A8A) accent, cool grey →
Obsidian/Iron/Pewter dark surfaces, warm parchment (#F5F1E8) light
mode, Inter body + JetBrains Mono code loaded alongside Fraunces, and
neutral hairline scrollbars (chrome is structural, not branded).

Adds the action token set (--color-action-primary Moss,
--color-action-secondary Bronze, --color-action-destructive Oxblood,
--color-action-ghost-border Pewter) but does not yet reclassify any
buttons — surface-phase work. Buttons remain dusty-violet gradients in
the meantime, by design.

Removes deprecated --color-accent-warm; replaces concrete usages with
--color-text-secondary (dates, flavor copy) or --color-warning (paused
status). Sweeps hardcoded indigo literals in component scoped CSS so
they don't bypass the token system.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-27 17:20:01 -04:00
parent 057b30b89e
commit 7a9a8b7819
15 changed files with 197 additions and 163 deletions
+3 -3
View File
@@ -151,7 +151,7 @@ router.afterEach(() => {
<style scoped>
.app-header {
background: linear-gradient(180deg, var(--color-surface), var(--color-bg));
border-bottom: 1px solid rgba(124, 58, 237, 0.18);
border-bottom: 1px solid rgba(91, 74, 138, 0.18);
position: relative;
}
.nav {
@@ -220,8 +220,8 @@ router.afterEach(() => {
.nav-link.router-link-active {
color: var(--color-primary-solid);
font-weight: 600;
background: rgba(124, 58, 237, 0.25);
box-shadow: 0 0 16px rgba(124, 58, 237, 0.3);
background: rgba(91, 74, 138, 0.25);
box-shadow: 0 0 16px rgba(91, 74, 138, 0.3);
}
/* Status indicator */
+1 -1
View File
@@ -573,7 +573,7 @@ defineExpose({ focus, prefill })
flex-shrink: 0;
transition: box-shadow 0.15s;
}
.btn-send:hover { box-shadow: 0 0 16px rgba(124, 58, 237, 0.35); }
.btn-send:hover { box-shadow: 0 0 16px rgba(91, 74, 138, 0.35); }
.btn-send:disabled { opacity: 0.35; cursor: default; box-shadow: none; }
.btn-abort-inline {
+1 -1
View File
@@ -175,7 +175,7 @@ const timingParts = computed((): string[] => {
.thinking-block {
margin-bottom: 0.5rem;
border-left: 2px solid rgba(129, 140, 248, 0.35);
border-left: 2px solid rgba(91, 74, 138, 0.35);
border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
overflow: hidden;
}
+5 -6
View File
@@ -703,13 +703,12 @@ defineExpose({ focus, prefill, send, contextCount, sidebarOpen, toggleContextSid
}
.empty-msg {
color: var(--color-text-muted);
color: var(--color-text-secondary);
font-size: 0.9rem;
text-align: center;
padding: 2rem 1rem;
font-family: 'Fraunces', Georgia, serif;
font-style: italic;
color: var(--color-accent-warm, #d4a017);
}
.chat-empty-state {
@@ -727,7 +726,7 @@ defineExpose({ focus, prefill, send, contextCount, sidebarOpen, toggleContextSid
font-style: italic;
font-weight: 400;
font-size: 1.75rem;
color: var(--color-accent-warm, #d4a017);
color: var(--color-text-secondary);
text-align: center;
margin: 0;
}
@@ -768,7 +767,7 @@ defineExpose({ focus, prefill, send, contextCount, sidebarOpen, toggleContextSid
.empty-recent-item:hover {
border-color: var(--color-primary);
background: rgba(99, 102, 241, 0.05);
background: rgba(91, 74, 138, 0.05);
transform: translateX(2px);
}
@@ -805,9 +804,9 @@ defineExpose({ focus, prefill, send, contextCount, sidebarOpen, toggleContextSid
.empty-voice-btn:hover {
border-color: var(--color-primary);
background: linear-gradient(135deg, #6366f1, #4f46e5);
background: linear-gradient(135deg, #5B4A8A, #3F3560);
color: #fff;
box-shadow: 0 4px 16px rgba(99, 102, 241, 0.35);
box-shadow: 0 4px 16px rgba(91, 74, 138, 0.35);
}
.empty-voice-btn .voice-icon {
+2 -2
View File
@@ -315,7 +315,7 @@ async function doDelete() {
<label class="so-label so-label-inline">Color</label>
<div class="color-row">
<input v-model="color" type="color" class="color-picker" title="Pick event color" />
<input v-model="color" class="so-input color-hex" placeholder="#7c3aed" />
<input v-model="color" class="so-input color-hex" placeholder="#5B4A8A" />
<button v-if="color" type="button" class="btn-clear-color" @click="color = ''"></button>
</div>
</div>
@@ -450,7 +450,7 @@ async function doDelete() {
.so-past-hint {
margin: 4px 0 0;
font-size: 0.75rem;
color: var(--color-accent-warm, #d4a017);
color: var(--color-text-secondary);
font-style: italic;
}
+3 -3
View File
@@ -64,11 +64,11 @@ function goEdit() {
text-decoration: none;
color: inherit;
background: var(--color-bg-card);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(124, 58, 237, 0.06);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(91, 74, 138, 0.06);
transition: box-shadow 0.2s, transform 0.18s ease;
}
.note-card:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(124, 58, 237, 0.14);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(91, 74, 138, 0.14);
transform: translateY(-2px);
}
@@ -89,7 +89,7 @@ function goEdit() {
}
.note-card.compact:hover {
box-shadow: none;
background: rgba(124, 58, 237, 0.04);
background: rgba(91, 74, 138, 0.04);
transform: none;
}
.note-title-compact {
+2 -2
View File
@@ -112,11 +112,11 @@ function isOverdue(): boolean {
text-decoration: none;
color: inherit;
background: var(--color-bg-card);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(124, 58, 237, 0.06);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(91, 74, 138, 0.06);
transition: box-shadow 0.2s, transform 0.18s ease;
}
.task-card:hover {
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(124, 58, 237, 0.14);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(91, 74, 138, 0.14);
transform: translateY(-2px);
}