slice 4: accent palette refinement — blue → teal

Replace the four accent-family hex codes site-wide with the teal palette
(keeps the dark theme; only swaps the accent family, not the dark base):

  #3b82f6 (accent primary CTA)   → #5B7C8D  (teal)        [839×]
  #2563eb (accent-dark / hover)  → #4A6473  (darker teal) [44×]
  #60a5fa (info link, lighter)   → #8FB0C3  (mid teal)    [68×]
  #1e3a5f (accent-muted bg)      → #2F4F5F  (navy)        [44×]

tailwind.config.js tokens updated to match (accent/accent-dark/accent-muted).
Sweep also covers tailwind.css. 108 files touched. The dark base (#0d0d0d,
#111, #161616, #1a1a1a etc.) is intentionally untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-15 23:33:04 +00:00
parent f6fa7570c4
commit 52fe7bceb6
109 changed files with 937 additions and 937 deletions

View File

@@ -214,7 +214,7 @@ function renderMarkdown(text: string): string {
.replace(/^# (.+)$/gm, '<h1 class="text-xl font-bold text-white mt-5 mb-2">$1</h1>')
.replace(/\*\*(.+?)\*\*/g, '<strong class="text-white font-semibold">$1</strong>')
.replace(/\*(.+?)\*/g, '<em>$1</em>')
.replace(/`([^`]+)`/g, '<code class="bg-[#1a2535] text-[#3b82f6] px-1 py-0.5 rounded text-sm font-mono">$1</code>')
.replace(/`([^`]+)`/g, '<code class="bg-[#1a2535] text-[#5B7C8D] px-1 py-0.5 rounded text-sm font-mono">$1</code>')
.replace(/^- (.+)$/gm, '<li class="ml-4 list-disc text-[#aaa]">$1</li>')
.replace(/^\d+\. (.+)$/gm, '<li class="ml-4 list-decimal text-[#aaa]">$1</li>')
.replace(/\n\n/g, '</p><p class="mb-3 text-[#ccc] leading-relaxed">')
@@ -294,7 +294,7 @@ function DraftPreviewModal({ content, title, penName, siteId, onClose, onSave }:
</button>
<button
onClick={() => onSave(true)}
className="bg-[#3b82f6] hover:bg-[#2563eb] text-white text-sm px-4 py-2 rounded-lg transition-colors font-medium"
className="bg-[#5B7C8D] hover:bg-[#4A6473] text-white text-sm px-4 py-2 rounded-lg transition-colors font-medium"
>
Open in Editor
</button>
@@ -353,7 +353,7 @@ function RegenerateModal({ onClose, onRegenerate }: RegenerateModalProps) {
onClick={() => { setSelectedVariant(v.prompt); setCustomPrompt(''); }}
className={`text-left text-xs px-3 py-2 rounded border transition-colors ${
selectedVariant === v.prompt
? 'border-[#3b82f6] bg-[#1e3a5f] text-white'
? 'border-[#5B7C8D] bg-[#2F4F5F] text-white'
: 'border-[#1e2a3a] text-[#aaa] hover:border-[#2a3a50] hover:text-white hover:bg-[#161f2e]'
}`}
>
@@ -370,7 +370,7 @@ function RegenerateModal({ onClose, onRegenerate }: RegenerateModalProps) {
onChange={e => { setCustomPrompt(e.target.value); setSelectedVariant(null); }}
placeholder="e.g. Rewrite this focusing on the European market impact..."
rows={3}
className="w-full bg-[#0d1117] border border-[#1e2a3a] text-white text-sm rounded-lg px-3 py-2 focus:outline-none focus:border-[#3b82f6] placeholder-[#333] resize-none"
className="w-full bg-[#0d1117] border border-[#1e2a3a] text-white text-sm rounded-lg px-3 py-2 focus:outline-none focus:border-[#5B7C8D] placeholder-[#333] resize-none"
/>
</div>
@@ -386,7 +386,7 @@ function RegenerateModal({ onClose, onRegenerate }: RegenerateModalProps) {
<button onClick={onClose} className="text-[#555] hover:text-[#aaa] text-sm transition-colors">Cancel</button>
<button
onClick={handleSubmit}
className="bg-[#3b82f6] hover:bg-[#2563eb] text-white text-sm px-4 py-2 rounded-lg transition-colors font-medium"
className="bg-[#5B7C8D] hover:bg-[#4A6473] text-white text-sm px-4 py-2 rounded-lg transition-colors font-medium"
>
Regenerate
</button>
@@ -418,7 +418,7 @@ function StyleGuidesPanel({ onClose, onSelectPenName }: StyleGuidesPanelProps) {
const found = PEN_NAME_PROFILES.find(p => p.name === e.target.value);
if (found) side === 'left' ? setLeftPen(found) : setRightPen(found);
}}
className="w-full bg-[#0d1117] border border-[#1e2a3a] text-white text-sm rounded px-2 py-1.5 focus:outline-none focus:border-[#3b82f6]"
className="w-full bg-[#0d1117] border border-[#1e2a3a] text-white text-sm rounded px-2 py-1.5 focus:outline-none focus:border-[#5B7C8D]"
>
{PEN_NAME_PROFILES.map(p => (
<option key={p.name} value={p.name}>{p.name} ({p.site})</option>
@@ -434,7 +434,7 @@ function StyleGuidesPanel({ onClose, onSelectPenName }: StyleGuidesPanelProps) {
</span>
<span className="text-white font-semibold text-sm">{profile.name}</span>
</div>
<p className="text-[#3b82f6] text-xs">{profile.title}</p>
<p className="text-[#5B7C8D] text-xs">{profile.title}</p>
</div>
<div>
@@ -458,7 +458,7 @@ function StyleGuidesPanel({ onClose, onSelectPenName }: StyleGuidesPanelProps) {
<div>
<p className="text-[#555] text-[10px] uppercase tracking-wider font-bold mb-1">Example Lead</p>
<p className="text-[#aaa] text-xs italic leading-relaxed border-l-2 border-[#3b82f6]/40 pl-3">"{profile.exampleLead}"</p>
<p className="text-[#aaa] text-xs italic leading-relaxed border-l-2 border-[#5B7C8D]/40 pl-3">"{profile.exampleLead}"</p>
</div>
<button
@@ -485,7 +485,7 @@ function StyleGuidesPanel({ onClose, onSelectPenName }: StyleGuidesPanelProps) {
<button
key={f}
onClick={() => setFilterSite(f)}
className={`text-xs px-2.5 py-1 rounded transition-colors ${filterSite === f ? 'bg-[#3b82f6] text-white' : 'bg-[#1e2a3a] text-[#aaa] hover:text-white'}`}
className={`text-xs px-2.5 py-1 rounded transition-colors ${filterSite === f ? 'bg-[#5B7C8D] text-white' : 'bg-[#1e2a3a] text-[#aaa] hover:text-white'}`}
>
{f === 'ALL' ? 'All Writers' : f === 'BB' ? 'Broadcast Beat' : 'AV Beat'}
</button>
@@ -514,7 +514,7 @@ function StyleGuidesPanel({ onClose, onSelectPenName }: StyleGuidesPanelProps) {
>
<div className="flex items-center gap-2 mb-0.5">
<span className={`text-[9px] font-bold px-1 rounded ${p.site === 'AV' ? 'bg-orange-900/40 text-orange-400' : 'bg-blue-900/40 text-blue-400'}`}>{p.site}</span>
<span className="text-white text-xs font-medium group-hover:text-[#3b82f6] transition-colors">{p.name}</span>
<span className="text-white text-xs font-medium group-hover:text-[#5B7C8D] transition-colors">{p.name}</span>
</div>
<p className="text-[#555] text-[10px]">{p.title}</p>
</button>
@@ -560,14 +560,14 @@ function ResponseHistorySidebar({ messages, onJumpTo, onClose }: ResponseHistory
className="w-full text-left p-3 rounded border border-[#1e2a3a] hover:border-[#2a3a50] hover:bg-[#161f2e] transition-colors group"
>
<div className="flex items-center justify-between mb-1">
<span className="text-[10px] text-[#3b82f6] font-bold">Response #{idx + 1}</span>
<span className="text-[10px] text-[#5B7C8D] font-bold">Response #{idx + 1}</span>
<span className={`w-1.5 h-1.5 rounded-full flex-shrink-0 ${msg.provider === 'ollama' ? 'bg-green-500' : 'bg-yellow-500'}`} />
</div>
<p className="text-[#aaa] text-xs line-clamp-3 leading-relaxed">{preview}</p>
<div className="flex items-center gap-3 mt-2">
<span className="text-[10px] text-[#444]">{msg.timestamp.toLocaleTimeString()}</span>
<span className="text-[10px] text-[#444]">{wordCount} words</span>
<span className="text-[10px] text-[#3b82f6] opacity-0 group-hover:opacity-100 transition-opacity">Jump </span>
<span className="text-[10px] text-[#5B7C8D] opacity-0 group-hover:opacity-100 transition-opacity">Jump </span>
</div>
</button>
);
@@ -927,7 +927,7 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
{/* Header */}
<div className="bg-[#111827] border-b border-[#1e2a3a] px-4 py-3 flex items-center justify-between">
<div className="flex items-center gap-3">
<Link href="/admin" className="text-[#555] hover:text-[#3b82f6] text-sm transition-colors"> Dashboard</Link>
<Link href="/admin" className="text-[#555] hover:text-[#5B7C8D] text-sm transition-colors"> Dashboard</Link>
<span className="text-[#333]">/</span>
<h1 className="text-white font-bold text-sm tracking-wide">AI Console</h1>
</div>
@@ -943,18 +943,18 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
onClick={() => setShowHistorySidebar(v => !v)}
className={`text-xs px-2.5 py-1.5 rounded border transition-colors ${
showHistorySidebar
? 'bg-[#1e3a5f] border-[#3b82f6]/40 text-[#3b82f6]'
? 'bg-[#2F4F5F] border-[#5B7C8D]/40 text-[#5B7C8D]'
: 'bg-[#1e2a3a] border-[#2a3a50] text-[#555] hover:text-[#aaa]'
}`}
title="Toggle response history sidebar"
>
History
{assistantMessageCount > 0 && (
<span className="ml-1.5 bg-[#3b82f6] text-white text-[9px] font-bold px-1 py-0.5 rounded-full">{assistantMessageCount}</span>
<span className="ml-1.5 bg-[#5B7C8D] text-white text-[9px] font-bold px-1 py-0.5 rounded-full">{assistantMessageCount}</span>
)}
</button>
<Link href="/dashboard/ai-console/health" className="text-[#555] hover:text-[#3b82f6] text-xs transition-colors">Health</Link>
<Link href="/dashboard/ai-console/settings" className="text-[#555] hover:text-[#3b82f6] text-xs transition-colors">Settings</Link>
<Link href="/dashboard/ai-console/health" className="text-[#555] hover:text-[#5B7C8D] text-xs transition-colors">Health</Link>
<Link href="/dashboard/ai-console/settings" className="text-[#555] hover:text-[#5B7C8D] text-xs transition-colors">Settings</Link>
<button onClick={handleNewSession} className="text-xs bg-[#1e2a3a] hover:bg-[#253347] text-[#aaa] px-3 py-1.5 rounded transition-colors">
+ New Session
</button>
@@ -1002,7 +1002,7 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
key={session.id}
className={`group p-2.5 rounded border cursor-pointer transition-colors ${
currentSessionId === session.id
? 'border-[#3b82f6]/40 bg-[#1e2a3a]'
? 'border-[#5B7C8D]/40 bg-[#1e2a3a]'
: 'border-[#1e2a3a] hover:border-[#2a3a50] hover:bg-[#161f2e]'
}`}
>
@@ -1046,11 +1046,11 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
onClick={() => {
fetch('/api/ai/console?action=ping').then(r => r.json()).then(setAiStatus).catch(() => {});
}}
className="text-[10px] text-[#555] hover:text-[#3b82f6] transition-colors"
className="text-[10px] text-[#555] hover:text-[#5B7C8D] transition-colors"
>
Refresh
</button>
<Link href="/dashboard/ai-console/health" className="text-[10px] text-[#555] hover:text-[#3b82f6] transition-colors">
<Link href="/dashboard/ai-console/health" className="text-[10px] text-[#555] hover:text-[#5B7C8D] transition-colors">
Health Dashboard
</Link>
</div>
@@ -1066,7 +1066,7 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
<select
value={selectedSite}
onChange={e => setSelectedSite(Number(e.target.value) as 1 | 2)}
className="bg-[#1e2a3a] border border-[#2a3a50] text-white text-xs rounded px-2 py-1 focus:outline-none focus:border-[#3b82f6]"
className="bg-[#1e2a3a] border border-[#2a3a50] text-white text-xs rounded px-2 py-1 focus:outline-none focus:border-[#5B7C8D]"
>
<option value={1}>Broadcast Beat</option>
<option value={2}>AV Beat</option>
@@ -1077,7 +1077,7 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
<select
value={selectedPenName}
onChange={e => setSelectedPenName(e.target.value)}
className="bg-[#1e2a3a] border border-[#2a3a50] text-white text-xs rounded px-2 py-1 focus:outline-none focus:border-[#3b82f6]"
className="bg-[#1e2a3a] border border-[#2a3a50] text-white text-xs rounded px-2 py-1 focus:outline-none focus:border-[#5B7C8D]"
>
{penNames.map(name => (
<option key={name} value={name}>{name}</option>
@@ -1086,7 +1086,7 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
</div>
<button
onClick={() => setShowStyleGuides(true)}
className="text-[10px] text-[#3b82f6] hover:text-[#60a5fa] transition-colors ml-auto"
className="text-[10px] text-[#5B7C8D] hover:text-[#8FB0C3] transition-colors ml-auto"
>
View style guide
</button>
@@ -1123,7 +1123,7 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
</div>
)}
<div className={`rounded-lg px-4 py-3 ${
msg.role === 'user' ?'bg-[#1e3a5f] text-white text-sm' :'bg-[#111827] border border-[#1e2a3a] text-[#ccc] text-sm'
msg.role === 'user' ?'bg-[#2F4F5F] text-white text-sm' :'bg-[#111827] border border-[#1e2a3a] text-[#ccc] text-sm'
}`}>
{msg.role === 'user' ? (
<p className="whitespace-pre-wrap">{msg.content}</p>
@@ -1151,7 +1151,7 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
</button>
<button
onClick={() => setShowDraftPreview(true)}
className="text-[10px] text-[#3b82f6] hover:text-[#60a5fa] bg-[#111827] border border-[#3b82f6]/30 px-2 py-1 rounded transition-colors font-medium"
className="text-[10px] text-[#5B7C8D] hover:text-[#8FB0C3] bg-[#111827] border border-[#5B7C8D]/30 px-2 py-1 rounded transition-colors font-medium"
>
Preview Draft
</button>
@@ -1195,9 +1195,9 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
<div className="flex justify-start">
<div className="bg-[#111827] border border-[#1e2a3a] rounded-lg px-4 py-3">
<div className="flex gap-1">
<div className="w-1.5 h-1.5 bg-[#3b82f6] rounded-full animate-bounce" style={{ animationDelay: '0ms' }} />
<div className="w-1.5 h-1.5 bg-[#3b82f6] rounded-full animate-bounce" style={{ animationDelay: '150ms' }} />
<div className="w-1.5 h-1.5 bg-[#3b82f6] rounded-full animate-bounce" style={{ animationDelay: '300ms' }} />
<div className="w-1.5 h-1.5 bg-[#5B7C8D] rounded-full animate-bounce" style={{ animationDelay: '0ms' }} />
<div className="w-1.5 h-1.5 bg-[#5B7C8D] rounded-full animate-bounce" style={{ animationDelay: '150ms' }} />
<div className="w-1.5 h-1.5 bg-[#5B7C8D] rounded-full animate-bounce" style={{ animationDelay: '300ms' }} />
</div>
</div>
</div>
@@ -1225,13 +1225,13 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
onChange={e => setUrlInput(e.target.value)}
onKeyDown={e => e.key === 'Enter' && handleFetchUrl()}
placeholder="https://example.com/press-release"
className="flex-1 bg-[#1e2a3a] border border-[#2a3a50] text-white text-sm rounded px-3 py-2 focus:outline-none focus:border-[#3b82f6] placeholder-[#444]"
className="flex-1 bg-[#1e2a3a] border border-[#2a3a50] text-white text-sm rounded px-3 py-2 focus:outline-none focus:border-[#5B7C8D] placeholder-[#444]"
autoFocus
/>
<button
onClick={handleFetchUrl}
disabled={fetchingUrl}
className="bg-[#3b82f6] hover:bg-[#2563eb] text-white text-xs px-3 py-2 rounded transition-colors disabled:opacity-50"
className="bg-[#5B7C8D] hover:bg-[#4A6473] text-white text-xs px-3 py-2 rounded transition-colors disabled:opacity-50"
>
{fetchingUrl ? 'Fetching...' : 'Add'}
</button>
@@ -1244,19 +1244,19 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
<div className="flex gap-2 mb-2">
<button
onClick={() => setShowUrlInput(!showUrlInput)}
className="text-xs text-[#555] hover:text-[#3b82f6] bg-[#111827] border border-[#1e2a3a] px-2 py-1 rounded transition-colors"
className="text-xs text-[#555] hover:text-[#5B7C8D] bg-[#111827] border border-[#1e2a3a] px-2 py-1 rounded transition-colors"
>
+ Add URL
</button>
<button
onClick={() => setInput(prev => prev + '\n\n[Paste story content here for reference]')}
className="text-xs text-[#555] hover:text-[#3b82f6] bg-[#111827] border border-[#1e2a3a] px-2 py-1 rounded transition-colors"
className="text-xs text-[#555] hover:text-[#5B7C8D] bg-[#111827] border border-[#1e2a3a] px-2 py-1 rounded transition-colors"
>
+ Add Story
</button>
<button
onClick={() => setInput(prev => prev + `\n\nWrite in the style of ${selectedPenName}.`)}
className="text-xs text-[#555] hover:text-[#3b82f6] bg-[#111827] border border-[#1e2a3a] px-2 py-1 rounded transition-colors"
className="text-xs text-[#555] hover:text-[#5B7C8D] bg-[#111827] border border-[#1e2a3a] px-2 py-1 rounded transition-colors"
>
+ Add Style
</button>
@@ -1274,13 +1274,13 @@ Respond conversationally and helpfully. If asked to write a story, write the ful
}}
placeholder="Ask the AI to write a story, generate headlines, translate content..."
rows={3}
className="flex-1 bg-[#111827] border border-[#1e2a3a] text-white text-sm rounded-lg px-4 py-3 focus:outline-none focus:border-[#3b82f6] placeholder-[#333] resize-none"
className="flex-1 bg-[#111827] border border-[#1e2a3a] text-white text-sm rounded-lg px-4 py-3 focus:outline-none focus:border-[#5B7C8D] placeholder-[#333] resize-none"
/>
<div className="flex flex-col gap-2">
<button
onClick={() => handleSend()}
disabled={isStreaming || !input.trim()}
className="bg-[#3b82f6] hover:bg-[#2563eb] disabled:opacity-40 disabled:cursor-not-allowed text-white text-sm px-4 py-2 rounded-lg transition-colors font-medium flex-1"
className="bg-[#5B7C8D] hover:bg-[#4A6473] disabled:opacity-40 disabled:cursor-not-allowed text-white text-sm px-4 py-2 rounded-lg transition-colors font-medium flex-1"
>
{isStreaming ? (
<span className="flex items-center gap-1">

View File

@@ -117,7 +117,7 @@ export default function AIConsoleSettingsPage() {
if (loading || loadingSettings) {
return (
<div className="min-h-screen bg-[#0d1117] flex items-center justify-center">
<div className="w-6 h-6 border-2 border-[#3b82f6]/30 border-t-[#3b82f6] rounded-full animate-spin" />
<div className="w-6 h-6 border-2 border-[#5B7C8D]/30 border-t-[#5B7C8D] rounded-full animate-spin" />
</div>
);
}
@@ -127,14 +127,14 @@ export default function AIConsoleSettingsPage() {
{/* Header */}
<div className="bg-[#111827] border-b border-[#1e2a3a] px-6 py-4 flex items-center justify-between">
<div className="flex items-center gap-3">
<Link href="/dashboard/ai-console" className="text-[#555] hover:text-[#3b82f6] text-sm transition-colors"> AI Console</Link>
<Link href="/dashboard/ai-console" className="text-[#555] hover:text-[#5B7C8D] text-sm transition-colors"> AI Console</Link>
<span className="text-[#333]">/</span>
<h1 className="text-white font-bold text-sm">AI Console Settings</h1>
</div>
<button
onClick={handleSave}
disabled={saving}
className="bg-[#3b82f6] hover:bg-[#2563eb] disabled:opacity-50 text-white text-sm px-4 py-2 rounded-lg transition-colors font-medium"
className="bg-[#5B7C8D] hover:bg-[#4A6473] disabled:opacity-50 text-white text-sm px-4 py-2 rounded-lg transition-colors font-medium"
>
{saving ? 'Saving...' : 'Save Settings'}
</button>
@@ -177,7 +177,7 @@ export default function AIConsoleSettingsPage() {
value={settings.ollama_endpoint}
onChange={e => update('ollama_endpoint', e.target.value)}
placeholder="http://192.168.1.x:11434 or https://your-tunnel.ngrok.io"
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#3b82f6] placeholder-[#333]"
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#5B7C8D] placeholder-[#333]"
/>
<p className="text-[#444] text-[10px] mt-1">
Use direct IP if on the same network, or a tunnel URL (ngrok, Cloudflare Tunnel, Tailscale) for remote access.
@@ -212,7 +212,7 @@ export default function AIConsoleSettingsPage() {
<select
value={settings.ollama_model_default}
onChange={e => update('ollama_model_default', e.target.value)}
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#3b82f6]"
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#5B7C8D]"
>
<option value="">Auto (largest available)</option>
{connectionResult.models.map(m => <option key={m} value={m}>{m}</option>)}
@@ -223,7 +223,7 @@ export default function AIConsoleSettingsPage() {
<select
value={settings.ollama_model_translation}
onChange={e => update('ollama_model_translation', e.target.value)}
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#3b82f6]"
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#5B7C8D]"
>
<option value="">Same as default</option>
{connectionResult.models.map(m => <option key={m} value={m}>{m}</option>)}
@@ -234,7 +234,7 @@ export default function AIConsoleSettingsPage() {
<select
value={settings.ollama_model_background}
onChange={e => update('ollama_model_background', e.target.value)}
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#3b82f6]"
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#5B7C8D]"
>
<option value="">Same as default</option>
{connectionResult.models.map(m => <option key={m} value={m}>{m}</option>)}
@@ -250,7 +250,7 @@ export default function AIConsoleSettingsPage() {
</div>
<button
onClick={() => update('auto_failover', !settings.auto_failover)}
className={`w-10 h-5 rounded-full transition-colors relative ${settings.auto_failover ? 'bg-[#3b82f6]' : 'bg-[#2a3a50]'}`}
className={`w-10 h-5 rounded-full transition-colors relative ${settings.auto_failover ? 'bg-[#5B7C8D]' : 'bg-[#2a3a50]'}`}
>
<div className={`w-4 h-4 bg-white rounded-full absolute top-0.5 transition-transform ${settings.auto_failover ? 'translate-x-5' : 'translate-x-0.5'}`} />
</button>
@@ -263,7 +263,7 @@ export default function AIConsoleSettingsPage() {
value={settings.failover_timeout_seconds}
onChange={e => update('failover_timeout_seconds', Number(e.target.value))}
min={3} max={30}
className="w-32 bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2 focus:outline-none focus:border-[#3b82f6]"
className="w-32 bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2 focus:outline-none focus:border-[#5B7C8D]"
/>
</div>
</div>
@@ -301,7 +301,7 @@ export default function AIConsoleSettingsPage() {
<select
value={settings.default_site_id}
onChange={e => update('default_site_id', Number(e.target.value))}
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#3b82f6]"
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#5B7C8D]"
>
<option value={1}>Broadcast Beat</option>
<option value={2}>AV Beat</option>
@@ -312,7 +312,7 @@ export default function AIConsoleSettingsPage() {
<select
value={settings.default_pen_name_bb}
onChange={e => update('default_pen_name_bb', e.target.value)}
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#3b82f6]"
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#5B7C8D]"
>
{BB_PEN_NAMES.map(n => <option key={n} value={n}>{n}</option>)}
</select>
@@ -322,7 +322,7 @@ export default function AIConsoleSettingsPage() {
<select
value={settings.default_pen_name_av}
onChange={e => update('default_pen_name_av', e.target.value)}
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#3b82f6]"
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#5B7C8D]"
>
{AV_PEN_NAMES.map(n => <option key={n} value={n}>{n}</option>)}
</select>
@@ -335,7 +335,7 @@ export default function AIConsoleSettingsPage() {
</div>
<button
onClick={() => update('save_session_history', !settings.save_session_history)}
className={`w-10 h-5 rounded-full transition-colors relative ${settings.save_session_history ? 'bg-[#3b82f6]' : 'bg-[#2a3a50]'}`}
className={`w-10 h-5 rounded-full transition-colors relative ${settings.save_session_history ? 'bg-[#5B7C8D]' : 'bg-[#2a3a50]'}`}
>
<div className={`w-4 h-4 bg-white rounded-full absolute top-0.5 transition-transform ${settings.save_session_history ? 'translate-x-5' : 'translate-x-0.5'}`} />
</button>
@@ -346,7 +346,7 @@ export default function AIConsoleSettingsPage() {
<select
value={settings.history_retention_days}
onChange={e => update('history_retention_days', Number(e.target.value))}
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#3b82f6]"
className="w-full bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2.5 focus:outline-none focus:border-[#5B7C8D]"
>
<option value={30}>30 days</option>
<option value={60}>60 days</option>
@@ -361,7 +361,7 @@ export default function AIConsoleSettingsPage() {
</div>
<button
onClick={() => update('streaming_enabled', !settings.streaming_enabled)}
className={`w-10 h-5 rounded-full transition-colors relative ${settings.streaming_enabled ? 'bg-[#3b82f6]' : 'bg-[#2a3a50]'}`}
className={`w-10 h-5 rounded-full transition-colors relative ${settings.streaming_enabled ? 'bg-[#5B7C8D]' : 'bg-[#2a3a50]'}`}
>
<div className={`w-4 h-4 bg-white rounded-full absolute top-0.5 transition-transform ${settings.streaming_enabled ? 'translate-x-5' : 'translate-x-0.5'}`} />
</button>
@@ -380,7 +380,7 @@ export default function AIConsoleSettingsPage() {
</div>
<button
onClick={() => update('background_use_local', !settings.background_use_local)}
className={`w-10 h-5 rounded-full transition-colors relative ${settings.background_use_local ? 'bg-[#3b82f6]' : 'bg-[#2a3a50]'}`}
className={`w-10 h-5 rounded-full transition-colors relative ${settings.background_use_local ? 'bg-[#5B7C8D]' : 'bg-[#2a3a50]'}`}
>
<div className={`w-4 h-4 bg-white rounded-full absolute top-0.5 transition-transform ${settings.background_use_local ? 'translate-x-5' : 'translate-x-0.5'}`} />
</button>
@@ -393,7 +393,7 @@ export default function AIConsoleSettingsPage() {
value={settings.background_timeout_seconds}
onChange={e => update('background_timeout_seconds', Number(e.target.value))}
min={30} max={300}
className="w-32 bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2 focus:outline-none focus:border-[#3b82f6]"
className="w-32 bg-[#0d1117] border border-[#2a3a50] text-white text-sm rounded-lg px-3 py-2 focus:outline-none focus:border-[#5B7C8D]"
/>
</div>
@@ -404,7 +404,7 @@ export default function AIConsoleSettingsPage() {
</div>
<button
onClick={() => update('priority_queue_enabled', !settings.priority_queue_enabled)}
className={`w-10 h-5 rounded-full transition-colors relative ${settings.priority_queue_enabled ? 'bg-[#3b82f6]' : 'bg-[#2a3a50]'}`}
className={`w-10 h-5 rounded-full transition-colors relative ${settings.priority_queue_enabled ? 'bg-[#5B7C8D]' : 'bg-[#2a3a50]'}`}
>
<div className={`w-4 h-4 bg-white rounded-full absolute top-0.5 transition-transform ${settings.priority_queue_enabled ? 'translate-x-5' : 'translate-x-0.5'}`} />
</button>
@@ -422,7 +422,7 @@ export default function AIConsoleSettingsPage() {
'Classification and extraction tasks',
].map((item, i) => (
<li key={i} className="flex items-center gap-2 text-xs text-[#555]">
<span className="w-4 h-4 rounded-full bg-[#1e2a3a] text-[#3b82f6] text-[10px] flex items-center justify-center font-bold flex-shrink-0">{i + 1}</span>
<span className="w-4 h-4 rounded-full bg-[#1e2a3a] text-[#5B7C8D] text-[10px] flex items-center justify-center font-bold flex-shrink-0">{i + 1}</span>
{item}
</li>
))}

View File

@@ -130,9 +130,9 @@ export default function OverviewTab({ companyId, selectedCompany }: Props) {
<Line
type="monotone"
dataKey="revenue"
stroke={selectedCompany === 'rmp' ? '#3b82f6' : '#a855f7'}
stroke={selectedCompany === 'rmp' ? '#5B7C8D' : '#a855f7'}
strokeWidth={2}
dot={{ fill: selectedCompany === 'rmp' ? '#3b82f6' : '#a855f7', r: 3 }}
dot={{ fill: selectedCompany === 'rmp' ? '#5B7C8D' : '#a855f7', r: 3 }}
/>
</LineChart>
</ResponsiveContainer>

View File

@@ -269,13 +269,13 @@ export default function EditorialDashboard() {
function SortIcon({ col }: { col: typeof sortBy }) {
if (sortBy !== col) return <span className="text-[#444] ml-1"></span>;
return <span className="text-[#3b82f6] ml-1">{sortDir === 'desc' ? '↓' : '↑'}</span>;
return <span className="text-[#5B7C8D] ml-1">{sortDir === 'desc' ? '↓' : '↑'}</span>;
}
if (loading || !authChecked) {
return (
<div className="min-h-screen bg-[#0a0a0a] flex items-center justify-center">
<div className="w-8 h-8 border-2 border-[#3b82f6] border-t-transparent rounded-full animate-spin" />
<div className="w-8 h-8 border-2 border-[#5B7C8D] border-t-transparent rounded-full animate-spin" />
</div>
);
}
@@ -294,7 +294,7 @@ export default function EditorialDashboard() {
<div className="flex items-center gap-3">
<Link
href="/admin/articles"
className="px-3 py-1.5 text-xs font-semibold bg-[#3b82f6] hover:bg-blue-500 text-white rounded transition-colors"
className="px-3 py-1.5 text-xs font-semibold bg-[#5B7C8D] hover:bg-blue-500 text-white rounded transition-colors"
>
+ New Article
</Link>
@@ -344,7 +344,7 @@ export default function EditorialDashboard() {
onClick={() => setStatusFilter(s)}
className={`px-3 py-1.5 text-xs font-semibold capitalize transition-colors ${
statusFilter === s
? 'bg-[#3b82f6] text-white'
? 'bg-[#5B7C8D] text-white'
: 'text-[#666] hover:text-[#aaa]'
}`}
>
@@ -360,7 +360,7 @@ export default function EditorialDashboard() {
placeholder="Search articles, clients, campaigns..."
value={searchQuery}
onChange={e => setSearchQuery(e.target.value)}
className="w-full bg-[#111] border border-[#1e1e1e] rounded-lg px-3 py-1.5 text-xs text-[#ccc] placeholder-[#444] focus:outline-none focus:border-[#3b82f6] transition-colors"
className="w-full bg-[#111] border border-[#1e1e1e] rounded-lg px-3 py-1.5 text-xs text-[#ccc] placeholder-[#444] focus:outline-none focus:border-[#5B7C8D] transition-colors"
/>
{searchQuery && (
<button
@@ -379,7 +379,7 @@ export default function EditorialDashboard() {
<div className="bg-[#0d0d0d] border border-[#1e1e1e] rounded-xl overflow-hidden">
{loadingData ? (
<div className="flex items-center justify-center py-20">
<div className="w-6 h-6 border-2 border-[#3b82f6] border-t-transparent rounded-full animate-spin" />
<div className="w-6 h-6 border-2 border-[#5B7C8D] border-t-transparent rounded-full animate-spin" />
</div>
) : filtered.length === 0 ? (
<div className="text-center py-20 text-[#444] text-sm">No articles found</div>
@@ -437,7 +437,7 @@ export default function EditorialDashboard() {
<span className="text-[#555]">{article.author_name}</span>
)}
{article.category && (
<span className="text-[#3b82f6]/70 bg-[#3b82f6]/10 px-1.5 py-0.5 rounded text-[10px]">
<span className="text-[#5B7C8D]/70 bg-[#5B7C8D]/10 px-1.5 py-0.5 rounded text-[10px]">
{article.category}
</span>
)}

View File

@@ -256,7 +256,7 @@ export default function ShowCalendarPage() {
if (loading) {
return (
<div className="min-h-screen bg-[#0a0a0a] flex items-center justify-center">
<div className="w-8 h-8 border-2 border-[#3b82f6] border-t-transparent rounded-full animate-spin" />
<div className="w-8 h-8 border-2 border-[#5B7C8D] border-t-transparent rounded-full animate-spin" />
</div>
);
}
@@ -294,7 +294,7 @@ export default function ShowCalendarPage() {
<div className="flex items-center gap-3">
<button
onClick={() => { setEditingEvent({ site_id: 1, year: new Date().getFullYear(), seo_tier: 3, event_type: 'trade_show' }); setShowEventModal(true); }}
className="px-3 py-1.5 bg-[#3b82f6] hover:bg-blue-500 text-white text-sm rounded-lg transition-colors"
className="px-3 py-1.5 bg-[#5B7C8D] hover:bg-blue-500 text-white text-sm rounded-lg transition-colors"
>
+ Add Event
</button>
@@ -316,7 +316,7 @@ export default function ShowCalendarPage() {
onClick={() => setSiteFilter(s)}
className={`px-3 py-1 rounded text-xs font-medium transition-colors ${
siteFilter === s
? 'bg-[#3b82f6] text-white'
? 'bg-[#5B7C8D] text-white'
: 'bg-[#1a1a1a] text-[#888] hover:text-white border border-[#333]'
}`}
>
@@ -333,7 +333,7 @@ export default function ShowCalendarPage() {
onClick={() => setActiveTab(tab.id)}
className={`px-4 py-2 text-sm font-medium transition-colors border-b-2 -mb-px ${
activeTab === tab.id
? 'border-[#3b82f6] text-white'
? 'border-[#5B7C8D] text-white'
: 'border-transparent text-[#666] hover:text-white'
}`}
>
@@ -347,7 +347,7 @@ export default function ShowCalendarPage() {
<div className="max-w-7xl mx-auto px-4 py-6">
{loadingData ? (
<div className="flex items-center justify-center py-20">
<div className="w-8 h-8 border-2 border-[#3b82f6] border-t-transparent rounded-full animate-spin" />
<div className="w-8 h-8 border-2 border-[#5B7C8D] border-t-transparent rounded-full animate-spin" />
</div>
) : (
<>
@@ -383,7 +383,7 @@ export default function ShowCalendarPage() {
<span>Engine: {formatDate(event.story_engine_start_date)} {formatDate(event.story_engine_end_date)}</span>
{event.official_site && (
<a href={`https://${event.official_site}`} target="_blank" rel="noopener noreferrer"
className="text-[#3b82f6] hover:underline">{event.official_site}</a>
className="text-[#5B7C8D] hover:underline">{event.official_site}</a>
)}
</div>
<div className="flex items-center gap-3 mt-2 text-xs text-[#555]">
@@ -440,7 +440,7 @@ export default function ShowCalendarPage() {
onClick={() => setQueueStatus(s)}
className={`px-3 py-1 rounded text-xs font-medium transition-colors ${
queueStatus === s
? 'bg-[#3b82f6] text-white'
? 'bg-[#5B7C8D] text-white'
: 'bg-[#1a1a1a] text-[#888] hover:text-white border border-[#333]'
}`}
>
@@ -779,7 +779,7 @@ export default function ShowCalendarPage() {
<button
type="submit"
disabled={actionLoading === 'save-event'}
className="flex-1 py-2 bg-[#3b82f6] hover:bg-blue-500 text-white text-sm rounded-lg transition-colors disabled:opacity-50"
className="flex-1 py-2 bg-[#5B7C8D] hover:bg-blue-500 text-white text-sm rounded-lg transition-colors disabled:opacity-50"
>
{actionLoading === 'save-event' ? 'Saving...' : 'Save Event'}
</button>
@@ -857,7 +857,7 @@ export default function ShowCalendarPage() {
<button
type="submit"
disabled={actionLoading === 'generate'}
className="flex-1 py-2 bg-[#3b82f6] hover:bg-blue-500 text-white text-sm rounded-lg transition-colors disabled:opacity-50"
className="flex-1 py-2 bg-[#5B7C8D] hover:bg-blue-500 text-white text-sm rounded-lg transition-colors disabled:opacity-50"
>
{actionLoading === 'generate' ? 'Generating...' : 'Generate Story'}
</button>