chore: change styling
Some checks failed
Deploy to Production / test (push) Failing after 34s

This commit is contained in:
syntaxbullet
2026-04-02 19:05:36 +02:00
parent e0dcfe6abe
commit abca1922f2
44 changed files with 427 additions and 7180 deletions

View File

@@ -62,7 +62,7 @@ function AppRoutes() {
<p className="text-sm text-muted-foreground mb-8">Welcome to Aurora</p>
<a
href={`/auth/discord?return_to=${encodeURIComponent(window.location.pathname)}`}
className="inline-flex items-center justify-center w-full rounded-md bg-primary text-primary-foreground px-4 py-2 text-sm font-medium hover:bg-primary/90 transition-colors"
className="inline-flex items-center justify-center w-full rounded-md bg-primary text-on-primary px-4 py-2 text-sm font-label font-medium hover:opacity-90 transition-colors"
>
Sign in with Discord
</a>

View File

@@ -91,7 +91,7 @@ export default function Layout({
key={path}
onClick={() => handleNav(path)}
className={cn(
"w-full flex items-center gap-3 rounded-md px-3 py-2.5 text-sm font-medium transition-colors",
"w-full flex items-center gap-3 rounded-xl px-3 py-2.5 text-sm font-medium transition-colors",
isActive(path)
? "bg-primary/15 text-primary border-l-4 border-primary"
: "text-text-tertiary hover:bg-primary/8 hover:text-foreground"
@@ -103,7 +103,7 @@ export default function Layout({
))}
</nav>
<div className="border-t border-border p-3 space-y-2">
<div className="pt-3 p-3 space-y-2">
{(!collapsed || mobileOpen) && (
<div className="flex items-center gap-3 px-2 py-1.5">
{avatarUrl ? (
@@ -143,7 +143,7 @@ export default function Layout({
return (
<div className="min-h-screen flex">
{/* Mobile header bar */}
<div className="fixed top-0 left-0 right-0 z-40 flex items-center h-14 px-4 bg-background border-b border-border md:hidden">
<div className="fixed top-0 left-0 right-0 z-40 flex items-center h-14 px-4 bg-background md:hidden">
<button
onClick={() => setMobileOpen(true)}
className="p-2 -ml-2 rounded-md text-text-tertiary hover:text-foreground hover:bg-primary/10 transition-colors"
@@ -164,7 +164,7 @@ export default function Layout({
{/* Sidebar - mobile drawer + desktop fixed */}
<aside
className={cn(
"fixed inset-y-0 left-0 z-50 flex flex-col bg-background border-r border-border transition-all duration-200",
"fixed inset-y-0 left-0 z-50 flex flex-col bg-surface-container-low transition-all duration-200",
// Mobile: off-screen drawer, shown when mobileOpen
"w-60 -translate-x-full md:translate-x-0",
mobileOpen && "translate-x-0",
@@ -172,7 +172,7 @@ export default function Layout({
!mobileOpen && collapsed && "md:w-16"
)}
>
<div className="flex items-center justify-between h-14 md:h-16 px-4 border-b border-border">
<div className="flex items-center justify-between h-14 md:h-16 px-4">
<div className="font-display text-xl font-bold tracking-tight">
{collapsed && !mobileOpen ? "A" : "Aurora"}
</div>

View File

@@ -56,7 +56,7 @@ export function GameLobby() {
</div>
<button
onClick={() => setShowCreate(true)}
className="rounded-md bg-primary text-primary-foreground px-4 py-2 text-sm font-medium hover:bg-primary/90 transition-colors shrink-0"
className="rounded-xl bg-primary text-on-primary px-4 py-2 text-sm font-label font-medium hover:opacity-90 transition-colors shrink-0"
>
+ Create Room
</button>
@@ -84,21 +84,21 @@ export function GameLobby() {
))}
</div>
<div className="bg-card rounded-lg border border-border">
<div className="flex items-center gap-2 px-5 py-3 border-b border-border">
<span className="text-sm font-semibold">Active Rooms</span>
<span className="text-xs text-text-disabled">({activeRooms.length})</span>
<div className="bg-card rounded-xl">
<div className="flex items-center gap-2 px-5 py-3">
<span className="text-sm font-display font-semibold">Active Rooms</span>
<span className="text-xs text-text-disabled font-label">({activeRooms.length})</span>
</div>
{activeRooms.length === 0 ? (
<div className="px-5 py-8 text-center text-sm text-text-tertiary">
No active rooms. Create one to get started!
</div>
) : (
<div className="divide-y divide-border">
<div className="px-2 pb-2 space-y-0.5">
{activeRooms.map(room => {
const plugin = gameUIRegistry.get(room.gameSlug);
return (
<div key={room.id} className="flex items-center justify-between gap-3 px-4 py-3 md:px-5 hover:bg-raised/40 transition-colors">
<div key={room.id} className="flex items-center justify-between gap-3 px-3 py-3 md:px-4 hover:bg-raised/30 transition-colors rounded-lg">
<div className="flex items-center gap-3 min-w-0">
<span className="text-lg shrink-0">{plugin?.icon ?? "🎮"}</span>
<div className="min-w-0">
@@ -120,10 +120,10 @@ export function GameLobby() {
onClick={() => navigate(`/${room.gameSlug}/${room.id}`, {
state: { preferAs: room.status === "waiting" ? "player" : "spectator" }
})}
className={`rounded-md px-3 py-1.5 text-xs font-semibold transition-colors shrink-0 ${
className={`rounded-xl px-3 py-1.5 text-xs font-label font-semibold transition-colors shrink-0 ${
room.status === "waiting"
? "bg-primary text-primary-foreground hover:bg-primary/90"
: "bg-card border border-border text-text-tertiary hover:text-foreground"
? "bg-primary text-on-primary hover:opacity-90"
: "bg-raised text-text-tertiary hover:text-foreground"
}`}
>
{room.status === "waiting" ? "Join" : "Spectate"}
@@ -137,14 +137,14 @@ export function GameLobby() {
{showCreate && (
<div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/50" onClick={() => setShowCreate(false)}>
<div className="bg-card border border-border rounded-t-xl sm:rounded-lg p-6 w-full sm:max-w-sm" onClick={e => e.stopPropagation()}>
<div className="bg-surface-container-highest rounded-xl p-6 w-full sm:max-w-sm shadow-[0_20px_40px_rgba(0,0,0,0.5)]" onClick={e => e.stopPropagation()}>
<h2 className="font-display text-base font-semibold mb-4">Create a Room</h2>
<div className="space-y-2">
{gameTypes.map(g => (
<button
key={g.slug}
onClick={() => createRoom(g.slug)}
className="w-full flex items-center gap-3 rounded-md border border-border px-4 py-3 text-sm font-medium hover:bg-raised/40 transition-colors"
className="w-full flex items-center gap-3 rounded-xl bg-raised px-4 py-3 text-sm font-medium hover:bg-surface-container-high transition-colors"
>
<span className="text-lg">{g.icon}</span>
<span>{g.name}</span>

View File

@@ -17,7 +17,7 @@ function CopyInviteLink({ url }: { url: string }) {
<div className="flex flex-col items-center gap-2">
<div className="text-xs text-text-disabled mb-1">Share this link to invite:</div>
<div className="flex items-center gap-2 w-full max-w-sm">
<span className="flex-1 font-mono bg-surface border border-border px-2 py-1.5 rounded text-[11px] text-text-tertiary truncate">
<span className="flex-1 font-mono bg-card rounded-lg px-2 py-1.5 text-[11px] text-text-tertiary truncate">
{url}
</span>
<button
@@ -25,7 +25,7 @@ function CopyInviteLink({ url }: { url: string }) {
className={`shrink-0 rounded px-3 py-1.5 text-xs font-medium transition-colors ${
copied
? "bg-success/15 text-success"
: "bg-card border border-border text-text-tertiary hover:text-foreground"
: "bg-raised text-text-tertiary hover:text-foreground"
}`}
>
{copied ? "Copied!" : "Copy"}
@@ -107,14 +107,14 @@ export function GameRoom({ userId, role }: { userId: string; role?: string }) {
</div>
<button
onClick={() => { leaveRoom(); navigate("/games"); }}
className="rounded-md px-3 py-1.5 text-sm font-medium bg-card border border-border text-text-tertiary hover:text-foreground transition-colors shrink-0"
className="rounded-md px-3 py-1.5 text-sm font-medium bg-raised text-text-tertiary hover:text-foreground transition-colors shrink-0"
>
Leave
</button>
</div>
{sessionReplaced && (
<div className="mb-4 rounded-lg border border-warning/40 bg-warning/10 px-4 py-3 flex items-center justify-between gap-3">
<div className="mb-4 rounded-xl bg-warning/10 px-4 py-3 flex items-center justify-between gap-3">
<p className="text-sm text-warning">
You opened this game in another tab. Actions from this tab are disabled.
</p>
@@ -128,13 +128,13 @@ export function GameRoom({ userId, role }: { userId: string; role?: string }) {
)}
{error && (
<div className="mb-4 rounded-lg border border-destructive/30 bg-destructive/10 px-4 py-2 text-sm text-destructive">
<div className="mb-4 rounded-xl bg-destructive/10 px-4 py-2 text-sm text-destructive">
{error}
</div>
)}
{gameOver && (
<div className="mb-4 rounded-lg border border-primary/30 bg-primary/10 px-4 py-3">
<div className="mb-4 rounded-xl bg-primary/10 px-4 py-3">
<div className="text-sm font-semibold text-primary">
{gameOver.winner
? `Winner: ${players.find(p => p.discordId === gameOver.winner)?.username ?? gameOver.winner}`
@@ -148,7 +148,7 @@ export function GameRoom({ userId, role }: { userId: string; role?: string }) {
<div className="mt-4 text-center">
<button
onClick={() => { leaveRoom(); navigate("/games"); }}
className="rounded-md bg-primary text-primary-foreground px-5 py-2 text-sm font-medium hover:bg-primary/90 transition-colors"
className="rounded-xl bg-primary text-on-primary px-5 py-2 text-sm font-label font-medium hover:opacity-90 transition-colors"
>
Back to Lobby
</button>
@@ -156,7 +156,7 @@ export function GameRoom({ userId, role }: { userId: string; role?: string }) {
)}
{roomStatus === "waiting" && (
<div className="bg-card rounded-lg border border-border p-5 md:p-8">
<div className="bg-card rounded-xl p-5 md:p-8">
<div className="text-sm font-semibold mb-4 text-center">
Waiting for players ({players.length}/{plugin.maxPlayers})
</div>
@@ -164,7 +164,7 @@ export function GameRoom({ userId, role }: { userId: string; role?: string }) {
{Array.from({ length: plugin.maxPlayers }).map((_, i) => {
const player = players[i];
return (
<div key={i} className={`flex flex-col items-center gap-2 px-4 py-3 rounded-lg border ${player ? "border-primary/40 bg-primary/5" : "border-border bg-surface"}`}>
<div key={i} className={`flex flex-col items-center gap-2 px-4 py-3 rounded-xl ${player ? "bg-primary/10" : "bg-surface"}`}>
<div className={`w-10 h-10 rounded-full flex items-center justify-center text-sm font-semibold ${player ? "bg-primary/20 text-primary" : "bg-surface text-text-disabled animate-pulse"}`}>
{player ? player.username[0]?.toUpperCase() : "?"}
</div>

View File

@@ -1,4 +1,4 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Space+Grotesk:wght@600;700&family=JetBrains+Mono:wght@400;500&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif:ital,wght@0,400;0,600;0,700;1,400&family=Manrope:wght@400;500;600;700&family=Space+Grotesk:wght@500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
@import "tailwindcss";
@plugin "tailwindcss-animate";
@@ -6,44 +6,72 @@
@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: #0A0A0F;
--color-foreground: #F9FAFB;
--color-muted: #151520;
--color-muted-foreground: #9CA3AF;
--color-border: rgba(139, 92, 246, 0.15);
--color-input: #1E1B4B;
--color-ring: #8B5CF6;
--color-primary: #8B5CF6;
--color-primary-foreground: #FFFFFF;
--color-secondary: #1E1B4B;
--color-secondary-foreground: #F9FAFB;
--color-accent: #2D2A5F;
--color-accent-foreground: #F9FAFB;
--color-destructive: #DC2626;
--color-destructive-foreground: #FFFFFF;
--color-card: #151520;
--color-card-foreground: #F9FAFB;
--color-success: #10B981;
--color-warning: #F59E0B;
--color-info: #3B82F6;
--color-gold: #FCD34D;
--color-surface: #1E1B4B;
--color-raised: #2D2A5F;
--color-text-secondary: #E5E7EB;
--color-text-tertiary: #9CA3AF;
--color-text-disabled: #6B7280;
--radius-sm: 0.25rem;
--radius-md: 0.5rem;
--radius-lg: 0.75rem;
/* ── Surface hierarchy: "The Void & The Light" ── */
--color-background: #0d1323;
--color-surface: #0d1323;
--color-surface-container-low: #151b2c;
--color-surface-container-high: #24293b;
--color-surface-container-highest: #2f3446;
--font-display: 'Space Grotesk', 'Inter', sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
/* Semantic aliases used by existing components */
--color-card: #151b2c;
--color-raised: #24293b;
--color-input: #0d1323;
--color-muted: #151b2c;
--color-muted-foreground: #7a7f96;
/* ── Primary — Celestial Gold ── */
--color-primary: #e9c349;
--color-primary-fixed-dim: #d4af37;
--color-primary-foreground: #1a1400;
--color-on-primary: #1a1400;
--color-primary-container: #3d2e00;
--color-ring: #e9c349;
/* ── Secondary — Midnight Blue / Silver ── */
--color-secondary: #1a2040;
--color-secondary-foreground: #c8cad6;
/* ── Accent ── */
--color-accent: #24293b;
--color-accent-foreground: #e2e4f0;
/* ── Neutral Text ── */
--color-foreground: #e2e4f0;
--color-card-foreground: #e2e4f0;
--color-text-secondary: #c8cad6;
--color-text-tertiary: #7a7f96;
--color-text-disabled: #4a4f66;
/* ── Borders: "Ghost Border" principle ── */
--color-border: rgba(69, 70, 76, 0.18);
--color-outline-variant: rgba(69, 70, 76, 0.45);
/* ── Semantic state colors ── */
--color-destructive: #dc2626;
--color-destructive-foreground: #ffffff;
--color-success: #10b981;
--color-warning: #f59e0b;
--color-info: #3b82f6;
--color-gold: #e9c349;
/* ── Roundedness Scale ── */
--radius-sm: 0.25rem;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--radius-xl: 0.75rem;
/* ── Type system: "Academic Authority" ── */
--font-display: 'Noto Serif', Georgia, 'Times New Roman', serif;
--font-body: 'Manrope', system-ui, -apple-system, sans-serif;
--font-label: 'Space Grotesk', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace;
}
body {
background-color: var(--color-background);
color: var(--color-foreground);
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
font-family: var(--font-body);
}
* {

View File

@@ -308,7 +308,7 @@ function AiRemoveTab({ imageFile, imageSrc, onClear }: {
<button
onClick={onClear}
className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-md border border-border text-xs text-text-tertiary",
"flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-xs text-text-tertiary",
"hover:text-destructive hover:border-destructive transition-colors",
)}
>
@@ -321,8 +321,8 @@ function AiRemoveTab({ imageFile, imageSrc, onClear }: {
className={cn(
"flex items-center gap-1.5 px-4 py-1.5 rounded-md text-xs font-semibold transition-colors",
status === "loading"
? "bg-raised border border-border text-text-tertiary cursor-not-allowed"
: "bg-primary text-white hover:bg-primary/90",
? "bg-raised text-text-tertiary cursor-not-allowed"
: "bg-primary text-on-primary hover:opacity-90",
)}
>
{status === "loading" ? (
@@ -334,7 +334,7 @@ function AiRemoveTab({ imageFile, imageSrc, onClear }: {
) : (
<button
onClick={handleDownload}
className="flex items-center gap-1.5 px-4 py-1.5 rounded-md text-xs font-semibold bg-primary text-white hover:bg-primary/90 transition-colors"
className="flex items-center gap-1.5 px-4 py-1.5 rounded-md text-xs font-semibold bg-primary text-on-primary hover:opacity-90 transition-colors"
>
<Download className="w-3.5 h-3.5" /> Download PNG
</button>
@@ -351,7 +351,7 @@ function AiRemoveTab({ imageFile, imageSrc, onClear }: {
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<p className="text-xs font-semibold text-text-tertiary uppercase tracking-wider">Original</p>
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
<img src={imageSrc} className="w-full block" alt="Original" />
</div>
</div>
@@ -378,7 +378,7 @@ function AiRemoveTab({ imageFile, imageSrc, onClear }: {
))}
</div>
</div>
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
{resultUrl ? (
<div style={BG_PRESETS[bgPreset].style}>
<img src={resultUrl} className="w-full block" alt="Result" />
@@ -643,7 +643,7 @@ export function BackgroundRemoval() {
<button
onClick={clearAll}
className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-md border border-border text-xs text-text-tertiary",
"flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-xs text-text-tertiary",
"hover:text-destructive hover:border-destructive transition-colors",
)}
>
@@ -655,8 +655,8 @@ export function BackgroundRemoval() {
className={cn(
"flex items-center gap-1.5 px-4 py-1.5 rounded-md text-xs font-semibold transition-colors",
hasResult
? "bg-primary text-white hover:bg-primary/90"
: "bg-raised border border-border text-text-tertiary cursor-not-allowed",
? "bg-primary text-on-primary hover:opacity-90"
: "bg-raised text-text-tertiary cursor-not-allowed",
)}
>
<Download className="w-3.5 h-3.5" /> Download PNG
@@ -664,14 +664,14 @@ export function BackgroundRemoval() {
</div>
{/* Controls */}
<div className="bg-card border border-border rounded-xl p-4 space-y-4">
<div className="bg-card rounded-xl p-4 space-y-4">
{/* Row 1 — Key color + mode */}
<div className="flex flex-wrap gap-6 items-center">
<div className="space-y-1.5 shrink-0">
<p className="text-xs font-medium text-text-secondary">Key Color</p>
<div className="flex items-center gap-2">
<div
className="w-7 h-7 rounded-md border border-border shadow-inner shrink-0"
className="w-7 h-7 rounded-lg shadow-inner shrink-0"
style={
keyColor
? { backgroundColor: rgbToHex(...keyColor) }
@@ -704,12 +704,12 @@ export function BackgroundRemoval() {
<div className="space-y-1.5 shrink-0">
<p className="text-xs font-medium text-text-secondary">Keying Mode</p>
<div className="flex rounded-md border border-border overflow-hidden text-xs font-medium">
<div className="flex rounded-xl overflow-hidden text-xs font-medium">
<button
onClick={() => setHueMode(false)}
className={cn(
"px-3 py-1.5 transition-colors",
!hueMode ? "bg-primary text-white" : "text-text-secondary hover:text-foreground hover:bg-raised",
!hueMode ? "bg-primary text-on-primary" : "text-text-secondary hover:text-foreground hover:bg-raised",
)}
>
RGB
@@ -718,7 +718,7 @@ export function BackgroundRemoval() {
onClick={() => setHueMode(true)}
className={cn(
"px-3 py-1.5 transition-colors border-l border-border",
hueMode ? "bg-primary text-white" : "text-text-secondary hover:text-foreground hover:bg-raised",
hueMode ? "bg-primary text-on-primary" : "text-text-secondary hover:text-foreground hover:bg-raised",
)}
>
HSV
@@ -804,7 +804,7 @@ export function BackgroundRemoval() {
<p className="text-xs font-semibold text-text-tertiary uppercase tracking-wider">
Original click to pick key color
</p>
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
<canvas ref={sourceCanvasRef} className="w-full cursor-crosshair block" onClick={handleCanvasClick} title="Click a pixel to set it as the chroma key color" />
</div>
</div>
@@ -831,7 +831,7 @@ export function BackgroundRemoval() {
))}
</div>
</div>
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
<div style={BG_PRESETS[bgPreset].style} className={cn("w-full", !hasResult && "hidden")}>
<canvas ref={glCanvasRef} className="w-full block" />
</div>
@@ -858,12 +858,12 @@ export function BackgroundRemoval() {
function ModeToggle({ mode, onChange }: { mode: Mode; onChange: (m: Mode) => void }) {
return (
<div className="flex rounded-md border border-border overflow-hidden text-xs font-medium shrink-0">
<div className="flex rounded-xl overflow-hidden text-xs font-medium shrink-0">
<button
onClick={() => onChange("chroma")}
className={cn(
"px-3 py-1.5 transition-colors",
mode === "chroma" ? "bg-primary text-white" : "text-text-secondary hover:text-foreground hover:bg-raised",
mode === "chroma" ? "bg-primary text-on-primary" : "text-text-secondary hover:text-foreground hover:bg-raised",
)}
>
Chroma Key
@@ -872,7 +872,7 @@ function ModeToggle({ mode, onChange }: { mode: Mode; onChange: (m: Mode) => voi
onClick={() => onChange("ai")}
className={cn(
"px-3 py-1.5 transition-colors border-l border-border",
mode === "ai" ? "bg-primary text-white" : "text-text-secondary hover:text-foreground hover:bg-raised",
mode === "ai" ? "bg-primary text-on-primary" : "text-text-secondary hover:text-foreground hover:bg-raised",
)}
>
AI Remove

View File

@@ -270,7 +270,7 @@ export function CanvasTool() {
<button
onClick={clearAll}
className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-md border border-border text-xs text-text-tertiary",
"flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-xs text-text-tertiary",
"hover:text-destructive hover:border-destructive transition-colors",
)}
>
@@ -282,8 +282,8 @@ export function CanvasTool() {
className={cn(
"flex items-center gap-1.5 px-4 py-1.5 rounded-md text-xs font-semibold transition-colors",
imageReady
? "bg-primary text-white hover:bg-primary/90"
: "bg-raised border border-border text-text-tertiary cursor-not-allowed",
? "bg-primary text-on-primary hover:opacity-90"
: "bg-raised text-text-tertiary cursor-not-allowed",
)}
>
<Download className="w-3.5 h-3.5" /> Download PNG
@@ -291,7 +291,7 @@ export function CanvasTool() {
</div>
{/* Controls */}
<div className="bg-card border border-border rounded-xl p-4 space-y-4">
<div className="bg-card rounded-xl p-4 space-y-4">
{/* Row 1: output size */}
<div className="flex flex-wrap gap-4 items-end">
<div className="space-y-1.5">
@@ -301,7 +301,7 @@ export function CanvasTool() {
type="number" min="1" max="4096" value={outW}
onChange={(e) => handleWChange(e.target.value)}
className={cn(
"w-20 bg-input border border-border rounded-md px-2 py-1.5 text-sm text-foreground font-mono",
"w-20 bg-input border-b-2 border-outline-variant rounded-none px-2 py-1.5 text-sm text-foreground font-mono",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
)}
placeholder="W"
@@ -311,7 +311,7 @@ export function CanvasTool() {
type="number" min="1" max="4096" value={outH}
onChange={(e) => handleHChange(e.target.value)}
className={cn(
"w-20 bg-input border border-border rounded-md px-2 py-1.5 text-sm text-foreground font-mono",
"w-20 bg-input border-b-2 border-outline-variant rounded-none px-2 py-1.5 text-sm text-foreground font-mono",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
)}
placeholder="H"
@@ -437,7 +437,7 @@ export function CanvasTool() {
<p className="text-xs font-semibold text-text-tertiary uppercase tracking-wider">
Original {naturalW}×{naturalH}
</p>
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
<div style={CHECKERBOARD}>
<img src={imageSrc} alt="Source" className="w-full block" />
</div>
@@ -467,7 +467,7 @@ export function CanvasTool() {
))}
</div>
</div>
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
<div style={BG_PRESETS[bgPreset].style} className={cn("w-full", !imageReady && "hidden")}>
<canvas ref={previewCanvasRef} className="w-full block" />
</div>

View File

@@ -480,7 +480,7 @@ export function CropTool() {
<button
onClick={clearAll}
className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-md border border-border text-xs text-text-tertiary",
"flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-xs text-text-tertiary",
"hover:text-destructive hover:border-destructive transition-colors",
)}
>
@@ -492,8 +492,8 @@ export function CropTool() {
className={cn(
"flex items-center gap-1.5 px-4 py-1.5 rounded-md text-xs font-semibold transition-colors",
imageReady
? "bg-primary text-white hover:bg-primary/90"
: "bg-raised border border-border text-text-tertiary cursor-not-allowed",
? "bg-primary text-on-primary hover:opacity-90"
: "bg-raised text-text-tertiary cursor-not-allowed",
)}
>
<Download className="w-3.5 h-3.5" /> Download PNG
@@ -501,7 +501,7 @@ export function CropTool() {
</div>
{/* Controls */}
<div className="bg-card border border-border rounded-xl p-4 space-y-3">
<div className="bg-card rounded-xl p-4 space-y-3">
<div className="flex flex-wrap gap-4 items-end">
<label className="space-y-1.5">
<span className="text-xs font-medium text-text-secondary block">Output W (px)</span>
@@ -511,7 +511,7 @@ export function CropTool() {
value={cropW}
onChange={(e) => setCropW(Math.max(MIN_CROP, parseIntSafe(e.target.value, MIN_CROP)))}
className={cn(
"w-24 bg-input border border-border rounded-md px-2 py-1.5 text-sm text-foreground font-mono",
"w-24 bg-input border-b-2 border-outline-variant rounded-none px-2 py-1.5 text-sm text-foreground font-mono",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
)}
/>
@@ -524,7 +524,7 @@ export function CropTool() {
value={cropH}
onChange={(e) => setCropH(Math.max(MIN_CROP, parseIntSafe(e.target.value, MIN_CROP)))}
className={cn(
"w-24 bg-input border border-border rounded-md px-2 py-1.5 text-sm text-foreground font-mono",
"w-24 bg-input border-b-2 border-outline-variant rounded-none px-2 py-1.5 text-sm text-foreground font-mono",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
)}
/>
@@ -536,7 +536,7 @@ export function CropTool() {
value={imgX}
onChange={(e) => setImgX(parseIntSafe(e.target.value, 0))}
className={cn(
"w-20 bg-input border border-border rounded-md px-2 py-1.5 text-sm text-foreground font-mono",
"w-20 bg-input border-b-2 border-outline-variant rounded-none px-2 py-1.5 text-sm text-foreground font-mono",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
)}
/>
@@ -548,7 +548,7 @@ export function CropTool() {
value={imgY}
onChange={(e) => setImgY(parseIntSafe(e.target.value, 0))}
className={cn(
"w-20 bg-input border border-border rounded-md px-2 py-1.5 text-sm text-foreground font-mono",
"w-20 bg-input border-b-2 border-outline-variant rounded-none px-2 py-1.5 text-sm text-foreground font-mono",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
)}
/>
@@ -567,7 +567,7 @@ export function CropTool() {
value={padding}
onChange={(e) => setPadding(Math.max(0, parseIntSafe(e.target.value, 0)))}
className={cn(
"w-20 bg-input border border-border rounded-md px-2 py-1.5 text-sm text-foreground font-mono",
"w-20 bg-input border-b-2 border-outline-variant rounded-none px-2 py-1.5 text-sm text-foreground font-mono",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
)}
/>
@@ -576,7 +576,7 @@ export function CropTool() {
<button
onClick={autoCenter}
className={cn(
"flex items-center gap-1.5 px-3 py-2 rounded-md border border-border text-xs font-medium transition-colors",
"flex items-center gap-1.5 px-3 py-2 rounded-xl text-xs font-medium transition-colors",
"bg-input text-text-secondary hover:text-primary hover:border-primary/60",
)}
title="Pan the image so non-transparent content is centered within the current output canvas"
@@ -586,7 +586,7 @@ export function CropTool() {
<button
onClick={fitToContent}
className={cn(
"flex items-center gap-1.5 px-3 py-2 rounded-md border border-border text-xs font-medium transition-colors",
"flex items-center gap-1.5 px-3 py-2 rounded-xl text-xs font-medium transition-colors",
"bg-input text-text-secondary hover:text-primary hover:border-primary/60",
)}
title="Resize output to the non-transparent content bounding box + padding, then center"
@@ -607,7 +607,7 @@ export function CropTool() {
Editor
</p>
<div
className="bg-card border border-border rounded-lg overflow-auto"
className="bg-card rounded-xl overflow-auto"
style={{ maxHeight: "62vh" }}
>
<canvas
@@ -626,7 +626,7 @@ export function CropTool() {
<p className="text-xs font-semibold text-text-tertiary uppercase tracking-wider">
Preview
</p>
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
{imageReady ? (
<div style={CHECKERBOARD}>
<canvas

View File

@@ -75,7 +75,7 @@ function StatCard({
return (
<div
className={cn(
"bg-gradient-to-br from-card to-surface rounded-lg border border-border p-6 border-l-4",
"bg-gradient-to-br from-card to-surface rounded-xl p-6 border-l-4",
accent
)}
>
@@ -105,19 +105,19 @@ function LeaderboardColumn({
valuePrefix?: string;
}) {
return (
<div className="bg-card rounded-lg border border-border">
<div className="flex items-center gap-2 px-5 py-4 border-b border-border">
<div className="bg-card rounded-xl">
<div className="flex items-center gap-2 px-5 py-4">
<Icon className="w-4 h-4 text-primary" />
<h3 className="text-sm font-semibold">{title}</h3>
<h3 className="text-sm font-display font-semibold">{title}</h3>
</div>
<div className="divide-y divide-border">
<div className="space-y-0">
{entries.length === 0 && (
<div className="px-5 py-4 text-sm text-text-tertiary">No data</div>
)}
{entries.slice(0, 10).map((entry, i) => (
<div
key={entry.username}
className="flex items-center justify-between px-5 py-3 hover:bg-raised/40 transition-colors"
className="flex items-center justify-between px-5 py-3 hover:bg-raised/30 transition-colors rounded-lg mx-2 mb-1"
>
<div className="flex items-center gap-3">
<span
@@ -179,7 +179,7 @@ function DashboardContent({ data }: { data: DashboardStats }) {
<div className="space-y-8">
{/* Maintenance banner */}
{data.maintenanceMode && (
<div className="flex items-center gap-3 bg-warning/10 border border-warning/30 rounded-lg px-5 py-3">
<div className="flex items-center gap-3 bg-warning/10 rounded-xl px-5 py-3">
<Wrench className="w-4 h-4 text-warning shrink-0" />
<span className="text-sm text-warning font-medium">
Maintenance mode is active
@@ -249,13 +249,13 @@ function DashboardContent({ data }: { data: DashboardStats }) {
{data.recentEvents.length > 0 && (
<section>
<h2 className="font-display text-lg font-semibold mb-4">Recent Events</h2>
<div className="bg-card rounded-lg border border-border divide-y divide-border">
<div className="bg-card rounded-xl">
{data.recentEvents.slice(0, 20).map((event, i) => {
const Icon = eventIcons[event.type];
return (
<div
key={i}
className="flex items-start gap-3 px-5 py-3 hover:bg-raised/40 transition-colors"
className="flex items-start gap-3 px-5 py-3 hover:bg-raised/30 transition-colors rounded-lg mx-2 first:mt-2 last:mb-2"
>
<Icon
className={cn("w-4 h-4 mt-0.5 shrink-0", eventColors[event.type])}
@@ -275,7 +275,7 @@ function DashboardContent({ data }: { data: DashboardStats }) {
)}
{/* Bot status footer */}
<footer className="flex flex-wrap items-center gap-x-6 gap-y-2 text-xs text-text-tertiary border-t border-border pt-6">
<footer className="flex flex-wrap items-center gap-x-6 gap-y-2 text-xs text-text-tertiary pt-8">
<span className="font-medium text-text-secondary">{data.bot.name}</span>
<span className="flex items-center gap-1.5">
<Wifi className="w-3 h-3" />

View File

@@ -370,7 +370,7 @@ export function HueShifter() {
onClick={handleReset}
disabled={isDefault}
className={cn(
"px-3 py-1.5 rounded-md border border-border text-xs text-text-tertiary transition-colors",
"px-3 py-1.5 rounded-xl text-xs text-text-tertiary transition-colors",
isDefault
? "opacity-40 cursor-not-allowed"
: "hover:text-foreground hover:border-primary/40",
@@ -381,7 +381,7 @@ export function HueShifter() {
<button
onClick={clearAll}
className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-md border border-border text-xs text-text-tertiary",
"flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-xs text-text-tertiary",
"hover:text-destructive hover:border-destructive transition-colors",
)}
>
@@ -393,8 +393,8 @@ export function HueShifter() {
className={cn(
"flex items-center gap-1.5 px-4 py-1.5 rounded-md text-xs font-semibold transition-colors",
imageReady && !isDefault
? "bg-primary text-white hover:bg-primary/90"
: "bg-raised border border-border text-text-tertiary cursor-not-allowed",
? "bg-primary text-on-primary hover:opacity-90"
: "bg-raised text-text-tertiary cursor-not-allowed",
)}
>
<Download className="w-3.5 h-3.5" /> Download PNG
@@ -402,7 +402,7 @@ export function HueShifter() {
</div>
{/* Controls */}
<div className="bg-card border border-border rounded-xl p-5 space-y-5">
<div className="bg-card rounded-xl p-5 space-y-5">
<Slider
label="Hue Shift"
value={hueShift}
@@ -438,7 +438,7 @@ export function HueShifter() {
<p className="text-xs font-semibold text-text-tertiary uppercase tracking-wider">
Original
</p>
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
<div style={CHECKERBOARD}>
<img src={imageSrc} alt="Original" className="w-full block" />
</div>
@@ -449,7 +449,7 @@ export function HueShifter() {
<p className="text-xs font-semibold text-text-tertiary uppercase tracking-wider">
Result
</p>
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
{/* WebGL canvas always in DOM; hidden until image is ready */}
<div style={CHECKERBOARD}>
<canvas

View File

@@ -328,7 +328,7 @@ export function ItemStudio({
{/* Error */}
{error && (
<div className="flex items-start gap-3 p-4 bg-destructive/10 border border-destructive/30 rounded-lg">
<div className="flex items-start gap-3 p-4 bg-destructive/10 rounded-xl">
<AlertTriangle className="w-5 h-5 text-destructive shrink-0 mt-0.5" />
<p className="text-sm text-destructive">{error}</p>
</div>
@@ -340,8 +340,8 @@ export function ItemStudio({
onClick={handleReset}
disabled={submitting}
className={cn(
"px-4 py-2 rounded-lg border border-border text-sm text-text-tertiary",
"hover:text-foreground hover:border-primary/40 transition-colors",
"px-4 py-2 rounded-xl bg-raised text-sm text-text-tertiary",
"hover:text-foreground hover:bg-surface-container-highest transition-colors",
"disabled:opacity-50 disabled:cursor-not-allowed"
)}
>
@@ -351,10 +351,10 @@ export function ItemStudio({
onClick={handleSubmit}
disabled={submitting || success}
className={cn(
"px-6 py-2 rounded-lg text-sm font-semibold transition-all flex items-center gap-2",
"px-6 py-2 rounded-xl text-sm font-label font-semibold transition-all flex items-center gap-2",
success
? "bg-success text-white"
: "bg-primary hover:bg-primary/90 text-white",
: "bg-primary hover:opacity-90 text-on-primary",
"disabled:opacity-70 disabled:cursor-not-allowed"
)}
>

View File

@@ -68,9 +68,9 @@ function SearchFilterBar({
onChange={(e) => onSearchChange(e.target.value)}
placeholder="Search items..."
className={cn(
"w-full bg-input border border-border rounded-md pl-10 pr-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"transition-colors"
"w-full bg-input border-b-2 border-outline-variant rounded-none pl-10 pr-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors placeholder:text-text-disabled"
)}
/>
</div>
@@ -79,8 +79,8 @@ function SearchFilterBar({
value={type ?? ""}
onChange={(e) => onTypeChange(e.target.value || null)}
className={cn(
"bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -95,8 +95,8 @@ function SearchFilterBar({
value={rarity ?? ""}
onChange={(e) => onRarityChange(e.target.value || null)}
className={cn(
"bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -110,8 +110,8 @@ function SearchFilterBar({
<button
onClick={onClear}
className={cn(
"bg-input border border-border rounded-md px-3 py-2 text-sm text-text-secondary",
"hover:bg-destructive hover:text-white hover:border-destructive transition-colors"
"bg-raised rounded-xl px-3 py-2 text-sm font-label text-text-secondary",
"hover:bg-destructive hover:text-white transition-colors"
)}
>
Clear
@@ -137,13 +137,13 @@ function ItemTable({
if (loading) {
return (
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-raised border-b border-border">
<thead className="bg-raised">
<tr>
{columns.map((col) => (
<th key={col} className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th key={col} className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
{col}
</th>
))}
@@ -151,7 +151,7 @@ function ItemTable({
</thead>
<tbody>
{[...Array(5)].map((_, i) => (
<tr key={i} className="border-b border-border">
<tr key={i}>
{columns.map((col) => (
<td key={col} className="px-4 py-3">
<div className="h-4 bg-raised rounded animate-pulse w-20"></div>
@@ -168,7 +168,7 @@ function ItemTable({
if (items.length === 0) {
return (
<div className="bg-card border border-border rounded-lg p-12 text-center">
<div className="bg-card rounded-xl p-12 text-center">
<Package className="w-16 h-16 mx-auto mb-4 text-text-tertiary" />
<p className="text-lg font-semibold text-text-secondary mb-2">
No items found
@@ -181,13 +181,13 @@ function ItemTable({
}
return (
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-raised border-b border-border">
<thead className="bg-raised">
<tr>
{columns.map((col) => (
<th key={col} className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th key={col} className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
{col}
</th>
))}
@@ -197,7 +197,7 @@ function ItemTable({
{items.map((item) => (
<tr
key={item.id}
className="border-b border-border hover:bg-raised transition-colors cursor-pointer"
className="hover:bg-raised/40 transition-colors cursor-pointer"
onClick={() => onItemClick(item)}
title="Click to edit"
>
@@ -317,10 +317,10 @@ function Pagination({
onClick={() => onPageChange(currentPage - 1)}
disabled={currentPage === 1}
className={cn(
"px-3 py-2 rounded-md text-sm font-medium transition-colors",
"px-3 py-2 rounded-xl text-sm font-medium transition-colors",
currentPage === 1
? "bg-raised text-text-tertiary cursor-not-allowed"
: "bg-input border border-border text-foreground hover:bg-raised"
: "bg-raised text-foreground hover:bg-surface-container-highest"
)}
>
<ChevronLeft className="w-4 h-4" />
@@ -332,10 +332,10 @@ function Pagination({
key={i}
onClick={() => onPageChange(page)}
className={cn(
"px-3 py-2 rounded-md text-sm font-medium transition-colors min-w-[40px]",
"px-3 py-2 rounded-xl text-sm font-label font-medium transition-colors min-w-[40px]",
page === currentPage
? "bg-primary text-white"
: "bg-input border border-border text-foreground hover:bg-raised"
? "bg-primary text-on-primary"
: "bg-raised text-foreground hover:bg-surface-container-highest"
)}
>
{page}
@@ -351,10 +351,10 @@ function Pagination({
onClick={() => onPageChange(currentPage + 1)}
disabled={currentPage === totalPages}
className={cn(
"px-3 py-2 rounded-md text-sm font-medium transition-colors",
"px-3 py-2 rounded-xl text-sm font-medium transition-colors",
currentPage === totalPages
? "bg-raised text-text-tertiary cursor-not-allowed"
: "bg-input border border-border text-foreground hover:bg-raised"
: "bg-raised text-foreground hover:bg-surface-container-highest"
)}
>
<ChevronRight className="w-4 h-4" />
@@ -364,8 +364,8 @@ function Pagination({
value={limit}
onChange={(e) => onLimitChange(Number(e.target.value))}
className={cn(
"ml-2 bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"ml-2 bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -422,11 +422,11 @@ export default function Items() {
return (
<div className="flex flex-col h-full">
{/* Header */}
<header className="border-b border-border p-6 space-y-4">
<h1 className="text-2xl font-bold text-foreground">Items</h1>
<header className="p-6 space-y-4">
<h1 className="text-2xl font-display font-bold text-foreground">Items</h1>
{/* Tabs */}
<div className="flex gap-1 border-b border-border -mb-4 pb-px">
<div className="flex gap-1 border-b border-border/30 -mb-4 pb-px">
<button
onClick={() => setActiveTab("all")}
className={cn(
@@ -504,7 +504,7 @@ export default function Items() {
{/* Error banner */}
{error && (
<div className="mx-6 mt-4 bg-destructive/10 border border-destructive/30 rounded-lg p-4 flex items-start gap-3">
<div className="mx-6 mt-4 bg-destructive/10 rounded-xl p-4 flex items-start gap-3">
<AlertTriangle className="w-5 h-5 text-destructive flex-shrink-0 mt-0.5" />
<div className="flex-1">
<p className="text-sm font-semibold text-destructive">Error</p>

View File

@@ -7,7 +7,7 @@ export default function NotEnrolled() {
You need to use the Aurora bot in Discord before you can access this panel.
</p>
<p className="text-xs text-text-disabled">
Use <span className="font-mono bg-surface px-1.5 py-0.5 rounded">/enroll</span> in any server with Aurora to get started.
Use <span className="font-mono bg-card px-1.5 py-0.5 rounded-md">/enroll</span> in any server with Aurora to get started.
</p>
</div>
</div>

View File

@@ -69,17 +69,17 @@ export default function PlayerDashboard({ userId }: { userId: string }) {
<StatCard label="Items" value={String(inventory.length)} accent="success" />
</div>
<div className="bg-card rounded-lg border border-border">
<div className="flex items-center gap-2 px-5 py-3 border-b border-border">
<span className="text-sm font-semibold">Inventory</span>
<span className="text-xs text-text-disabled">({inventory.length})</span>
<div className="bg-card rounded-xl">
<div className="flex items-center gap-2 px-5 py-3">
<span className="text-sm font-display font-semibold">Inventory</span>
<span className="text-xs text-text-disabled font-label">({inventory.length})</span>
</div>
{inventory.length === 0 ? (
<div className="px-5 py-6 text-center text-sm text-text-tertiary">No items yet</div>
) : (
<div className="divide-y divide-border">
<div className="px-2 pb-2 space-y-0.5">
{inventory.slice(0, 10).map((item, i) => (
<div key={i} className="flex items-center justify-between px-5 py-3 hover:bg-raised/40 transition-colors">
<div key={i} className="flex items-center justify-between px-3 py-3 hover:bg-raised/30 transition-colors rounded-lg">
<div className="text-sm font-medium">{item.name}</div>
<div className="flex items-center gap-2">
<span className={`text-[10px] font-semibold px-1.5 py-0.5 rounded ${rarityColor(item.rarity)}`}>
@@ -111,7 +111,7 @@ function StatCard({ label, value, accent, subtitle }: { label: string; value: st
success: "border-l-success",
};
return (
<div className={`bg-gradient-to-br from-card to-surface border border-border rounded-lg p-5 border-l-4 ${borderColor[accent] ?? ""}`}>
<div className={`bg-gradient-to-br from-card to-surface rounded-xl p-5 border-l-4 ${borderColor[accent] ?? ""}`}>
<div className="text-[11px] font-semibold uppercase tracking-wider text-text-tertiary">{label}</div>
<div className="text-2xl font-bold font-display tracking-tight mt-1">{value}</div>
{subtitle && <div className="text-sm text-text-tertiary mt-0.5">{subtitle}</div>}

View File

@@ -207,7 +207,7 @@ export default function Settings() {
{dirty && (
<button
onClick={handleReset}
className="inline-flex items-center gap-2 rounded-md border border-border px-4 py-2 text-sm font-medium text-text-secondary hover:bg-primary/10 transition-colors"
className="inline-flex items-center gap-2 rounded-xl bg-raised px-4 py-2 text-sm font-label font-medium text-text-secondary hover:bg-surface-container-highest transition-colors"
>
<RotateCcw className="w-4 h-4" />
Discard
@@ -217,10 +217,10 @@ export default function Settings() {
onClick={handleSave}
disabled={!dirty || saving}
className={cn(
"inline-flex items-center gap-2 rounded-md px-5 py-2 text-sm font-medium transition-colors",
"inline-flex items-center gap-2 rounded-xl px-5 py-2 text-sm font-label font-medium transition-colors",
dirty
? "bg-primary text-primary-foreground hover:bg-primary/90 shadow-sm shadow-primary/30"
: "bg-primary/30 text-primary-foreground/50 cursor-not-allowed"
? "bg-primary text-on-primary hover:opacity-90 shadow-sm shadow-primary/30"
: "bg-primary/30 text-on-primary/50 cursor-not-allowed"
)}
>
{saving ? (
@@ -237,14 +237,14 @@ export default function Settings() {
{/* Error banner */}
{error && (
<div className="flex items-center gap-3 bg-destructive/10 border border-destructive/30 rounded-lg px-5 py-3">
<div className="flex items-center gap-3 bg-destructive/10 rounded-xl px-5 py-3">
<AlertTriangle className="w-4 h-4 text-destructive shrink-0" />
<span className="text-sm text-destructive">{error}</span>
</div>
)}
{/* Section tabs */}
<div className="flex gap-1 overflow-x-auto border-b border-border pb-px">
<div className="flex gap-1 overflow-x-auto border-b border-border/30 pb-px">
{sections.map(({ key, label, icon: Icon }) => (
<button
key={key}
@@ -324,7 +324,7 @@ export default function Settings() {
{/* Dirty indicator footer */}
{dirty && (
<div className="sticky bottom-0 -mx-6 px-6 py-3 bg-background/80 backdrop-blur border-t border-border flex items-center justify-between">
<div className="sticky bottom-0 -mx-6 px-6 py-3 bg-surface-container-high/90 backdrop-blur flex items-center justify-between">
<span className="text-sm text-warning font-medium">
You have unsaved changes
</span>
@@ -338,7 +338,7 @@ export default function Settings() {
<button
onClick={handleSave}
disabled={saving}
className="inline-flex items-center gap-2 rounded-md bg-primary text-primary-foreground px-4 py-1.5 text-sm font-medium hover:bg-primary/90 transition-colors"
className="inline-flex items-center gap-2 rounded-xl bg-primary text-on-primary px-4 py-1.5 text-sm font-label font-medium hover:opacity-90 transition-colors"
>
{saving ? (
<Loader2 className="w-3.5 h-3.5 animate-spin" />

View File

@@ -93,7 +93,7 @@ export default function Users() {
return (
<div className="flex flex-col h-full">
{/* Header */}
<header className="border-b border-border p-6 space-y-4">
<header className="p-6 space-y-4">
<h1 className="text-2xl font-bold text-foreground">Users</h1>
<SearchFilterBar
search={searchInput}
@@ -113,7 +113,7 @@ export default function Users() {
{/* Error banner */}
{error && (
<div className="mx-6 mt-4 bg-destructive/10 border border-destructive/30 rounded-lg p-4 flex items-start gap-3">
<div className="mx-6 mt-4 bg-destructive/10 rounded-xl p-4 flex items-start gap-3">
<AlertTriangle className="w-5 h-5 text-destructive flex-shrink-0 mt-0.5" />
<div className="flex-1">
<p className="text-sm font-semibold text-destructive">Error</p>

View File

@@ -38,10 +38,10 @@ export function EffectEditor({
return (
<div
className={cn(
"border rounded-lg p-4 space-y-3",
"rounded-xl p-4 space-y-3",
isLootbox
? "bg-amber-500/5 border-amber-500/25"
: "bg-raised/20 border-border"
? "bg-amber-500/5"
: "bg-surface-container-high"
)}
>
<div className="flex items-center gap-2">
@@ -57,8 +57,8 @@ export function EffectEditor({
update({ kind: e.target.value as EffectKind, ...resetFields })
}
className={cn(
"flex-1 bg-input border border-border rounded-md px-3 py-1.5 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30 transition-colors"
"flex-1 bg-input border-b-2 border-outline-variant rounded-none px-3 py-1.5 text-sm text-foreground",
"focus:outline-none focus:border-primary transition-colors"
)}
>
{(Object.keys(EFFECT_META) as EffectKind[]).map((kind) => (

View File

@@ -91,7 +91,7 @@ export function ItemPreviewCard({
{/* Lootbox pool mini-preview */}
{lootboxEffect && lootboxEffect.pool.length > 0 && (
<div className="pt-2 border-t border-border space-y-1.5">
<div className="pt-2 mt-2 space-y-1.5">
<div className="flex items-center gap-1.5">
<Gift className="w-3.5 h-3.5 text-amber-400" />
<span className="text-xs text-amber-400 font-medium">
@@ -131,7 +131,7 @@ export function ItemPreviewCard({
)}
{(draft.effects.length > 0 || draft.consume) && !lootboxEffect && (
<div className="pt-2 border-t border-border flex flex-wrap gap-1.5">
<div className="pt-2 mt-2 flex flex-wrap gap-1.5">
{draft.consume && (
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-red-500/10 text-red-400 text-xs">
Consumed on use

View File

@@ -64,7 +64,7 @@ export function ItemSearchPicker({
if (value) {
return (
<div className="flex items-center gap-2 p-2 bg-raised/50 rounded-md border border-border">
<div className="flex items-center gap-2 p-2 bg-raised/50 rounded-xl">
<span
className={cn(
"text-xs px-1.5 py-0.5 rounded font-bold shrink-0",
@@ -105,7 +105,7 @@ export function ItemSearchPicker({
)}
</div>
{open && results.length > 0 && (
<div className="absolute top-full left-0 right-0 z-50 mt-1 bg-card border border-border rounded-lg shadow-xl overflow-hidden">
<div className="absolute top-full left-0 right-0 z-50 mt-1 bg-surface-container-high rounded-xl shadow-[0_20px_40px_rgba(0,0,0,0.4)] overflow-hidden">
{results.map((item) => (
<button
key={item.id}

View File

@@ -72,10 +72,10 @@ export function ClassificationSection({
key={t}
onClick={() => update({ type: t })}
className={cn(
"flex flex-col items-center gap-1.5 py-3 px-2 rounded-lg border text-xs font-medium transition-all",
"flex flex-col items-center gap-1.5 py-3 px-2 rounded-xl text-xs font-label font-medium transition-all",
active
? "bg-primary/15 border-primary text-primary"
: "bg-input border-border text-text-tertiary hover:border-primary/40 hover:text-foreground"
? "bg-primary/15 text-primary"
: "bg-raised text-text-tertiary hover:text-foreground"
)}
>
<Icon className="w-4 h-4" />
@@ -96,10 +96,10 @@ export function ClassificationSection({
key={r}
onClick={() => update({ rarity: r })}
className={cn(
"py-3 px-2 rounded-lg border text-center transition-all",
"py-3 px-2 rounded-xl text-center transition-all border",
active
? cn(meta.bg, meta.text, meta.activeBorder)
: "bg-input border-border text-text-tertiary hover:border-primary/40"
: "bg-raised border-transparent text-text-tertiary hover:text-foreground"
)}
>
<div className="text-sm font-bold">{r}</div>
@@ -188,10 +188,10 @@ export function ArtworkSection({
key={mode}
onClick={() => setImageMode(mode)}
className={cn(
"px-3 py-1.5 rounded-md text-xs font-medium transition-colors border",
"px-3 py-1.5 rounded-xl text-xs font-label font-medium transition-colors",
imageMode === mode
? "bg-primary/15 border-primary text-primary"
: "bg-input border-border text-text-tertiary hover:text-foreground"
? "bg-primary/15 text-primary"
: "bg-raised text-text-tertiary hover:text-foreground"
)}
>
{mode === "upload" ? "Upload File" : "Enter URL"}
@@ -202,7 +202,7 @@ export function ArtworkSection({
{imageMode === "upload" ? (
<div className="space-y-2">
{imageFile ? (
<div className="relative rounded-lg overflow-hidden border border-border">
<div className="relative rounded-xl overflow-hidden">
<img
src={imagePreview!}
alt="Selected"
@@ -214,7 +214,7 @@ export function ArtworkSection({
>
<X className="w-4 h-4" />
</button>
<div className="px-3 py-2 bg-card border-t border-border">
<div className="px-3 py-2 bg-surface-container-high">
<p className="text-xs text-text-tertiary truncate">
{imageFile.name} ({(imageFile.size / 1024).toFixed(1)}{" "}
KB)
@@ -231,10 +231,10 @@ export function ArtworkSection({
onDragLeave={() => setDragOver(false)}
onClick={() => fileInputRef.current?.click()}
className={cn(
"border-2 border-dashed rounded-lg p-10 flex flex-col items-center gap-3 cursor-pointer transition-all select-none",
"border-2 border-dashed rounded-xl p-10 flex flex-col items-center gap-3 cursor-pointer transition-all select-none",
dragOver
? "border-primary bg-primary/5"
: "border-border hover:border-primary/50 hover:bg-primary/3"
: "border-outline-variant hover:border-primary/50 hover:bg-primary/3"
)}
>
<Upload
@@ -296,7 +296,7 @@ export function ArtworkSection({
/>
</Field>
{iconUrlInput && (
<div className="flex items-center gap-3 p-3 bg-raised/40 rounded-lg border border-border">
<div className="flex items-center gap-3 p-3 bg-raised/40 rounded-xl">
<img
src={iconUrlInput}
alt="Icon preview"
@@ -337,10 +337,10 @@ export function EffectsSection({
aria-checked={draft.consume}
onClick={() => update({ consume: !draft.consume })}
className={cn(
"relative w-10 h-5 rounded-full border transition-all shrink-0",
"relative w-10 h-5 rounded-full transition-all shrink-0",
draft.consume
? "bg-primary border-primary"
: "bg-input border-border"
? "bg-primary"
: "bg-raised"
)}
>
<span
@@ -367,8 +367,8 @@ export function EffectsSection({
<button
onClick={addEffect}
className={cn(
"w-full flex items-center justify-center gap-2 py-2.5 rounded-lg border border-dashed text-sm",
"border-border text-text-tertiary hover:border-primary/50 hover:text-primary transition-colors"
"w-full flex items-center justify-center gap-2 py-2.5 rounded-xl border border-dashed text-sm",
"border-outline-variant text-text-tertiary hover:border-primary/50 hover:text-primary transition-colors"
)}
>
<Plus className="w-4 h-4" />

View File

@@ -8,8 +8,8 @@ export function SectionCard({
children: React.ReactNode;
}) {
return (
<div className="bg-card border border-border rounded-xl p-5 space-y-4">
<h3 className="text-xs font-semibold text-text-tertiary uppercase tracking-wider">
<div className="bg-card rounded-xl p-5 space-y-4">
<h3 className="text-xs font-label font-semibold text-text-tertiary uppercase tracking-widest">
{title}
</h3>
{children}

View File

@@ -298,7 +298,7 @@ export function draftFromItem(item: FullItem): Draft {
}
export const inputCls = cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"placeholder:text-text-tertiary transition-colors"
);

View File

@@ -40,7 +40,7 @@ export function LootPoolEntryEditor({
};
return (
<div className="bg-raised/30 border border-border rounded-lg p-3 space-y-3">
<div className="bg-surface-container-high rounded-xl p-3 space-y-3">
{/* Header row: type tabs + weight input + percentage + remove */}
<div className="flex items-center gap-2 flex-wrap">
<div className="flex gap-1 flex-1 flex-wrap">
@@ -49,10 +49,10 @@ export function LootPoolEntryEditor({
key={t}
onClick={() => upd({ type: t, ...resetAmounts })}
className={cn(
"px-2 py-1 rounded text-xs font-medium transition-colors border",
"px-2 py-1 rounded-lg text-xs font-label font-medium transition-colors",
entry.type === t
? "bg-primary/15 border-primary text-primary"
: "bg-input border-border text-text-tertiary hover:text-foreground"
? "bg-primary/15 text-primary"
: "bg-raised text-text-tertiary hover:text-foreground"
)}
>
{LOOT_TYPE_META[t].label}
@@ -67,7 +67,7 @@ export function LootPoolEntryEditor({
value={entry.weight}
onChange={(e) => upd({ weight: e.target.value })}
className={cn(
"w-14 bg-input border border-border rounded-md px-2 py-1 text-xs text-foreground text-center",
"w-14 bg-input border-b-2 border-outline-variant rounded-none px-2 py-1 text-xs text-foreground text-center",
"focus:outline-none focus:border-primary transition-colors"
)}
/>
@@ -106,10 +106,10 @@ export function LootPoolEntryEditor({
key={mode}
onClick={() => upd({ amountMode: mode })}
className={cn(
"px-2.5 py-1 rounded text-xs font-medium border transition-colors",
"px-2.5 py-1 rounded-lg text-xs font-label font-medium transition-colors",
entry.amountMode === mode
? "bg-primary/15 border-primary text-primary"
: "bg-input border-border text-text-tertiary hover:text-foreground"
? "bg-primary/15 text-primary"
: "bg-raised text-text-tertiary hover:text-foreground"
)}
>
{mode === "fixed" ? "Fixed" : "Random Range"}

View File

@@ -99,8 +99,8 @@ export function LootboxEditor({
<button
onClick={addEntry}
className={cn(
"w-full flex items-center justify-center gap-2 py-2 rounded-lg border border-dashed text-xs",
"border-border text-text-tertiary hover:border-amber-500/50 hover:text-amber-400 transition-colors"
"w-full flex items-center justify-center gap-2 py-2 rounded-xl border border-dashed text-xs",
"border-outline-variant text-text-tertiary hover:border-amber-500/50 hover:text-amber-400 transition-colors"
)}
>
<Plus className="w-3.5 h-3.5" />

View File

@@ -43,9 +43,9 @@ export function SearchFilterBar({
onChange={(e) => onSearchChange(e.target.value)}
placeholder="Search by username..."
className={cn(
"w-full bg-input border border-border rounded-md pl-10 pr-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"transition-colors"
"w-full bg-input border-b-2 border-outline-variant rounded-none pl-10 pr-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors placeholder:text-text-disabled"
)}
/>
</div>
@@ -55,8 +55,8 @@ export function SearchFilterBar({
value={classId ?? ""}
onChange={(e) => onClassChange(e.target.value || null)}
className={cn(
"bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -75,8 +75,8 @@ export function SearchFilterBar({
onActiveChange(e.target.value === "" ? null : e.target.value === "true")
}
className={cn(
"bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -90,8 +90,8 @@ export function SearchFilterBar({
value={sortBy}
onChange={(e) => onSortByChange(e.target.value)}
className={cn(
"bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -105,8 +105,8 @@ export function SearchFilterBar({
<button
onClick={() => onSortOrderChange(sortOrder === "asc" ? "desc" : "asc")}
className={cn(
"bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"hover:bg-raised transition-colors"
"bg-raised rounded-xl px-3 py-2 text-sm font-label text-foreground",
"hover:bg-surface-container-highest transition-colors"
)}
>
{sortOrder === "asc" ? "\u2191 Asc" : "\u2193 Desc"}
@@ -116,8 +116,8 @@ export function SearchFilterBar({
<button
onClick={onClear}
className={cn(
"bg-input border border-border rounded-md px-3 py-2 text-sm text-text-secondary",
"hover:bg-destructive hover:text-white hover:border-destructive transition-colors"
"bg-raised rounded-xl px-3 py-2 text-sm font-label text-text-secondary",
"hover:bg-destructive hover:text-white transition-colors"
)}
>
Clear

View File

@@ -18,7 +18,7 @@ export function Field({
}) {
return (
<div className="space-y-1.5">
<label className="block text-xs font-semibold text-text-secondary">
<label className="block text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
{label}
</label>
{children}
@@ -51,8 +51,8 @@ export function NumberInput({
max={max}
step={step}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm font-mono text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors",
className
)}
@@ -78,9 +78,9 @@ export function StringInput({
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"transition-colors",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm font-mono text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors placeholder:text-text-disabled",
className
)}
/>
@@ -105,9 +105,9 @@ export function TextArea({
placeholder={placeholder}
rows={rows}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground resize-y",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"transition-colors"
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground resize-y",
"focus:outline-none focus:border-primary",
"transition-colors placeholder:text-text-disabled"
)}
/>
);
@@ -155,8 +155,8 @@ export function SelectInput({
value={value}
onChange={(e) => onChange(e.target.value)}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -186,8 +186,8 @@ export function RolePicker({
value={value ?? ""}
onChange={(e) => onChange(e.target.value || undefined)}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -220,8 +220,8 @@ export function ChannelPicker({
value={value ?? ""}
onChange={(e) => onChange(e.target.value || undefined)}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -257,7 +257,7 @@ export function MultiRolePicker({
{selectedRoles.map((r) => (
<span
key={r.id}
className="inline-flex items-center gap-1.5 bg-primary/15 border border-primary/30 rounded-full px-3 py-1 text-xs font-medium"
className="inline-flex items-center gap-1.5 bg-primary/15 rounded-full px-3 py-1 text-xs font-label font-medium"
>
<span
className="w-2.5 h-2.5 rounded-full"
@@ -282,8 +282,8 @@ export function MultiRolePicker({
if (e.target.value) onChange([...selected, e.target.value]);
}}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -346,7 +346,7 @@ export function CategoryPicker({
{selectedCats.map((c) => (
<span
key={c.id}
className="inline-flex items-center gap-1.5 bg-info/15 border border-info/30 rounded-full px-3 py-1 text-xs font-medium"
className="inline-flex items-center gap-1.5 bg-info/15 rounded-full px-3 py-1 text-xs font-label font-medium"
>
{c.name}
<button
@@ -368,8 +368,8 @@ export function CategoryPicker({
if (id) onChange([...selected, id]);
}}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -452,9 +452,9 @@ export function FeatureOverridesEditor({
onClick={addFlag}
disabled={!newKey.trim()}
className={cn(
"rounded-md px-4 py-2 text-sm font-medium transition-colors",
"rounded-xl px-4 py-2 text-sm font-label font-medium transition-colors",
newKey.trim()
? "bg-primary/15 text-primary hover:bg-primary/25 border border-primary/30"
? "bg-primary/15 text-primary hover:bg-primary/25"
: "bg-raised text-text-disabled cursor-not-allowed"
)}
>
@@ -475,12 +475,12 @@ export function SectionCard({
children: React.ReactNode;
}) {
return (
<div className="bg-card rounded-lg border border-border">
<div className="flex items-center gap-2.5 px-6 py-4 border-b border-border">
<div className="bg-card rounded-xl">
<div className="flex items-center gap-2.5 px-6 py-4">
<Icon className="w-4 h-4 text-primary" />
<h3 className="text-sm font-semibold">{title}</h3>
<h3 className="text-sm font-display font-semibold">{title}</h3>
</div>
<div className="px-6 py-5 space-y-5">{children}</div>
<div className="px-6 py-5 pt-0 space-y-5">{children}</div>
</div>
);
}

View File

@@ -44,13 +44,13 @@ function InventoryAddForm({
return (
<div className="space-y-3">
<p className="text-xs font-semibold text-text-secondary">Add Item</p>
<p className="text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">Add Item</p>
<select
value={selectedItemId}
onChange={(e) => setSelectedItemId(e.target.value)}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -69,8 +69,8 @@ function InventoryAddForm({
min="1"
placeholder="Qty"
className={cn(
"w-20 bg-input border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-20 bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm font-mono text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
/>
@@ -78,8 +78,8 @@ function InventoryAddForm({
onClick={handleAdd}
disabled={!selectedItemId}
className={cn(
"flex-1 px-3 py-2 rounded-md text-sm font-medium transition-colors",
"bg-primary text-white hover:bg-primary/90",
"flex-1 px-3 py-2 rounded-xl text-sm font-label font-medium transition-colors",
"bg-primary text-on-primary hover:opacity-90",
"disabled:opacity-50 disabled:cursor-not-allowed",
"flex items-center justify-center gap-1.5"
)}
@@ -135,12 +135,12 @@ export function UserDetailPanel({
];
return (
<div className="fixed inset-0 md:relative md:w-96 border-l border-border bg-card overflow-auto z-50 md:z-auto">
<div className="fixed inset-0 md:relative md:w-96 bg-surface-container-low overflow-auto z-50 md:z-auto">
<div className="p-6 space-y-6 pb-24">
{/* Header */}
<div className="flex items-start justify-between">
<div className="flex-1">
<h2 className="text-lg font-semibold text-foreground mb-1">
<h2 className="text-lg font-display font-semibold text-foreground mb-1">
{user.username}
</h2>
<p className="text-xs font-mono text-text-tertiary">{user.id}</p>
@@ -226,7 +226,7 @@ export function UserDetailPanel({
{inventoryDraft.map((entry) => (
<div
key={entry.itemId}
className="flex items-center justify-between gap-3 p-2 bg-raised rounded-md"
className="flex items-center justify-between gap-3 p-2 bg-raised rounded-xl"
>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-foreground truncate">
@@ -238,7 +238,7 @@ export function UserDetailPanel({
</div>
<button
onClick={() => onRemoveItem(entry.itemId)}
className="p-1.5 text-text-tertiary hover:text-destructive hover:bg-destructive/10 rounded transition-colors"
className="p-1.5 text-text-tertiary hover:text-destructive hover:bg-destructive/10 rounded-lg transition-colors"
title="Remove item"
>
<Trash2 className="w-4 h-4" />
@@ -249,7 +249,7 @@ export function UserDetailPanel({
)}
{/* Add Item Form */}
<div className="mt-4 pt-4 border-t border-border">
<div className="mt-4 pt-4">
<InventoryAddForm items={items} onAdd={onAddItem} />
</div>
</SectionCard>
@@ -257,7 +257,7 @@ export function UserDetailPanel({
{/* Sticky footer for save/discard (only shown when dirty) */}
{isDirty && (
<div className="sticky bottom-0 left-0 right-0 border-t border-border bg-card p-4 space-y-3">
<div className="sticky bottom-0 left-0 right-0 bg-surface-container-high p-4 space-y-3">
<div className="flex items-center gap-2 text-amber-400">
<AlertTriangle className="w-4 h-4" />
<span className="text-sm font-medium">You have unsaved changes</span>
@@ -267,8 +267,8 @@ export function UserDetailPanel({
onClick={onDiscard}
disabled={saving}
className={cn(
"flex-1 px-4 py-2 rounded-md text-sm font-medium transition-colors",
"bg-input border border-border text-foreground hover:bg-raised",
"flex-1 px-4 py-2 rounded-xl text-sm font-label font-medium transition-colors",
"bg-raised text-foreground hover:bg-surface-container-highest",
saving && "opacity-50 cursor-not-allowed"
)}
>
@@ -278,8 +278,8 @@ export function UserDetailPanel({
onClick={onSave}
disabled={saving}
className={cn(
"flex-1 px-4 py-2 rounded-md text-sm font-medium transition-colors",
"bg-primary text-white hover:bg-primary/90",
"flex-1 px-4 py-2 rounded-xl text-sm font-label font-medium transition-colors",
"bg-primary text-on-primary hover:opacity-90",
"flex items-center justify-center gap-2",
saving && "opacity-50 cursor-not-allowed"
)}

View File

@@ -15,7 +15,7 @@ export function Field({
}) {
return (
<div className="space-y-1.5">
<label className="block text-xs font-semibold text-text-secondary">
<label className="block text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
{label}
</label>
{children}
@@ -48,8 +48,8 @@ export function NumberInput({
max={max}
step={step}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm font-mono text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors",
className
)}
@@ -75,9 +75,9 @@ export function StringInput({
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm font-mono text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"transition-colors",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm font-mono text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors placeholder:text-text-disabled",
className
)}
/>
@@ -126,8 +126,8 @@ export function SelectInput({
value={value}
onChange={(e) => onChange(e.target.value)}
className={cn(
"w-full bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"w-full bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>
@@ -150,10 +150,10 @@ export function SectionCard({
children: React.ReactNode;
}) {
return (
<div className="bg-card border border-border rounded-lg p-4">
<div className="bg-card rounded-xl p-4">
<div className="flex items-center gap-2 mb-4">
<Icon className="w-4 h-4 text-primary" />
<h3 className="text-sm font-semibold text-foreground">{title}</h3>
<h3 className="text-sm font-display font-semibold text-foreground">{title}</h3>
</div>
{children}
</div>

View File

@@ -57,7 +57,7 @@ export function UserPagination({
return (
<div className="mt-4 flex flex-wrap gap-4 items-center justify-between">
{/* Items info */}
<p className="text-sm text-text-secondary">
<p className="text-sm font-label text-text-secondary">
Showing {startItem}\u2013{endItem} of {formatNumber(total)} users
</p>
@@ -68,10 +68,10 @@ export function UserPagination({
onClick={() => onPageChange(currentPage - 1)}
disabled={currentPage === 1}
className={cn(
"px-3 py-2 rounded-md text-sm font-medium transition-colors",
"px-3 py-2 rounded-xl text-sm font-medium transition-colors",
currentPage === 1
? "bg-raised text-text-tertiary cursor-not-allowed"
: "bg-input border border-border text-foreground hover:bg-raised"
: "bg-raised text-foreground hover:bg-surface-container-highest"
)}
>
<ChevronLeft className="w-4 h-4" />
@@ -84,10 +84,10 @@ export function UserPagination({
key={i}
onClick={() => onPageChange(page)}
className={cn(
"px-3 py-2 rounded-md text-sm font-medium transition-colors min-w-[40px]",
"px-3 py-2 rounded-xl text-sm font-label font-medium transition-colors min-w-[40px]",
page === currentPage
? "bg-primary text-white"
: "bg-input border border-border text-foreground hover:bg-raised"
? "bg-primary text-on-primary"
: "bg-raised text-foreground hover:bg-surface-container-highest"
)}
>
{page}
@@ -104,10 +104,10 @@ export function UserPagination({
onClick={() => onPageChange(currentPage + 1)}
disabled={currentPage === totalPages}
className={cn(
"px-3 py-2 rounded-md text-sm font-medium transition-colors",
"px-3 py-2 rounded-xl text-sm font-medium transition-colors",
currentPage === totalPages
? "bg-raised text-text-tertiary cursor-not-allowed"
: "bg-input border border-border text-foreground hover:bg-raised"
: "bg-raised text-foreground hover:bg-surface-container-highest"
)}
>
<ChevronRight className="w-4 h-4" />
@@ -118,8 +118,8 @@ export function UserPagination({
value={limit}
onChange={(e) => onLimitChange(Number(e.target.value))}
className={cn(
"ml-2 bg-input border border-border rounded-md px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary/30",
"ml-2 bg-input border-b-2 border-outline-variant rounded-none px-3 py-2 text-sm text-foreground",
"focus:outline-none focus:border-primary",
"transition-colors"
)}
>

View File

@@ -18,31 +18,31 @@ export function UserTable({
}) {
if (loading) {
return (
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-raised border-b border-border">
<thead className="bg-raised">
<tr>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
Username
</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
Level
</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
Balance
</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
Class
</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
Status
</th>
</tr>
</thead>
<tbody>
{[...Array(5)].map((_, i) => (
<tr key={i} className="border-b border-border">
<tr key={i}>
<td className="px-4 py-3">
<div className="h-4 bg-raised rounded animate-pulse w-32"></div>
</td>
@@ -69,9 +69,9 @@ export function UserTable({
if (users.length === 0) {
return (
<div className="bg-card border border-border rounded-lg p-12 text-center">
<div className="bg-card rounded-xl p-12 text-center">
<UserCircle2 className="w-16 h-16 mx-auto mb-4 text-text-tertiary" />
<p className="text-lg font-semibold text-text-secondary mb-2">
<p className="text-lg font-display font-semibold text-text-secondary mb-2">
No users found
</p>
<p className="text-sm text-text-tertiary">
@@ -82,27 +82,27 @@ export function UserTable({
}
return (
<div className="bg-card border border-border rounded-lg overflow-hidden">
<div className="bg-card rounded-xl overflow-hidden">
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-raised border-b border-border">
<thead className="bg-raised">
<tr>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
Username
</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
Level
</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
Balance
</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
XP
</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
Class
</th>
<th className="px-4 py-3 text-left text-xs font-semibold text-text-secondary">
<th className="px-4 py-3 text-left text-xs font-label font-semibold text-text-secondary uppercase tracking-wide">
Status
</th>
</tr>
@@ -112,7 +112,7 @@ export function UserTable({
<tr
key={user.id}
onClick={() => onSelectUser(user)}
className="border-b border-border hover:bg-raised cursor-pointer transition-colors"
className="hover:bg-raised/40 cursor-pointer transition-colors"
>
<td className="px-4 py-3">
<div className="flex items-center gap-3">
@@ -152,7 +152,7 @@ export function UserTable({
<td className="px-4 py-3">
<span
className={cn(
"inline-flex items-center px-2 py-1 rounded-full text-xs font-medium",
"inline-flex items-center px-2 py-1 rounded-full text-xs font-label font-medium",
user.isActive
? "bg-green-500/20 text-green-400"
: "bg-gray-500/20 text-gray-400"