Refresh app theme and update dependencies
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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'}
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
))}
|
||||
|
||||
@@ -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 }) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>();
|
||||
|
||||
Reference in New Issue
Block a user