refactor: charcoal palette + sidebar drawer fixes

- Switch from true-dark to charcoal palette (sidebar darkest, content lighter)
  Page #1a1c23, Sidebar #10121a, Card #22252e, Border #2e3240
- Update all Tailwind semantic mappings to match new palette
- Update landing page CSS hardcoded hex to new palette values
- Fix remaining hardcoded hex in SurveyResponsesPage, SessionsPanel, FlowPilotMessageBar
- Sidebar drawer starts below topbar (top: var(--topbar-h)) instead of viewport top
- Drawer section title uses amber (#fbbf24) for visual pop
- Unify all rail icons: white when inactive, cyan with bg-accent-dim when active

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-22 21:39:05 +00:00
parent dfbb51b582
commit 8fd4207ee6
6 changed files with 63 additions and 68 deletions

View File

@@ -28,7 +28,7 @@ export function SessionsPanel({ sessions, delay = 200 }: SessionsPanelProps) {
View All View All
</Link> </Link>
</div> </div>
<div className="divide-y divide-[#1e2130]"> <div className="divide-y divide-border">
{sessions.map(session => ( {sessions.map(session => (
<Link <Link
key={session.id} key={session.id}

View File

@@ -51,7 +51,7 @@ export function FlowPilotMessageBar({ onRespond, disabled = false, isProcessing
? 'border-border/50 opacity-50' ? 'border-border/50 opacity-50'
: 'border-border focus-within:border-[rgba(6,182,212,0.3)]' : 'border-border focus-within:border-[rgba(6,182,212,0.3)]'
)} )}
style={{ background: '#14161d' }} style={{ background: 'var(--color-bg-card)' }}
> >
<textarea <textarea
ref={textareaRef} ref={textareaRef}

View File

@@ -243,9 +243,6 @@ export function Sidebar() {
const Icon = item.icon const Icon = item.icon
const hasChildren = item.children && item.children.length > 0 const hasChildren = item.children && item.children.length > 0
// Home icon: always cyan icon, but only bg-accent-dim when route is exactly "/"
const isHome = item.href === '/' && item.shortLabel === 'Home'
return ( return (
<div <div
key={key} key={key}
@@ -258,18 +255,14 @@ export function Sidebar() {
onFocus={() => hasChildren && !sidebarPinned ? openFlyout(key) : undefined} onFocus={() => hasChildren && !sidebarPinned ? openFlyout(key) : undefined}
className={cn( className={cn(
'group relative flex flex-col items-center justify-center rounded-lg px-2 py-3 transition-all duration-150', 'group relative flex flex-col items-center justify-center rounded-lg px-2 py-3 transition-all duration-150',
isHome active
? active ? 'bg-accent-dim text-accent-text'
? 'bg-accent-dim text-accent-text' : 'text-text-rail-label hover:text-foreground'
: 'text-accent-text'
: active
? 'bg-accent-dim text-accent-text'
: 'text-text-rail-label hover:text-muted-foreground'
)} )}
title={item.label} title={item.label}
> >
<span className="relative"> <span className="relative">
<Icon size={24} strokeWidth={1.6} className={active || isHome ? 'opacity-100' : 'opacity-60 group-hover:opacity-85'} /> <Icon size={24} strokeWidth={1.6} className={active ? 'opacity-100' : 'opacity-60 group-hover:opacity-85'} />
{item.badge !== undefined && item.badge > 0 && ( {item.badge !== undefined && item.badge > 0 && (
<span className="absolute -right-2 -top-1.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-primary px-1 text-[0.5rem] font-bold text-background"> <span className="absolute -right-2 -top-1.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-primary px-1 text-[0.5rem] font-bold text-background">
{item.badge > 99 ? '99+' : item.badge} {item.badge > 99 ? '99+' : item.badge}
@@ -448,8 +441,8 @@ export function Sidebar() {
{/* Drawer panel — fixed position, full height, resizable, overlays main content */} {/* Drawer panel — fixed position, full height, resizable, overlays main content */}
{activeFlyoutGroup && activeFlyoutGroup.children && ( {activeFlyoutGroup && activeFlyoutGroup.children && (
<div <div
className="fixed top-0 bottom-0 z-50 flex" className="fixed bottom-0 z-50 flex"
style={{ left: '72px' }} style={{ top: 'var(--topbar-h)', left: '72px' }}
onMouseEnter={keepFlyout} onMouseEnter={keepFlyout}
onMouseLeave={closeFlyout} onMouseLeave={closeFlyout}
> >
@@ -464,7 +457,7 @@ export function Sidebar() {
> >
{/* Drawer header */} {/* Drawer header */}
<div className="px-3 mb-3"> <div className="px-3 mb-3">
<h3 className="text-[0.6875rem] font-mono uppercase tracking-[0.12em] text-text-muted"> <h3 className="text-[0.6875rem] font-mono uppercase tracking-[0.12em] text-[#fbbf24]">
{activeFlyoutGroup.label} {activeFlyoutGroup.label}
</h3> </h3>
</div> </div>

View File

@@ -8,25 +8,25 @@
@import '@xyflow/react/dist/style.css'; @import '@xyflow/react/dist/style.css';
@theme { @theme {
/* ── Surface colors ────────────────────────────── */ /* ── Surface colors (Charcoal — sidebar darkest) ─ */
--color-bg-page: #0c0d10; --color-bg-page: #1a1c23;
--color-bg-sidebar: #0f1118; --color-bg-sidebar: #10121a;
--color-bg-card: #14161d; --color-bg-card: #22252e;
--color-bg-card-hover: #191c25; --color-bg-card-hover: #282b35;
--color-bg-input: #191c25; --color-bg-input: #282b35;
--color-bg-code: #0e1017; --color-bg-code: #14161e;
--color-bg-elevated: #1c1f2a; --color-bg-elevated: #2e3140;
/* ── Text colors ───────────────────────────────── */ /* ── Text colors ───────────────────────────────── */
--color-text-heading: #f0f2f5; --color-text-heading: #f0f2f5;
--color-text-primary: #e2e5eb; --color-text-primary: #e2e5eb;
--color-text-secondary: #848b9b; --color-text-secondary: #848b9b;
--color-text-muted: #4f5666; --color-text-muted: #4f5666;
--color-text-rail-label: #6b7280; --color-text-rail-label: #e2e5eb;
/* ── Border colors ─────────────────────────────── */ /* ── Border colors ─────────────────────────────── */
--color-border-default: #1e2130; --color-border-default: #2e3240;
--color-border-hover: #2a2f3d; --color-border-hover: #3d4252;
/* ── Accent (cyan) ─────────────────────────────── */ /* ── Accent (cyan) ─────────────────────────────── */
--color-accent: #22d3ee; --color-accent: #22d3ee;
@@ -43,24 +43,24 @@
--color-danger-dim: rgba(248,113,113,0.10); --color-danger-dim: rgba(248,113,113,0.10);
/* ── Tailwind semantic mappings ─────────────────── */ /* ── Tailwind semantic mappings ─────────────────── */
--color-background: #0c0d10; --color-background: #1a1c23;
--color-foreground: #e2e5eb; --color-foreground: #e2e5eb;
--color-card: #14161d; --color-card: #22252e;
--color-card-foreground: #e2e5eb; --color-card-foreground: #e2e5eb;
--color-popover: #14161d; --color-popover: #22252e;
--color-popover-foreground: #e2e5eb; --color-popover-foreground: #e2e5eb;
--color-primary: #22d3ee; --color-primary: #22d3ee;
--color-primary-foreground: #ffffff; --color-primary-foreground: #ffffff;
--color-secondary: #1c1f2a; --color-secondary: #2e3140;
--color-secondary-foreground: #e2e5eb; --color-secondary-foreground: #e2e5eb;
--color-muted: #1c1f2a; --color-muted: #2e3140;
--color-muted-foreground: #848b9b; --color-muted-foreground: #848b9b;
--color-accent-tw: #1c1f2a; --color-accent-tw: #2e3140;
--color-accent-foreground: #e2e5eb; --color-accent-foreground: #e2e5eb;
--color-destructive: #f87171; --color-destructive: #f87171;
--color-destructive-foreground: #ffffff; --color-destructive-foreground: #ffffff;
--color-border: #1e2130; --color-border: #2e3240;
--color-input: #191c25; --color-input: #282b35;
--color-ring: #22d3ee; --color-ring: #22d3ee;
/* ── Radii ─────────────────────────────────────── */ /* ── Radii ─────────────────────────────────────── */
@@ -106,6 +106,7 @@
:root { :root {
--sidebar-w: 72px; --sidebar-w: 72px;
--sidebar-w-pinned: 260px; --sidebar-w-pinned: 260px;
--topbar-h: 44px;
--ease-out-smooth: cubic-bezier(0.4, 0, 0.2, 1); --ease-out-smooth: cubic-bezier(0.4, 0, 0.2, 1);
} }
@@ -274,6 +275,7 @@
.topbar { .topbar {
grid-column: 1 / -1; grid-column: 1 / -1;
height: var(--topbar-h);
} }
.sidebar { .sidebar {

View File

@@ -100,7 +100,7 @@ function ExpandedDetail({ response }: { response: SurveyResponseDetail }) {
key={q.id} key={q.id}
className="rounded-lg p-4" className="rounded-lg p-4"
style={{ style={{
background: '#14161d', background: 'var(--color-bg-card)',
border: '1px solid var(--glass-border)', border: '1px solid var(--glass-border)',
}} }}
> >
@@ -223,7 +223,7 @@ function ResponseRow({
<div className="fixed inset-0 z-40" onClick={() => setShowMenu(false)} /> <div className="fixed inset-0 z-40" onClick={() => setShowMenu(false)} />
<div <div
className="absolute right-3 top-full z-50 mt-1 w-44 rounded-xl py-1 shadow-xl" className="absolute right-3 top-full z-50 mt-1 w-44 rounded-xl py-1 shadow-xl"
style={{ background: '#14161d', border: '1px solid var(--glass-border)', }} style={{ background: 'var(--color-bg-card)', border: '1px solid var(--glass-border)', }}
> >
<button <button
onClick={() => { onMarkRead(); setShowMenu(false) }} onClick={() => { onMarkRead(); setShowMenu(false) }}

View File

@@ -6,7 +6,7 @@
.landing-page { .landing-page {
font-family: 'IBM Plex Sans', sans-serif; font-family: 'IBM Plex Sans', sans-serif;
background: #0c0d10; background: #1a1c23;
color: #e2e5eb; color: #e2e5eb;
line-height: 1.6; line-height: 1.6;
overflow-x: hidden; overflow-x: hidden;
@@ -61,7 +61,7 @@
.landing-nav.scrolled { .landing-nav.scrolled {
background: rgba(12, 13, 16, 0.95); background: rgba(12, 13, 16, 0.95);
border-bottom: 1px solid #1e2130; border-bottom: 1px solid #2e3240;
} }
.landing-nav-inner { .landing-nav-inner {
@@ -184,8 +184,8 @@
gap: 8px; gap: 8px;
padding: 6px 16px; padding: 6px 16px;
border-radius: 100px; border-radius: 100px;
background: #14161d; background: #22252e;
border: 1px solid #1e2130; border: 1px solid #2e3240;
font-family: 'IBM Plex Sans', sans-serif; font-family: 'IBM Plex Sans', sans-serif;
font-size: 0.75rem; font-size: 0.75rem;
font-weight: 500; font-weight: 500;
@@ -280,8 +280,8 @@
text-decoration: none; text-decoration: none;
padding: 0.85rem 2rem; padding: 0.85rem 2rem;
border-radius: 10px; border-radius: 10px;
background: #14161d; background: #22252e;
border: 1px solid #1e2130; border: 1px solid #2e3240;
transition: background 0.3s, border-color 0.3s, color 0.3s; transition: background 0.3s, border-color 0.3s, color 0.3s;
} }
@@ -341,8 +341,8 @@
.landing-preview-window { .landing-preview-window {
border-radius: 12px; border-radius: 12px;
border: 1px solid #1e2130; border: 1px solid #2e3240;
background: #14161d; background: #22252e;
overflow: hidden; overflow: hidden;
box-shadow: 0 20px 80px rgba(0, 0, 0, 0.4); box-shadow: 0 20px 80px rgba(0, 0, 0, 0.4);
} }
@@ -353,7 +353,7 @@
padding: 0 0 0 14px; padding: 0 0 0 14px;
height: 40px; height: 40px;
background: rgba(255, 255, 255, 0.02); background: rgba(255, 255, 255, 0.02);
border-bottom: 1px solid #1e2130; border-bottom: 1px solid #2e3240;
} }
.landing-preview-tab { .landing-preview-tab {
@@ -365,7 +365,7 @@
font-family: 'IBM Plex Sans', sans-serif; font-family: 'IBM Plex Sans', sans-serif;
font-size: 0.7rem; font-size: 0.7rem;
color: #848b9b; color: #848b9b;
border-right: 1px solid #1e2130; border-right: 1px solid #2e3240;
background: rgba(255, 255, 255, 0.02); background: rgba(255, 255, 255, 0.02);
position: relative; position: relative;
} }
@@ -409,7 +409,7 @@
padding: 4px 12px; padding: 4px 12px;
border-radius: 6px; border-radius: 6px;
background: rgba(255, 255, 255, 0.03); background: rgba(255, 255, 255, 0.03);
border: 1px solid #1e2130; border: 1px solid #2e3240;
font-family: 'IBM Plex Sans', sans-serif; font-family: 'IBM Plex Sans', sans-serif;
font-size: 0.65rem; font-size: 0.65rem;
color: #5a6170; color: #5a6170;
@@ -496,7 +496,7 @@
flex: 1; flex: 1;
background: rgba(255, 255, 255, 0.01); background: rgba(255, 255, 255, 0.01);
border-radius: 12px; border-radius: 12px;
border: 1px dashed #1e2130; border: 1px dashed #2e3240;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -525,8 +525,8 @@
} }
.landing-tree-node.decision { .landing-tree-node.decision {
background: #14161d; background: #22252e;
border: 1px solid #1e2130; border: 1px solid #2e3240;
color: #e2e5eb; color: #e2e5eb;
font-size: 0.7rem; font-size: 0.7rem;
} }
@@ -614,7 +614,7 @@
max-width: 1100px; max-width: 1100px;
margin: 0 auto; margin: 0 auto;
height: 1px; height: 1px;
background: #1e2130; background: #2e3240;
} }
/* ---- PROBLEM SECTION ---- */ /* ---- PROBLEM SECTION ---- */
@@ -629,7 +629,7 @@
.landing-problem-card { .landing-problem-card {
padding: 2rem; padding: 2rem;
border-radius: 16px; border-radius: 16px;
background: #14161d; background: #22252e;
border: 1px solid #2a2f3d; border: 1px solid #2a2f3d;
transition: border-color 0.3s, transform 0.3s; transition: border-color 0.3s, transform 0.3s;
} }
@@ -712,8 +712,8 @@
.landing-eq-item { .landing-eq-item {
padding: 0.5rem 1.25rem; padding: 0.5rem 1.25rem;
border-radius: 12px; border-radius: 12px;
background: #14161d; background: #22252e;
border: 1px solid #1e2130; border: 1px solid #2e3240;
} }
.landing-eq-operator { .landing-eq-operator {
@@ -747,7 +747,7 @@
.landing-step-card { .landing-step-card {
padding: 2rem; padding: 2rem;
border-radius: 16px; border-radius: 16px;
background: #14161d; background: #22252e;
border: 1px solid #2a2f3d; border: 1px solid #2a2f3d;
position: relative; position: relative;
counter-increment: landing-step; counter-increment: landing-step;
@@ -787,8 +787,8 @@
height: 120px; height: 120px;
border-radius: 10px; border-radius: 10px;
margin-top: 1.25rem; margin-top: 1.25rem;
background: #0c0d10; background: #1a1c23;
border: 1px solid #1e2130; border: 1px solid #2e3240;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -821,7 +821,7 @@
.landing-mock-node.step { .landing-mock-node.step {
background: rgba(255, 255, 255, 0.03); background: rgba(255, 255, 255, 0.03);
color: #848b9b; color: #848b9b;
border: 1px solid #1e2130; border: 1px solid #2e3240;
} }
.landing-mock-connector { .landing-mock-connector {
@@ -879,7 +879,7 @@
color: #67e8f9; color: #67e8f9;
font-weight: 600; font-weight: 600;
padding-bottom: 0.35rem; padding-bottom: 0.35rem;
border-bottom: 1px solid #1e2130; border-bottom: 1px solid #2e3240;
margin-bottom: 0.15rem; margin-bottom: 0.15rem;
} }
@@ -911,7 +911,7 @@
.landing-feature-card { .landing-feature-card {
padding: 2rem; padding: 2rem;
border-radius: 16px; border-radius: 16px;
background: #14161d; background: #22252e;
border: 1px solid #2a2f3d; border: 1px solid #2a2f3d;
transition: border-color 0.3s ease, transform 0.3s ease; transition: border-color 0.3s ease, transform 0.3s ease;
} }
@@ -949,7 +949,7 @@
.landing-feature-card.highlight { .landing-feature-card.highlight {
border-color: rgba(34, 211, 238, 0.15); border-color: rgba(34, 211, 238, 0.15);
background: #14161d; background: #22252e;
grid-column: span 2; grid-column: span 2;
} }
@@ -965,7 +965,7 @@
.landing-pricing-card { .landing-pricing-card {
padding: 2.5rem 2rem; padding: 2.5rem 2rem;
border-radius: 16px; border-radius: 16px;
background: #14161d; background: #22252e;
border: 1px solid #2a2f3d; border: 1px solid #2a2f3d;
transition: border-color 0.3s, transform 0.3s; transition: border-color 0.3s, transform 0.3s;
} }
@@ -976,7 +976,7 @@
.landing-pricing-card.featured { .landing-pricing-card.featured {
border-color: #22d3ee; border-color: #22d3ee;
background: #14161d; background: #22252e;
position: relative; position: relative;
} }
@@ -1210,8 +1210,8 @@
flex: 1; flex: 1;
padding: 0.85rem 1.25rem; padding: 0.85rem 1.25rem;
border-radius: 10px; border-radius: 10px;
border: 1px solid #1e2130; border: 1px solid #2e3240;
background: #14161d; background: #22252e;
color: #e2e5eb; color: #e2e5eb;
font-family: 'IBM Plex Sans', sans-serif; font-family: 'IBM Plex Sans', sans-serif;
font-size: 0.9rem; font-size: 0.9rem;
@@ -1248,7 +1248,7 @@
/* ---- FOOTER ---- */ /* ---- FOOTER ---- */
.landing-footer { .landing-footer {
border-top: 1px solid #1e2130; border-top: 1px solid #2e3240;
padding: 3rem 2rem; padding: 3rem 2rem;
} }
@@ -1376,7 +1376,7 @@
gap: 0; gap: 0;
padding: 0.5rem 1.5rem 1.5rem; padding: 0.5rem 1.5rem 1.5rem;
background: rgba(12, 13, 16, 0.98); background: rgba(12, 13, 16, 0.98);
border-bottom: 1px solid #1e2130; border-bottom: 1px solid #2e3240;
} }
.landing-mobile-menu a { .landing-mobile-menu a {