Refresh app theme and update dependencies

This commit is contained in:
2026-03-08 11:09:36 -04:00
parent 2f7933f4a3
commit c3f3c3d5a9
19 changed files with 502 additions and 477 deletions

View File

@@ -89,11 +89,11 @@ const FINANCIAL_VALUE_SCALE_OPTIONS: Array<{ value: NumberScaleUnit; label: stri
{ value: 'billions', label: 'Billions (B)' }
];
const CHART_TEXT = '#e8fff8';
const CHART_MUTED = '#b4ced9';
const CHART_GRID = 'rgba(126, 217, 255, 0.24)';
const CHART_TOOLTIP_BG = 'rgba(6, 17, 24, 0.95)';
const CHART_TOOLTIP_BORDER = 'rgba(123, 255, 217, 0.45)';
const CHART_TEXT = '#f3f5f7';
const CHART_MUTED = '#a1a9b3';
const CHART_GRID = 'rgba(196, 202, 211, 0.18)';
const CHART_TOOLTIP_BG = 'rgba(31, 34, 39, 0.96)';
const CHART_TOOLTIP_BORDER = 'rgba(220, 226, 234, 0.24)';
function formatShortDate(value: string) {
return format(new Date(value), 'MMM yyyy');
@@ -633,9 +633,9 @@ function AnalysisPageContent() {
}}
labelStyle={{ color: CHART_TEXT }}
itemStyle={{ color: CHART_TEXT }}
cursor={{ stroke: 'rgba(104, 255, 213, 0.35)', strokeWidth: 1 }}
cursor={{ stroke: 'rgba(220, 226, 234, 0.28)', strokeWidth: 1 }}
/>
<Line type="monotone" dataKey="close" stroke="#68ffd5" strokeWidth={2} dot={false} />
<Line type="monotone" dataKey="close" stroke="#d9dee5" strokeWidth={2} dot={false} />
</LineChart>
</ResponsiveContainer>
</div>

View File

