feat(admin): design system audit fixes

- Add CSS design tokens for consistency (--admin-danger-hover, --admin-accent-dot, shadow-md warm tone)
- Replace unicode icons with inline SVG (⋮, ✕, ▼, ▶)
- Consolidate duplicate PageHeader/AdminPageHeader components
- Standardize border-radius (rounded-xl → rounded-lg for ViewModeTabs)
- Remove hardcoded brand UUID in products page
- Replace hardcoded bg-red-600 with CSS variables in delete buttons
- Add AdminButton, AdminFilterTabs, AdminSearchInput, PageHeader design system components
- Fix GlassModal and AdminModal close button styling
- Remove duplicate 'New Lot' button on Route Trace dashboard
This commit is contained in:
2026-06-02 03:31:54 +00:00
parent 15e939ad7e
commit 7203cf1ead
65 changed files with 3478 additions and 3176 deletions
@@ -8,6 +8,7 @@ import {
regenerateHeadgateToken,
updateWaterHeadgate,
} from "@/actions/water-log/admin";
import { AdminButton } from "@/components/admin/design-system";
type Headgate = {
id: string;
@@ -159,20 +160,20 @@ export default function HeadgatesManager({ initialHeadgates, brandId }: Props) {
}
return (
<div className="min-h-screen bg-zinc-950">
<div className="min-h-screen bg-[var(--admin-bg)]">
{/* Header */}
<div className="bg-zinc-900 border-b border-zinc-800 px-6 py-4">
<div className="bg-white border-b border-[var(--admin-border)] px-6 py-4">
<div className="mx-auto max-w-4xl flex items-center justify-between">
<div>
<div className="flex items-center gap-2">
<button onClick={() => router.back()} className="text-stone-400 hover:text-stone-600 text-sm"> Back</button>
<h1 className="text-2xl font-bold text-zinc-100">Headgates & QR Codes</h1>
<button onClick={() => router.back()} className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-primary)] text-sm"> Back</button>
<h1 className="text-2xl font-bold text-[var(--admin-text-primary)]">Headgates & QR Codes</h1>
</div>
<p className="text-xs text-stone-500 mt-0.5">Manage headgates and generate QR codes for field access</p>
<p className="text-xs text-[var(--admin-text-muted)] mt-0.5">Manage headgates and generate QR codes for field access</p>
</div>
<button onClick={() => setShowAdd(true)} className="rounded-lg bg-stone-900 px-4 py-2 text-sm font-semibold text-white hover:bg-stone-700">
<AdminButton onClick={() => setShowAdd(true)}>
+ Add Headgate
</button>
</AdminButton>
</div>
</div>
@@ -180,138 +181,137 @@ export default function HeadgatesManager({ initialHeadgates, brandId }: Props) {
{/* Bulk actions bar */}
{headgates.length > 0 && (
<div className="flex items-center gap-3 rounded-xl bg-zinc-900 ring-1 ring-stone-200 px-4 py-3">
<button onClick={toggleAll} className="text-sm text-stone-600 hover:text-zinc-100">
<div className="flex items-center gap-3 rounded-xl border border-[var(--admin-border)] bg-white px-4 py-3">
<button onClick={toggleAll} className="text-sm text-[var(--admin-text-muted)] hover:text-[var(--admin-text-primary)]">
{selected.size === headgates.length ? "Deselect all" : "Select all"}
</button>
<span className="text-xs text-stone-400">|</span>
<span className="text-xs text-stone-500">{selected.size} selected</span>
<span className="text-xs text-[var(--admin-text-muted)]">|</span>
<span className="text-xs text-[var(--admin-text-muted)]">{selected.size} selected</span>
<div className="flex-1" />
<button
<AdminButton
onClick={printSelected}
disabled={selected.size === 0 || printLoading}
className="rounded-lg bg-blue-600 px-3 py-1.5 text-xs font-semibold text-white disabled:opacity-40 hover:bg-blue-700"
disabled={selected.size === 0}
isLoading={printLoading}
>
{printLoading ? "..." : `Print ${selected.size > 0 ? `(${selected.size})` : ""} QR Codes`}
</button>
Print {selected.size > 0 ? `(${selected.size})` : ""} QR Codes
</AdminButton>
</div>
)}
{/* Add form */}
{showAdd && (
<div className="rounded-xl bg-zinc-900 ring-1 ring-stone-200 p-5">
<div className="rounded-xl border border-[var(--admin-border)] bg-white p-5">
<form onSubmit={handleAdd} className="flex gap-3 items-end">
<div className="flex-1">
<label className="block text-xs font-semibold text-stone-600 mb-1">Headgate Name</label>
<label className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">Headgate Name</label>
<input
autoFocus
type="text"
value={newName}
onChange={(e) => setNewName(e.target.value)}
placeholder="e.g. North Field Gate 1"
className="w-full rounded-xl border border-stone-300 px-4 py-3 text-sm outline-none focus:border-stone-900"
className="w-full rounded-xl border border-[var(--admin-border)] px-4 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
required
/>
</div>
<div>
<label className="block text-xs font-semibold text-stone-600 mb-1">Unit</label>
<label className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">Unit</label>
<select
value={newUnit}
onChange={(e) => setNewUnit(e.target.value)}
className="rounded-xl border border-stone-300 px-3 py-3 text-sm outline-none focus:border-stone-900"
className="rounded-xl border border-[var(--admin-border)] px-3 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
>
{["CFS", "GPM", "Inches", "AF/Day"].map((u) => (
<option key={u} value={u}>{u}</option>
))}
</select>
</div>
<button type="submit" disabled={saving} className="rounded-xl bg-green-600 px-5 py-3 text-sm font-bold text-white disabled:opacity-50">
{saving ? "..." : "Create"}
</button>
<button type="button" onClick={() => setShowAdd(false)} className="rounded-xl border border-stone-300 px-4 py-3 text-sm text-stone-600">Cancel</button>
<AdminButton type="submit" disabled={saving} isLoading={saving}>
Create
</AdminButton>
<AdminButton type="button" variant="secondary" onClick={() => setShowAdd(false)}>
Cancel
</AdminButton>
</form>
</div>
)}
{/* Table */}
{headgates.length === 0 ? (
<div className="rounded-xl bg-zinc-900 py-16 text-center text-stone-400 ring-1 ring-stone-200">
<div className="rounded-xl bg-white py-16 text-center text-[var(--admin-text-muted)] border border-[var(--admin-border)]">
No headgates yet. Create one to get started.
</div>
) : (
<div className="rounded-xl bg-zinc-900 shadow-black/20 ring-1 ring-stone-200 overflow-hidden">
<div className="rounded-xl border border-[var(--admin-border)] bg-white overflow-hidden">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-stone-100 bg-zinc-950 text-left">
<tr className="border-b border-[var(--admin-border)] bg-[var(--admin-bg-subtle)] text-left">
<th className="px-4 py-3 w-8">
<input type="checkbox" className="rounded" onChange={toggleAll} checked={selected.size === headgates.length} />
</th>
<th className="px-4 py-3 text-xs font-semibold text-stone-500">Name</th>
<th className="px-4 py-3 text-xs font-semibold text-stone-500">Token</th>
<th className="px-4 py-3 text-xs font-semibold text-stone-500">Unit</th>
<th className="px-4 py-3 text-xs font-semibold text-stone-500">Last Used</th>
<th className="px-4 py-3 text-xs font-semibold text-stone-500">Status</th>
<th className="px-4 py-3 text-xs font-semibold text-stone-500 text-right">QR Code</th>
<th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)]">Name</th>
<th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)]">Token</th>
<th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)]">Unit</th>
<th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)]">Last Used</th>
<th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)]">Status</th>
<th className="px-4 py-3 text-xs font-semibold text-[var(--admin-text-muted)] text-right">QR Code</th>
</tr>
</thead>
<tbody>
{headgates.map((hg) => (
<tr key={hg.id} className={`border-b border-stone-50 last:border-0 hover:bg-zinc-950 ${selected.has(hg.id) ? "bg-blue-900/30" : ""}`}>
<tr key={hg.id} className={`border-b border-[var(--admin-border)] last:border-0 hover:bg-[var(--admin-bg-subtle)] ${selected.has(hg.id) ? "bg-blue-50" : ""}`}>
<td className="px-4 py-3">
<input type="checkbox" className="rounded" checked={selected.has(hg.id)} onChange={() => toggleSelect(hg.id)} />
</td>
<td className="px-4 py-3">
<div className="flex items-center gap-2 flex-wrap">
<span className="font-semibold text-zinc-100">{hg.name}</span>
<span className="font-semibold text-[var(--admin-text-primary)]">{hg.name}</span>
{hg.high_threshold != null && (
<span className="inline-flex items-center rounded-full bg-red-900/30 border border-red-200 px-1.5 py-0.5 text-xs font-semibold text-red-400">
<span className="inline-flex items-center rounded-full bg-red-100 border border-red-200 px-1.5 py-0.5 text-xs font-semibold text-red-700">
High: {hg.high_threshold}
</span>
)}
{hg.low_threshold != null && (
<span className="inline-flex items-center rounded-full bg-blue-900/30 border border-blue-200 px-1.5 py-0.5 text-xs font-semibold text-blue-700">
<span className="inline-flex items-center rounded-full bg-blue-100 border border-blue-200 px-1.5 py-0.5 text-xs font-semibold text-blue-700">
Low: {hg.low_threshold}
</span>
)}
</div>
</td>
<td className="px-4 py-3">
<code className="text-xs text-stone-500">{hg.headgate_token?.slice(0, 8)}</code>
<code className="text-xs text-[var(--admin-text-muted)]">{hg.headgate_token?.slice(0, 8)}</code>
</td>
<td className="px-4 py-3">
<span className="text-xs text-stone-500">{hg.unit}</span>
<span className="text-xs text-[var(--admin-text-muted)]">{hg.unit}</span>
</td>
<td className="px-4 py-3">
<span className="text-xs text-stone-500">
<span className="text-xs text-[var(--admin-text-muted)]">
{hg.last_used_at
? new Date(hg.last_used_at).toLocaleDateString("en-US", { month: "short", day: "numeric" })
: "Never"}
</span>
</td>
<td className="px-4 py-3">
<span className={`inline-flex rounded-full px-2 py-0.5 text-xs font-semibold ${hg.active ? "bg-green-900/40 text-green-400" : "bg-stone-100 text-stone-500"}`}>
<span className={`inline-flex rounded-full px-2 py-0.5 text-xs font-semibold ${hg.active ? "bg-green-100 text-green-700" : "bg-stone-100 text-stone-500"}`}>
{hg.active ? "Active" : "Inactive"}
</span>
</td>
<td className="px-4 py-3 text-right">
<div className="flex items-center justify-end gap-2">
<button onClick={() => openEdit(hg)} className="rounded-lg border border-zinc-800 bg-zinc-900 px-2 py-1 text-xs font-medium text-stone-600 hover:bg-zinc-950">
<AdminButton variant="secondary" size="sm" onClick={() => openEdit(hg)}>
Edit
</button>
</AdminButton>
{/* QR preview thumbnail */}
<button onClick={() => setQrModal(hg)} className="hover:opacity-80" title="View / Print QR">
<img
src={`/api/water-qr?token=${hg.headgate_token}&size=80`}
alt={`QR for ${hg.name}`}
className="w-10 h-10 rounded border border-zinc-800"
className="w-10 h-10 rounded border border-[var(--admin-border)]"
/>
</button>
<button
onClick={() => setQrModal(hg)}
className="rounded-lg border border-zinc-800 bg-zinc-900 px-2 py-1 text-xs font-medium text-stone-600 hover:bg-zinc-950"
>
<AdminButton variant="secondary" size="sm" onClick={() => setQrModal(hg)}>
Print
</button>
</AdminButton>
</div>
</td>
</tr>
@@ -324,7 +324,7 @@ export default function HeadgatesManager({ initialHeadgates, brandId }: Props) {
{/* Toast */}
{toast && (
<div className={`fixed bottom-6 right-6 rounded-xl px-4 py-3 text-sm font-semibold shadow-lg ${toast.ok ? "bg-green-900/40 text-green-800 border border-green-200" : "bg-red-900/40 text-red-800 border border-red-200"}`}>
<div className={`fixed bottom-6 right-6 rounded-xl px-4 py-3 text-sm font-semibold shadow-lg ${toast.ok ? "bg-green-100 text-green-800 border border-green-200" : "bg-red-100 text-red-800 border border-red-200"}`}>
{toast.msg}
</div>
)}
@@ -332,29 +332,33 @@ export default function HeadgatesManager({ initialHeadgates, brandId }: Props) {
{/* Edit Modal */}
{editHg && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50" onClick={() => setEditHg(null)}>
<div className="bg-zinc-900 rounded-2xl shadow-2xl w-full max-w-sm mx-4 overflow-hidden" onClick={(e) => e.stopPropagation()}>
<div className="flex items-center justify-between px-5 py-4 border-b border-zinc-800">
<p className="font-bold text-zinc-100">Edit Headgate</p>
<button onClick={() => setEditHg(null)} className="text-stone-400 hover:text-stone-600 text-xl leading-none"></button>
<div className="bg-white rounded-2xl shadow-2xl w-full max-w-sm mx-4 overflow-hidden border border-[var(--admin-border)]" onClick={(e) => e.stopPropagation()}>
<div className="flex items-center justify-between px-5 py-4 border-b border-[var(--admin-border)]">
<p className="font-bold text-[var(--admin-text-primary)]">Edit Headgate</p>
<button onClick={() => setEditHg(null)} className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-primary)]">
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<form onSubmit={handleEditSave} className="p-5 space-y-4">
<div>
<label className="block text-xs font-semibold text-stone-600 mb-1">Name</label>
<label className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">Name</label>
<input
type="text"
value={editName}
onChange={(e) => setEditName(e.target.value)}
className="w-full rounded-xl border border-stone-300 px-4 py-3 text-sm outline-none focus:border-stone-900"
className="w-full rounded-xl border border-[var(--admin-border)] px-4 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
required
/>
</div>
<div className="grid grid-cols-2 gap-3">
<div>
<label className="block text-xs font-semibold text-stone-600 mb-1">Unit</label>
<label className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">Unit</label>
<select
value={editUnit}
onChange={(e) => setEditUnit(e.target.value)}
className="w-full rounded-xl border border-stone-300 px-3 py-3 text-sm outline-none focus:border-stone-900"
className="w-full rounded-xl border border-[var(--admin-border)] px-3 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
>
{["CFS", "GPM", "Inches", "AF/Day"].map((u) => (
<option key={u} value={u}>{u}</option>
@@ -362,7 +366,7 @@ export default function HeadgatesManager({ initialHeadgates, brandId }: Props) {
</select>
</div>
<div className="flex items-center">
<label className="flex items-center gap-2 text-sm text-stone-700 cursor-pointer">
<label className="flex items-center gap-2 text-sm text-[var(--admin-text-secondary)] cursor-pointer">
<input type="checkbox" checked={editActive} onChange={(e) => setEditActive(e.target.checked)} className="rounded" />
Active
</label>
@@ -370,34 +374,36 @@ export default function HeadgatesManager({ initialHeadgates, brandId }: Props) {
</div>
<div className="grid grid-cols-2 gap-3">
<div>
<label className="block text-xs font-semibold text-stone-600 mb-1">High Alert Threshold</label>
<label className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">High Alert Threshold</label>
<input
type="number"
step="any"
value={editHigh}
onChange={(e) => setEditHigh(e.target.value)}
placeholder="e.g. 15.0"
className="w-full rounded-xl border border-stone-300 px-4 py-3 text-sm outline-none focus:border-stone-900"
className="w-full rounded-xl border border-[var(--admin-border)] px-4 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
/>
</div>
<div>
<label className="block text-xs font-semibold text-stone-600 mb-1">Low Alert Threshold</label>
<label className="block text-xs font-semibold text-[var(--admin-text-muted)] mb-1">Low Alert Threshold</label>
<input
type="number"
step="any"
value={editLow}
onChange={(e) => setEditLow(e.target.value)}
placeholder="e.g. 5.0"
className="w-full rounded-xl border border-stone-300 px-4 py-3 text-sm outline-none focus:border-stone-900"
className="w-full rounded-xl border border-[var(--admin-border)] px-4 py-3 text-sm outline-none focus:border-[var(--admin-accent)]"
/>
</div>
</div>
<p className="text-xs text-stone-400">Leave thresholds blank to disable alerts for this headgate.</p>
<p className="text-xs text-[var(--admin-text-muted)]">Leave thresholds blank to disable alerts for this headgate.</p>
<div className="flex gap-2">
<button type="submit" disabled={editSaving} className="flex-1 rounded-xl bg-green-600 py-3 text-sm font-bold text-white disabled:opacity-50">
{editSaving ? "..." : "Save Changes"}
</button>
<button type="button" onClick={() => setEditHg(null)} className="rounded-xl border border-stone-300 px-4 py-3 text-sm text-stone-600">Cancel</button>
<AdminButton type="submit" disabled={editSaving} isLoading={editSaving} fullWidth>
Save Changes
</AdminButton>
<AdminButton type="button" variant="secondary" onClick={() => setEditHg(null)}>
Cancel
</AdminButton>
</div>
</form>
</div>
@@ -454,21 +460,25 @@ function QRModal({ hg, onClose, onRegenerate }: { hg: Headgate; onClose: () => v
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50" onClick={onClose}>
<div className="bg-zinc-900 rounded-2xl shadow-2xl w-full max-w-sm mx-4 overflow-hidden" onClick={(e) => e.stopPropagation()}>
<div className="bg-white rounded-2xl shadow-2xl w-full max-w-sm mx-4 overflow-hidden border border-[var(--admin-border)]" onClick={(e) => e.stopPropagation()}>
{/* Header */}
<div className="flex items-center justify-between px-5 py-4 border-b border-slate-100">
<div className="flex items-center justify-between px-5 py-4 border-b border-[var(--admin-border)]">
<div>
<p className="font-bold text-zinc-100">{hg.name}</p>
<p className="text-xs text-slate-400 mt-0.5">QR Label Preview</p>
<p className="font-bold text-[var(--admin-text-primary)]">{hg.name}</p>
<p className="text-xs text-[var(--admin-text-muted)] mt-0.5">QR Label Preview</p>
</div>
<button onClick={onClose} className="text-slate-400 hover:text-zinc-400 text-xl leading-none"></button>
<button onClick={onClose} className="text-[var(--admin-text-muted)] hover:text-[var(--admin-text-primary)]">
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
{/* ── Simplified label preview ── */}
<div className="flex justify-center bg-zinc-900 py-6 px-4">
<div className="flex justify-center bg-[var(--admin-bg-subtle)] py-6 px-4">
{/* Mini version of the new label design */}
<div className="w-40 border-2 border-black rounded-lg p-3 text-center bg-zinc-900 shadow-black/20">
<div className="w-40 border-2 border-black rounded-lg p-3 text-center bg-white shadow-sm">
<div className="text-xl font-black text-black leading-tight tracking-tight">{hg.name}</div>
<div className="text-[9px] font-bold text-gray-500 uppercase tracking-widest mt-0.5 mb-3">{code}</div>
<div className="flex justify-center mb-2">
@@ -478,17 +488,17 @@ function QRModal({ hg, onClose, onRegenerate }: { hg: Headgate; onClose: () => v
className="w-28 h-28 rounded"
/>
</div>
<div className="text-[5.5px] text-gray-300 leading-tight break-all">{waterUrl}</div>
<div className="text-[5.5px] text-gray-500 leading-tight break-all">{waterUrl}</div>
</div>
</div>
{/* Tab toggle */}
<div className="flex border-b border-slate-100">
<div className="flex border-b border-[var(--admin-border)]">
{(["preview", "print", "download"] as const).map((t) => (
<button
key={t}
onClick={() => setTab(t)}
className={`flex-1 py-3 text-sm font-semibold transition-colors ${tab === t ? "text-zinc-100 border-b-2 border-slate-900" : "text-slate-400"}`}
className={`flex-1 py-3 text-sm font-semibold transition-colors ${tab === t ? "text-[var(--admin-text-primary)] border-b-2 border-[var(--admin-accent)]" : "text-[var(--admin-text-muted)]"}`}
>
{t === "preview" ? "Preview" : t === "print" ? "🖨️ Print" : "💾 Download"}
</button>
@@ -497,38 +507,39 @@ function QRModal({ hg, onClose, onRegenerate }: { hg: Headgate; onClose: () => v
<div className="p-5 space-y-3">
{tab === "preview" ? (
<div className="space-y-2 text-sm text-zinc-400">
<div className="space-y-2 text-sm text-[var(--admin-text-secondary)]">
<p>This label is optimized for physical signs and thermal printing:</p>
<ul className="list-disc list-inside space-y-1 text-xs text-zinc-500">
<ul className="list-disc list-inside space-y-1 text-xs text-[var(--admin-text-muted)]">
<li><strong>Large name</strong> (24pt bold) scannable from distance</li>
<li><strong>Short code</strong> (e.g. <code className="font-mono bg-zinc-950 px-1 rounded">{code}</code>) field reference</li>
<li><strong>Short code</strong> (e.g. <code className="font-mono bg-[var(--admin-bg-subtle)] px-1 rounded">{code}</code>) field reference</li>
<li><strong>High-contrast QR</strong> error correction H for outdoor use</li>
<li><strong>Tiny URL</strong> at bottom reference only</li>
</ul>
<button onClick={() => setTab("print")} className="w-full rounded-xl bg-slate-900 py-3 text-base font-bold text-white hover:bg-slate-800 transition-colors mt-2">
<AdminButton onClick={() => setTab("print")} fullWidth>
🖨 Print This Label
</button>
</AdminButton>
</div>
) : tab === "print" ? (
<button onClick={handlePrintLabel} disabled={loading} className="w-full rounded-xl bg-slate-900 py-3 text-base font-bold text-white disabled:opacity-50">
{loading ? "..." : "🖨️ Print Label"}
</button>
<AdminButton onClick={handlePrintLabel} disabled={loading} isLoading={loading} fullWidth>
🖨 Print Label
</AdminButton>
) : (
<button onClick={handleDownload} disabled={loading} className="w-full rounded-xl bg-blue-600 py-3 text-base font-bold text-white disabled:opacity-50">
{loading ? "..." : "💾 Download PNG"}
</button>
<AdminButton onClick={handleDownload} disabled={loading} isLoading={loading} fullWidth>
💾 Download PNG
</AdminButton>
)}
<button
<AdminButton
onClick={() => { onRegenerate(hg); onClose(); }}
className="w-full rounded-xl border border-zinc-800 py-2.5 text-sm font-medium text-zinc-400 hover:bg-zinc-800"
variant="secondary"
fullWidth
>
🔄 Regenerate Token
</button>
</AdminButton>
<div className="rounded-lg bg-zinc-900 p-3">
<p className="text-xs text-zinc-500 mb-1">Token</p>
<code className="text-xs text-zinc-300 font-mono break-all">{hg.headgate_token}</code>
<div className="rounded-lg border border-[var(--admin-border)] p-3">
<p className="text-xs text-[var(--admin-text-muted)] mb-1">Token</p>
<code className="text-xs text-[var(--admin-text-secondary)] font-mono break-all">{hg.headgate_token}</code>
</div>
</div>
</div>