fix(frontend): finish the token migration — raw grey classes -> theme tokens

UI_REDESIGN chunk 4 was never finished: 39 app/component files still used
raw Tailwind greys, kept readable in light mode only by the !important
override sheet. In dark mode text-gray-600 is ~2.3:1 on surface, and the
light override maps it to #94a3b8 (~2.6:1 on white) — unreadable in both.

Mechanical mapping (886 classes): gray-100/200 -> ink, 300/400 -> ink-2,
500/600/700 -> ink-muted, bg 950/900/800 -> page/surface/raised,
border 800 -> line, 700/600 -> line-strong, plus hover/divide/placeholder.
Alpha suffixes kept (tokens are color-mix, so /60 works). bg-gray-700,
text-white and marketing pages left alone. text-[9px] -> text-[10px].

Frontend unverified: no Node on the authoring box (#207).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Logan Cusano
2026-10-25 21:29:13 -04:00
co-authored by Claude Opus 5.5
parent 3968b49b80
commit bf206334e3
39 changed files with 655 additions and 655 deletions
+16 -16
View File
@@ -92,13 +92,13 @@ export default function ProfilePage() {
<div>
<h1 className="text-white text-xl font-bold">{displayName}</h1>
{user.displayName && user.email && (
<p className="text-gray-400 text-sm mt-0.5">{user.email}</p>
<p className="text-ink-2 text-sm mt-0.5">{user.email}</p>
)}
{role && (
<span className={`inline-block mt-1 text-xs font-mono px-2 py-0.5 rounded-full ${
role === "admin" ? "bg-indigo-900 text-indigo-300" :
role === "operator" ? "bg-green-900 text-green-300" :
"bg-gray-800 text-gray-400"
"bg-raised text-ink-2"
}`}>
{role === "admin" ? "Admin" : role === "operator" ? "Operator" : "Viewer"}
</span>
@@ -107,9 +107,9 @@ export default function ProfilePage() {
</div>
{/* Firebase account */}
<section className="bg-gray-900 border border-gray-800 rounded-xl divide-y divide-gray-800">
<section className="bg-surface border border-line rounded-xl divide-y divide-line">
<div className="px-4 py-3">
<p className="text-xs text-gray-500 uppercase tracking-wider font-mono mb-2">Account</p>
<p className="text-xs text-ink-muted uppercase tracking-wider font-mono mb-2">Account</p>
<div className="space-y-2">
<Row label="Email" value={user.email ?? "—"} />
<Row label="UID" value={user.uid} mono truncate />
@@ -125,12 +125,12 @@ export default function ProfilePage() {
</section>
{/* Discord linking */}
<section className="bg-gray-900 border border-gray-800 rounded-xl overflow-hidden">
<section className="bg-surface border border-line rounded-xl overflow-hidden">
<div className="px-4 py-3">
<p className="text-xs text-gray-500 uppercase tracking-wider font-mono mb-3">Discord</p>
<p className="text-xs text-ink-muted uppercase tracking-wider font-mono mb-3">Discord</p>
{linkLoading ? (
<p className="text-gray-500 text-sm">Loading…</p>
<p className="text-ink-muted text-sm">Loading…</p>
) : linkStatus?.linked ? (
<div className="space-y-3">
<div className="space-y-2">
@@ -156,21 +156,21 @@ export default function ProfilePage() {
</div>
) : (
<div className="space-y-3">
<p className="text-sm text-gray-400">
<p className="text-sm text-ink-2">
Link your Discord account to access private trips from both the web and Discord.
</p>
{code ? (
<div className="space-y-2">
<div className="bg-gray-800 rounded-lg px-4 py-3 flex items-center gap-3">
<div className="bg-raised rounded-lg px-4 py-3 flex items-center gap-3">
<span className="font-mono text-2xl tracking-[0.4em] text-white select-all">{code}</span>
</div>
<p className="text-xs text-gray-400">
Run <span className="font-mono text-gray-200">/link {code}</span> in Discord. Code expires in {codeExpiry} minutes.
<p className="text-xs text-ink-2">
Run <span className="font-mono text-ink">/link {code}</span> in Discord. Code expires in {codeExpiry} minutes.
</p>
<button
onClick={generateCode}
disabled={generating}
className="text-xs text-gray-500 hover:text-gray-300 transition-colors disabled:opacity-50"
className="text-xs text-ink-muted hover:text-ink transition-colors disabled:opacity-50"
>
Generate new code
</button>
@@ -190,9 +190,9 @@ export default function ProfilePage() {
</section>
{/* Sign out */}
<section className="bg-gray-900 border border-gray-800 rounded-xl">
<section className="bg-surface border border-line rounded-xl">
<div className="px-4 py-3 flex items-center justify-between">
<p className="text-sm text-gray-400">Sign out of this device</p>
<p className="text-sm text-ink-2">Sign out of this device</p>
<button
onClick={handleSignOut}
className="text-sm text-red-500 hover:text-red-400 transition-colors"
@@ -213,8 +213,8 @@ function Row({ label, value, mono = false, truncate = false }: {
}) {
return (
<div className="flex items-start justify-between gap-4">
<span className="text-xs text-gray-500 shrink-0">{label}</span>
<span className={`text-sm text-gray-200 text-right ${mono ? "font-mono text-xs" : ""} ${truncate ? "truncate max-w-[200px]" : ""}`}>
<span className="text-xs text-ink-muted shrink-0">{label}</span>
<span className={`text-sm text-ink text-right ${mono ? "font-mono text-xs" : ""} ${truncate ? "truncate max-w-[200px]" : ""}`}>
{value}
</span>
</div>