@@ -128,7 +128,7 @@ function SignInPageContent() {
</div>
{error ? <p className="text-sm text-[#ff9f9f]">{error}</p> : null}
{message ? <p className="text-sm text-[#9fffcf]">{message}</p> : null}
{message ? <p className="text-sm text-[color:var(--accent)]">{message}</p> : null}
<Button type="submit" className="w-full" disabled={busyAction !== null}>
{busyAction === 'password' ? 'Signing in...' : 'Sign in with password'}

View File

@@ -91,10 +91,10 @@ const DISPLAY_MODE_OPTIONS: FinancialControlOption[] = [
{ value: 'faithful', label: 'Filing-faithful' }
];
const CHART_MUTED = '#b4ced9';
const CHART_GRID = 'rgba(126, 217, 255, 0.24)';
const CHART_TOOLTIP_BG = 'rgba(6, 17, 24, 0.95)';
const CHART_TOOLTIP_BORDER = 'rgba(123, 255, 217, 0.45)';
const CHART_MUTED = '#a1a9b3';
const CHART_GRID = 'rgba(196, 202, 211, 0.18)';
const CHART_TOOLTIP_BG = 'rgba(31, 34, 39, 0.96)';
const CHART_TOOLTIP_BORDER = 'rgba(220, 226, 234, 0.24)';
function formatLongDate(value: string) {
const parsed = new Date(value);
@@ -714,7 +714,7 @@ function FinancialsPageContent() {
type="monotone"
dataKey={series.key}
name={series.label}
stroke={['#68ffd5', '#5fd3ff', '#ffd08a', '#ff8a8a'][index % 4]}
stroke={['#d9dee5', '#c1c8d1', '#aab2bc', '#8f98a3'][index % 4]}
strokeWidth={2}
dot={false}
/>

View File

@@ -3,20 +3,21 @@
:root {
--font-display: "Avenir Next", "Segoe UI", "Helvetica Neue", Arial, sans-serif;
--font-mono: "Menlo", "SFMono-Regular", "Consolas", "Liberation Mono", monospace;
--bg-0: #05080d;
--bg-1: #08121a;
--bg-2: #0b1f28;
--panel: rgba(6, 17, 24, 0.8);
--panel-soft: rgba(7, 22, 31, 0.62);
--panel-bright: rgba(10, 33, 45, 0.9);
--line-weak: rgba(126, 217, 255, 0.22);
--line-strong: rgba(123, 255, 217, 0.75);
--accent: #68ffd5;
--accent-strong: #8cffeb;
--danger: #ff7070;
--danger-soft: rgba(122, 33, 33, 0.44);
--terminal-bright: #e8fff8;
--terminal-muted: #94b9c5;
--bg-0: #121417;
--bg-1: #181b20;
--bg-2: #21252b;
--panel: rgba(28, 31, 36, 0.84);
--panel-soft: rgba(36, 39, 45, 0.72);
--panel-bright: rgba(49, 53, 60, 0.94);
--line-weak: rgba(196, 202, 211, 0.18);
--line-strong: rgba(220, 226, 234, 0.34);
--accent: #d9dee5;
--accent-strong: #f4f7fb;
--danger: #ff8e8e;
--danger-soft: rgba(111, 46, 46, 0.42);
--terminal-bright: #f3f5f7;
--terminal-muted: #a1a9b3;
--focus-ring: rgba(229, 231, 235, 0.14);
}
* {
@@ -34,13 +35,13 @@ html {
}
[data-sonner-toaster] {
--normal-bg: rgba(7, 22, 31, 0.96);
--normal-text: #e8fff8;
--normal-border: rgba(123, 255, 217, 0.45);
--success-bg: rgba(8, 58, 42, 0.96);
--success-text: #d0ffe9;
--success-border: rgba(104, 255, 213, 0.7);
--error-bg: rgba(67, 22, 22, 0.96);
--normal-bg: rgba(31, 34, 39, 0.96);
--normal-text: #f3f5f7;
--normal-border: rgba(220, 226, 234, 0.24);
--success-bg: rgba(34, 44, 39, 0.96);
--success-text: #e4efe7;
--success-border: rgba(163, 191, 171, 0.55);
--error-bg: rgba(67, 27, 27, 0.96);
--error-text: #ffd6d6;
--error-border: rgba(255, 112, 112, 0.8);
}
@@ -56,8 +57,8 @@ body {
font-family: var(--font-display), sans-serif;
color: var(--terminal-bright);
background:
radial-gradient(circle at 18% -10%, rgba(126, 217, 255, 0.25), transparent 35%),
radial-gradient(circle at 84% 0%, rgba(104, 255, 213, 0.2), transparent 30%),
radial-gradient(circle at 18% -10%, rgba(170, 178, 188, 0.16), transparent 35%),
radial-gradient(circle at 84% 0%, rgba(121, 128, 138, 0.14), transparent 30%),
linear-gradient(140deg, var(--bg-0), var(--bg-1) 50%, var(--bg-2));
}
@@ -72,8 +73,8 @@ body {
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(126, 217, 255, 0.08) 1px, transparent 1px),
linear-gradient(90deg, rgba(126, 217, 255, 0.07) 1px, transparent 1px);
linear-gradient(rgba(204, 210, 218, 0.06) 1px, transparent 1px),
linear-gradient(90deg, rgba(204, 210, 218, 0.05) 1px, transparent 1px);
background-size: 34px 34px;
mask-image: radial-gradient(ellipse at center, black 20%, transparent 75%);
pointer-events: none;
@@ -83,8 +84,8 @@ body {
position: absolute;
inset: 0;
pointer-events: none;
opacity: 0.3;
background-image: radial-gradient(rgba(160, 255, 227, 0.15) 0.7px, transparent 0.7px);
opacity: 0.24;
background-image: radial-gradient(rgba(220, 226, 234, 0.1) 0.7px, transparent 0.7px);
background-size: 4px 4px;
}
@@ -127,7 +128,7 @@ textarea {
}
.data-table tbody tr:hover {
background-color: rgba(17, 47, 61, 0.45);
background-color: rgba(63, 68, 76, 0.32);
}
@media (prefers-reduced-motion: no-preference) {
@@ -157,8 +158,8 @@ textarea {
@media (max-width: 640px) {
body {
background:
radial-gradient(circle at 24% -4%, rgba(126, 217, 255, 0.2), transparent 36%),
radial-gradient(circle at 82% 2%, rgba(104, 255, 213, 0.16), transparent 30%),
radial-gradient(circle at 24% -4%, rgba(170, 178, 188, 0.14), transparent 36%),
radial-gradient(circle at 82% 2%, rgba(121, 128, 138, 0.12), transparent 30%),
linear-gradient(155deg, var(--bg-0), var(--bg-1) 54%, var(--bg-2));
}

View File

@@ -49,11 +49,11 @@ import type {
import { companyFinancialStatementsQueryOptions } from '@/lib/query/options';
import { cn } from '@/lib/utils';
const CHART_COLORS = ['#68ffd5', '#5fd3ff', '#ffd08a', '#ff8a8a', '#c39bff'] as const;
const CHART_MUTED = '#b4ced9';
const CHART_GRID = 'rgba(126, 217, 255, 0.24)';
const CHART_TOOLTIP_BG = 'rgba(6, 17, 24, 0.95)';
const CHART_TOOLTIP_BORDER = 'rgba(123, 255, 217, 0.45)';
const CHART_COLORS = ['#d9dee5', '#c7cdd5', '#b5bcc5', '#a4acb6', '#939ca7'] as const;
const CHART_MUTED = '#a1a9b3';
const CHART_GRID = 'rgba(196, 202, 211, 0.18)';
const CHART_TOOLTIP_BG = 'rgba(31, 34, 39, 0.96)';
const CHART_TOOLTIP_BORDER = 'rgba(220, 226, 234, 0.24)';
type TooltipEntry = {
dataKey?: string | number;
@@ -215,7 +215,7 @@ function ComparisonTooltip(props: {
</p>
<div className="mt-3 space-y-2">
{entries.map((entry) => (
<div key={entry.ticker} className="rounded-lg border border-[color:var(--line-weak)] bg-[color:rgba(4,16,24,0.72)] px-2 py-2">
<div key={entry.ticker} className="rounded-lg border border-[color:var(--line-weak)] bg-[color:rgba(45,49,55,0.72)] px-2 py-2">
<div className="flex items-center justify-between gap-3">
<div className="flex items-center gap-2">
<span className="size-2 rounded-full" style={{ backgroundColor: entry.color }} aria-hidden="true" />
@@ -495,10 +495,10 @@ function GraphingPageContent() {
aria-label="Metric selector"
value={graphState.metric}
onChange={(event) => replaceGraphState({ metric: event.target.value })}
className="w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2.5 text-sm text-[color:var(--terminal-bright)] outline-none transition focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_rgba(0,255,180,0.14)]"
className="w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2.5 text-sm text-[color:var(--terminal-bright)] outline-none transition focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_var(--focus-ring)]"
>
{metricOptions.map((option) => (
<option key={option.key} value={option.key} className="bg-[#07161f]">
<option key={option.key} value={option.key} className="bg-[#1f2227]">
{option.label}
</option>
))}

View File

@@ -11,7 +11,7 @@ export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
viewportFit: 'cover',
themeColor: '#05080d'
themeColor: '#121417'
};
export default function RootLayout({ children }: { children: React.ReactNode }) {

View File

@@ -35,12 +35,12 @@ type FormState = {
currentPrice: string;
};
const CHART_COLORS = ['#6effd8', '#5fd3ff', '#66ffa1', '#8dbbff', '#f4f88f', '#ff9c9c'];
const CHART_TEXT = '#e8fff8';
const CHART_MUTED = '#b4ced9';
const CHART_GRID = 'rgba(126, 217, 255, 0.24)';
const CHART_TOOLTIP_BG = 'rgba(6, 17, 24, 0.95)';
const CHART_TOOLTIP_BORDER = 'rgba(123, 255, 217, 0.45)';
const CHART_COLORS = ['#d9dee5', '#c7cdd5', '#b5bcc5', '#a4acb6', '#939ca7', '#828b97'];
const CHART_TEXT = '#f3f5f7';
const CHART_MUTED = '#a1a9b3';
const CHART_GRID = 'rgba(196, 202, 211, 0.18)';
const CHART_TOOLTIP_BG = 'rgba(31, 34, 39, 0.96)';
const CHART_TOOLTIP_BORDER = 'rgba(220, 226, 234, 0.24)';
const EMPTY_SUMMARY: PortfolioSummary = {
positions: 0,
@@ -283,9 +283,9 @@ export default function PortfolioPage() {
}}
labelStyle={{ color: CHART_TEXT }}
itemStyle={{ color: CHART_TEXT }}
cursor={{ fill: 'rgba(104, 255, 213, 0.08)' }}
cursor={{ fill: 'rgba(220, 226, 234, 0.08)' }}
/>
<Bar dataKey="value" fill="#68ffd5" radius={[4, 4, 0, 0]} />
<Bar dataKey="value" fill="#d9dee5" radius={[4, 4, 0, 0]} />
</BarChart>
</ResponsiveContainer>
</div>

View File

@@ -444,7 +444,7 @@ function ResearchPageContent() {
{ticker && workspace ? (
<>
<Panel className="overflow-hidden border-[color:var(--line-strong)] bg-[linear-gradient(135deg,rgba(6,16,20,0.96),rgba(6,16,20,0.82)_45%,rgba(8,28,30,0.9))]">
<Panel className="overflow-hidden border-[color:var(--line-strong)] bg-[linear-gradient(135deg,rgba(29,31,36,0.97),rgba(34,37,42,0.9)_45%,rgba(42,46,52,0.94))]">
<div className="grid gap-5 lg:grid-cols-[1.6fr_1fr]">
<div>
<p className="text-xs uppercase tracking-[0.22em] text-[color:var(--accent)]">Buy-Side Research Workspace</p>
@@ -456,14 +456,14 @@ function ResearchPageContent() {
</p>
<div className="mt-4 flex flex-wrap gap-2">
{(workspace.coverage?.tags ?? []).map((tag) => (
<span key={tag} className="rounded-full border border-[color:var(--line-weak)] bg-[rgba(255,255,255,0.02)] px-3 py-1 text-xs uppercase tracking-[0.14em] text-[color:var(--terminal-muted)]">
<span key={tag} className="rounded-full border border-[color:var(--line-weak)] bg-[rgba(255,255,255,0.03)] px-3 py-1 text-xs uppercase tracking-[0.14em] text-[color:var(--terminal-muted)]">
{tag}
</span>
))}
</div>
</div>
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-1">
<div className="rounded-2xl border border-[color:var(--line-weak)] bg-[rgba(255,255,255,0.03)] p-4">
<div className="rounded-2xl border border-[color:var(--line-weak)] bg-[rgba(255,255,255,0.04)] p-4">
<p className="text-xs uppercase tracking-[0.14em] text-[color:var(--terminal-muted)]">Memo posture</p>
<p className="mt-2 text-lg font-semibold text-[color:var(--terminal-bright)]">
{workspace.memo?.rating ? workspace.memo.rating.replace('_', ' ') : 'Unrated'}
@@ -472,7 +472,7 @@ function ResearchPageContent() {
Conviction: {workspace.memo?.conviction ?? 'unset'}
</p>
</div>
<div className="rounded-2xl border border-[color:var(--line-weak)] bg-[rgba(255,255,255,0.03)] p-4">
<div className="rounded-2xl border border-[color:var(--line-weak)] bg-[rgba(255,255,255,0.04)] p-4">
<p className="text-xs uppercase tracking-[0.14em] text-[color:var(--terminal-muted)]">Research depth</p>
<p className="mt-2 text-lg font-semibold text-[color:var(--terminal-bright)]">{workspace.library.length} artifacts</p>
<p className="mt-1 text-sm text-[color:var(--terminal-muted)]">{memoEvidenceCount} evidence links in the packet</p>
@@ -542,7 +542,7 @@ function ResearchPageContent() {
<input type="checkbox" checked={linkedOnly} onChange={(event) => setLinkedOnly(event.target.checked)} />
Show memo-linked evidence only
</label>
<div className="rounded-2xl border border-[color:var(--line-weak)] bg-[rgba(255,255,255,0.02)] p-4">
<div className="rounded-2xl border border-[color:var(--line-weak)] bg-[rgba(255,255,255,0.03)] p-4">
<div className="flex items-center gap-2 text-xs uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">
<ShieldCheck className="size-4 text-[color:var(--accent)]" />
Access Model
@@ -566,7 +566,7 @@ function ResearchPageContent() {
value={noteForm.bodyMarkdown}
onChange={(event) => setNoteForm((current) => ({ ...current, bodyMarkdown: event.target.value }))}
placeholder="Write the actual research note, variant view, or diligence conclusion..."
className="min-h-[160px] w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] outline-none transition placeholder:text-[color:var(--terminal-muted)] focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_rgba(0,255,180,0.14)]"
className="min-h-[160px] w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] outline-none transition placeholder:text-[color:var(--terminal-muted)] focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_var(--focus-ring)]"
/>
<Input aria-label="Research note tags" value={noteForm.tags} onChange={(event) => setNoteForm((current) => ({ ...current, tags: event.target.value }))} placeholder="Tags, comma-separated" />
<div className="flex flex-wrap gap-2">
@@ -746,7 +746,7 @@ function ResearchPageContent() {
aria-label={`Memo ${section.label}`}
value={memoForm[field]}
onChange={(event) => setMemoForm((current) => ({ ...current, [field]: event.target.value }))}
className="min-h-[108px] w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] outline-none transition placeholder:text-[color:var(--terminal-muted)] focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_rgba(0,255,180,0.14)]"
className="min-h-[108px] w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] outline-none transition placeholder:text-[color:var(--terminal-muted)] focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_var(--focus-ring)]"
placeholder={`Write ${section.label.toLowerCase()}...`}
/>
</div>

View File

@@ -58,7 +58,7 @@ const EMPTY_FORM: FormState = {
tags: ''
};
const SELECT_CLASS_NAME = 'min-h-11 w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] outline-none transition focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_rgba(0,255,180,0.14)]';
const SELECT_CLASS_NAME = 'min-h-11 w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] outline-none transition focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_var(--focus-ring)]';
function parseTagsInput(input: string) {
const unique = new Set<string>();

792
bun.lock

File diff suppressed because it is too large Load Diff

View File

@@ -154,10 +154,10 @@ export function TaskDetailModal({ isOpen, taskId, onClose }: TaskDetailModalProp
</div>
<div className="flex items-center gap-2">
<span className={item.state === 'active'
? 'text-[11px] uppercase tracking-[0.12em] text-[#9fffcf]'
? 'text-[11px] uppercase tracking-[0.12em] text-[color:var(--accent)]'
: item.state === 'completed'
? 'text-[11px] uppercase tracking-[0.12em] text-[color:var(--terminal-muted)]'
: 'text-[11px] uppercase tracking-[0.12em] text-[#6f8791]'}
: 'text-[11px] uppercase tracking-[0.12em] text-[#7f8994]'}
>
{item.state}
</span>

View File

@@ -50,7 +50,7 @@ export function TaskNotificationsTrigger({
>
{unreadCount > 0 ? <BellRing className="size-4" /> : <Bell className="size-4" />}
{unreadCount > 0 ? (
<span className="absolute -right-1.5 -top-1.5 inline-flex min-w-[1.15rem] items-center justify-center rounded-full bg-[color:var(--accent)] px-1 text-[10px] font-semibold text-[#00241d]">
<span className="absolute -right-1.5 -top-1.5 inline-flex min-w-[1.15rem] items-center justify-center rounded-full bg-[color:var(--accent)] px-1 text-[10px] font-semibold text-[#16181c]">
{unreadCount > 99 ? '99+' : unreadCount}
</span>
) : null}

View File

@@ -448,7 +448,7 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
<div className="noise-layer" aria-hidden="true" />
<div className="relative z-10 mx-auto flex min-h-screen w-full max-w-[1300px] gap-4 px-3 pb-10 pt-4 sm:px-4 sm:pb-12 sm:pt-6 md:px-8 lg:gap-6">
<aside className="hidden w-72 shrink-0 flex-col gap-6 rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] p-5 shadow-[0_0_0_1px_rgba(0,255,180,0.06),0_20px_60px_rgba(1,4,10,0.55)] lg:flex">
<aside className="hidden w-72 shrink-0 flex-col gap-6 rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] p-5 shadow-[0_0_0_1px_rgba(255,255,255,0.04),0_20px_60px_rgba(0,0,0,0.42)] lg:flex">
<div>
<p className="terminal-caption text-xs uppercase tracking-[0.25em] text-[color:var(--terminal-muted)]">Fiscal Clone</p>
<h1 className="mt-2 text-2xl font-semibold text-[color:var(--terminal-bright)]">Neon Desk</h1>
@@ -474,7 +474,7 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
className={cn(
'flex items-center gap-3 rounded-xl border px-3 py-2 text-sm transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--line-strong)] focus-visible:ring-offset-2 focus-visible:ring-offset-transparent',
item.active
? 'border-[color:var(--line-strong)] bg-[color:var(--panel-bright)] text-[color:var(--terminal-bright)] shadow-[0_0_18px_rgba(0,255,180,0.16)]'
? 'border-[color:var(--line-strong)] bg-[color:var(--panel-bright)] text-[color:var(--terminal-bright)] shadow-[0_0_18px_rgba(255,255,255,0.06)]'
: 'border-transparent text-[color:var(--terminal-muted)] hover:border-[color:var(--line-weak)] hover:bg-[color:var(--panel-soft)] hover:text-[color:var(--terminal-bright)]'
)}
>
@@ -502,7 +502,7 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
</aside>
<div className="min-w-0 flex-1 pb-24 lg:pb-0">
<header className="relative mb-4 rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] px-4 py-4 pr-16 shadow-[0_0_0_1px_rgba(0,255,180,0.05),0_14px_40px_rgba(1,4,10,0.5)] sm:px-6 sm:py-5 sm:pr-20">
<header className="relative mb-4 rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] px-4 py-4 pr-16 shadow-[0_0_0_1px_rgba(255,255,255,0.04),0_14px_40px_rgba(0,0,0,0.4)] sm:px-6 sm:py-5 sm:pr-20">
<div className="absolute right-4 top-4 z-10 sm:right-5 sm:top-5">
<TaskNotificationsTrigger
unreadCount={notifications.unreadCount}
@@ -573,7 +573,7 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
</div>
<nav
className="fixed inset-x-0 bottom-0 z-40 border-t border-[color:var(--line-weak)] bg-[color:rgba(5,14,22,0.96)] px-2 py-2 backdrop-blur lg:hidden"
className="fixed inset-x-0 bottom-0 z-40 border-t border-[color:var(--line-weak)] bg-[color:rgba(24,27,32,0.96)] px-2 py-2 backdrop-blur lg:hidden"
aria-label="Mobile primary"
>
<div className="mx-auto flex w-full max-w-[1300px] items-center justify-between gap-1 px-1" style={{ paddingBottom: 'calc(env(safe-area-inset-bottom) * 0.5)' }}>

View File

@@ -7,7 +7,7 @@ type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
};
const variantMap: Record<ButtonVariant, string> = {
primary: 'border-[color:var(--line-strong)] bg-[color:var(--accent)] text-[#001515] hover:bg-[color:var(--accent-strong)]',
primary: 'border-[color:var(--line-strong)] bg-[color:var(--accent)] text-[#16181c] hover:bg-[color:var(--accent-strong)]',
secondary: 'border-[color:var(--line-weak)] bg-[color:var(--panel-bright)] text-[color:var(--terminal-bright)] hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel)]',
ghost: 'border-[color:var(--line-weak)] bg-transparent text-[color:var(--terminal-bright)] hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel-soft)]',
danger: 'border-[color:var(--danger)] bg-[color:var(--danger-soft)] text-[#ffc9c9] hover:bg-[color:var(--danger)] hover:text-[#1e0d0d]'

View File

@@ -6,7 +6,7 @@ export function Input({ className, ...props }: InputProps) {
return (
<input
className={cn(
'min-h-11 w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] outline-none transition placeholder:text-[color:var(--terminal-muted)] focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_rgba(0,255,180,0.14)]',
'min-h-11 w-full rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2 text-sm text-[color:var(--terminal-bright)] outline-none transition placeholder:text-[color:var(--terminal-muted)] focus:border-[color:var(--line-strong)] focus:shadow-[0_0_0_3px_var(--focus-ring)]',
className
)}
{...props}

View File

@@ -12,7 +12,7 @@ export function Panel({ title, subtitle, actions, children, className }: PanelPr
return (
<section
className={cn(
'min-w-0 rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] p-4 shadow-[0_0_0_1px_rgba(0,255,180,0.03),0_12px_30px_rgba(1,4,10,0.45)] sm:p-5',
'min-w-0 rounded-2xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] p-4 shadow-[0_0_0_1px_rgba(255,255,255,0.03),0_12px_30px_rgba(0,0,0,0.38)] sm:p-5',
className
)}
>

View File

@@ -6,9 +6,9 @@ type StatusPillProps = {
};
const classes: Record<TaskStatus, string> = {
queued: 'border-[#33587a] bg-[#0a2c3f] text-[#7ecaf5]',
running: 'border-[#4f7a33] bg-[#0f311d] text-[#99f085]',
completed: 'border-[#1a7a53] bg-[#083a2a] text-[#8bf7cb]',
queued: 'border-[#525861] bg-[#262a30] text-[#c0c7d0]',
running: 'border-[#686e77] bg-[#2d3137] text-[#d8dde4]',
completed: 'border-[#7b828c] bg-[#353a42] text-[#eef2f6]',
failed: 'border-[#8f3d3d] bg-[#431616] text-[#ff9c9c]'
};

2
next-env.d.ts vendored
View File

@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@@ -30,10 +30,10 @@
"@libsql/client": "^0.17.0",
"@tailwindcss/postcss": "^4.2.1",
"@tanstack/react-query": "^5.90.21",
"@workflow/world-postgres": "^4.1.0-beta.34",
"ai": "^6.0.104",
"better-auth": "^1.4.19",
"cheerio": "^1.1.2",
"@workflow/world-postgres": "^4.1.0-beta.42",
"ai": "^6.0.116",
"better-auth": "^1.5.4",
"cheerio": "^1.2.0",
"clsx": "^2.1.1",
"date-fns": "^4.1.0",
"drizzle-orm": "^0.41.0",
@@ -42,21 +42,21 @@
"next": "^16.1.6",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"recharts": "^3.7.0",
"recharts": "^3.8.0",
"sonner": "^2.0.7",
"sqlite-vec": "^0.1.7-alpha.2",
"workflow": "^4.1.0-beta.60",
"workflow": "^4.1.0-beta.63",
"zhipu-ai-provider": "^0.2.2"
},
"devDependencies": {
"@playwright/test": "^1.56.1",
"@types/node": "^25.3.0",
"@playwright/test": "^1.58.2",
"@types/node": "^25.3.5",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"autoprefixer": "^10.4.24",
"autoprefixer": "^10.4.27",
"bun-types": "^1.3.10",
"drizzle-kit": "^0.31.4",
"postcss": "^8.5.6",
"drizzle-kit": "^0.31.9",
"postcss": "^8.5.8",
"tailwindcss": "^4.2.1",
"typescript": "^5.9.3"
}