UI polish: Illuminated Transcript design language

- Fraunces serif for headings and assistant identity label
- Chat bubbles flipped: assistant responses elevated (card + left indigo
  accent + shadow), user prompts ghosted (transparent bg, muted text)
- AppLogo: book fill changed from text-color to indigo in light mode
- AppHeader: border-bottom removed; active nav uses underline accent
- NoteCard/TaskCard: border replaced with whisper indigo-tint shadow
- HomeView: dashboard-response uses left accent; progress bars indigo;
  empty-state decorative marker; project cards use shadow depth
- NotesListView: btn-new/btn-cta use indigo gradient + glow
- All primary CTA buttons: indigo gradient (135deg #6366f1 → #4f46e5)
  with box-shadow glow on hover
- Dark palette: navy (#1a1a2e family) → slate-indigo (#111113 family)
- Scrollbars: thin 4px indigo-tinted

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Bryan Van Deusen
2026-03-10 15:18:22 -04:00
parent a56f514df6
commit 3c3dd7377a
8 changed files with 84 additions and 22 deletions
+7
View File
@@ -1,3 +1,5 @@
@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..900;1,9..144,300..900&display=swap');
:root { :root {
--color-bg: #f5f5fb; --color-bg: #f5f5fb;
--color-bg-secondary: #ededf5; --color-bg-secondary: #ededf5;
@@ -111,6 +113,11 @@ body {
transition: background-color 0.2s, color 0.2s; transition: background-color 0.2s, color 0.2s;
} }
h1, h2, h3 {
font-family: 'Fraunces', Georgia, serif;
font-optical-sizing: auto;
}
input:focus-visible, input:focus-visible,
textarea:focus-visible, textarea:focus-visible,
select:focus-visible, select:focus-visible,
+8 -5
View File
@@ -166,7 +166,6 @@ onUnmounted(() => document.removeEventListener("click", handleClickOutside));
<style scoped> <style scoped>
.app-header { .app-header {
background: var(--color-bg-secondary); background: var(--color-bg-secondary);
border-bottom: 1px solid var(--color-border);
position: relative; position: relative;
} }
.nav { .nav {
@@ -182,8 +181,11 @@ onUnmounted(() => document.removeEventListener("click", handleClickOutside));
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.4rem; gap: 0.4rem;
font-weight: 700; font-family: 'Fraunces', Georgia, serif;
font-size: 1.1rem; font-optical-sizing: auto;
font-weight: 600;
font-size: 1.15rem;
letter-spacing: -0.01em;
color: var(--color-primary); color: var(--color-primary);
text-decoration: none; text-decoration: none;
flex-shrink: 0; flex-shrink: 0;
@@ -217,12 +219,13 @@ onUnmounted(() => document.removeEventListener("click", handleClickOutside));
} }
.nav-link:hover { .nav-link:hover {
color: var(--color-primary); color: var(--color-primary);
background: var(--color-bg-card); background: color-mix(in srgb, var(--color-primary) 8%, transparent);
} }
.nav-link.router-link-active { .nav-link.router-link-active {
color: var(--color-primary); color: var(--color-primary);
background: var(--color-bg-card);
font-weight: 600; font-weight: 600;
box-shadow: inset 0 -2px 0 var(--color-primary);
border-radius: 0;
} }
/* Status indicator */ /* Status indicator */
+6
View File
@@ -155,6 +155,12 @@ const timingParts = computed((): string[] => {
} }
.role-assistant .role-label { .role-assistant .role-label {
color: var(--color-primary); color: var(--color-primary);
font-family: 'Fraunces', Georgia, serif;
font-optical-sizing: auto;
font-style: italic;
font-size: 0.8rem;
text-transform: none;
letter-spacing: 0;
} }
.thinking-block { .thinking-block {
+3 -3
View File
@@ -60,15 +60,15 @@ function goEdit() {
.note-card { .note-card {
display: block; display: block;
padding: 1rem; padding: 1rem;
border: 1px solid var(--color-border);
border-radius: var(--radius-md); border-radius: var(--radius-md);
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
background: var(--color-bg-card); background: var(--color-bg-card);
transition: box-shadow 0.15s; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(99, 102, 241, 0.06);
transition: box-shadow 0.2s;
} }
.note-card:hover { .note-card:hover {
box-shadow: 0 2px 8px var(--color-shadow); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(99, 102, 241, 0.14);
} }
/* Compact single-row layout */ /* Compact single-row layout */
+3 -3
View File
@@ -97,15 +97,15 @@ function isOverdue(): boolean {
.task-card { .task-card {
display: block; display: block;
padding: 1rem; padding: 1rem;
border: 1px solid var(--color-border);
border-radius: var(--radius-md); border-radius: var(--radius-md);
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
background: var(--color-bg-card); background: var(--color-bg-card);
transition: box-shadow 0.15s; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(99, 102, 241, 0.06);
transition: box-shadow 0.2s;
} }
.task-card:hover { .task-card:hover {
box-shadow: 0 2px 8px var(--color-shadow); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(99, 102, 241, 0.14);
} }
/* Compact single-row layout */ /* Compact single-row layout */
+28 -8
View File
@@ -523,6 +523,7 @@ function clearDashboardResponse() {
.quick-action-chip:hover:not(:disabled) { .quick-action-chip:hover:not(:disabled) {
border-color: var(--color-primary); border-color: var(--color-primary);
color: var(--color-primary); color: var(--color-primary);
background: color-mix(in srgb, var(--color-primary) 8%, transparent);
} }
.quick-action-chip:disabled { opacity: 0.4; cursor: default; } .quick-action-chip:disabled { opacity: 0.4; cursor: default; }
@@ -530,9 +531,10 @@ function clearDashboardResponse() {
.dashboard-response { .dashboard-response {
margin-bottom: 1.5rem; margin-bottom: 1.5rem;
padding: 0.75rem 1rem; padding: 0.75rem 1rem;
background: var(--color-bg-secondary); background: var(--color-bg-card);
border: 1px solid var(--color-border); border-left: 2px solid var(--color-primary);
border-radius: var(--radius-md); border-radius: var(--radius-md);
box-shadow: var(--color-bubble-asst-shadow);
} }
.dashboard-response-query { .dashboard-response-query {
font-size: 0.8rem; font-size: 0.8rem;
@@ -579,7 +581,6 @@ function clearDashboardResponse() {
gap: 0.75rem; gap: 0.75rem;
margin-top: 0.75rem; margin-top: 0.75rem;
padding-top: 0.5rem; padding-top: 0.5rem;
border-top: 1px solid var(--color-border);
} }
.btn-open-chat { .btn-open-chat {
font-size: 0.85rem; font-size: 0.85rem;
@@ -589,13 +590,18 @@ function clearDashboardResponse() {
} }
.btn-open-chat:hover { text-decoration: underline; } .btn-open-chat:hover { text-decoration: underline; }
.btn-open-chat.prominent { .btn-open-chat.prominent {
background: var(--color-primary); background: linear-gradient(135deg, #6366f1, #4f46e5);
color: #fff; color: #fff;
padding: 0.35rem 0.85rem; padding: 0.35rem 0.85rem;
border-radius: var(--radius-sm); border-radius: var(--radius-sm);
font-size: 0.9rem; font-size: 0.9rem;
box-shadow: 0 1px 6px rgba(99, 102, 241, 0.25);
}
.btn-open-chat.prominent:hover {
text-decoration: none;
box-shadow: 0 3px 12px rgba(99, 102, 241, 0.45);
filter: brightness(1.08);
} }
.btn-open-chat.prominent:hover { text-decoration: none; opacity: 0.9; }
.btn-clear-response { .btn-clear-response {
font-size: 0.8rem; font-size: 0.8rem;
color: var(--color-text-muted); color: var(--color-text-muted);
@@ -680,15 +686,15 @@ function clearDashboardResponse() {
.project-mini-card { .project-mini-card {
display: block; display: block;
padding: 0.75rem; padding: 0.75rem;
border: 1px solid var(--color-border);
border-radius: var(--radius-md); border-radius: var(--radius-md);
background: var(--color-bg-card); background: var(--color-bg-card);
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(99, 102, 241, 0.06);
transition: box-shadow 0.15s; transition: box-shadow 0.15s;
} }
.project-mini-card:hover { .project-mini-card:hover {
box-shadow: 0 2px 8px var(--color-shadow); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.10), 0 0 0 1px rgba(99, 102, 241, 0.14);
} }
.project-mini-title { .project-mini-title {
font-size: 0.9rem; font-size: 0.9rem;
@@ -723,6 +729,7 @@ function clearDashboardResponse() {
.ms-fill { .ms-fill {
height: 100%; height: 100%;
border-radius: 999px; border-radius: 999px;
background: var(--color-primary);
transition: width 0.3s; transition: width 0.3s;
} }
.ms-pct { .ms-pct {
@@ -743,17 +750,30 @@ function clearDashboardResponse() {
.loading { color: var(--color-text-secondary); } .loading { color: var(--color-text-secondary); }
.empty-state { text-align: center; padding: 1.5rem 0; } .empty-state { text-align: center; padding: 1.5rem 0; }
.empty-state::before {
content: "✦";
display: block;
font-size: 1.2rem;
color: var(--color-primary);
opacity: 0.4;
margin-bottom: 0.4rem;
}
.empty-text { color: var(--color-text-muted); margin: 0 0 0.75rem; } .empty-text { color: var(--color-text-muted); margin: 0 0 0.75rem; }
.btn-cta { .btn-cta {
display: inline-block; display: inline-block;
padding: 0.45rem 1rem; padding: 0.45rem 1rem;
background: var(--color-primary); background: linear-gradient(135deg, #6366f1, #4f46e5);
color: #fff; color: #fff;
border: none; border: none;
border-radius: var(--radius-sm); border-radius: var(--radius-sm);
text-decoration: none; text-decoration: none;
font-size: 0.9rem; font-size: 0.9rem;
cursor: pointer; cursor: pointer;
box-shadow: 0 1px 6px rgba(99, 102, 241, 0.25);
}
.btn-cta:hover {
box-shadow: 0 3px 12px rgba(99, 102, 241, 0.45);
filter: brightness(1.08);
} }
/* Mobile */ /* Mobile */
+12 -2
View File
@@ -201,11 +201,16 @@ function onOffsetUpdate(offset: number) {
} }
.btn-new { .btn-new {
padding: 0.45rem 1rem; padding: 0.45rem 1rem;
background: var(--color-primary); background: linear-gradient(135deg, #6366f1, #4f46e5);
color: #fff; color: #fff;
border-radius: var(--radius-sm); border-radius: var(--radius-sm);
text-decoration: none; text-decoration: none;
font-size: 0.9rem; font-size: 0.9rem;
box-shadow: 0 1px 6px rgba(99, 102, 241, 0.25);
}
.btn-new:hover {
box-shadow: 0 3px 12px rgba(99, 102, 241, 0.45);
filter: brightness(1.08);
} }
.controls { .controls {
display: flex; display: flex;
@@ -312,11 +317,16 @@ function onOffsetUpdate(offset: number) {
.btn-cta { .btn-cta {
display: inline-block; display: inline-block;
padding: 0.45rem 1rem; padding: 0.45rem 1rem;
background: var(--color-primary); background: linear-gradient(135deg, #6366f1, #4f46e5);
color: #fff; color: #fff;
border-radius: var(--radius-sm); border-radius: var(--radius-sm);
text-decoration: none; text-decoration: none;
font-size: 0.9rem; font-size: 0.9rem;
box-shadow: 0 1px 6px rgba(99, 102, 241, 0.25);
}
.btn-cta:hover {
box-shadow: 0 3px 12px rgba(99, 102, 241, 0.45);
filter: brightness(1.08);
} }
.kb-active-item { .kb-active-item {
+17 -1
View File
@@ -12,7 +12,23 @@
> Include file-level details in the commit body when the change is non-trivial. > Include file-level details in the commit body when the change is non-trivial.
## Last Updated ## Last Updated
2026-03-10 — CI/CD optimization: custom runner base image, explicit label naming, pip caching, Node 22. 2026-03-10 — UI polish pass: "Illuminated Transcript" design language, Fraunces typography, indigo gradient buttons, shadow-based card depth, bubble hierarchy flip.
**UI polish pass — design language:**
- `frontend/src/assets/theme.css`: added Fraunces Google Font import; `h1/h2/h3` use `font-family: 'Fraunces', Georgia, serif`; `--radius-md` 8→12px, `--radius-lg` 12→18px; added thin indigo-tinted scrollbars (4px); added bubble-specific CSS variables (`--color-bubble-user-*`, `--color-bubble-asst-shadow`); dark palette shifted from generic navy (#1a1a2e family) to slate-indigo (#111113 family).
- `frontend/src/components/AppLogo.vue`: logo book fill changed from `var(--color-text)` (black in light mode) to `var(--color-primary)` (indigo). Stroke updated to `color-mix(in srgb, var(--color-primary) 70%, transparent)`.
- `frontend/src/components/AppHeader.vue`: removed `border-bottom` from `.app-header`; nav brand uses Fraunces font; active nav link uses `inset 0 -2px 0 var(--color-primary)` underline instead of background fill.
- `frontend/src/components/ChatMessage.vue`: user bubble ghosted (transparent bg, thin border, muted text); assistant bubble elevated with left `2px solid var(--color-primary)` accent + shadow; assistant role label in Fraunces italic indigo; thinking block uses left-accent instead of full border.
- `frontend/src/views/ChatView.vue`: removed sidebar/header/context-sidebar borders; streaming bubble matches assistant style; active conversation item uses 15% indigo tint; send button and queued bubbles use indigo gradient + glow.
- `frontend/src/components/NoteCard.vue`, `TaskCard.vue`: removed `border: 1px solid`; replaced with whisper shadow (`0 1px 4px + 0 0 0 1px indigo tint`); elevated shadow on hover.
- `frontend/src/views/HomeView.vue`: `dashboard-response` uses left indigo accent + elevation shadow (no border); `dashboard-response-actions` border-top removed; quick-action-chip hover adds indigo bg tint; project-mini-card uses whisper shadow; ms-fill progress bars use `var(--color-primary)`; `.btn-cta` and `.btn-open-chat.prominent` use indigo gradient + glow; `.empty-state::before` adds decorative `✦` marker.
- `frontend/src/views/NotesListView.vue`: `.btn-new` and `.btn-cta` use indigo gradient + glow on hover.
**Design intent:** "Illuminated Transcript" — LLM responses are primary artifacts (elevated, card-like, indigo accent left-border), user prompts are subordinate margin notes (ghosted, recessed). Buttons with the gradient carry intentional weight. Borders replaced by shadow depth throughout.
---
**Previous session (2026-03-10):** CI/CD optimization: custom runner base image, explicit label naming, pip caching, Node 22.
**CI/CD infrastructure overhaul:** **CI/CD infrastructure overhaul:**
- `infra/Dockerfile.runner-base` (new): Ubuntu 24.04 base image with Python 3.12 (native, no PPA) and Node 22 LTS pre-installed. Tagged `py3.12-node22`. Eliminates the ~3-4 min deadsnakes PPA install that ran on every test job. Build/push command in file header. - `infra/Dockerfile.runner-base` (new): Ubuntu 24.04 base image with Python 3.12 (native, no PPA) and Node 22 LTS pre-installed. Tagged `py3.12-node22`. Eliminates the ~3-4 min deadsnakes PPA install that ran on every test job. Build/push command in file header.