Merge branch 't3code/clean-flat-ui-layout'

This commit is contained in:
2026-03-08 22:48:45 -04:00
16 changed files with 106 additions and 83 deletions

View File

@@ -456,7 +456,7 @@ function AnalysisPageContent() {
</Panel>
{error ? (
<Panel>
<Panel variant="surface">
<p className="text-sm text-[#ffb5b5]">{error}</p>
</Panel>
) : null}
@@ -597,7 +597,7 @@ function AnalysisPageContent() {
</div>
<div className="grid grid-cols-1 gap-6 xl:grid-cols-2">
<Panel title="Price History" subtitle="Weekly close over the last year.">
<Panel title="Price History" subtitle="Weekly close over the last year." variant="surface">
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading price history...</p>
) : priceSeries.length === 0 ? (
@@ -625,7 +625,7 @@ function AnalysisPageContent() {
tickFormatter={(value: number) => `$${value.toFixed(0)}`}
/>
<Tooltip
formatter={(value: number | string | undefined) => formatCurrency(value)}
formatter={(value) => formatCurrency(Array.isArray(value) ? value[0] : value)}
contentStyle={{
backgroundColor: CHART_TOOLTIP_BG,
border: `1px solid ${CHART_TOOLTIP_BORDER}`,
@@ -645,6 +645,7 @@ function AnalysisPageContent() {
<Panel
title="Financial Table"
subtitle={`Quarter-end (10-Q) and fiscal-year-end (10-K) snapshots for revenue, net income, assets, and margin. Values shown in ${selectedFinancialScaleLabel}.`}
variant="surface"
actions={(
<div className="flex flex-col items-end gap-2">
<div className="flex flex-wrap justify-end gap-2">
@@ -712,7 +713,7 @@ function AnalysisPageContent() {
))}
</div>
<div className="hidden overflow-x-auto lg:block">
<div className="data-table-wrap hidden lg:block">
<table className="data-table min-w-[820px]">
<thead>
<tr>
@@ -750,6 +751,7 @@ function AnalysisPageContent() {
<Panel
title="Filings"
subtitle={`${periodEndFilings.length} quarter-end and fiscal-year-end SEC records loaded. Values shown in ${selectedFinancialScaleLabel}.`}
variant="surface"
>
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading filings...</p>
@@ -789,7 +791,7 @@ function AnalysisPageContent() {
))}
</div>
<div className="hidden overflow-x-auto lg:block">
<div className="data-table-wrap hidden lg:block">
<table className="data-table min-w-[860px]">
<thead>
<tr>
@@ -829,7 +831,7 @@ function AnalysisPageContent() {
)}
</Panel>
<Panel title="AI Reports" subtitle="Generated filing analyses for this company.">
<Panel title="AI Reports" subtitle="Generated filing analyses for this company." variant="surface">
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading AI reports...</p>
) : !analysis || analysis.recentAiReports.length === 0 ? (
@@ -901,7 +903,7 @@ function AnalysisPageContent() {
</div>
</Panel>
<Panel title="Recent Research Feed" subtitle={`Previewing the latest ${Math.min(journalEntries.length, 4)} research entries for ${activeTicker}.`}>
<Panel title="Recent Research Feed" subtitle={`Previewing the latest ${Math.min(journalEntries.length, 4)} research entries for ${activeTicker}.`} variant="surface">
{journalLoading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading research entries...</p>
) : journalEntries.length === 0 ? (

View File

@@ -354,6 +354,7 @@ function FilingsPageContent() {
<Panel
title="Filing Ledger"
subtitle={`${filings.length} records loaded${searchTicker ? ` for ${searchTicker}` : ''}. Values shown in ${selectedFinancialScaleLabel}.`}
variant="surface"
actions={(
<div className="flex w-full flex-wrap justify-start gap-2 sm:justify-end">
{FINANCIAL_VALUE_SCALE_OPTIONS.map((option) => (
@@ -454,7 +455,7 @@ function FilingsPageContent() {
})}
</div>
<div className="hidden overflow-x-auto lg:block">
<div className="data-table-wrap hidden lg:block">
<table className="data-table w-full">
<thead>
<tr>

View File

@@ -654,7 +654,7 @@ function FinancialsPageContent() {
</Panel>
{error ? (
<Panel>
<Panel variant="surface">
<p className="text-sm text-[#ffb5b5]">{error}</p>
</Panel>
) : null}
@@ -680,7 +680,7 @@ function FinancialsPageContent() {
</div>
</Panel>
<Panel title="Trend Chart" subtitle="Default trend series for the selected surface.">
<Panel title="Trend Chart" subtitle="Default trend series for the selected surface." variant="surface">
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading trend chart...</p>
) : chartData.length === 0 || trendSeries.length === 0 ? (
@@ -725,7 +725,7 @@ function FinancialsPageContent() {
)}
</Panel>
<Panel title="Surface Matrix" subtitle="Standardized statements, ratios, and KPIs render in one shared matrix.">
<Panel title="Surface Matrix" subtitle="Standardized statements, ratios, and KPIs render in one shared matrix." variant="surface">
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading financial matrix...</p>
) : surfaceKind === 'adjusted' || surfaceKind === 'custom_metrics' ? (
@@ -736,7 +736,7 @@ function FinancialsPageContent() {
) : periods.length === 0 || filteredRows.length === 0 ? (
<p className="text-sm text-[color:var(--terminal-muted)]">No rows available for the selected filters yet.</p>
) : (
<div className="overflow-x-auto">
<div className="data-table-wrap">
<table className="data-table min-w-[980px]">
<thead>
<tr>
@@ -804,7 +804,7 @@ function FinancialsPageContent() {
)}
</Panel>
<Panel title="Row Details" subtitle="Inspect provenance, formulas, and dimensional evidence for the selected row.">
<Panel title="Row Details" subtitle="Inspect provenance, formulas, and dimensional evidence for the selected row." variant="surface">
{!selectedRow ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Select a row to inspect details.</p>
) : (
@@ -854,7 +854,7 @@ function FinancialsPageContent() {
) : dimensionRows.length === 0 ? (
<p className="text-sm text-[color:var(--terminal-muted)]">No dimensional facts were returned for the selected row.</p>
) : (
<div className="overflow-x-auto">
<div className="data-table-wrap">
<table className="data-table min-w-[760px]">
<thead>
<tr>
@@ -882,7 +882,7 @@ function FinancialsPageContent() {
</Panel>
{(surfaceKind === 'income_statement' || surfaceKind === 'balance_sheet' || surfaceKind === 'cash_flow_statement') && financials ? (
<Panel title="Metric Validation" subtitle="Validation remains limited to statement-derived taxonomy metrics in v1.">
<Panel title="Metric Validation" subtitle="Validation remains limited to statement-derived taxonomy metrics in v1." variant="surface">
<div className="mb-3 flex items-center gap-2 text-sm text-[color:var(--terminal-muted)]">
<AlertTriangle className="size-4" />
<span>Overall status: {financials.metrics.validation?.status ?? 'not_run'}</span>
@@ -890,7 +890,7 @@ function FinancialsPageContent() {
{(financials.metrics.validation?.checks.length ?? 0) === 0 ? (
<p className="text-sm text-[color:var(--terminal-muted)]">No validation checks available yet.</p>
) : (
<div className="overflow-x-auto">
<div className="data-table-wrap">
<table className="data-table min-w-[760px]">
<thead>
<tr>

View File

@@ -111,12 +111,26 @@ textarea {
border-collapse: collapse;
}
.data-surface {
border: 1px solid var(--line-weak);
border-radius: 1rem;
background: linear-gradient(180deg, rgba(40, 43, 49, 0.92), rgba(24, 27, 32, 0.78));
}
.data-table-wrap {
overflow-x: auto;
border: 1px solid var(--line-weak);
border-radius: 1rem;
background: linear-gradient(180deg, rgba(34, 37, 42, 0.9), rgba(20, 23, 27, 0.76));
}
.data-table th,
.data-table td {
border-bottom: 1px solid var(--line-weak);
padding: 0.75rem 0.65rem;
padding: 0.8rem 0.8rem;
text-align: left;
font-size: 0.875rem;
vertical-align: top;
}
.data-table th {

View File

@@ -454,7 +454,7 @@ function GraphingPageContent() {
</form>
</Panel>
<Panel title="Chart Controls" subtitle="Surface, metric, cadence, chart style, and scale stay in the URL for deep-linking.">
<Panel title="Chart Controls" subtitle="Surface, metric, cadence, chart style, and scale stay in the URL for deep-linking." variant="surface">
<div className="grid gap-5 lg:grid-cols-[1.2fr_1fr]">
<div className="space-y-5">
<ControlSection
@@ -515,7 +515,7 @@ function GraphingPageContent() {
</div>
</Panel>
<Panel title="Comparison Chart" subtitle="One metric, multiple companies, aligned by actual reported dates.">
<Panel title="Comparison Chart" subtitle="One metric, multiple companies, aligned by actual reported dates." variant="surface">
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading comparison chart...</p>
) : !selectedMetric || !comparison.hasAnyData ? (
@@ -607,8 +607,8 @@ function GraphingPageContent() {
)}
</Panel>
<Panel title="Latest Values" subtitle="Most recent reported point per company, plus the prior point and one-step change.">
<div className="overflow-x-auto">
<Panel title="Latest Values" subtitle="Most recent reported point per company, plus the prior point and one-step change." variant="surface">
<div className="data-table-wrap">
<table className="data-table min-w-[920px]">
<thead>
<tr>

View File

@@ -151,7 +151,7 @@ export default function CommandCenterPage() {
actions={headerActions}
>
{error ? (
<Panel>
<Panel variant="surface">
<p className="text-sm text-[#ffb5b5]">{error}</p>
</Panel>
) : null}
@@ -169,7 +169,7 @@ export default function CommandCenterPage() {
</div>
<div className="grid grid-cols-1 gap-6 xl:grid-cols-3">
<Panel title="Recent Tasks" subtitle="Durable jobs from queue processor" className="xl:col-span-1">
<Panel title="Recent Tasks" subtitle="Durable jobs from queue processor" className="xl:col-span-1" variant="surface">
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading tasks...</p>
) : (
@@ -177,7 +177,7 @@ export default function CommandCenterPage() {
)}
</Panel>
<Panel title="AI Brief" subtitle="Latest portfolio insight from AI SDK (Zhipu)" className="xl:col-span-2">
<Panel title="AI Brief" subtitle="Latest portfolio insight from AI SDK (Zhipu)" className="xl:col-span-2" variant="surface">
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading intelligence output...</p>
) : state.latestInsight ? (
@@ -195,21 +195,21 @@ export default function CommandCenterPage() {
</div>
<Panel title="Quick Links" subtitle="Feature modules">
<div className="grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-5">
<Link className="rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4 transition hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel-bright)]" href="/analysis">
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-3">
<Link className="border-l-2 border-[color:var(--line-weak)] py-1 pl-4 pr-2 transition hover:border-[color:var(--line-strong)]" href="/analysis">
<p className="panel-heading text-xs uppercase text-[color:var(--terminal-muted)]">Analysis</p>
<p className="mt-2 text-sm text-[color:var(--terminal-bright)]">Inspect one company across prices, filings, financials, and AI reports.</p>
</Link>
<Link className="rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4 transition hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel-bright)]" href="/financials">
<Link className="border-l-2 border-[color:var(--line-weak)] py-1 pl-4 pr-2 transition hover:border-[color:var(--line-strong)]" href="/financials">
<p className="panel-heading text-xs uppercase text-[color:var(--terminal-muted)]">Financials</p>
<p className="mt-2 text-sm text-[color:var(--terminal-bright)]">Focus on multi-period filing metrics, margins, leverage, and balance sheet composition.</p>
</Link>
<Link className="rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4 transition hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel-bright)]" href={buildGraphingHref()}>
<Link className="border-l-2 border-[color:var(--line-weak)] py-1 pl-4 pr-2 transition hover:border-[color:var(--line-strong)]" href={buildGraphingHref()}>
<p className="panel-heading text-xs uppercase text-[color:var(--terminal-muted)]">Graphing</p>
<p className="mt-2 text-sm text-[color:var(--terminal-bright)]">Compare one normalized metric across multiple companies with shareable chart state.</p>
</Link>
<Link
className="rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4 transition hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel-bright)]"
className="border-l-2 border-[color:var(--line-weak)] py-1 pl-4 pr-2 transition hover:border-[color:var(--line-strong)]"
href="/filings"
onMouseEnter={() => {
void queryClient.prefetchQuery(filingsQueryOptions({ limit: 120 }));
@@ -222,7 +222,7 @@ export default function CommandCenterPage() {
<p className="mt-2 text-sm text-[color:var(--terminal-bright)]">Sync SEC filings and trigger AI memo analysis.</p>
</Link>
<Link
className="rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4 transition hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel-bright)]"
className="border-l-2 border-[color:var(--line-weak)] py-1 pl-4 pr-2 transition hover:border-[color:var(--line-strong)]"
href="/portfolio"
onMouseEnter={() => prefetchPortfolioSurfaces()}
onFocus={() => prefetchPortfolioSurfaces()}
@@ -231,7 +231,7 @@ export default function CommandCenterPage() {
<p className="mt-2 text-sm text-[color:var(--terminal-bright)]">Manage the active private portfolio and mark positions to market.</p>
</Link>
<Link
className="rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4 transition hover:border-[color:var(--line-strong)] hover:bg-[color:var(--panel-bright)]"
className="border-l-2 border-[color:var(--line-weak)] py-1 pl-4 pr-2 transition hover:border-[color:var(--line-strong)]"
href="/watchlist"
onMouseEnter={() => prefetchPortfolioSurfaces()}
onFocus={() => prefetchPortfolioSurfaces()}

View File

@@ -192,7 +192,7 @@ export default function PortfolioPage() {
)}
>
{error ? (
<Panel>
<Panel variant="surface">
<p className="text-sm text-[#ffb5b5]">{error}</p>
</Panel>
) : null}
@@ -215,7 +215,7 @@ export default function PortfolioPage() {
</div>
<div className="grid grid-cols-1 gap-6 xl:grid-cols-2">
<Panel title="Allocation">
<Panel title="Allocation" variant="surface">
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading chart...</p>
) : allocationData.length > 0 ? (
@@ -228,7 +228,7 @@ export default function PortfolioPage() {
))}
</Pie>
<Tooltip
formatter={(value: number | string | undefined) => formatCurrency(value)}
formatter={(value) => formatCurrency(Array.isArray(value) ? value[0] : value)}
contentStyle={{
backgroundColor: CHART_TOOLTIP_BG,
border: `1px solid ${CHART_TOOLTIP_BORDER}`,
@@ -251,7 +251,7 @@ export default function PortfolioPage() {
)}
</Panel>
<Panel title="Performance %">
<Panel title="Performance %" variant="surface">
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading chart...</p>
) : performanceData.length > 0 ? (
@@ -275,7 +275,7 @@ export default function PortfolioPage() {
tick={{ fill: CHART_MUTED }}
/>
<Tooltip
formatter={(value: number | string | undefined) => `${asNumber(value).toFixed(2)}%`}
formatter={(value) => `${asNumber(Array.isArray(value) ? value[0] : value).toFixed(2)}%`}
contentStyle={{
backgroundColor: CHART_TOOLTIP_BG,
border: `1px solid ${CHART_TOOLTIP_BORDER}`,
@@ -296,7 +296,7 @@ export default function PortfolioPage() {
</div>
<div className="grid grid-cols-1 gap-6 xl:grid-cols-[1.5fr_1fr]">
<Panel title="Holdings Table" subtitle="Live mark-to-market values from latest refresh.">
<Panel title="Holdings Table" subtitle="Live mark-to-market values from latest refresh." variant="surface">
{loading ? (
<p className="text-sm text-[color:var(--terminal-muted)]">Loading holdings...</p>
) : holdings.length === 0 ? (
@@ -409,7 +409,7 @@ export default function PortfolioPage() {
))}
</div>
<div className="hidden max-w-full overflow-x-auto lg:block">
<div className="data-table-wrap hidden max-w-full lg:block">
<table className="data-table min-w-[1020px]">
<thead>
<tr>
@@ -514,7 +514,7 @@ export default function PortfolioPage() {
)}
</Panel>
<Panel title={editingHoldingId === null ? 'Add Holding' : 'Edit Holding'}>
<Panel title={editingHoldingId === null ? 'Add Holding' : 'Edit Holding'} variant="surface">
<form onSubmit={submitHolding} className="space-y-3">
<div>
<label className="mb-1 block text-xs uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">Ticker</label>

View File

@@ -196,7 +196,7 @@ function SearchPageContent() {
</form>
</Panel>
<Panel title="Cited Answer" subtitle="Single-turn answer grounded only in retrieved evidence.">
<Panel title="Cited Answer" subtitle="Single-turn answer grounded only in retrieved evidence." variant="surface">
{answer ? (
<div className="space-y-3">
<p className="whitespace-pre-wrap text-sm leading-7 text-[color:var(--terminal-bright)]">{answer.answer}</p>
@@ -226,6 +226,7 @@ function SearchPageContent() {
<Panel
title="Semantic Search"
subtitle={query ? `${results.length} results${ticker ? ` for ${ticker}` : ''}.` : 'Search results will appear here.'}
variant="surface"
>
{error ? <p className="text-sm text-[#ffb5b5]">{error}</p> : null}
{loading ? (

View File

@@ -274,6 +274,7 @@ export default function WatchlistPage() {
<Panel
title="Coverage Board"
subtitle={`${items.length} tracked companies across backlog, active work, and archive.`}
variant="surface"
actions={(
<div className="flex w-full flex-col gap-2 sm:w-auto sm:flex-row">
<Input
@@ -452,7 +453,7 @@ export default function WatchlistPage() {
))}
</div>
<div className="hidden overflow-x-auto lg:block">
<div className="data-table-wrap hidden lg:block">
<table className="data-table min-w-[1120px]">
<thead>
<tr>
@@ -621,6 +622,7 @@ export default function WatchlistPage() {
<Panel
title={editingItemId === null ? 'Add Coverage' : 'Edit Coverage'}
subtitle={editingItemId === null ? 'Create a new company coverage record.' : 'Update metadata, priority, and workflow status.'}
variant="surface"
>
<form onSubmit={saveCoverage} className="space-y-3">
<div>

View File

@@ -10,9 +10,9 @@ type MetricCardProps = {
export function MetricCard({ label, value, delta, positive = true, className }: MetricCardProps) {
return (
<div className={cn('rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-4', className)}>
<p className="text-xs uppercase tracking-[0.2em] text-[color:var(--terminal-muted)]">{label}</p>
<p className="mt-2 text-2xl font-semibold text-[color:var(--terminal-bright)]">{value}</p>
<div className={cn('min-w-0 border-t border-[color:var(--line-weak)] pt-3', className)}>
<p className="panel-heading text-[11px] uppercase tracking-[0.18em] text-[color:var(--terminal-muted)]">{label}</p>
<p className="mt-2 text-3xl font-semibold text-[color:var(--terminal-bright)]">{value}</p>
{delta ? (
<p className={cn('mt-2 text-xs', positive ? 'text-[#96f5bf]' : 'text-[#ff9898]')}>
{delta}

View File

@@ -20,9 +20,9 @@ export function TaskFeed({ tasks }: TaskFeedProps) {
}
return (
<ul className="space-y-2">
<ul>
{tasks.slice(0, 8).map((task) => (
<li key={task.id} className="flex items-center justify-between rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2">
<li key={task.id} className="flex items-center justify-between gap-3 border-b border-[color:var(--line-weak)] py-3 last:border-b-0 last:pb-0 first:pt-0">
<div>
<p className="text-sm text-[color:var(--terminal-bright)]">{taskLabels[task.task_type]}</p>
<p className="text-xs text-[color:var(--terminal-muted)]">

View File

@@ -41,12 +41,12 @@ export function FinancialControlBar({
className
}: FinancialControlBarProps) {
return (
<section className={cn('rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] px-4 py-3', className)}>
<section className={cn('border-t border-[color:var(--line-weak)] pt-4', className)}>
<div className="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
<div className="min-w-0">
<h3 className="text-sm font-semibold text-[color:var(--terminal-bright)]">{title}</h3>
<h3 className="text-base font-semibold text-[color:var(--terminal-bright)]">{title}</h3>
{subtitle ? (
<p className="mt-1 text-xs text-[color:var(--terminal-muted)]">{subtitle}</p>
<p className="mt-1 text-sm text-[color:var(--terminal-muted)]">{subtitle}</p>
) : null}
</div>
@@ -68,29 +68,29 @@ export function FinancialControlBar({
) : null}
</div>
<div className="mt-3 grid grid-cols-1 gap-2">
{sections.map((section) => (
<div
key={section.id}
className="rounded-lg border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] px-3 py-2"
>
<span className="mb-2 block text-[10px] uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">{section.label}</span>
<div className="flex flex-wrap items-center gap-1.5">
{section.options.map((option) => (
<Button
key={`${section.id}-${option.value}`}
type="button"
variant={option.value === section.value ? 'primary' : 'ghost'}
disabled={option.disabled}
className="px-2 py-1 text-xs sm:min-h-9"
onClick={() => section.onChange(option.value)}
>
{option.label}
</Button>
))}
</div>
<div className="mt-4 grid grid-cols-1 gap-3">
{sections.map((section) => (
<div
key={section.id}
className="data-surface px-3 py-3"
>
<span className="mb-2 block text-[10px] uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">{section.label}</span>
<div className="flex flex-wrap items-center gap-1.5">
{section.options.map((option) => (
<Button
key={`${section.id}-${option.value}`}
type="button"
variant={option.value === section.value ? 'primary' : 'ghost'}
disabled={option.disabled}
className="px-2 py-1 text-xs sm:min-h-9"
onClick={() => section.onChange(option.value)}
>
{option.label}
</Button>
))}
</div>
))}
</div>
))}
</div>
</section>
);

View File

@@ -447,8 +447,8 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
<div className="ambient-grid" aria-hidden="true" />
<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(255,255,255,0.04),0_20px_60px_rgba(0,0,0,0.42)] lg:flex">
<div className="relative z-10 mx-auto flex min-h-screen w-full max-w-[1440px] gap-6 px-4 pb-10 pt-4 sm:px-5 sm:pb-12 sm:pt-6 md:px-8 lg:gap-8">
<aside className="hidden w-72 shrink-0 flex-col gap-6 border-r border-[color:var(--line-weak)] pr-6 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>
@@ -472,10 +472,10 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
onMouseEnter={() => prefetchForHref(item.href)}
onFocus={() => prefetchForHref(item.href)}
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',
'flex items-center gap-3 rounded-xl border border-transparent 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(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)]'
? 'border-[color:var(--line-strong)] bg-[color:var(--panel-bright)] text-[color:var(--terminal-bright)] shadow-[inset_2px_0_0_var(--accent)]'
: 'text-[color:var(--terminal-muted)] hover:border-[color:var(--line-weak)] hover:bg-[color:var(--panel-soft)] hover:text-[color:var(--terminal-bright)]'
)}
>
<Icon className="size-4" />
@@ -487,7 +487,7 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
))}
</nav>
<div className="mt-auto rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-3">
<div className="mt-auto rounded-[1rem] border border-[color:var(--line-weak)] bg-[color:var(--panel-soft)] p-3">
<p className="text-xs uppercase tracking-[0.2em] text-[color:var(--terminal-muted)]">Runtime</p>
<p className="mt-1 truncate text-sm text-[color:var(--terminal-bright)]">{displayName}</p>
{role ? <p className="mt-1 text-xs uppercase tracking-[0.16em] text-[color:var(--terminal-muted)]">Role: {role}</p> : null}
@@ -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(255,255,255,0.04),0_14px_40px_rgba(0,0,0,0.4)] sm:px-6 sm:py-5 sm:pr-20">
<header className="relative mb-4 border-b border-[color:var(--line-weak)] pb-4 pr-16 sm:pb-5 sm:pr-20">
<div className="absolute right-4 top-4 z-10 sm:right-5 sm:top-5">
<TaskNotificationsTrigger
unreadCount={notifications.unreadCount}
@@ -539,7 +539,7 @@ export function AppShell({ title, subtitle, actions, activeTicker, breadcrumbs,
<nav
aria-label="Breadcrumb"
className="mb-6 overflow-x-auto rounded-xl border border-[color:var(--line-weak)] bg-[color:var(--panel)] px-3 py-2"
className="mb-6 overflow-x-auto border-b border-[color:var(--line-weak)] pb-3"
>
<ol className="flex min-w-max items-center gap-2 text-xs text-[color:var(--terminal-muted)] sm:min-w-0 sm:flex-wrap">
{breadcrumbItems.map((item, index) => {

View File

@@ -17,7 +17,7 @@ export function Button({ className, variant = 'primary', ...props }: ButtonProps
return (
<button
className={cn(
'inline-flex min-h-11 items-center justify-center gap-2 rounded-lg border px-3 py-2 text-sm font-medium transition duration-200 disabled:cursor-not-allowed disabled:opacity-50',
'inline-flex min-h-11 items-center justify-center gap-2 rounded-xl border px-3 py-2 text-sm font-medium transition duration-200 disabled:cursor-not-allowed disabled:opacity-50',
variantMap[variant],
className
)}

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_var(--focus-ring)]',
'min-h-11 w-full rounded-xl 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

@@ -6,13 +6,16 @@ type PanelProps = {
actions?: React.ReactNode;
children: React.ReactNode;
className?: string;
variant?: 'flat' | 'surface';
};
export function Panel({ title, subtitle, actions, children, className }: PanelProps) {
export function Panel({ title, subtitle, actions, children, className, variant = 'flat' }: PanelProps) {
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(255,255,255,0.03),0_12px_30px_rgba(0,0,0,0.38)] sm:p-5',
variant === 'surface'
? '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'
: 'min-w-0 border-t border-[color:var(--line-weak)] pt-4 sm:pt-5',
className
)}
>