Comprehensive UX polish: fix 19 friction points across all pages
CI / build-and-push (push) Successful in 33s

Addresses broken interactions (notification bell, browser dialogs),
missing feedback states (disabled buttons, pricing changes, paused
indicator), unclear affordances (research queue, model tuning, funding
requirements), and navigation gaps (hash routing, keyboard shortcuts,
clickable dashboard cards, sidebar grouping, tutorial hints).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-24 21:44:18 -04:00
parent d25dfe0435
commit f9f6233b69
19 changed files with 540 additions and 121 deletions
+18 -11
View File
@@ -81,17 +81,24 @@ export function CompetitorsPage() {
</span>
</div>
<div className="flex items-center gap-2">
{canAcquire(era) && rival.status === 'active' && (
<button
onClick={() => acquireCompetitor(rival.id)}
disabled={money < rival.estimatedRevenue * 500 + rival.estimatedCapability * 100_000}
className="flex items-center gap-1 bg-blue-600/20 hover:bg-blue-600/30 text-blue-400 border border-blue-600/30 rounded px-3 py-1.5 text-xs disabled:opacity-40 disabled:cursor-not-allowed"
title={`Cost: ${formatMoney(rival.estimatedRevenue * 500 + rival.estimatedCapability * 100_000)}`}
>
<ShoppingCart size={12} />
Acquire
</button>
)}
{canAcquire(era) && rival.status === 'active' && (() => {
const cost = rival.estimatedRevenue * 500 + rival.estimatedCapability * 100_000;
return (
<div className="text-right">
<button
onClick={() => acquireCompetitor(rival.id)}
disabled={money < cost}
className="flex items-center gap-1 bg-blue-600/20 hover:bg-blue-600/30 text-blue-400 border border-blue-600/30 rounded px-3 py-1.5 text-xs disabled:opacity-40 disabled:cursor-not-allowed"
>
<ShoppingCart size={12} />
Acquire ({formatMoney(cost)})
</button>
{money < cost && (
<div className="text-[10px] text-warning mt-0.5">Need {formatMoney(cost - money)} more</div>
)}
</div>
);
})()}
<span className={`text-xs px-2 py-1 rounded-full ${
rival.status === 'active' ? 'bg-success/20 text-success' :
rival.status === 'acquired' ? 'bg-blue-500/20 text-blue-400' :