refactor: normalize FlowPilot/Assistant/ScriptBuilder to design system tokens

Replace hardcoded Tailwind color utilities with semantic CSS variable tokens
across 31 files in the FlowPilot, Assistant Chat, and Script Builder feature
communities — the areas graphify identified as design-system-free.

- text-blue-400 → text-accent, bg-blue-500/10 → bg-accent-dim, border-blue-500/20 → border-accent/20
- text-amber-400 → text-warning, bg-amber-400/10 → bg-warning-dim, border-l-amber-500 → border-l-warning
- text-rose-400/500 → text-danger, bg-rose-500/10 → bg-danger-dim
- text-emerald-400 → text-success, bg-emerald-500/10 → bg-success-dim, border-l-emerald-500 → border-l-success
- bg-white/[0.08] → bg-elevated (opacity hack → semantic surface token)
- bg-gradient-to-r from-blue-500 to-blue-400 → bg-accent (no gradient surfaces)
- bg-[#60a5fa] → bg-accent (hard-coded hex removed)

Also adds graphify-out/ to .gitignore.

Theme resilience: accent color has changed twice in 5 weeks. Semantic tokens
mean the next change is a 1-line edit in index.css, not 110 grep-and-replace.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-04-06 20:20:07 -04:00
parent 37179096b0
commit cef853d7ea
25 changed files with 114 additions and 110 deletions

4
.gitignore vendored
View File

@@ -233,3 +233,7 @@ package.json
package-lock.json package-lock.json
.worktrees/ .worktrees/
.gstack/ .gstack/
# graphify knowledge graph outputs
graphify-out/
.graphify_python

View File

@@ -17,7 +17,7 @@ export function ChatMessage({ role, content, suggestedFlows }: ChatMessageProps)
className={`shrink-0 w-8 h-8 rounded-full flex items-center justify-center ${ className={`shrink-0 w-8 h-8 rounded-full flex items-center justify-center ${
role === 'assistant' role === 'assistant'
? 'bg-primary/15 text-primary' ? 'bg-primary/15 text-primary'
: 'bg-white/[0.08] text-muted-foreground' : 'bg-elevated text-muted-foreground'
}`} }`}
> >
{role === 'assistant' ? <Sparkles size={14} /> : <User size={14} />} {role === 'assistant' ? <Sparkles size={14} /> : <User size={14} />}

View File

@@ -193,7 +193,7 @@ function ChatItem({
className={cn( className={cn(
'group flex items-center gap-2 px-3 py-2.5 mx-1.5 rounded-lg cursor-pointer transition-colors', 'group flex items-center gap-2 px-3 py-2.5 mx-1.5 rounded-lg cursor-pointer transition-colors',
confirming confirming
? 'bg-rose-500/10 border border-rose-500/20' ? 'bg-danger-dim border border-danger/20'
: isActive : isActive
? 'bg-accent-dim text-foreground' ? 'bg-accent-dim text-foreground'
: 'text-muted-foreground hover:bg-input hover:text-foreground' : 'text-muted-foreground hover:bg-input hover:text-foreground'
@@ -203,10 +203,10 @@ function ChatItem({
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
{confirming ? ( {confirming ? (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-[0.75rem] text-rose-400 font-medium">Delete?</span> <span className="text-[0.75rem] text-danger font-medium">Delete?</span>
<button <button
onClick={e => { e.stopPropagation(); onDelete(); setConfirming(false) }} onClick={e => { e.stopPropagation(); onDelete(); setConfirming(false) }}
className="text-[0.6875rem] font-medium text-rose-400 hover:text-rose-300 px-1.5 py-0.5 rounded bg-rose-500/15 hover:bg-rose-500/25 transition-colors" className="text-[0.6875rem] font-medium text-danger hover:text-danger px-1.5 py-0.5 rounded bg-danger/15 hover:bg-danger/25 transition-colors"
> >
Yes Yes
</button> </button>
@@ -230,14 +230,14 @@ function ChatItem({
<div className="flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity"> <div className="flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity">
<button <button
onClick={e => { e.stopPropagation(); onTogglePin() }} onClick={e => { e.stopPropagation(); onTogglePin() }}
className="p-1 rounded hover:bg-white/[0.08]" className="p-1 rounded hover:bg-elevated"
title={chat.pinned ? 'Unpin' : 'Pin'} title={chat.pinned ? 'Unpin' : 'Pin'}
> >
<Pin size={12} className={chat.pinned ? 'text-primary' : ''} /> <Pin size={12} className={chat.pinned ? 'text-primary' : ''} />
</button> </button>
<button <button
onClick={e => { e.stopPropagation(); setConfirming(true) }} onClick={e => { e.stopPropagation(); setConfirming(true) }}
className="p-1 rounded hover:bg-white/[0.08] text-muted-foreground hover:text-rose-400" className="p-1 rounded hover:bg-elevated text-muted-foreground hover:text-danger"
title="Delete" title="Delete"
> >
<Trash2 size={12} /> <Trash2 size={12} />

View File

@@ -36,7 +36,7 @@ const OUTCOMES: { value: ConclusionOutcome; label: string; description: string;
label: 'Resolved', label: 'Resolved',
description: 'Issue has been fixed or answered', description: 'Issue has been fixed or answered',
icon: CheckCircle2, icon: CheckCircle2,
color: 'text-emerald-400', color: 'text-success',
bg: 'bg-emerald-400/10', bg: 'bg-emerald-400/10',
border: 'border-emerald-400/30', border: 'border-emerald-400/30',
}, },
@@ -45,17 +45,17 @@ const OUTCOMES: { value: ConclusionOutcome; label: string; description: string;
label: 'Escalate', label: 'Escalate',
description: 'Needs to be handed off or escalated', description: 'Needs to be handed off or escalated',
icon: ArrowUpRight, icon: ArrowUpRight,
color: 'text-amber-400', color: 'text-warning',
bg: 'bg-amber-400/10', bg: 'bg-warning-dim',
border: 'border-amber-400/30', border: 'border-warning/30',
}, },
{ {
value: 'paused', value: 'paused',
label: 'Paused', label: 'Paused',
description: 'Continuing later — saving progress', description: 'Continuing later — saving progress',
icon: Pause, icon: Pause,
color: 'text-blue-400', color: 'text-accent',
bg: 'bg-blue-400/10', bg: 'bg-accent-dim',
border: 'border-blue-400/30', border: 'border-blue-400/30',
}, },
] ]
@@ -362,7 +362,7 @@ export function ConcludeSessionModal({
</div> </div>
{error && ( {error && (
<div className="text-sm text-rose-400 bg-rose-400/10 border border-rose-400/20 rounded-lg px-4 py-2"> <div className="text-sm text-danger bg-danger-dim border border-danger/20 rounded-lg px-4 py-2">
{error} {error}
</div> </div>
)} )}
@@ -410,7 +410,7 @@ export function ConcludeSessionModal({
<div className="h-3 bg-elevated rounded w-4/5" /> <div className="h-3 bg-elevated rounded w-4/5" />
</div> </div>
) : streamError ? ( ) : streamError ? (
<div className="flex items-center gap-2 text-sm text-amber-400"> <div className="flex items-center gap-2 text-sm text-warning">
<AlertTriangle size={14} /> <AlertTriangle size={14} />
{streamError} {streamError}
</div> </div>
@@ -467,7 +467,7 @@ export function ConcludeSessionModal({
{/* Paused/Escalated: generating spinner */} {/* Paused/Escalated: generating spinner */}
{(outcome === 'paused' || outcome === 'escalated') && generatingUpdate && ( {(outcome === 'paused' || outcome === 'escalated') && generatingUpdate && (
<div className="flex flex-col items-center justify-center py-8 gap-3"> <div className="flex flex-col items-center justify-center py-8 gap-3">
<Loader2 size={24} className="animate-spin text-blue-400" /> <Loader2 size={24} className="animate-spin text-accent" />
<p className="text-sm text-muted-foreground">Generating status update...</p> <p className="text-sm text-muted-foreground">Generating status update...</p>
</div> </div>
)} )}
@@ -544,7 +544,7 @@ export function ConcludeSessionModal({
{outcome === 'paused' && ( {outcome === 'paused' && (
<button <button
onClick={handleResumeNew} onClick={handleResumeNew}
className="flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-medium text-blue-400 bg-blue-400/10 border border-blue-400/20 hover:bg-blue-400/15 transition-all" className="flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-medium text-accent bg-accent-dim border border-accent/20 hover:bg-accent/15 transition-all"
> >
<RefreshCw size={14} /> <RefreshCw size={14} />
Resume in New Chat Resume in New Chat
@@ -566,7 +566,7 @@ export function ConcludeSessionModal({
className={cn( className={cn(
'flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-semibold transition-all', 'flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-semibold transition-all',
copied copied
? 'bg-emerald-400/15 text-emerald-400 border border-emerald-400/30' ? 'bg-emerald-400/15 text-success border border-emerald-400/30'
: 'bg-primary text-white hover:brightness-110 active:scale-[0.98]' : 'bg-primary text-white hover:brightness-110 active:scale-[0.98]'
)} )}
> >

View File

@@ -360,7 +360,7 @@ export function TaskLane({ questions, actions, sessionId, onSubmit, onClose, loa
<section> <section>
<div className="sticky top-0 z-10 pb-2" style={{ background: 'var(--color-bg-page)' }}> <div className="sticky top-0 z-10 pb-2" style={{ background: 'var(--color-bg-page)' }}>
<div className="flex items-center gap-2 text-[10px] font-semibold uppercase tracking-[1.2px] text-muted-foreground pl-0.5"> <div className="flex items-center gap-2 text-[10px] font-semibold uppercase tracking-[1.2px] text-muted-foreground pl-0.5">
<span className="w-1.5 h-1.5 rounded-full bg-[#60a5fa]" /> <span className="w-1.5 h-1.5 rounded-full bg-accent" />
Diagnostic Checks Diagnostic Checks
{actionTasks.every(a => a.state === 'done' || a.state === 'skipped') && ( {actionTasks.every(a => a.state === 'done' || a.state === 'skipped') && (
<Check size={10} className="text-success" /> <Check size={10} className="text-success" />

View File

@@ -9,9 +9,9 @@ interface AISessionListItemProps {
const STATUS_CONFIG = { const STATUS_CONFIG = {
active: { icon: Clock, color: 'text-primary', label: 'Active' }, active: { icon: Clock, color: 'text-primary', label: 'Active' },
paused: { icon: Pause, color: 'text-amber-400', label: 'Paused' }, paused: { icon: Pause, color: 'text-warning', label: 'Paused' },
resolved: { icon: CheckCircle2, color: 'text-emerald-400', label: 'Resolved' }, resolved: { icon: CheckCircle2, color: 'text-success', label: 'Resolved' },
escalated: { icon: ArrowUpRight, color: 'text-amber-400', label: 'Escalated' }, escalated: { icon: ArrowUpRight, color: 'text-warning', label: 'Escalated' },
abandoned: { icon: AlertCircle, color: 'text-text-muted', label: 'Abandoned' }, abandoned: { icon: AlertCircle, color: 'text-text-muted', label: 'Abandoned' },
} as const } as const
@@ -64,7 +64,7 @@ export function AISessionListItem({ session }: AISessionListItemProps) {
</div> </div>
</div> </div>
{session.session_rating && ( {session.session_rating && (
<span className="font-sans text-xs text-xs text-amber-400"> <span className="font-sans text-xs text-xs text-warning">
{'★'.repeat(session.session_rating)} {'★'.repeat(session.session_rating)}
</span> </span>
)} )}

View File

@@ -35,9 +35,9 @@ export function EscalateModal({ open, onClose, onEscalate, isProcessing, hasPsaT
return ( return (
<Modal isOpen={open} onClose={handleClose} title="Escalate Session" size="sm"> <Modal isOpen={open} onClose={handleClose} title="Escalate Session" size="sm">
<div className="space-y-4"> <div className="space-y-4">
<div className="flex items-start gap-3 rounded-xl border border-amber-400/20 bg-amber-400/5 p-3"> <div className="flex items-start gap-3 rounded-xl border border-warning/20 bg-warning/5 p-3">
<AlertTriangle size={16} className="text-amber-400 shrink-0 mt-0.5" /> <AlertTriangle size={16} className="text-warning shrink-0 mt-0.5" />
<p className="text-sm text-amber-400"> <p className="text-sm text-warning">
This will mark the session as requesting escalation. Team members will see it in their escalation queue and can pick it up with full context. This will mark the session as requesting escalation. Team members will see it in their escalation queue and can pick it up with full context.
</p> </p>
</div> </div>
@@ -70,7 +70,7 @@ export function EscalateModal({ open, onClose, onEscalate, isProcessing, hasPsaT
<button <button
onClick={handleSubmit} onClick={handleSubmit}
disabled={!reason.trim() || reason.trim().length < 5 || isProcessing} disabled={!reason.trim() || reason.trim().length < 5 || isProcessing}
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-amber-500/90 px-4 py-2.5 min-h-[44px] text-sm font-semibold text-white hover:bg-amber-500 active:scale-[0.98] disabled:opacity-40 transition-all" className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-warning px-4 py-2.5 min-h-[44px] text-sm font-semibold text-white hover:bg-warning active:scale-[0.98] disabled:opacity-40 transition-all"
> >
{isProcessing ? ( {isProcessing ? (
<Loader2 size={14} className="animate-spin" /> <Loader2 size={14} className="animate-spin" />

View File

@@ -50,7 +50,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
if (error) { if (error) {
return ( return (
<div className="py-12 text-center"> <div className="py-12 text-center">
<p className="text-sm text-rose-400">{error}</p> <p className="text-sm text-danger">{error}</p>
<button <button
onClick={loadQueue} onClick={loadQueue}
className="mt-2 text-xs text-muted-foreground hover:text-foreground transition-colors" className="mt-2 text-xs text-muted-foreground hover:text-foreground transition-colors"
@@ -99,7 +99,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
{session.problem_summary || 'Untitled session'} {session.problem_summary || 'Untitled session'}
</p> </p>
{session.escalation_reason && ( {session.escalation_reason && (
<p className="mt-1 text-xs text-amber-400 line-clamp-2"> <p className="mt-1 text-xs text-warning line-clamp-2">
Reason: {session.escalation_reason} Reason: {session.escalation_reason}
</p> </p>
)} )}

View File

@@ -91,7 +91,7 @@ export function FlowPilotActionBar({
<button <button
onClick={() => { setShowResolve(true); setShowEscalate(false) }} onClick={() => { setShowResolve(true); setShowEscalate(false) }}
disabled={!canResolve || isProcessing} disabled={!canResolve || isProcessing}
className="flex items-center justify-center gap-1.5 rounded-lg bg-emerald-500/10 border border-emerald-500/20 px-2.5 sm:px-4 py-2 min-h-[40px] sm:min-h-[44px] text-xs sm:text-sm font-medium text-emerald-400 hover:bg-emerald-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors" className="flex items-center justify-center gap-1.5 rounded-lg bg-success-dim border border-success/20 px-2.5 sm:px-4 py-2 min-h-[40px] sm:min-h-[44px] text-xs sm:text-sm font-medium text-success hover:bg-success/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
> >
<CheckCircle2 size={15} /> <CheckCircle2 size={15} />
Resolve Resolve
@@ -99,7 +99,7 @@ export function FlowPilotActionBar({
<button <button
onClick={() => setShowEscalate(true)} onClick={() => setShowEscalate(true)}
disabled={!canEscalate || isProcessing} disabled={!canEscalate || isProcessing}
className="flex items-center justify-center gap-1.5 rounded-lg bg-amber-500/10 border border-amber-500/20 px-2.5 sm:px-4 py-2 min-h-[40px] sm:min-h-[44px] text-xs sm:text-sm font-medium text-amber-400 hover:bg-amber-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors" className="flex items-center justify-center gap-1.5 rounded-lg bg-warning-dim border border-warning/20 px-2.5 sm:px-4 py-2 min-h-[40px] sm:min-h-[44px] text-xs sm:text-sm font-medium text-warning hover:bg-warning/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
> >
<ArrowUpRight size={15} /> <ArrowUpRight size={15} />
Escalate Escalate
@@ -108,7 +108,7 @@ export function FlowPilotActionBar({
<button <button
onClick={() => setShowStatusUpdate(true)} onClick={() => setShowStatusUpdate(true)}
disabled={isProcessing} disabled={isProcessing}
className="flex items-center justify-center gap-1.5 rounded-lg bg-blue-500/10 border border-blue-500/20 px-2.5 sm:px-4 py-2 min-h-[40px] sm:min-h-[44px] text-xs sm:text-sm font-medium text-blue-400 hover:bg-blue-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors" className="flex items-center justify-center gap-1.5 rounded-lg bg-accent-dim border border-accent/20 px-2.5 sm:px-4 py-2 min-h-[40px] sm:min-h-[44px] text-xs sm:text-sm font-medium text-accent hover:bg-accent/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
title="Share Update" title="Share Update"
> >
<FileText size={15} /> <FileText size={15} />
@@ -166,7 +166,7 @@ export function FlowPilotActionBar({
<button <button
onClick={handleResolve} onClick={handleResolve}
disabled={resolutionSummary.length < 5 || submitting} disabled={resolutionSummary.length < 5 || submitting}
className="rounded-lg bg-emerald-500/20 border border-emerald-500/30 px-4 py-2 min-h-[44px] text-sm font-medium text-emerald-400 hover:bg-emerald-500/30 disabled:opacity-50 transition-colors" className="rounded-lg bg-success/20 border border-success/30 px-4 py-2 min-h-[44px] text-sm font-medium text-success hover:bg-success/30 disabled:opacity-50 transition-colors"
> >
{submitting ? 'Resolving...' : 'Resolve Session'} {submitting ? 'Resolving...' : 'Resolve Session'}
</button> </button>
@@ -193,7 +193,7 @@ export function FlowPilotActionBar({
<button <button
onClick={handleAbandon} onClick={handleAbandon}
disabled={submitting} disabled={submitting}
className="rounded-lg bg-rose-500/20 border border-rose-500/30 px-4 py-2 min-h-[44px] text-sm font-medium text-rose-400 hover:bg-rose-500/30 disabled:opacity-50 transition-colors" className="rounded-lg bg-danger/20 border border-danger/30 px-4 py-2 min-h-[44px] text-sm font-medium text-danger hover:bg-danger/30 disabled:opacity-50 transition-colors"
> >
{submitting ? 'Closing...' : 'Close Session'} {submitting ? 'Closing...' : 'Close Session'}
</button> </button>

View File

@@ -155,7 +155,7 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
</div> </div>
<button <button
onClick={handleClearTicket} onClick={handleClearTicket}
className="ml-2 rounded-md p-1 text-muted-foreground hover:bg-white/[0.06] hover:text-foreground transition-colors" className="ml-2 rounded-md p-1 text-muted-foreground hover:bg-elevated hover:text-foreground transition-colors"
> >
<X size={14} /> <X size={14} />
</button> </button>
@@ -215,7 +215,7 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
Pull from Ticket Pull from Ticket
</button> </button>
{psaChecked && !psaConnection && ( {psaChecked && !psaConnection && (
<span className="flex items-center gap-1 text-[0.625rem] text-amber-400/80"> <span className="flex items-center gap-1 text-[0.625rem] text-warning/80">
<AlertTriangle size={10} /> <AlertTriangle size={10} />
No PSA connected No PSA connected
</span> </span>

View File

@@ -243,17 +243,17 @@ export function FlowPilotMessageBar({ onRespond, disabled = false, isProcessing
<button <button
type="button" type="button"
onClick={() => handleRemoveUpload(upload.id)} onClick={() => handleRemoveUpload(upload.id)}
className="absolute -top-1 -right-1 w-4 h-4 rounded-full bg-background border border-border flex items-center justify-center hover:bg-rose-500/20 transition-colors" className="absolute -top-1 -right-1 w-4 h-4 rounded-full bg-background border border-border flex items-center justify-center hover:bg-danger/20 transition-colors"
> >
<X size={8} className="text-muted-foreground" /> <X size={8} className="text-muted-foreground" />
</button> </button>
)} )}
{upload.status === 'error' && ( {upload.status === 'error' && (
<div <div
className="absolute inset-0 bg-rose-500/20 border-2 border-rose-500 flex items-center justify-center cursor-pointer" className="absolute inset-0 bg-danger/20 border-2 border-danger flex items-center justify-center cursor-pointer"
onClick={() => retryUpload(upload.id)} onClick={() => retryUpload(upload.id)}
> >
<RotateCcw size={10} className="text-rose-500" /> <RotateCcw size={10} className="text-danger" />
</div> </div>
)} )}
</div> </div>

View File

@@ -148,7 +148,7 @@ export function FlowPilotSession({
<div className="mb-4"> <div className="mb-4">
<button <button
onClick={() => setShowShareCommunication(true)} onClick={() => setShowShareCommunication(true)}
className="flex items-center gap-2 rounded-lg bg-blue-500/10 border border-blue-500/20 px-4 py-2.5 text-sm font-medium text-blue-400 hover:bg-blue-500/20 transition-colors" className="flex items-center gap-2 rounded-lg bg-accent-dim border border-accent/20 px-4 py-2.5 text-sm font-medium text-accent hover:bg-accent/20 transition-colors"
> >
<FileText size={16} /> <FileText size={16} />
{shareLabel} {shareLabel}

View File

@@ -161,7 +161,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
<div <div
className={cn( className={cn(
'card-flat p-3 sm:p-4 lg:p-5', 'card-flat p-3 sm:p-4 lg:p-5',
isResolutionSuggestion && 'border-emerald-500/30' isResolutionSuggestion && 'border-success/30'
)} )}
> >
{/* Context message */} {/* Context message */}
@@ -175,7 +175,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
<div className="flex items-start gap-3 mb-4"> <div className="flex items-start gap-3 mb-4">
<span className={cn( <span className={cn(
'mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-lg', 'mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-lg',
isResolutionSuggestion ? 'bg-emerald-500/10 text-emerald-400' : 'bg-accent-dim text-primary' isResolutionSuggestion ? 'bg-success-dim text-success' : 'bg-accent-dim text-primary'
)}> )}>
<Icon size={14} /> <Icon size={14} />
</span> </span>
@@ -197,7 +197,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
<div className="flex flex-col gap-2 sm:flex-row"> <div className="flex flex-col gap-2 sm:flex-row">
<button <button
onClick={() => handleResolutionResponse(true)} onClick={() => handleResolutionResponse(true)}
className="flex-1 min-h-[44px] rounded-lg bg-emerald-500/10 border border-emerald-500/20 px-4 py-2.5 text-sm font-medium text-emerald-400 hover:bg-emerald-500/20 transition-colors" className="flex-1 min-h-[44px] rounded-lg bg-success-dim border border-success/20 px-4 py-2.5 text-sm font-medium text-success hover:bg-success/20 transition-colors"
> >
Yes, this is resolved Yes, this is resolved
</button> </button>

View File

@@ -128,7 +128,7 @@ export function InSessionScriptGenerator({
onClick={handleCopy} onClick={handleCopy}
className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors" className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors"
> >
{copied ? <Check size={12} className="text-emerald-400" /> : <Copy size={12} />} {copied ? <Check size={12} className="text-success" /> : <Copy size={12} />}
{copied ? 'Copied' : 'Copy'} {copied ? 'Copied' : 'Copy'}
</button> </button>
</div> </div>

View File

@@ -2,9 +2,9 @@ import { GitBranch, ArrowUpRight, Sparkles, Clock, Hash } from 'lucide-react'
import type { FlowProposalSummary } from '@/types/flow-proposal' import type { FlowProposalSummary } from '@/types/flow-proposal'
const TYPE_CONFIG = { const TYPE_CONFIG = {
new_flow: { label: 'New Flow', color: 'text-emerald-400 bg-emerald-400/10 border-emerald-400/20', icon: Sparkles }, new_flow: { label: 'New Flow', color: 'text-success bg-emerald-400/10 border-emerald-400/20', icon: Sparkles },
enhancement: { label: 'Enhancement', color: 'text-amber-400 bg-amber-400/10 border-amber-400/20', icon: ArrowUpRight }, enhancement: { label: 'Enhancement', color: 'text-warning bg-warning-dim border-warning/20', icon: ArrowUpRight },
branch_addition: { label: 'Branch', color: 'text-blue-400 bg-blue-400/10 border-blue-400/20', icon: GitBranch }, branch_addition: { label: 'Branch', color: 'text-accent bg-accent-dim border-accent/20', icon: GitBranch },
auto_reinforced: { label: 'Reinforced', color: 'text-muted-foreground bg-card border-border', icon: Sparkles }, auto_reinforced: { label: 'Reinforced', color: 'text-muted-foreground bg-card border-border', icon: Sparkles },
} as const } as const

View File

@@ -105,7 +105,7 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
{proposal.proposed_diff && (() => { {proposal.proposed_diff && (() => {
const diff = proposal.proposed_diff as { diff_description?: string; new_nodes?: Array<{ title?: string; question?: string; description?: string }> } const diff = proposal.proposed_diff as { diff_description?: string; new_nodes?: Array<{ title?: string; question?: string; description?: string }> }
return ( return (
<div className="card-flat border-l-2 border-l-amber-500 p-4"> <div className="card-flat border-l-2 border-l-warning p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-2">Proposed Changes</h4> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-2">Proposed Changes</h4>
{diff.diff_description && ( {diff.diff_description && (
<p className="text-sm text-foreground">{diff.diff_description}</p> <p className="text-sm text-foreground">{diff.diff_description}</p>
@@ -114,8 +114,8 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
<div className="mt-3 space-y-1.5"> <div className="mt-3 space-y-1.5">
<p className="text-xs font-medium text-muted-foreground">New nodes:</p> <p className="text-xs font-medium text-muted-foreground">New nodes:</p>
{diff.new_nodes.map((node, i) => ( {diff.new_nodes.map((node, i) => (
<div key={i} className="rounded-lg bg-emerald-500/5 border border-emerald-500/10 px-3 py-2 text-xs text-foreground"> <div key={i} className="rounded-lg bg-success/5 border border-success/10 px-3 py-2 text-xs text-foreground">
<span className="text-emerald-400">+ </span> <span className="text-success">+ </span>
{node.title || node.question || node.description || 'New node'} {node.title || node.question || node.description || 'New node'}
</div> </div>
))} ))}
@@ -196,7 +196,7 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
<button <button
onClick={() => handleAction('approve')} onClick={() => handleAction('approve')}
disabled={isSubmitting} disabled={isSubmitting}
className="flex items-center gap-2 rounded-lg bg-emerald-500/10 border border-emerald-500/20 px-4 py-2 text-sm font-medium text-emerald-400 hover:bg-emerald-500/20 disabled:opacity-40 transition-colors" className="flex items-center gap-2 rounded-lg bg-success-dim border border-success/20 px-4 py-2 text-sm font-medium text-success hover:bg-success/20 disabled:opacity-40 transition-colors"
> >
{isSubmitting ? <Loader2 size={14} className="animate-spin" /> : <CheckCircle2 size={14} />} {isSubmitting ? <Loader2 size={14} className="animate-spin" /> : <CheckCircle2 size={14} />}
Approve & Publish Approve & Publish
@@ -225,7 +225,7 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
<button <button
onClick={() => showRejectConfirm ? handleAction('reject') : setShowRejectConfirm(true)} onClick={() => showRejectConfirm ? handleAction('reject') : setShowRejectConfirm(true)}
disabled={isSubmitting} disabled={isSubmitting}
className="flex items-center gap-2 rounded-lg bg-rose-500/10 border border-rose-500/20 px-4 py-2 text-sm font-medium text-rose-500 hover:bg-rose-500/20 disabled:opacity-40 transition-colors" className="flex items-center gap-2 rounded-lg bg-danger-dim border border-danger/20 px-4 py-2 text-sm font-medium text-danger hover:bg-danger/20 disabled:opacity-40 transition-colors"
> >
<XCircle size={14} /> <XCircle size={14} />
{showRejectConfirm ? 'Confirm Reject' : 'Reject'} {showRejectConfirm ? 'Confirm Reject' : 'Reject'}

View File

@@ -38,7 +38,7 @@ export function SessionBriefing({
const pkg = escalationPackage const pkg = escalationPackage
return ( return (
<div className="card-flat border-l-2 border-l-amber-500 p-5 space-y-4"> <div className="card-flat border-l-2 border-l-warning p-5 space-y-4">
<div> <div>
<h3 className="font-heading text-base font-semibold text-foreground"> <h3 className="font-heading text-base font-semibold text-foreground">
Escalation from {originalEngineerName || 'another engineer'} Escalation from {originalEngineerName || 'another engineer'}
@@ -60,7 +60,7 @@ export function SessionBriefing({
{pkg.escalation_reason && ( {pkg.escalation_reason && (
<div> <div>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">Why escalated</h4> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">Why escalated</h4>
<p className="text-sm text-amber-400">{pkg.escalation_reason}</p> <p className="text-sm text-warning">{pkg.escalation_reason}</p>
</div> </div>
)} )}
@@ -111,7 +111,7 @@ export function SessionBriefing({
<ul className="space-y-1"> <ul className="space-y-1">
{pkg.suggested_next_steps.map((s, i) => ( {pkg.suggested_next_steps.map((s, i) => (
<li key={i} className="text-sm text-foreground flex items-start gap-2"> <li key={i} className="text-sm text-foreground flex items-start gap-2">
<span className="text-emerald-400 mt-0.5"></span> <span className="text-success mt-0.5"></span>
{s} {s}
</li> </li>
))} ))}

View File

@@ -55,38 +55,38 @@ export function SessionDocView({
currentPushStatus === 'sent' currentPushStatus === 'sent'
? 'border-emerald-400/20 bg-emerald-400/5' ? 'border-emerald-400/20 bg-emerald-400/5'
: currentPushStatus === 'pending_retry' : currentPushStatus === 'pending_retry'
? 'border-amber-400/20 bg-amber-400/5' ? 'border-warning/20 bg-warning/5'
: 'border-rose-500/20 bg-rose-500/5' : 'border-danger/20 bg-rose-500/5'
}`} }`}
> >
{currentPushStatus === 'sent' && ( {currentPushStatus === 'sent' && (
<> <>
<CheckCircle2 size={16} className="text-emerald-400 shrink-0" /> <CheckCircle2 size={16} className="text-success shrink-0" />
<span className="text-sm text-emerald-400"> <span className="text-sm text-success">
Documentation pushed to ticket {ticketId ? `#${ticketId}` : ''} Documentation pushed to ticket {ticketId ? `#${ticketId}` : ''}
</span> </span>
</> </>
)} )}
{currentPushStatus === 'pending_retry' && ( {currentPushStatus === 'pending_retry' && (
<> <>
<Loader2 size={16} className="text-amber-400 shrink-0 animate-spin" /> <Loader2 size={16} className="text-warning shrink-0 animate-spin" />
<span className="text-sm text-amber-400"> <span className="text-sm text-warning">
Documentation queued for push will sync shortly Documentation queued for push will sync shortly
</span> </span>
</> </>
)} )}
{currentPushStatus === 'failed' && ( {currentPushStatus === 'failed' && (
<> <>
<AlertTriangle size={16} className="text-rose-500 shrink-0" /> <AlertTriangle size={16} className="text-danger shrink-0" />
<div className="flex-1"> <div className="flex-1">
<span className="text-sm text-rose-500"> <span className="text-sm text-danger">
Failed to push to ticket{currentPushError ? `${currentPushError}` : ''} Failed to push to ticket{currentPushError ? `${currentPushError}` : ''}
</span> </span>
</div> </div>
<button <button
onClick={handleRetry} onClick={handleRetry}
disabled={retrying} disabled={retrying}
className="flex items-center gap-1.5 rounded-lg bg-rose-500/10 px-3 py-1.5 text-xs font-medium text-rose-500 hover:bg-rose-500/20 transition-colors disabled:opacity-50" className="flex items-center gap-1.5 rounded-lg bg-danger-dim px-3 py-1.5 text-xs font-medium text-danger hover:bg-danger/20 transition-colors disabled:opacity-50"
> >
{retrying ? <Loader2 size={12} className="animate-spin" /> : <RefreshCw size={12} />} {retrying ? <Loader2 size={12} className="animate-spin" /> : <RefreshCw size={12} />}
Retry Retry
@@ -98,9 +98,9 @@ export function SessionDocView({
{/* Member mapping warning */} {/* Member mapping warning */}
{memberMappingWarning && ( {memberMappingWarning && (
<div className="rounded-xl border border-blue-400/20 bg-blue-400/5 px-4 py-3 flex items-start gap-3"> <div className="rounded-xl border border-accent/20 bg-accent/5 px-4 py-3 flex items-start gap-3">
<Info size={16} className="text-blue-400 shrink-0 mt-0.5" /> <Info size={16} className="text-accent shrink-0 mt-0.5" />
<span className="text-sm text-blue-400"> <span className="text-sm text-accent">
Time entry was not created {memberMappingWarning} Session timing is included in the ticket note. Time entry was not created {memberMappingWarning} Session timing is included in the ticket note.
</span> </span>
</div> </div>
@@ -137,12 +137,12 @@ export function SessionDocView({
{/* Outcome */} {/* Outcome */}
{(documentation.resolution_summary || documentation.escalation_reason) && ( {(documentation.resolution_summary || documentation.escalation_reason) && (
<div className={`card-flat p-4 border-l-2 ${documentation.resolution_summary ? 'border-l-emerald-500' : 'border-l-amber-500'}`}> <div className={`card-flat p-4 border-l-2 ${documentation.resolution_summary ? 'border-l-success' : 'border-l-warning'}`}>
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
{documentation.resolution_summary ? ( {documentation.resolution_summary ? (
<CheckCircle2 size={14} className="text-emerald-400" /> <CheckCircle2 size={14} className="text-success" />
) : ( ) : (
<ArrowUpRight size={14} className="text-amber-400" /> <ArrowUpRight size={14} className="text-warning" />
)} )}
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-muted-foreground"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-muted-foreground">
{documentation.resolution_summary ? 'Resolved' : 'Escalated'} {documentation.resolution_summary ? 'Resolved' : 'Escalated'}
@@ -202,8 +202,8 @@ export function SessionDocView({
size={20} size={20}
className={ className={
(currentRating ?? 0) >= star (currentRating ?? 0) >= star
? 'fill-amber-400 text-amber-400' ? 'fill-warning text-warning'
: 'text-muted-foreground hover:text-amber-400' : 'text-muted-foreground hover:text-warning'
} }
/> />
</button> </button>

View File

@@ -80,9 +80,9 @@ export function SimilarSessions({ sessionId }: SimilarSessionsProps) {
className={cn( className={cn(
'text-[0.5rem] font-sans text-xs uppercase', 'text-[0.5rem] font-sans text-xs uppercase',
session.status === 'resolved' session.status === 'resolved'
? 'text-emerald-400' ? 'text-success'
: session.status === 'escalated' : session.status === 'escalated'
? 'text-amber-400' ? 'text-warning'
: 'text-muted-foreground' : 'text-muted-foreground'
)} )}
> >

View File

@@ -168,7 +168,7 @@ export function StatusUpdateModal({ open, onClose, onGenerate, context = 'status
{/* Step 3: Generating */} {/* Step 3: Generating */}
{step === 'generating' && ( {step === 'generating' && (
<div className="flex flex-col items-center justify-center py-8 gap-3"> <div className="flex flex-col items-center justify-center py-8 gap-3">
<Loader2 size={24} className="animate-spin text-blue-400" /> <Loader2 size={24} className="animate-spin text-accent" />
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Generating {audience === 'email_draft' ? 'email draft' : audience === 'client_update' ? 'client update' : 'ticket notes'}... Generating {audience === 'email_draft' ? 'email draft' : audience === 'client_update' ? 'client update' : 'ticket notes'}...
</p> </p>
@@ -180,7 +180,7 @@ export function StatusUpdateModal({ open, onClose, onGenerate, context = 'status
<div className="space-y-4"> <div className="space-y-4">
{/* Meta badges */} {/* Meta badges */}
<div className="flex items-center gap-2 flex-wrap"> <div className="flex items-center gap-2 flex-wrap">
<span className="inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium bg-blue-500/10 text-blue-400 border border-blue-500/20"> <span className="inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium bg-accent-dim text-accent border border-accent/20">
{AUDIENCES.find(a => a.value === result.audience)?.label} {AUDIENCES.find(a => a.value === result.audience)?.label}
</span> </span>
<span className="inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium bg-[rgba(255,255,255,0.06)] text-muted-foreground border border-[rgba(255,255,255,0.08)]"> <span className="inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium bg-[rgba(255,255,255,0.06)] text-muted-foreground border border-[rgba(255,255,255,0.08)]">
@@ -208,8 +208,8 @@ export function StatusUpdateModal({ open, onClose, onGenerate, context = 'status
className={cn( className={cn(
'flex items-center gap-2 rounded-lg px-4 py-2 min-h-[44px] text-sm font-medium transition-colors', 'flex items-center gap-2 rounded-lg px-4 py-2 min-h-[44px] text-sm font-medium transition-colors',
copied copied
? 'bg-emerald-500/20 border border-emerald-500/30 text-emerald-400' ? 'bg-success/20 border border-success/30 text-success'
: 'bg-blue-500/10 border border-blue-500/20 text-blue-400 hover:bg-blue-500/20' : 'bg-accent-dim border border-accent/20 text-accent hover:bg-accent/20'
)} )}
> >
{copied ? <Check size={16} /> : <Copy size={16} />} {copied ? <Check size={16} /> : <Copy size={16} />}

View File

@@ -57,7 +57,7 @@ export function ScriptBuilderChat({
> >
{msg.role === 'assistant' && ( {msg.role === 'assistant' && (
<div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(96,165,250,0.1)] flex items-center justify-center mt-0.5"> <div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(96,165,250,0.1)] flex items-center justify-center mt-0.5">
<Bot size={16} className="text-blue-400" /> <Bot size={16} className="text-accent" />
</div> </div>
)} )}
@@ -99,10 +99,10 @@ export function ScriptBuilderChat({
{isLoading && ( {isLoading && (
<div className="flex gap-3 justify-start"> <div className="flex gap-3 justify-start">
<div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(96,165,250,0.1)] flex items-center justify-center"> <div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(96,165,250,0.1)] flex items-center justify-center">
<Bot size={16} className="text-blue-400" /> <Bot size={16} className="text-accent" />
</div> </div>
<div className="card-flat rounded-xl px-4 py-3 text-sm flex items-center gap-2"> <div className="card-flat rounded-xl px-4 py-3 text-sm flex items-center gap-2">
<Loader2 size={14} className="animate-spin text-blue-400" /> <Loader2 size={14} className="animate-spin text-accent" />
<span className="text-muted-foreground">Generating script...</span> <span className="text-muted-foreground">Generating script...</span>
</div> </div>
</div> </div>

View File

@@ -55,7 +55,7 @@ export function ScriptCodeBlock({
<div className="mt-3 rounded-lg border bg-[rgba(0,0,0,0.3)] border-[rgba(255,255,255,0.06)] overflow-hidden"> <div className="mt-3 rounded-lg border bg-[rgba(0,0,0,0.3)] border-[rgba(255,255,255,0.06)] overflow-hidden">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between px-3 py-2 border-b border-[rgba(255,255,255,0.06)]"> <div className="flex items-center justify-between px-3 py-2 border-b border-[rgba(255,255,255,0.06)]">
<span className="font-mono text-xs text-blue-400 truncate"> <span className="font-mono text-xs text-accent truncate">
{filename || 'script'} {filename || 'script'}
</span> </span>
{lineCount != null && ( {lineCount != null && (
@@ -110,14 +110,14 @@ export function ScriptCodeBlock({
"bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground hover:border-[rgba(255,255,255,0.12)]" "bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground hover:border-[rgba(255,255,255,0.12)]"
)} )}
> >
{copied ? <Check size={14} className="text-emerald-400" /> : <Copy size={14} />} {copied ? <Check size={14} className="text-success" /> : <Copy size={14} />}
{copied ? 'Copied' : 'Copy'} {copied ? 'Copied' : 'Copy'}
</button> </button>
<button <button
onClick={(e) => { e.stopPropagation(); onSave() }} onClick={(e) => { e.stopPropagation(); onSave() }}
className={cn( className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors", "flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors",
"bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 hover:bg-emerald-500/15" "bg-success-dim border border-success/20 text-success hover:bg-emerald-500/15"
)} )}
> >
<BookmarkPlus size={14} /> <BookmarkPlus size={14} />

View File

@@ -62,7 +62,7 @@ export function ScriptPreviewModal({
{/* Header */} {/* Header */}
<div className="flex items-center justify-between px-5 py-3.5 border-b border-[rgba(255,255,255,0.06)]"> <div className="flex items-center justify-between px-5 py-3.5 border-b border-[rgba(255,255,255,0.06)]">
<div className="flex items-center gap-3 min-w-0"> <div className="flex items-center gap-3 min-w-0">
<span className="font-mono text-sm text-blue-400 truncate"> <span className="font-mono text-sm text-accent truncate">
{filename || 'script'} {filename || 'script'}
</span> </span>
<span className="shrink-0 font-mono text-[0.625rem] uppercase tracking-wider px-2 py-0.5 rounded-full bg-[rgba(255,255,255,0.06)] text-muted-foreground"> <span className="shrink-0 font-mono text-[0.625rem] uppercase tracking-wider px-2 py-0.5 rounded-full bg-[rgba(255,255,255,0.06)] text-muted-foreground">
@@ -77,14 +77,14 @@ export function ScriptPreviewModal({
"bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground hover:border-[rgba(255,255,255,0.12)]" "bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground hover:border-[rgba(255,255,255,0.12)]"
)} )}
> >
{copied ? <Check size={14} className="text-emerald-400" /> : <Copy size={14} />} {copied ? <Check size={14} className="text-success" /> : <Copy size={14} />}
{copied ? 'Copied' : 'Copy'} {copied ? 'Copied' : 'Copy'}
</button> </button>
<button <button
onClick={onSave} onClick={onSave}
className={cn( className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors", "flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors",
"bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 hover:bg-emerald-500/15" "bg-success-dim border border-success/20 text-success hover:bg-emerald-500/15"
)} )}
> >
<BookmarkPlus size={14} /> <BookmarkPlus size={14} />

View File

@@ -708,13 +708,13 @@ export default function AssistantChatPage() {
</div> </div>
)} )}
{upload.status === 'done' && ( {upload.status === 'done' && (
<button type="button" onClick={() => handleRemoveUpload(upload.id)} className="absolute -top-1 -right-1 w-4 h-4 rounded-full bg-background border border-border flex items-center justify-center hover:bg-rose-500/20 transition-colors"> <button type="button" onClick={() => handleRemoveUpload(upload.id)} className="absolute -top-1 -right-1 w-4 h-4 rounded-full bg-background border border-border flex items-center justify-center hover:bg-danger/20 transition-colors">
<X size={8} className="text-muted-foreground" /> <X size={8} className="text-muted-foreground" />
</button> </button>
)} )}
{upload.status === 'error' && ( {upload.status === 'error' && (
<div className="absolute inset-0 bg-rose-500/20 border-2 border-rose-500 flex items-center justify-center cursor-pointer" onClick={() => retryUpload(upload.id)}> <div className="absolute inset-0 bg-danger/20 border-2 border-danger flex items-center justify-center cursor-pointer" onClick={() => retryUpload(upload.id)}>
<RotateCcw size={10} className="text-rose-500" /> <RotateCcw size={10} className="text-danger" />
</div> </div>
)} )}
</div> </div>
@@ -755,11 +755,11 @@ export default function AssistantChatPage() {
)} )}
{messages.length >= 2 && ( {messages.length >= 2 && (
<> <>
<button type="button" onClick={() => setShowStatusUpdate(true)} disabled={loading} className="flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-xs text-muted-foreground hover:text-blue-400 hover:bg-blue-500/10 transition-colors disabled:opacity-40" title="Share status update"> <button type="button" onClick={() => setShowStatusUpdate(true)} disabled={loading} className="flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-xs text-muted-foreground hover:text-accent hover:bg-accent-dim transition-colors disabled:opacity-40" title="Share status update">
<FileText size={14} /> <FileText size={14} />
<span className="hidden sm:inline">Update</span> <span className="hidden sm:inline">Update</span>
</button> </button>
<button type="button" onClick={() => setShowConclude(true)} disabled={loading} className="flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-xs text-muted-foreground hover:text-amber-400 hover:bg-amber-400/10 transition-colors disabled:opacity-40" title="Conclude session"> <button type="button" onClick={() => setShowConclude(true)} disabled={loading} className="flex items-center gap-1.5 rounded-lg px-2 py-1.5 text-xs text-muted-foreground hover:text-warning hover:bg-warning-dim transition-colors disabled:opacity-40" title="Conclude session">
<Flag size={14} /> <Flag size={14} />
<span className="hidden sm:inline">Conclude</span> <span className="hidden sm:inline">Conclude</span>
</button> </button>

View File

@@ -108,7 +108,7 @@ export default function FlowPilotSessionPage() {
return ( return (
<div className="flex items-center justify-center min-h-[50vh]"> <div className="flex items-center justify-center min-h-[50vh]">
<div className="card-flat p-6 text-center max-w-md"> <div className="card-flat p-6 text-center max-w-md">
<p className="text-sm text-rose-400">{fp.error}</p> <p className="text-sm text-danger">{fp.error}</p>
<button <button
onClick={() => window.location.reload()} onClick={() => window.location.reload()}
className="mt-3 text-xs text-muted-foreground hover:text-foreground transition-colors" className="mt-3 text-xs text-muted-foreground hover:text-foreground transition-colors"
@@ -160,15 +160,15 @@ export default function FlowPilotSessionPage() {
className="flex items-center gap-3 border-b px-5 py-3 shrink-0" className="flex items-center gap-3 border-b px-5 py-3 shrink-0"
style={{ borderColor: 'var(--color-border-default)' }} style={{ borderColor: 'var(--color-border-default)' }}
> >
<span className="flex h-7 w-7 items-center justify-center rounded-lg bg-amber-500/10"> <span className="flex h-7 w-7 items-center justify-center rounded-lg bg-warning-dim">
<Sparkles size={14} className="text-amber-400" /> <Sparkles size={14} className="text-warning" />
</span> </span>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<h1 className="font-heading text-sm font-semibold text-foreground truncate"> <h1 className="font-heading text-sm font-semibold text-foreground truncate">
Escalation Pickup {fp.session.problem_summary || 'FlowPilot Session'} Escalation Pickup {fp.session.problem_summary || 'FlowPilot Session'}
</h1> </h1>
</div> </div>
<span className="font-sans text-xs rounded-md bg-amber-500/10 px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-amber-400 border border-amber-500/20"> <span className="font-sans text-xs rounded-md bg-warning-dim px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-warning border border-warning/20">
Awaiting pickup Awaiting pickup
</span> </span>
</div> </div>
@@ -196,8 +196,8 @@ export default function FlowPilotSessionPage() {
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80"> <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/80">
<div className="bg-card border border-border rounded-xl w-full max-w-md p-6 shadow-lg"> <div className="bg-card border border-border rounded-xl w-full max-w-md p-6 shadow-lg">
<div className="flex items-center gap-3 mb-3"> <div className="flex items-center gap-3 mb-3">
<span className="flex h-9 w-9 items-center justify-center rounded-lg bg-amber-500/10"> <span className="flex h-9 w-9 items-center justify-center rounded-lg bg-warning-dim">
<AlertTriangle size={18} className="text-amber-400" /> <AlertTriangle size={18} className="text-warning" />
</span> </span>
<h2 className="text-lg font-heading font-semibold text-foreground">Active Session</h2> <h2 className="text-lg font-heading font-semibold text-foreground">Active Session</h2>
</div> </div>
@@ -207,7 +207,7 @@ export default function FlowPilotSessionPage() {
<div className="flex gap-2"> <div className="flex gap-2">
<button <button
onClick={() => blocker.reset()} onClick={() => blocker.reset()}
className="flex-1 rounded-lg bg-gradient-to-r from-blue-500 to-blue-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-accent px-4 py-2.5 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all"
> >
Stay in Session Stay in Session
</button> </button>
@@ -246,7 +246,7 @@ export default function FlowPilotSessionPage() {
<button <button
onClick={() => setShowResolve(true)} onClick={() => setShowResolve(true)}
disabled={!fp.canResolve || fp.isProcessing} disabled={!fp.canResolve || fp.isProcessing}
className="flex items-center gap-1.5 rounded-lg bg-emerald-500/10 border border-emerald-500/20 px-3 py-1.5 text-xs font-medium text-emerald-400 hover:bg-emerald-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors" className="flex items-center gap-1.5 rounded-lg bg-success-dim border border-success/20 px-3 py-1.5 text-xs font-medium text-success hover:bg-success/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
> >
<CheckCircle2 size={13} /> <CheckCircle2 size={13} />
Resolve Resolve
@@ -254,7 +254,7 @@ export default function FlowPilotSessionPage() {
<button <button
onClick={() => setShowEscalate(true)} onClick={() => setShowEscalate(true)}
disabled={!fp.canEscalate || fp.isProcessing} disabled={!fp.canEscalate || fp.isProcessing}
className="flex items-center gap-1.5 rounded-lg bg-amber-500/10 border border-amber-500/20 px-3 py-1.5 text-xs font-medium text-amber-400 hover:bg-amber-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors" className="flex items-center gap-1.5 rounded-lg bg-warning-dim border border-warning/20 px-3 py-1.5 text-xs font-medium text-warning hover:bg-warning/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
> >
<ArrowUpRight size={13} /> <ArrowUpRight size={13} />
Escalate Escalate
@@ -263,7 +263,7 @@ export default function FlowPilotSessionPage() {
<button <button
onClick={() => setShowStatusUpdate(true)} onClick={() => setShowStatusUpdate(true)}
disabled={fp.isProcessing} disabled={fp.isProcessing}
className="flex items-center gap-1.5 rounded-lg bg-blue-500/10 border border-blue-500/20 px-3 py-1.5 text-xs font-medium text-blue-400 hover:bg-blue-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors" className="flex items-center gap-1.5 rounded-lg bg-accent-dim border border-accent/20 px-3 py-1.5 text-xs font-medium text-accent hover:bg-accent/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
title="Share Update" title="Share Update"
> >
<FileText size={13} /> <FileText size={13} />
@@ -291,7 +291,7 @@ export default function FlowPilotSessionPage() {
</button> </button>
<button <button
onClick={() => { setShowOverflow(false); setShowAbandon(true) }} onClick={() => { setShowOverflow(false); setShowAbandon(true) }}
className="flex w-full items-center gap-2 px-3 py-2 text-xs text-muted-foreground hover:text-rose-400 hover:bg-rose-500/10 transition-colors" className="flex w-full items-center gap-2 px-3 py-2 text-xs text-muted-foreground hover:text-danger hover:bg-danger-dim transition-colors"
> >
<X size={13} /> <X size={13} />
Close Session Close Session
@@ -317,7 +317,7 @@ export default function FlowPilotSessionPage() {
<button <button
onClick={() => { setShowOverflow(false); setShowResolve(true) }} onClick={() => { setShowOverflow(false); setShowResolve(true) }}
disabled={!fp.canResolve} disabled={!fp.canResolve}
className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-emerald-400 hover:bg-emerald-500/10 transition-colors disabled:opacity-40" className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-success hover:bg-success-dim transition-colors disabled:opacity-40"
> >
<CheckCircle2 size={14} /> <CheckCircle2 size={14} />
Resolve Resolve
@@ -325,7 +325,7 @@ export default function FlowPilotSessionPage() {
<button <button
onClick={() => { setShowOverflow(false); setShowEscalate(true) }} onClick={() => { setShowOverflow(false); setShowEscalate(true) }}
disabled={!fp.canEscalate} disabled={!fp.canEscalate}
className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-amber-400 hover:bg-amber-500/10 transition-colors disabled:opacity-40" className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-warning hover:bg-warning-dim transition-colors disabled:opacity-40"
> >
<ArrowUpRight size={14} /> <ArrowUpRight size={14} />
Escalate Escalate
@@ -333,7 +333,7 @@ export default function FlowPilotSessionPage() {
{fp.allSteps.length >= 2 && ( {fp.allSteps.length >= 2 && (
<button <button
onClick={() => { setShowOverflow(false); setShowStatusUpdate(true) }} onClick={() => { setShowOverflow(false); setShowStatusUpdate(true) }}
className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-blue-400 hover:bg-blue-500/10 transition-colors" className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-accent hover:bg-accent-dim transition-colors"
> >
<FileText size={14} /> <FileText size={14} />
Share Update Share Update
@@ -349,7 +349,7 @@ export default function FlowPilotSessionPage() {
</button> </button>
<button <button
onClick={() => { setShowOverflow(false); setShowAbandon(true) }} onClick={() => { setShowOverflow(false); setShowAbandon(true) }}
className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-muted-foreground hover:text-rose-400 hover:bg-rose-500/10 transition-colors" className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-muted-foreground hover:text-danger hover:bg-danger-dim transition-colors"
> >
<X size={14} /> <X size={14} />
Close Session Close Session
@@ -364,8 +364,8 @@ export default function FlowPilotSessionPage() {
{/* Status badge — non-active states */} {/* Status badge — non-active states */}
{fp.session.status !== 'active' && ( {fp.session.status !== 'active' && (
<span className={`flex items-center gap-1.5 text-[0.625rem] uppercase tracking-wider font-sans ${ <span className={`flex items-center gap-1.5 text-[0.625rem] uppercase tracking-wider font-sans ${
fp.session.status === 'resolved' ? 'text-emerald-400' : fp.session.status === 'resolved' ? 'text-success' :
fp.session.status === 'escalated' ? 'text-amber-400' : fp.session.status === 'escalated' ? 'text-warning' :
fp.session.status === 'paused' ? 'text-muted-foreground' : fp.session.status === 'paused' ? 'text-muted-foreground' :
'text-muted-foreground' 'text-muted-foreground'
}`}> }`}>
@@ -437,7 +437,7 @@ export default function FlowPilotSessionPage() {
} }
}} }}
disabled={resolutionSummary.length < 5 || submitting} disabled={resolutionSummary.length < 5 || submitting}
className="rounded-lg bg-emerald-500/20 border border-emerald-500/30 px-4 py-2 min-h-[44px] text-sm font-medium text-emerald-400 hover:bg-emerald-500/30 disabled:opacity-50 transition-colors" className="rounded-lg bg-success/20 border border-success/30 px-4 py-2 min-h-[44px] text-sm font-medium text-success hover:bg-success/30 disabled:opacity-50 transition-colors"
> >
{submitting ? 'Resolving...' : 'Resolve Session'} {submitting ? 'Resolving...' : 'Resolve Session'}
</button> </button>
@@ -473,7 +473,7 @@ export default function FlowPilotSessionPage() {
} }
}} }}
disabled={submitting} disabled={submitting}
className="rounded-lg bg-rose-500/20 border border-rose-500/30 px-4 py-2 min-h-[44px] text-sm font-medium text-rose-400 hover:bg-rose-500/30 disabled:opacity-50 transition-colors" className="rounded-lg bg-danger/20 border border-danger/30 px-4 py-2 min-h-[44px] text-sm font-medium text-danger hover:bg-danger/30 disabled:opacity-50 transition-colors"
> >
{submitting ? 'Closing...' : 'Close Session'} {submitting ? 'Closing...' : 'Close Session'}
</button> </button>