0.2.27-0.2.32: LP portal polish, brand palette, default investor logins

Cumulative checkpoint since 0.2.26:
- 0.2.27/28: entity valuation-history table; investor gain/loss = NAV +
  distributions vs paid-in
- 0.2.29: Reset Fund Partners (endpoint, Partners-tab button, CLI, action)
- 0.2.30: "Current Capital Balance" label, %-only gain/loss
- 0.2.31: Management Entities rename, Carry Vehicle type, chart
  distributions-line gate
- 0.2.32: LP-facing polish pass
  * Ten31 brand palette from the logo (navy/mint); orange retired
  * portfolio summary card across funds; gain labeled "net of paid-in"
  * whole-dollar headline figures; "History · N quarters" toggle
  * documents grouped by year with a "New" badge (users.docs_seen_at)
  * eNAV-created members start on default password with login enabled;
    enable-investor-logins CLI + StartOS action for existing accounts
  * password minimum raised to 8 chars; login help line (Portal@ten31.xyz)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jonathan Kirkwood
2026-07-03 08:40:40 -05:00
co-authored by Claude Opus 4.8
parent 69f12b0519
commit 4215d4478f
47 changed files with 935 additions and 111 deletions
+1 -1
View File
@@ -115,7 +115,7 @@ export default function AccessGrid() {
disabled={loading}
className={`w-full h-10 flex items-center justify-center transition-colors ${
on
? "bg-orange-50 text-orange-600 hover:bg-orange-100"
? "bg-accent-50 text-accent-600 hover:bg-accent-100"
: "text-gray-300 hover:bg-gray-100"
} ${loading ? "opacity-50" : ""}`}
title={on ? "Click to revoke" : "Click to grant"}
+2 -2
View File
@@ -186,7 +186,7 @@ function EntryForm({
<button
onClick={submit}
disabled={busy || entityId === "" || investorId === "" || !asOf}
className="px-3 py-1.5 bg-gray-900 text-white text-sm rounded hover:bg-gray-800 disabled:opacity-50"
className="px-3 py-1.5 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50"
>
{busy ? "Saving…" : "Save statement"}
</button>
@@ -219,4 +219,4 @@ function DollarField({
}
const inputCls =
"w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-orange-500 focus:border-transparent";
"w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-accent-500 focus:border-transparent";
+4 -4
View File
@@ -87,7 +87,7 @@ export default function Documents() {
<td className="px-4 py-2 text-right whitespace-nowrap">
<a
href={api.downloadUrl(d.id)}
className="text-orange-600 hover:text-orange-700 mr-3"
className="text-accent-600 hover:text-accent-700 mr-3"
>
Download
</a>
@@ -242,7 +242,7 @@ function UploadForm({
{targetLabel ? (
<p className="text-xs text-gray-500">
Uploading to <span className="font-medium text-gray-700">{entityName}</span> ·{" "}
<span className={investorId === "" ? "text-gray-700" : "text-orange-600 font-medium"}>
<span className={investorId === "" ? "text-gray-700" : "text-accent-600 font-medium"}>
{targetLabel}
</span>
</p>
@@ -252,7 +252,7 @@ function UploadForm({
<button
onClick={submit}
disabled={busy || entityId === "" || !file}
className="px-3 py-1.5 bg-gray-900 text-white text-sm rounded hover:bg-gray-800 disabled:opacity-50"
className="px-3 py-1.5 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50"
>
{busy ? "Uploading…" : "Upload"}
</button>
@@ -262,4 +262,4 @@ function UploadForm({
}
const inputCls =
"w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-orange-500 focus:border-transparent";
"w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-accent-500 focus:border-transparent";
+11 -7
View File
@@ -21,6 +21,7 @@ const TYPE_LABELS: Record<string, string> = {
spv: "SPV",
gp: "GP",
mgmt_co: "Mgmt Co",
carry: "Carry Vehicle",
};
export default function EntitiesList() {
@@ -62,7 +63,9 @@ export default function EntitiesList() {
}
const funds = entities.filter((e) => e.type === "fund" || e.type === "spv");
const gps = entities.filter((e) => e.type === "gp" || e.type === "mgmt_co");
const gps = entities.filter(
(e) => e.type === "gp" || e.type === "mgmt_co" || e.type === "carry",
);
return (
<div className="space-y-8">
@@ -71,7 +74,7 @@ export default function EntitiesList() {
{isWriter && (
<button
onClick={() => setShowForm(true)}
className="px-4 py-2 bg-gray-900 text-white text-sm rounded hover:bg-gray-800"
className="px-4 py-2 bg-brand-900 text-white text-sm rounded hover:bg-brand-800"
>
Add Entity
</button>
@@ -89,7 +92,7 @@ export default function EntitiesList() {
)}
<EntityTable title="Funds and SPVs" rows={funds} />
<EntityTable title="GP Entities and Management Companies" rows={gps} />
<EntityTable title="Management Entities" rows={gps} />
</div>
);
}
@@ -155,7 +158,7 @@ function AddEntityForm({
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-orange-500 focus:border-transparent"
className="w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-accent-500 focus:border-transparent"
placeholder="Low Time Preference Fund I, LLC"
required
/>
@@ -171,6 +174,7 @@ function AddEntityForm({
<option value="spv">SPV</option>
<option value="gp">GP</option>
<option value="mgmt_co">Mgmt Co</option>
<option value="carry">Carry Vehicle</option>
</select>
</div>
<div className="flex gap-3">
@@ -202,7 +206,7 @@ function AddEntityForm({
<button
type="submit"
disabled={saving}
className="px-4 py-2 bg-gray-900 text-white text-sm rounded hover:bg-gray-800 disabled:opacity-50"
className="px-4 py-2 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50"
>
{saving ? "Creating..." : "Create"}
</button>
@@ -261,7 +265,7 @@ function EntityTable({ title, rows }: { title: string; rows: EntityRow[] }) {
return (
<th className={`px-4 py-3 font-medium text-gray-600 select-none ${a}`}>
<button onClick={() => sortBy(k)} className={`w-full hover:text-gray-900 ${a}`}>
{label}<span className="text-orange-500">{arrow(k)}</span>
{label}<span className="text-accent-500">{arrow(k)}</span>
</button>
</th>
);
@@ -345,7 +349,7 @@ function EntityTable({ title, rows }: { title: string; rows: EntityRow[] }) {
<td className="px-4 py-3">
<Link
to={`/entities/${row.id}`}
className="text-gray-900 font-medium hover:text-orange-600"
className="text-gray-900 font-medium hover:text-accent-600"
>
{row.name}
</Link>
+2 -2
View File
@@ -77,7 +77,7 @@ export default function EntityAssets() {
<p>This entity isn't linked to an investor account yet, so there are no balances to show.</p>
<p className="mt-2 text-gray-500">
Link it on the{" "}
<Link to={`/entities/${entityId}`} className="text-orange-600 hover:text-orange-700">
<Link to={`/entities/${entityId}`} className="text-accent-600 hover:text-accent-700">
Overview tab Edit entity
</Link>{" "}
(choose its investor account). Its capital-account balance in each fund will then
@@ -110,7 +110,7 @@ export default function EntityAssets() {
{rows.map((r) => (
<tr key={r.fundId} className="border-t border-gray-100">
<td className="px-4 py-2 text-gray-900">
<Link to={`/entities/${r.fundId}`} className="hover:text-orange-600">
<Link to={`/entities/${r.fundId}`} className="hover:text-accent-600">
{fundName(r.fundId)}
</Link>
</td>
+1 -1
View File
@@ -61,7 +61,7 @@ export default function EntityDocuments() {
</td>
<td className="px-4 py-2 text-gray-500">{formatDate(d.created_at)}</td>
<td className="px-4 py-2 text-right whitespace-nowrap">
<a href={api.downloadUrl(d.id)} className="text-orange-600 hover:text-orange-700 mr-3">
<a href={api.downloadUrl(d.id)} className="text-accent-600 hover:text-accent-700 mr-3">
Download
</a>
<button
+55 -6
View File
@@ -20,6 +20,7 @@ export default function EntityOverview() {
const [totalInvested, setTotalInvested] = useState(0);
const [lastValue, setLastValue] = useState(0);
const [latestRound, setLatestRound] = useState<ValuationRound | null>(null);
const [rounds, setRounds] = useState<ValuationRound[]>([]);
const [assetBalances, setAssetBalances] = useState<AssetBalances | null>(null);
const [loading, setLoading] = useState(true);
const [editing, setEditing] = useState(false);
@@ -49,7 +50,10 @@ export default function EntityOverview() {
const ent = await api.getEntity(entityId);
setEntity(ent);
if ((ent.type === "gp" || ent.type === "mgmt_co") && ent.linked_user_id != null) {
if (
(ent.type === "gp" || ent.type === "mgmt_co" || ent.type === "carry") &&
ent.linked_user_id != null
) {
api.entityAssetBalances(entityId).then(setAssetBalances).catch(() => {});
}
@@ -66,6 +70,9 @@ export default function EntityOverview() {
setTotalInvested(invested);
const rounds = await api.listRounds(entityId);
// Newest quarter first, so the history table reads top-down like a statement run.
const sorted = [...rounds].sort((a, b) => b.quarter_end.localeCompare(a.quarter_end));
setRounds(sorted);
const approved = rounds.filter((r) => r.status === "approved");
if (approved.length > 0) {
setLatestRound(approved[0]);
@@ -141,7 +148,7 @@ export default function EntityOverview() {
{assetBalances.linked_name ? ` · ${assetBalances.linked_name}` : ""}
</div>
</div>
<Link to={`/entities/${entity.id}/assets`} className="text-sm text-orange-600 hover:text-orange-700">
<Link to={`/entities/${entity.id}/assets`} className="text-sm text-accent-600 hover:text-accent-700">
View by fund
</Link>
</div>
@@ -165,6 +172,47 @@ export default function EntityOverview() {
</div>
</div>
)}
{/* Valuation history — every quarter uploaded/signed for this entity */}
{rounds.length > 0 && (
<div className="bg-white border border-gray-200 rounded-lg overflow-x-auto mt-6">
<div className="px-4 py-3 border-b border-gray-100">
<h3 className="text-sm font-medium text-gray-700">Valuation history</h3>
<p className="text-xs text-gray-400 mt-0.5">
{rounds.length} quarter{rounds.length === 1 ? "" : "s"} on record
</p>
</div>
<table className="w-full text-sm">
<thead className="bg-gray-50 text-gray-500 text-left">
<tr>
<th className="px-4 py-2 font-medium">Quarter</th>
<th className="px-4 py-2 font-medium text-right">NAV</th>
<th className="px-4 py-2 font-medium">Status</th>
<th className="px-4 py-2 font-medium">Signed</th>
</tr>
</thead>
<tbody>
{rounds.map((r) => {
const nav = r.valuations.reduce((s, v) => s + v.value_cents, 0);
return (
<tr key={r.id} className="border-t border-gray-100">
<td className="px-4 py-2 text-gray-900">{formatQuarter(r.quarter_end)}</td>
<td className="px-4 py-2 text-right text-gray-900 font-medium">{formatMoney(nav)}</td>
<td className="px-4 py-2">
<span className={`inline-block px-2 py-0.5 text-xs rounded ${STATUS_COLORS[r.status]}`}>
{r.status}
</span>
</td>
<td className="px-4 py-2 text-gray-500">
{r.status === "approved" && r.approved_at ? formatDate(r.approved_at) : "—"}
</td>
</tr>
);
})}
</tbody>
</table>
</div>
)}
</div>
);
}
@@ -191,9 +239,9 @@ function EditEntityForm({
const [saving, setSaving] = useState(false);
const inputCls = "w-full px-3 py-2 border border-gray-300 rounded text-sm";
// A GP / management company can be linked to its own investor account, so its Assets view
// shows its real per-fund balances.
const isGp = type === "gp" || type === "mgmt_co";
// A GP / management company / carry vehicle can be linked to its own investor account, so its
// Assets view shows its real per-fund balances.
const isGp = type === "gp" || type === "mgmt_co" || type === "carry";
useEffect(() => {
if (!isGp) return;
api.listUsers().then((us) => setInvestors(us.filter((u) => u.role === "investor"))).catch(() => {});
@@ -243,6 +291,7 @@ function EditEntityForm({
<option value="spv">SPV</option>
<option value="gp">GP</option>
<option value="mgmt_co">Mgmt Co</option>
<option value="carry">Carry Vehicle</option>
</select>
</div>
<div className="flex-1">
@@ -282,7 +331,7 @@ function EditEntityForm({
)}
{error && <p className="text-sm text-red-600">{error}</p>}
<div className="flex gap-2 pt-1">
<button type="submit" disabled={saving} className="px-4 py-2 bg-gray-900 text-white text-sm rounded hover:bg-gray-800 disabled:opacity-50">
<button type="submit" disabled={saving} className="px-4 py-2 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50">
{saving ? "Saving…" : "Save"}
</button>
<button type="button" onClick={onClose} className="px-4 py-2 border border-gray-300 text-sm rounded hover:bg-gray-50">
+52 -6
View File
@@ -1,16 +1,22 @@
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { api, type Entity, type Partner } from "../api";
import { api, canEditRound, type Entity, type Partner } from "../api";
import { useAuth } from "../context/AuthContext";
import { formatDate, formatMoneyExact } from "../format";
import EntityHeader from "../components/EntityHeader";
export default function EntityPartners() {
const { id } = useParams<{ id: string }>();
const { user } = useAuth();
const [entity, setEntity] = useState<Entity | null>(null);
const [partners, setPartners] = useState<Partner[]>([]);
const [error, setError] = useState("");
const [notice, setNotice] = useState("");
const [clearing, setClearing] = useState(false);
const [loading, setLoading] = useState(true);
const isWriter = !!user && canEditRound(user.role);
useEffect(() => {
if (!id) return;
const eid = parseInt(id);
@@ -23,6 +29,34 @@ export default function EntityPartners() {
.finally(() => setLoading(false));
}, [id]);
async function clearAllPartners() {
if (!entity) return;
if (
!confirm(
`Remove ALL ${partners.length} partner(s) from ${entity.name}?\n\n` +
"This deletes this fund's capital-account statements and the investors' access to " +
"it. The investor accounts themselves are kept (they may belong to other funds), " +
"and holdings/NAV are not affected. Re-import the correct roster afterward.",
)
)
return;
setClearing(true);
setError("");
setNotice("");
try {
const res = await api.clearPartners(entity.id);
const fresh = await api.listPartners(entity.id);
setPartners(fresh);
setNotice(
`Cleared: removed ${res.statements} capital statement(s) and ${res.access_grants} access grant(s).`,
);
} catch (err: any) {
setError(err.message || "Failed to clear partners");
} finally {
setClearing(false);
}
}
if (loading || !entity) return <div className="text-gray-500 text-sm">Loading</div>;
const totalCommitted = partners.reduce((s, p) => s + (p.latest_commitment_cents || 0), 0);
@@ -33,16 +67,28 @@ export default function EntityPartners() {
<EntityHeader entity={entity} active="partners" />
{error && <p className="text-sm text-red-600 mb-3">{error}</p>}
{notice && <p className="text-sm text-green-600 mb-3">{notice}</p>}
<div className="flex items-center justify-between mb-3">
<p className="text-sm text-gray-500">
{partners.length} member{partners.length === 1 ? "" : "s"} with access to this fund.
</p>
<p className="text-sm text-gray-700">
Total committed: <span className="font-medium">{formatMoneyExact(totalCommitted)}</span>
<span className="mx-2 text-gray-300">·</span>
Total capital: <span className="font-medium">{formatMoneyExact(totalCapital)}</span>
</p>
<div className="flex items-center gap-4">
<p className="text-sm text-gray-700">
Total committed: <span className="font-medium">{formatMoneyExact(totalCommitted)}</span>
<span className="mx-2 text-gray-300">·</span>
Total capital: <span className="font-medium">{formatMoneyExact(totalCapital)}</span>
</p>
{isWriter && partners.length > 0 && (
<button
onClick={clearAllPartners}
disabled={clearing}
className="px-3 py-1.5 border border-red-300 text-red-600 text-sm rounded hover:bg-red-50 disabled:opacity-50"
>
{clearing ? "Clearing…" : "Clear all partners"}
</button>
)}
</div>
</div>
<div className="bg-white border border-gray-200 rounded-lg overflow-x-auto">
+7 -6
View File
@@ -230,7 +230,7 @@ export default function Import() {
<li>{result.members} members ({result.created} newly created)</li>
{result.note && <li className="text-amber-700">{result.note}</li>}
</ul>
<button onClick={() => setResult(null)} className="mt-3 px-3 py-1.5 bg-gray-900 text-white rounded hover:bg-gray-800">
<button onClick={() => setResult(null)} className="mt-3 px-3 py-1.5 bg-brand-900 text-white rounded hover:bg-brand-800">
Import another
</button>
</div>
@@ -240,11 +240,11 @@ export default function Import() {
<label className="block text-sm text-gray-700 mb-2">Fund</label>
<div className="flex gap-4 mb-2">
<label className="flex items-center gap-2 text-sm text-gray-700 cursor-pointer">
<input type="radio" checked={entityMode === "existing"} onChange={() => { setEntityMode("existing"); reset(); }} className="text-orange-500" />
<input type="radio" checked={entityMode === "existing"} onChange={() => { setEntityMode("existing"); reset(); }} className="text-accent-500" />
Use existing fund
</label>
<label className="flex items-center gap-2 text-sm text-gray-700 cursor-pointer">
<input type="radio" checked={entityMode === "from_file"} onChange={() => { setEntityMode("from_file"); reset(); }} className="text-orange-500" />
<input type="radio" checked={entityMode === "from_file"} onChange={() => { setEntityMode("from_file"); reset(); }} className="text-accent-500" />
Create from file
</label>
</div>
@@ -260,6 +260,7 @@ export default function Import() {
<option value="spv">SPV</option>
<option value="gp">GP</option>
<option value="mgmt_co">Mgmt Co</option>
<option value="carry">Carry Vehicle</option>
</select>
<input className={inputCls} placeholder="Vintage year" value={vintageYear} onChange={(e) => setVintageYear(e.target.value)} />
</div>
@@ -278,7 +279,7 @@ export default function Import() {
</div>
<div className="flex justify-end">
<button onClick={readEnav} disabled={busy || !file} className="px-3 py-1.5 bg-gray-900 text-white text-sm rounded hover:bg-gray-800 disabled:opacity-50">
<button onClick={readEnav} disabled={busy || !file} className="px-3 py-1.5 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50">
{busy ? "Reading…" : "Read eNAV"}
</button>
</div>
@@ -373,7 +374,7 @@ export default function Import() {
{decisions.filter((d) => d.action === "match").length} matched ·{" "}
{decisions.filter((d) => d.action === "skip").length} skipped
</span>
<button onClick={handleConfirmClick} disabled={busy || !asOf} className="px-4 py-1.5 bg-gray-900 text-white text-sm rounded hover:bg-gray-800 disabled:opacity-50">
<button onClick={handleConfirmClick} disabled={busy || !asOf} className="px-4 py-1.5 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50">
{busy ? (step || "Importing…") : "Confirm import"}
</button>
</div>
@@ -491,7 +492,7 @@ function BatchBackfill({ entities }: { entities: Entity[] }) {
<button
onClick={run}
disabled={busy || !entityId || files.length === 0}
className="px-3 py-1.5 bg-gray-900 text-white text-sm rounded hover:bg-gray-800 disabled:opacity-50"
className="px-3 py-1.5 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50"
>
{busy ? "Loading history…" : "Load history"}
</button>
+8 -2
View File
@@ -37,7 +37,7 @@ export default function Login() {
autoComplete="username"
value={handle}
onChange={(e) => setHandle(e.target.value)}
className="w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-orange-500 focus:border-transparent"
className="w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-accent-500 focus:border-transparent"
required
/>
</div>
@@ -49,11 +49,17 @@ export default function Login() {
<button
type="submit"
disabled={loading}
className="w-full py-2 bg-gray-900 text-white text-sm rounded hover:bg-gray-800 disabled:opacity-50"
className="w-full py-2 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50"
>
{loading ? "Signing in..." : "Sign in"}
</button>
</form>
<p className="mt-5 text-xs text-gray-400 text-center">
Trouble signing in?{" "}
<a href="mailto:Portal@ten31.xyz" className="text-accent-600 hover:text-accent-700">
Contact Portal@ten31.xyz
</a>
</p>
</div>
</div>
);
+5 -5
View File
@@ -40,7 +40,7 @@ export default function Users() {
<h2 className="text-xl font-semibold text-gray-900">Users</h2>
<button
onClick={() => setCreating(true)}
className="px-3 py-1.5 bg-gray-900 text-white text-sm rounded hover:bg-gray-800"
className="px-3 py-1.5 bg-brand-900 text-white text-sm rounded hover:bg-brand-800"
>
New user
</button>
@@ -94,7 +94,7 @@ export default function Users() {
onClick={() =>
api.getUser(u.id).then(setEditing).catch((e) => setError(e.message))
}
className="text-orange-600 hover:text-orange-700"
className="text-accent-600 hover:text-accent-700"
>
Manage
</button>
@@ -254,7 +254,7 @@ function CreateUserModal({
<button
onClick={submit}
disabled={busy || !name || !username || !password}
className="px-3 py-1.5 bg-gray-900 text-white text-sm rounded hover:bg-gray-800 disabled:opacity-50"
className="px-3 py-1.5 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50"
>
Create
</button>
@@ -387,7 +387,7 @@ function EditUserModal({
<button
onClick={save}
disabled={busy}
className="px-3 py-1.5 bg-gray-900 text-white text-sm rounded hover:bg-gray-800 disabled:opacity-50"
className="px-3 py-1.5 bg-brand-900 text-white text-sm rounded hover:bg-brand-800 disabled:opacity-50"
>
Save
</button>
@@ -398,7 +398,7 @@ function EditUserModal({
}
const inputCls =
"w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-orange-500 focus:border-transparent";
"w-full px-3 py-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-accent-500 focus:border-transparent";
function Field({ label, children }: { label: string; children: React.ReactNode }) {
return (
+4 -4
View File
@@ -187,7 +187,7 @@ export default function ValuationWorkflow() {
<Link to={`/entities/${entity.id}/investments`} className="pb-2 text-sm text-gray-500 hover:text-gray-800">
Investments
</Link>
<span className="pb-2 border-b-2 border-orange-500 text-sm font-medium text-orange-600">
<span className="pb-2 border-b-2 border-accent-500 text-sm font-medium text-accent-600">
Valuation
</span>
</div>
@@ -214,7 +214,7 @@ export default function ValuationWorkflow() {
/>
<button
onClick={handleCreateRound}
className="px-3 py-1.5 bg-gray-900 text-white text-sm rounded hover:bg-gray-800"
className="px-3 py-1.5 bg-brand-900 text-white text-sm rounded hover:bg-brand-800"
>
Create
</button>
@@ -228,7 +228,7 @@ export default function ValuationWorkflow() {
<button
onClick={() => selectRound(r)}
className={`w-full text-left px-3 py-2 rounded text-sm ${
selectedRound?.id === r.id ? "bg-orange-50 text-orange-700" : "hover:bg-gray-50 text-gray-700"
selectedRound?.id === r.id ? "bg-accent-50 text-accent-700" : "hover:bg-gray-50 text-gray-700"
}`}
>
<div className="font-medium">{formatQuarter(r.quarter_end)}</div>
@@ -271,7 +271,7 @@ export default function ValuationWorkflow() {
</button>
<button
onClick={handleSubmit}
className="px-3 py-1.5 bg-gray-900 text-white text-sm rounded hover:bg-gray-800"
className="px-3 py-1.5 bg-brand-900 text-white text-sm rounded hover:bg-brand-800"
>
Submit for Review
</button>