refactor: replace cyan accent with ember orange across entire frontend

Swap accent color from cyan (#22d3ee) to ember orange (#f97316) site-wide.
Cyan caused contrast issues and felt generic — orange brings warmth and
urgency fitting for a troubleshooting tool.

Changes:
- CSS variables: accent, accent-hover, accent-dim, accent-text, primary, ring
- Warning color shifted from amber (#fbbf24) to yellow (#eab308) for
  semantic separation from orange accent
- Brand SVGs: logo gradient updated to orange
- 50+ component files: all hardcoded cyan hex values, Tailwind cyan-*
  classes, and rgba(34,211,238,...) glow values replaced
- landing.css: all 45+ cyan references + 5 old border color fixes
- DESIGN-SYSTEM.md bumped to v5 with decisions log
- CLAUDE.md: all color references synced to charcoal palette + orange accent
- PWA theme-color meta tag updated to match sidebar (#10121a)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
chihlasm
2026-03-24 07:37:44 +00:00
parent 13860ced33
commit ff985fb755
52 changed files with 291 additions and 274 deletions

View File

@@ -215,7 +215,7 @@ export default function FlowPilotAnalyticsPage() {
icon={BarChart3}
label="Total Sessions"
value={dashboard.total_sessions}
iconColor="#22d3ee"
iconColor="#f97316"
/>
<MetricCard
icon={CheckCircle2}
@@ -233,7 +233,7 @@ export default function FlowPilotAnalyticsPage() {
icon={Star}
label="Avg Rating"
value={dashboard.avg_rating ? `${dashboard.avg_rating.toFixed(1)}/5` : '—'}
iconColor="#fbbf24"
iconColor="#eab308"
/>
<MetricCard
icon={Ticket}
@@ -271,14 +271,14 @@ export default function FlowPilotAnalyticsPage() {
<Area
type="monotone"
dataKey="mttr_minutes"
stroke="#22d3ee"
stroke="#f97316"
fill="url(#mttrGradient)"
strokeWidth={2}
/>
<defs>
<linearGradient id="mttrGradient" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="#22d3ee" stopOpacity={0.3} />
<stop offset="95%" stopColor="#22d3ee" stopOpacity={0} />
<stop offset="5%" stopColor="#f97316" stopOpacity={0.3} />
<stop offset="95%" stopColor="#f97316" stopOpacity={0} />
</linearGradient>
</defs>
</AreaChart>
@@ -311,7 +311,7 @@ export default function FlowPilotAnalyticsPage() {
labelStyle={{ color: '#f8fafc' }}
/>
<Bar dataKey="resolved" name="Resolved" fill="#34d399" radius={[0, 4, 4, 0]} />
<Bar dataKey="escalated" name="Escalated" fill="#fbbf24" radius={[0, 4, 4, 0]} />
<Bar dataKey="escalated" name="Escalated" fill="#eab308" radius={[0, 4, 4, 0]} />
</BarChart>
</ResponsiveContainer>
) : (
@@ -341,7 +341,7 @@ export default function FlowPilotAnalyticsPage() {
label="Exploring"
count={conf.exploring_sessions}
rate={conf.exploring_resolution_rate}
color="#fbbf24"
color="#eab308"
total={conf.guided_sessions + conf.exploring_sessions + conf.discovery_sessions}
/>
<ConfidenceTierRow

View File

@@ -186,7 +186,7 @@ export default function FlowPilotSessionPage() {
<div className="flex gap-2">
<button
onClick={() => blocker.reset()}
className="flex-1 rounded-lg bg-gradient-to-r from-cyan-500 to-cyan-400 px-4 py-2.5 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all"
className="flex-1 rounded-lg bg-gradient-to-r from-orange-500 to-orange-400 px-4 py-2.5 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all"
>
Stay in Session
</button>
@@ -242,7 +242,7 @@ export default function FlowPilotSessionPage() {
<button
onClick={() => setShowStatusUpdate(true)}
disabled={fp.isProcessing}
className="flex items-center gap-1.5 rounded-lg bg-cyan-500/10 border border-cyan-500/20 px-3 py-1.5 text-xs font-medium text-cyan-400 hover:bg-cyan-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
className="flex items-center gap-1.5 rounded-lg bg-orange-500/10 border border-orange-500/20 px-3 py-1.5 text-xs font-medium text-orange-400 hover:bg-orange-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
title="Share Update"
>
<FileText size={13} />
@@ -312,7 +312,7 @@ export default function FlowPilotSessionPage() {
{fp.allSteps.length >= 2 && (
<button
onClick={() => { setShowOverflow(false); setShowStatusUpdate(true) }}
className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-cyan-400 hover:bg-cyan-500/10 transition-colors"
className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-orange-400 hover:bg-orange-500/10 transition-colors"
>
<FileText size={14} />
Share Update
@@ -390,7 +390,7 @@ export default function FlowPilotSessionPage() {
value={resolutionSummary}
onChange={(e) => setResolutionSummary(e.target.value)}
placeholder="What resolved the issue?"
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none resize-none"
rows={4}
autoFocus
/>

View File

@@ -194,7 +194,7 @@ export default function LandingPage() {
<div className="landing-preview-body">
<div className="landing-preview-sidebar">
<div className="landing-preview-sidebar-item active">
<div className="dot" style={{ background: '#22d3ee' }} />
<div className="dot" style={{ background: '#f97316' }} />
FlowPilot
</div>
<div className="landing-preview-sidebar-item">
@@ -221,15 +221,15 @@ export default function LandingPage() {
<span className="text">User can&apos;t access shared drive after password reset</span>
</div>
<div className="landing-mock-chat-line">
<span className="label" style={{ color: '#22d3ee' }}>FlowPilot:</span>
<span className="label" style={{ color: '#f97316' }}>FlowPilot:</span>
<span className="text">This is likely a cached credential issue. Let&apos;s check a few things:</span>
</div>
<div className="landing-mock-chat-line">
<span className="label" style={{ color: '#22d3ee' }}>FlowPilot:</span>
<span className="label" style={{ color: '#f97316' }}>FlowPilot:</span>
<span className="text">1. Run <code>klist purge</code> to clear Kerberos tickets</span>
</div>
<div className="landing-mock-chat-line">
<span className="label" style={{ color: '#22d3ee' }}>FlowPilot:</span>
<span className="label" style={{ color: '#f97316' }}>FlowPilot:</span>
<span className="text">2. Open Credential Manager &rarr; remove saved entries for the share</span>
</div>
<div className="landing-mock-chat-line doc">

View File

@@ -20,7 +20,7 @@ import type { PersonalAnalyticsResponse, AnalyticsPeriod } from '@/types'
const OUTCOME_COLORS: Record<string, string> = {
resolved: '#34d399',
escalated: '#f87171',
workaround: '#fbbf24',
workaround: '#eab308',
unresolved: '#94a3b8',
}

View File

@@ -872,7 +872,7 @@ export function ProceduralNavigationPage() {
key={field.variable_name}
className={cn(
'rounded-lg border px-3 py-2.5',
isFilled ? 'border-border bg-accent' : 'border-cyan-500/20 bg-cyan-500/5'
isFilled ? 'border-border bg-accent' : 'border-orange-500/20 bg-orange-500/5'
)}
>
<div className="flex items-center justify-between gap-2">
@@ -880,7 +880,7 @@ export function ProceduralNavigationPage() {
{isFilled ? (
<Check className="h-3.5 w-3.5 shrink-0 text-emerald-400" />
) : (
<AlertCircle className="h-3.5 w-3.5 shrink-0 text-cyan-400" />
<AlertCircle className="h-3.5 w-3.5 shrink-0 text-orange-400" />
)}
<span className="text-xs font-medium text-muted-foreground truncate">
{field.label}
@@ -903,7 +903,7 @@ export function ProceduralNavigationPage() {
value={editingVarValue}
onChange={(e) => setEditingVarValue(e.target.value)}
autoFocus
className="w-full rounded-md border border-cyan-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground focus:border-cyan-400 focus:outline-hidden focus:ring-1 focus:ring-cyan-400/30"
className="w-full rounded-md border border-orange-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground focus:border-orange-400 focus:outline-hidden focus:ring-1 focus:ring-orange-400/30"
>
<option value="">{field.placeholder || 'Select...'}</option>
{field.options.map((opt) => (
@@ -917,7 +917,7 @@ export function ProceduralNavigationPage() {
autoFocus
rows={3}
placeholder={field.placeholder}
className="w-full rounded-md border border-cyan-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-cyan-400 focus:outline-hidden focus:ring-1 focus:ring-cyan-400/30"
className="w-full rounded-md border border-orange-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-orange-400 focus:outline-hidden focus:ring-1 focus:ring-orange-400/30"
/>
) : (
<input
@@ -927,7 +927,7 @@ export function ProceduralNavigationPage() {
onKeyDown={(e) => { if (e.key === 'Enter') saveEditingVar() }}
autoFocus
placeholder={field.placeholder}
className="w-full rounded-md border border-cyan-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-cyan-400 focus:outline-hidden focus:ring-1 focus:ring-cyan-400/30"
className="w-full rounded-md border border-orange-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-orange-400 focus:outline-hidden focus:ring-1 focus:ring-orange-400/30"
/>
)}
{field.help_text && (

View File

@@ -329,7 +329,7 @@ export function SessionHistoryPage() {
value={aiSearchInput}
onChange={(e) => setAiSearchInput(e.target.value)}
placeholder="Search sessions..."
className="w-full rounded-lg border border-border bg-card pl-8 pr-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none"
className="w-full rounded-lg border border-border bg-card pl-8 pr-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none"
/>
</div>
@@ -356,7 +356,7 @@ export function SessionHistoryPage() {
value={aiFilters.problem_domain}
onChange={(e) => setAiFilters((f) => ({ ...f, problem_domain: e.target.value }))}
title="Filter by problem domain"
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none [&>option]:bg-card [&>option]:text-foreground"
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none [&>option]:bg-card [&>option]:text-foreground"
>
<option value="">All domains</option>
<option value="Active Directory">Active Directory</option>
@@ -396,7 +396,7 @@ export function SessionHistoryPage() {
value={aiFilters.date_from}
onChange={(e) => setAiFilters((f) => ({ ...f, date_from: e.target.value }))}
title="From date"
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none [color-scheme:dark]"
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none [color-scheme:dark]"
/>
<span className="text-xs text-muted-foreground">to</span>
<input
@@ -404,7 +404,7 @@ export function SessionHistoryPage() {
value={aiFilters.date_to}
onChange={(e) => setAiFilters((f) => ({ ...f, date_to: e.target.value }))}
title="To date"
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none [color-scheme:dark]"
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none [color-scheme:dark]"
/>
</div>
@@ -564,7 +564,7 @@ export function SessionHistoryPage() {
session.outcome === 'escalated' && 'bg-blue-500/20 text-blue-300',
session.outcome === 'unresolved' && 'bg-rose-500/20 text-rose-300',
session.outcome === 'cancelled' && 'bg-zinc-500/20 text-zinc-300',
session.outcome === 'resolved_externally' && 'bg-cyan-500/20 text-cyan-300',
session.outcome === 'resolved_externally' && 'bg-orange-500/20 text-orange-300',
!session.outcome && 'bg-accent text-muted-foreground'
)}
>
@@ -647,7 +647,7 @@ export function SessionHistoryPage() {
value={closeOutcome}
onChange={(e) => setCloseOutcome(e.target.value as SessionOutcome)}
title="Session outcome"
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none mb-3"
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none mb-3"
>
<option value="">Select outcome...</option>
<option value="resolved">Resolved</option>
@@ -664,7 +664,7 @@ export function SessionHistoryPage() {
onChange={(e) => setCloseNotes(e.target.value)}
rows={2}
placeholder="Add closure notes..."
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none mb-3"
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none resize-none mb-3"
/>
<div className="flex items-center justify-end gap-2">

View File

@@ -21,7 +21,7 @@ import type { TeamAnalyticsResponse, AnalyticsPeriod } from '@/types'
const CHART_COLORS = {
resolved: '#34d399',
escalated: '#f87171',
workaround: '#fbbf24',
workaround: '#eab308',
unresolved: '#94a3b8',
}

View File

@@ -11,7 +11,7 @@ interface AccountBranding {
company_name: string | null
}
const DEFAULT_COLOR = '#06b6d4'
const DEFAULT_COLOR = '#ea580c'
export function BrandingSettingsPage() {
const [branding, setBranding] = useState<AccountBranding | null>(null)
@@ -137,7 +137,7 @@ export function BrandingSettingsPage() {
className={cn(
'mt-1 w-full rounded-lg border border-border bg-card px-3 py-2 text-sm',
'text-foreground placeholder:text-muted-foreground',
'focus:border-[rgba(6,182,212,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
'focus:border-[rgba(249,115,22,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
)}
/>
<p className="mt-1 text-xs text-muted-foreground">
@@ -163,7 +163,7 @@ export function BrandingSettingsPage() {
className={cn(
'mt-1 w-full rounded-lg border border-border bg-card px-3 py-2 text-sm',
'text-foreground placeholder:text-muted-foreground font-mono',
'focus:border-[rgba(6,182,212,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
'focus:border-[rgba(249,115,22,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
)}
/>
<p className="mt-1 text-xs text-muted-foreground">
@@ -207,12 +207,12 @@ export function BrandingSettingsPage() {
const val = e.target.value
setPrimaryColor(val)
}}
placeholder="#06b6d4"
placeholder="#ea580c"
maxLength={7}
className={cn(
'w-32 rounded-lg border border-border bg-card px-3 py-2 text-sm',
'text-foreground placeholder:text-muted-foreground font-mono',
'focus:border-[rgba(6,182,212,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
'focus:border-[rgba(249,115,22,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
)}
/>
<button
@@ -224,7 +224,7 @@ export function BrandingSettingsPage() {
</button>
</div>
<p className="mt-1 text-xs text-muted-foreground">
Hex color code for the primary accent color (e.g. #06b6d4).
Hex color code for the primary accent color (e.g. #ea580c).
</p>
</div>
</div>