Redesign to dark-mode-only with navy palette and accent colors (#13)

Removes light mode entirely in favour of a permanent dark theme with a
navy-tinted background and three signature accents (electric blue,
amber/gold, coral) exposed as CSS custom properties and Tailwind
utilities (bg-electric, text-amber-accent, text-coral-accent).

- Set class="dark" on <html> and apply Clerk dark base theme
- Rewrite app.css: single :root palette (oklch navy values), custom
  --electric / --amber-accent / --coral-accent variables, remove
  duplicate .dark block and light-mode bg-white/bg-gray-950 rule
- Install @clerk/themes for Clerk dark modal support
- Replace hardcoded Tailwind colors across 30+ files:
  - Draft grid cells: blue-50/blue-950 → electric/15, green-50/950 → emerald/10
  - Timer: green-600/yellow-600/red-600 → emerald-400/amber-accent/coral-accent
  - Status badges: blue-50/green-50/gray-50 → electric/emerald/muted variants
  - Success messages: green-500/15 text-green-700 dark:text-green-400 → emerald-500/15 text-emerald-400
  - Info cards: blue-50 dark:bg-blue-950 → electric/10
  - Warning cards: yellow-500 → amber-accent variants
  - Medal/placement badges: yellow-500/orange-600 → amber-accent/coral-accent
  - Movement indicators: green-600/red-600 → emerald-400/coral-accent
  - Connection dots: green-500/red-500 → emerald-500/coral-accent
- Remove dark:hidden/dark:block logo toggle in welcome.tsx (always dark)
- Update DraftGrid test assertions to match new class names

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris Parsons 2026-02-20 19:26:11 -08:00 committed by GitHub
parent 8b480a0b9a
commit 1584d34b89
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 214 additions and 237 deletions

View file

@ -8,15 +8,6 @@
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
html,
body {
@apply bg-white dark:bg-gray-950;
@media (prefers-color-scheme: dark) {
color-scheme: dark;
}
}
@theme inline {
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
@ -53,75 +44,51 @@ body {
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--color-electric: var(--electric);
--color-amber-accent: var(--amber-accent);
--color-coral-accent: var(--coral-accent);
}
html {
color-scheme: dark;
}
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823);
--card: oklch(1 0 0);
--card-foreground: oklch(0.141 0.005 285.823);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.141 0.005 285.823);
--primary: oklch(0.21 0.006 285.885);
--background: oklch(0.13 0.015 255);
--foreground: oklch(0.95 0.01 255);
--card: oklch(0.18 0.02 255);
--card-foreground: oklch(0.95 0.01 255);
--popover: oklch(0.18 0.02 255);
--popover-foreground: oklch(0.95 0.01 255);
--primary: oklch(0.623 0.214 259.815);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.967 0.001 286.375);
--secondary-foreground: oklch(0.21 0.006 285.885);
--muted: oklch(0.967 0.001 286.375);
--muted-foreground: oklch(0.552 0.016 285.938);
--accent: oklch(0.967 0.001 286.375);
--accent-foreground: oklch(0.21 0.006 285.885);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.92 0.004 286.32);
--input: oklch(0.92 0.004 286.32);
--ring: oklch(0.705 0.015 286.067);
--secondary: oklch(0.22 0.025 255);
--secondary-foreground: oklch(0.95 0.01 255);
--muted: oklch(0.22 0.025 255);
--muted-foreground: oklch(0.65 0.02 255);
--accent: oklch(0.25 0.03 255);
--accent-foreground: oklch(0.95 0.01 255);
--destructive: oklch(0.65 0.22 25);
--border: oklch(1 0 0 / 8%);
--input: oklch(1 0 0 / 12%);
--ring: oklch(0.623 0.214 259.815 / 50%);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.141 0.005 285.823);
--sidebar-primary: oklch(0.21 0.006 285.885);
--sidebar: oklch(0.18 0.02 255);
--sidebar-foreground: oklch(0.95 0.01 255);
--sidebar-primary: oklch(0.623 0.214 259.815);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.967 0.001 286.375);
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
--sidebar-border: oklch(0.92 0.004 286.32);
--sidebar-ring: oklch(0.705 0.015 286.067);
}
.dark {
--background: oklch(0.141 0.005 285.823);
--foreground: oklch(0.985 0 0);
--card: oklch(0.21 0.006 285.885);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.21 0.006 285.885);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.92 0.004 286.32);
--primary-foreground: oklch(0.21 0.006 285.885);
--secondary: oklch(0.274 0.006 286.033);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.274 0.006 286.033);
--muted-foreground: oklch(0.705 0.015 286.067);
--accent: oklch(0.274 0.006 286.033);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.552 0.016 285.938);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.21 0.006 285.885);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.274 0.006 286.033);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.552 0.016 285.938);
--sidebar-accent: oklch(0.25 0.03 255);
--sidebar-accent-foreground: oklch(0.95 0.01 255);
--sidebar-border: oklch(1 0 0 / 8%);
--sidebar-ring: oklch(0.623 0.214 259.815 / 50%);
--electric: oklch(0.623 0.214 259.815);
--amber-accent: oklch(0.79 0.17 70);
--coral-accent: oklch(0.68 0.19 35);
}
@layer base {

View file

@ -66,10 +66,10 @@ export function DraftGrid({
teamTime === undefined
? "text-muted-foreground"
: teamTime > 60
? "text-green-600"
? "text-emerald-400"
: teamTime > 30
? "text-yellow-600"
: "text-red-600"
? "text-amber-accent"
: "text-coral-accent"
}`}
>
{formatTime(teamTime)}
@ -107,10 +107,10 @@ export function DraftGrid({
<div
className={`flex-1 min-w-0 h-20 border-2 rounded-lg p-2 transition-all ${
isPicked
? "border-green-500 bg-green-50 dark:bg-green-950"
? "bg-emerald-500/10 border-emerald-500/30"
: isCurrent
? "border-blue-500 bg-blue-50 dark:bg-blue-950 shadow-lg"
: "border-gray-300 bg-white dark:bg-gray-900"
? "border-electric bg-electric/15 shadow-lg shadow-electric/10"
: "border-border bg-card"
}`}
title={`Overall Pick #${pickNumber}`}
>
@ -127,7 +127,7 @@ export function DraftGrid({
</div>
</div>
) : isCurrent ? (
<div className="text-xs font-semibold text-blue-600 dark:text-blue-400">
<div className="text-xs font-semibold text-electric">
On Clock
</div>
) : null}

View file

@ -44,14 +44,14 @@ export function StandingsTable({
if (change > 0) {
return (
<div className="flex items-center gap-1 text-green-600 dark:text-green-400">
<div className="flex items-center gap-1 text-emerald-400">
<TrendingUp className="h-3 w-3" />
<span className="text-xs">+{change}</span>
</div>
);
} else if (change < 0) {
return (
<div className="flex items-center gap-1 text-red-600 dark:text-red-400">
<div className="flex items-center gap-1 text-coral-accent">
<TrendingDown className="h-3 w-3" />
<span className="text-xs">{change}</span>
</div>

View file

@ -82,8 +82,8 @@ describe('DraftGrid Component', () => {
);
const currentPickCell = screen.getByText('On Clock').parentElement;
expect(currentPickCell).toHaveClass('border-blue-500');
expect(currentPickCell).toHaveClass('bg-blue-50');
expect(currentPickCell).toHaveClass('border-electric');
expect(currentPickCell).toHaveClass('bg-electric/15');
});
});

View file

@ -152,7 +152,7 @@ export function AvailableParticipantsSection({
isDrafted
? "bg-muted/50 opacity-60"
: !isEligible
? "bg-red-50/30 dark:bg-red-950/20 opacity-75"
? "bg-destructive/10 opacity-75"
: "hover:bg-muted/50"
}`}
title={

View file

@ -23,9 +23,9 @@ export function ConnectionOverlay({
<div className="flex flex-col items-center gap-6">
{/* Spinner or Error Icon */}
{connectionError ? (
<div className="w-16 h-16 rounded-full bg-red-100 dark:bg-red-950 flex items-center justify-center">
<div className="w-16 h-16 rounded-full bg-destructive/15 flex items-center justify-center">
<svg
className="w-8 h-8 text-red-600 dark:text-red-400"
className="w-8 h-8 text-destructive"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"

View file

@ -65,10 +65,10 @@ export function DraftGridSection({
const getTimerColor = (seconds: number | null) => {
if (seconds === null) return "text-muted-foreground";
if (seconds > 60) return "text-green-600 dark:text-green-400";
if (seconds > 30) return "text-yellow-600 dark:text-yellow-400";
if (seconds > 10) return "text-red-600 dark:text-red-400";
return "text-red-600 dark:text-red-400 animate-pulse";
if (seconds > 60) return "text-emerald-400";
if (seconds > 30) return "text-amber-accent";
if (seconds > 10) return "text-coral-accent";
return "text-coral-accent animate-pulse";
};
return (
@ -126,10 +126,10 @@ export function DraftGridSection({
<div
className={`flex-1 min-w-32 h-20 border-2 rounded-lg p-2 transition-all ${
isCurrent
? "border-blue-500 bg-blue-50 dark:bg-blue-950 shadow-lg"
? "border-electric bg-electric/15 shadow-lg shadow-electric/10"
: isPicked
? "border-green-500 bg-green-50 dark:bg-green-950"
: "border-gray-300 bg-white dark:bg-gray-900"
? "bg-emerald-500/10 border-emerald-500/30"
: "border-border bg-card"
}`}
title={`Overall Pick #${cell.pickNumber}`}
>
@ -147,7 +147,7 @@ export function DraftGridSection({
</div>
</div>
) : isCurrent ? (
<div className="text-xs font-semibold text-blue-600 dark:text-blue-400">
<div className="text-xs font-semibold text-electric">
On Clock
</div>
) : null}
@ -178,10 +178,10 @@ export function DraftGridSection({
key={cell.pickNumber}
className={`flex-1 min-w-32 h-20 border-2 rounded-lg p-2 transition-all ${
isCurrent
? "border-blue-500 bg-blue-50 dark:bg-blue-950 shadow-lg"
? "border-electric bg-electric/15 shadow-lg shadow-electric/10"
: isPicked
? "border-green-500 bg-green-50 dark:bg-green-950"
: "border-gray-300 bg-white dark:bg-gray-900"
? "bg-emerald-500/10 border-emerald-500/30"
: "border-border bg-card"
}`}
title={`Overall Pick #${cell.pickNumber}`}
>
@ -199,7 +199,7 @@ export function DraftGridSection({
</div>
</div>
) : isCurrent ? (
<div className="text-xs font-semibold text-blue-600 dark:text-blue-400">
<div className="text-xs font-semibold text-electric">
On Clock
</div>
) : null}

View file

@ -103,15 +103,15 @@ export function QualifyingPointsStandings({
}
return (
<Card className={isFinalized ? "border-green-200 dark:border-green-800" : "border-amber-200 dark:border-amber-800"}>
<Card className={isFinalized ? "border-emerald-500/30" : "border-amber-accent/30"}>
<CardHeader>
<CardTitle className={isFinalized ? "text-green-600 dark:text-green-400" : "text-amber-600 dark:text-amber-400"}>
<CardTitle className={isFinalized ? "text-emerald-400" : "text-amber-accent"}>
<Trophy className="inline mr-2 h-5 w-5" />
Qualifying Points Standings
</CardTitle>
<CardDescription>
{isFinalized ? (
<span className="text-green-600 dark:text-green-400 font-semibold">
<span className="text-emerald-400 font-semibold">
<CheckCircle2 className="inline h-4 w-4 mr-1" />
Finalized - Fantasy points have been assigned
</span>
@ -185,7 +185,7 @@ export function QualifyingPointsStandings({
{standing.participant.name}
</TableCell>
<TableCell className="text-right">
<span className="font-semibold text-amber-600 dark:text-amber-400">
<span className="font-semibold text-amber-accent">
{parseFloat(standing.totalQualifyingPoints).toFixed(2)} QP
</span>
</TableCell>
@ -195,7 +195,7 @@ export function QualifyingPointsStandings({
{scoringRules && !isFinalized && (
<TableCell className="text-right">
{isTop8 ? (
<span className="font-semibold text-green-600 dark:text-green-400">
<span className="font-semibold text-emerald-400">
{projectedPoints} pts
</span>
) : (

View file

@ -74,8 +74,8 @@ export function ScoringRulesEditor({ scoringRules, disabled = false }: ScoringRu
))}
</div>
<div className="bg-blue-500/10 border border-blue-500/20 rounded-md p-3">
<p className="text-sm text-blue-700 dark:text-blue-400">
<div className="bg-electric/10 border border-electric/20 rounded-md p-3">
<p className="text-sm text-electric">
<strong>💡 Tip:</strong> The default scoring rewards winning heavily (100 pts for 1st)
but also values consistency (25 pts for 5th/6th). Customize these values to fit your
league's strategy preferences.

View file

@ -109,14 +109,14 @@ export function SeasonStandings({
if (change > 0) {
return (
<div className="flex items-center gap-1 text-green-600 dark:text-green-400">
<div className="flex items-center gap-1 text-emerald-400">
<TrendingUp className="h-3 w-3" />
<span className="text-xs">+{change}</span>
</div>
);
} else if (change < 0) {
return (
<div className="flex items-center gap-1 text-red-600 dark:text-red-400">
<div className="flex items-center gap-1 text-coral-accent">
<TrendingDown className="h-3 w-3" />
<span className="text-xs">{change}</span>
</div>
@ -186,16 +186,16 @@ export function SeasonStandings({
<Card
className={
isFinalized
? "border-green-200 dark:border-green-800"
: "border-blue-200 dark:border-blue-800"
? "border-emerald-500/30"
: "border-electric/30"
}
>
<CardHeader>
<CardTitle
className={
isFinalized
? "text-green-600 dark:text-green-400"
: "text-blue-600 dark:text-blue-400"
? "text-emerald-400"
: "text-electric"
}
>
<Flag className="inline mr-2 h-5 w-5" />
@ -203,7 +203,7 @@ export function SeasonStandings({
</CardTitle>
<CardDescription>
{isFinalized ? (
<span className="text-green-600 dark:text-green-400 font-semibold">
<span className="text-emerald-400 font-semibold">
<CheckCircle2 className="inline h-4 w-4 mr-1" />
Season complete - Fantasy points assigned to top 8 finishers
</span>
@ -281,7 +281,7 @@ export function SeasonStandings({
<span
className={`font-semibold ${
isTop8
? "text-blue-600 dark:text-blue-400"
? "text-electric"
: "text-muted-foreground"
}`}
>

View file

@ -30,21 +30,21 @@ export function SportSeasonCard({
switch (status) {
case "upcoming":
return (
<Badge variant="outline" className="bg-blue-50 text-blue-700 border-blue-200">
<Badge variant="outline" className="bg-electric/15 text-electric border-electric/30">
<Flag className="mr-1 h-3 w-3" />
Upcoming
</Badge>
);
case "active":
return (
<Badge variant="outline" className="bg-green-50 text-green-700 border-green-200">
<Badge variant="outline" className="bg-emerald-500/15 text-emerald-400 border-emerald-500/30">
<Target className="mr-1 h-3 w-3" />
Active
</Badge>
);
case "completed":
return (
<Badge variant="outline" className="bg-gray-50 text-gray-700 border-gray-200">
<Badge variant="outline" className="bg-muted text-muted-foreground border-border">
<Trophy className="mr-1 h-3 w-3" />
Completed
</Badge>

View file

@ -112,7 +112,7 @@ export function StandingsTable({
function RankBadge({ rank }: { rank: number }) {
if (rank === 1) {
return (
<Badge className="bg-yellow-500 hover:bg-yellow-600 text-white font-bold">
<Badge className="bg-amber-accent hover:bg-amber-accent/80 text-background font-bold">
🏆 1st
</Badge>
);
@ -120,7 +120,7 @@ function RankBadge({ rank }: { rank: number }) {
if (rank === 2) {
return (
<Badge className="bg-gray-400 hover:bg-gray-500 text-white font-bold">
<Badge className="bg-muted hover:bg-muted/80 text-muted-foreground font-bold">
🥈 2nd
</Badge>
);
@ -128,7 +128,7 @@ function RankBadge({ rank }: { rank: number }) {
if (rank === 3) {
return (
<Badge className="bg-orange-600 hover:bg-orange-700 text-white font-bold">
<Badge className="bg-coral-accent hover:bg-coral-accent/80 text-background font-bold">
🥉 3rd
</Badge>
);
@ -147,7 +147,7 @@ function RankBadge({ rank }: { rank: number }) {
function MovementIndicator({ change }: { change: number }) {
if (change > 0) {
return (
<span className="text-green-600 text-sm font-medium" title={`Up ${change} ${change === 1 ? 'place' : 'places'}`}>
<span className="text-emerald-400 text-sm font-medium" title={`Up ${change} ${change === 1 ? 'place' : 'places'}`}>
{change}
</span>
);
@ -155,7 +155,7 @@ function MovementIndicator({ change }: { change: number }) {
if (change < 0) {
return (
<span className="text-red-600 text-sm font-medium" title={`Down ${Math.abs(change)} ${Math.abs(change) === 1 ? 'place' : 'places'}`}>
<span className="text-coral-accent text-sm font-medium" title={`Down ${Math.abs(change)} ${Math.abs(change) === 1 ? 'place' : 'places'}`}>
{Math.abs(change)}
</span>
);
@ -182,14 +182,14 @@ function PlacementBreakdown({
};
}) {
const items = [
{ label: "1st", count: placements.first, color: "text-yellow-600" },
{ label: "2nd", count: placements.second, color: "text-gray-500" },
{ label: "3rd", count: placements.third, color: "text-orange-600" },
{ label: "4th", count: placements.fourth, color: "text-blue-600" },
{ label: "5th", count: placements.fifth, color: "text-purple-600" },
{ label: "6th", count: placements.sixth, color: "text-green-600" },
{ label: "7th", count: placements.seventh, color: "text-pink-600" },
{ label: "8th", count: placements.eighth, color: "text-indigo-600" },
{ label: "1st", count: placements.first, color: "text-amber-accent" },
{ label: "2nd", count: placements.second, color: "text-muted-foreground" },
{ label: "3rd", count: placements.third, color: "text-coral-accent" },
{ label: "4th", count: placements.fourth, color: "text-electric" },
{ label: "5th", count: placements.fifth, color: "text-purple-400" },
{ label: "6th", count: placements.sixth, color: "text-emerald-400" },
{ label: "7th", count: placements.seventh, color: "text-pink-400" },
{ label: "8th", count: placements.eighth, color: "text-indigo-400" },
];
// Only show placements that have counts > 0

View file

@ -99,7 +99,7 @@ export function TeamScoreBreakdown({
Actual Points
</div>
{breakdown.projectedPoints > breakdown.actualPoints && (
<div className="text-xl font-semibold text-blue-600 mt-1">
<div className="text-xl font-semibold text-electric mt-1">
{breakdown.projectedPoints.toFixed(1)}
<span className="text-xs text-muted-foreground ml-1">projected</span>
</div>
@ -174,19 +174,19 @@ export function TeamScoreBreakdown({
<div className="space-y-1">
{standing.placementCounts.first > 0 && (
<div className="flex justify-between text-sm">
<span className="text-yellow-600 font-medium">1st place</span>
<span className="text-amber-accent font-medium">1st place</span>
<span className="font-bold">{standing.placementCounts.first}</span>
</div>
)}
{standing.placementCounts.second > 0 && (
<div className="flex justify-between text-sm">
<span className="text-gray-500 font-medium">2nd place</span>
<span className="text-muted-foreground font-medium">2nd place</span>
<span className="font-bold">{standing.placementCounts.second}</span>
</div>
)}
{standing.placementCounts.third > 0 && (
<div className="flex justify-between text-sm">
<span className="text-orange-600 font-medium">3rd place</span>
<span className="text-coral-accent font-medium">3rd place</span>
<span className="font-bold">{standing.placementCounts.third}</span>
</div>
)}
@ -278,7 +278,7 @@ export function TeamScoreBreakdown({
<TableCell className="text-center">
{pick.isComplete ? (
pick.finalPosition === 0 ? (
<Badge variant="secondary" className="bg-gray-200 text-gray-700">
<Badge variant="secondary">
Did Not Score
</Badge>
) : (
@ -330,14 +330,14 @@ export function TeamScoreBreakdown({
*/
function PlacementBadge({ position }: { position: number }) {
const badges: Record<number, { label: string; className: string }> = {
1: { label: "1st", className: "bg-yellow-500 hover:bg-yellow-600 text-white" },
2: { label: "2nd", className: "bg-gray-400 hover:bg-gray-500 text-white" },
3: { label: "3rd", className: "bg-orange-600 hover:bg-orange-700 text-white" },
4: { label: "4th", className: "bg-blue-600 hover:bg-blue-700 text-white" },
5: { label: "5th", className: "bg-purple-600 hover:bg-purple-700 text-white" },
6: { label: "6th", className: "bg-green-600 hover:bg-green-700 text-white" },
7: { label: "7th", className: "bg-pink-600 hover:bg-pink-700 text-white" },
8: { label: "8th", className: "bg-indigo-600 hover:bg-indigo-700 text-white" },
1: { label: "1st", className: "bg-amber-accent hover:bg-amber-accent/80 text-background" },
2: { label: "2nd", className: "bg-muted hover:bg-muted/80 text-muted-foreground" },
3: { label: "3rd", className: "bg-coral-accent hover:bg-coral-accent/80 text-background" },
4: { label: "4th", className: "bg-electric/20 hover:bg-electric/30 text-electric" },
5: { label: "5th", className: "bg-purple-500/20 hover:bg-purple-500/30 text-purple-400" },
6: { label: "6th", className: "bg-emerald-500/20 hover:bg-emerald-500/30 text-emerald-400" },
7: { label: "7th", className: "bg-pink-500/20 hover:bg-pink-500/30 text-pink-400" },
8: { label: "8th", className: "bg-indigo-500/20 hover:bg-indigo-500/30 text-indigo-400" },
};
const badge = badges[position] || { label: `${position}th`, className: "" };

View file

@ -13,6 +13,7 @@ import "./app.css";
import { clerkMiddleware, rootAuthLoader, getAuth } from "@clerk/react-router/server";
import { Navbar } from "~/components/navbar";
import { ClerkProvider } from "@clerk/react-router";
import { dark } from "@clerk/themes";
import { Toaster } from "~/components/ui/sonner";
import { isUserAdminByClerkId } from "~/models/user";
@ -46,7 +47,7 @@ export const links: Route.LinksFunction = () => [
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<html lang="en" className="dark">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
@ -67,7 +68,7 @@ export default function App({ loaderData }: Route.ComponentProps) {
const isDraftRoute = location.pathname.includes('/draft');
return (
<ClerkProvider loaderData={loaderData}>
<ClerkProvider loaderData={loaderData} appearance={{ baseTheme: dark }}>
{!isDraftRoute && <Navbar isAdmin={loaderData?.isAdmin ?? false} />}
{isDraftRoute ? (
<Outlet />

View file

@ -168,7 +168,7 @@ export default function DataSync({ loaderData, actionData }: Route.ComponentProp
</div>
{actionData?.success && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm mb-6">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm mb-6">
{actionData.message || "Operation completed successfully!"}
</div>
)}
@ -342,11 +342,11 @@ export default function DataSync({ loaderData, actionData }: Route.ComponentProp
</Card>
</div>
<Card className="mt-6 border-blue-200 bg-blue-50 dark:bg-blue-950 dark:border-blue-800">
<Card className="mt-6 border-electric/30 bg-electric/10">
<CardHeader>
<CardTitle className="text-blue-900 dark:text-blue-100">How It Works</CardTitle>
<CardTitle className="text-electric">How It Works</CardTitle>
</CardHeader>
<CardContent className="text-sm text-blue-800 dark:text-blue-200 space-y-3">
<CardContent className="text-sm text-foreground/80 space-y-3">
<div>
<strong>Export:</strong> Downloads all sports data as a JSON file that you can
save, version control, or transfer to another environment.
@ -359,7 +359,7 @@ export default function DataSync({ loaderData, actionData }: Route.ComponentProp
<strong>Import (Replace):</strong> Deletes all existing sports data and recreates
it from the file. Use this for a clean slate.
</div>
<div className="pt-2 border-t border-blue-200 dark:border-blue-800">
<div className="pt-2 border-t border-electric/30">
<strong>Typical workflow:</strong>
<ol className="list-decimal list-inside mt-1 space-y-1">
<li>Export data from development</li>

View file

@ -228,7 +228,7 @@ export default function EventBracket({
)}
{actionData?.success && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
{actionData.success}
</div>
)}
@ -702,10 +702,10 @@ export default function EventBracket({
{/* Finalize Bracket Button */}
{allMatchesComplete && !event.isComplete && (
<Card className="border-green-500 bg-green-50 dark:bg-green-950">
<Card className="border-emerald-500/30 bg-emerald-500/10">
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Trophy className="h-5 w-5 text-green-600" />
<Trophy className="h-5 w-5 text-emerald-400" />
Finalize Bracket
</CardTitle>
<CardDescription>
@ -726,7 +726,7 @@ export default function EventBracket({
<li>Recalculate all team standings</li>
</ul>
</div>
<Button type="submit" className="w-full bg-green-600 hover:bg-green-700">
<Button type="submit" className="w-full">
Finalize Bracket & Update Standings
</Button>
</div>
@ -739,9 +739,9 @@ export default function EventBracket({
{/* Event Complete Badge */}
{event.isComplete && (
<Card className="border-blue-500 bg-blue-50 dark:bg-blue-950">
<Card className="border-electric/30 bg-electric/10">
<CardContent className="pt-6">
<div className="flex items-center gap-2 text-blue-700 dark:text-blue-400">
<div className="flex items-center gap-2 text-electric">
<Trophy className="h-5 w-5" />
<span className="font-semibold">Event Complete</span>
<span className="text-sm text-muted-foreground ml-auto">

View file

@ -101,7 +101,7 @@ export default function EventResults({
</Button>
)}
{event.isComplete ? (
<Badge variant="default" className="bg-green-500">
<Badge variant="default" className="bg-emerald-500">
<CheckCircle2 className="mr-1 h-3 w-3" />
Completed
</Badge>
@ -120,9 +120,9 @@ export default function EventResults({
<div className="space-y-6">
{/* Debug info and manual QP processing for completed major tournaments */}
{event.isComplete && event.eventType === "major_tournament" && (
<Card className="border-blue-200 dark:border-blue-800">
<Card className="border-electric/30">
<CardHeader>
<CardTitle className="text-blue-600 dark:text-blue-400">
<CardTitle className="text-electric">
Event Processing Status
</CardTitle>
<CardDescription>
@ -169,7 +169,7 @@ export default function EventResults({
)}
{actionData?.success && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
{actionData.success}
</div>
)}
@ -240,9 +240,9 @@ export default function EventResults({
</Card>
{/* Complete Season Button */}
<Card className="border-orange-200 dark:border-orange-800">
<Card className="border-amber-accent/30">
<CardHeader>
<CardTitle className="text-orange-600 dark:text-orange-400">
<CardTitle className="text-amber-accent">
<Trophy className="inline mr-2 h-5 w-5" />
Finalize Season
</CardTitle>
@ -489,13 +489,13 @@ export default function EventResults({
{/* Bracket Explanation Card for Playoff Events */}
{event.eventType === "playoff_game" && !participantResults?.length && (
<Card className="border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-950">
<Card className="border-electric/30 bg-electric/10">
<CardHeader>
<CardTitle className="text-blue-700 dark:text-blue-300">
<CardTitle className="text-electric">
<Brackets className="inline mr-2 h-5 w-5" />
Bracket Event
</CardTitle>
<CardDescription className="text-blue-600 dark:text-blue-400">
<CardDescription className="text-electric">
This is a bracket/playoff event. Results are managed through the bracket interface.
</CardDescription>
</CardHeader>
@ -522,11 +522,11 @@ export default function EventResults({
{/* Participant Results with Fantasy Points */}
{participantResults && participantResults.length > 0 && (
<Card className={event.eventType === "playoff_game" ? "border-green-200 dark:border-green-800" : ""}>
<Card className={event.eventType === "playoff_game" ? "border-emerald-500/30" : ""}>
<CardHeader>
<div className="flex items-center justify-between">
<div>
<CardTitle className={event.eventType === "playoff_game" ? "text-green-700 dark:text-green-300" : ""}>
<CardTitle className={event.eventType === "playoff_game" ? "text-emerald-400" : ""}>
{event.eventType === "playoff_game" ? (
<>
<Trophy className="inline mr-2 h-5 w-5" />
@ -544,7 +544,7 @@ export default function EventResults({
</CardDescription>
</div>
{event.eventType === "playoff_game" && event.isComplete && (
<Badge variant="default" className="bg-green-500">
<Badge variant="default" className="bg-emerald-500">
<CheckCircle2 className="mr-1 h-3 w-3" />
Bracket Finalized
</Badge>
@ -600,7 +600,7 @@ export default function EventResults({
<TableCell>{result.participant.name}</TableCell>
<TableCell className="text-right font-semibold">
{result.qualifyingPoints ? (
<span className={result.qualifyingPoints === "0.00" ? "text-muted-foreground" : "text-green-600 dark:text-green-400"}>
<span className={result.qualifyingPoints === "0.00" ? "text-muted-foreground" : "text-emerald-400"}>
{parseFloat(result.qualifyingPoints).toFixed(2)} pts
</span>
) : (

View file

@ -46,7 +46,7 @@ export default function SportsSeasonEvents({
const getStatusBadge = (isComplete: boolean) => {
return isComplete ? (
<Badge variant="default" className="bg-green-500">
<Badge variant="default" className="bg-emerald-500">
Completed
</Badge>
) : (
@ -86,7 +86,7 @@ export default function SportsSeasonEvents({
)}
{actionData?.success && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
{actionData.success}
</div>
)}

View file

@ -53,17 +53,17 @@ export default function ExpectedValuesPage({ loaderData, actionData }: Route.Com
</CardHeader>
<CardContent className="space-y-6">
{actionData?.error && (
<div className="p-4 bg-red-50 border border-red-200 rounded-md text-red-700">
<div className="p-4 bg-destructive/10 border border-destructive/30 rounded-md text-destructive">
{actionData.error}
</div>
)}
{actionData?.success && (
<div className="p-4 bg-green-50 border border-green-200 rounded-md text-green-700">
<div className="p-4 bg-emerald-500/15 border border-emerald-500/30 rounded-md text-emerald-400">
All participants saved successfully!
</div>
)}
<div className="text-sm text-gray-600 space-y-2">
<div className="text-sm text-muted-foreground space-y-2">
<p><strong>Default Scoring Rules (for EV calculation):</strong></p>
<div className="grid grid-cols-4 gap-2">
<span>1st: 100 pts</span>
@ -75,7 +75,7 @@ export default function ExpectedValuesPage({ loaderData, actionData }: Route.Com
<span>7th: 15 pts</span>
<span>8th: 15 pts</span>
</div>
<p className="text-xs text-gray-500 italic">
<p className="text-xs text-muted-foreground italic">
Note: EVs will be recalculated with actual league scoring rules when used in fantasy leagues.
</p>
</div>
@ -209,7 +209,7 @@ export default function ExpectedValuesPage({ loaderData, actionData }: Route.Com
</Table>
{participants.length === 0 ? (
<p className="text-center text-gray-500 py-8">
<p className="text-center text-muted-foreground py-8">
No participants found. Please add participants to this sports season first.
</p>
) : (

View file

@ -308,11 +308,11 @@ export default function AdminSportsSeasonFuturesOdds() {
<div className="space-y-3">
{parseResults.matched.length > 0 && (
<div>
<div className="flex items-center gap-2 text-sm font-medium text-green-700 mb-2">
<div className="flex items-center gap-2 text-sm font-medium text-emerald-400 mb-2">
<CheckCircle2 className="h-4 w-4" />
Matched ({parseResults.matched.length})
</div>
<div className="rounded-md border border-green-200 bg-green-50 divide-y divide-green-100 text-sm">
<div className="rounded-md border border-emerald-500/30 bg-emerald-500/10 divide-y divide-emerald-500/20 text-sm">
{parseResults.matched.map(m => (
<div key={m.participantId} className="flex justify-between px-3 py-1.5">
<span className="text-muted-foreground">{m.inputName}</span>
@ -538,9 +538,9 @@ export default function AdminSportsSeasonFuturesOdds() {
)}
{actionData && actionData.success && !actionData.preview && (
<Card className="border-green-500">
<Card className="border-emerald-500/30 bg-emerald-500/10">
<CardContent className="pt-6">
<div className="text-green-700 font-medium">Success</div>
<div className="text-emerald-400 font-medium">Success</div>
<div className="text-sm mt-2">{actionData.message}</div>
</CardContent>
</Card>

View file

@ -163,7 +163,7 @@ export default function ManageParticipants({ loaderData, actionData }: Route.Com
)}
{actionData?.success && !actionData?.count && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
Participant added successfully!
</div>
)}
@ -209,7 +209,7 @@ export default function ManageParticipants({ loaderData, actionData }: Route.Com
)}
{actionData?.success && actionData?.count && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
{actionData.count} participant{actionData.count !== 1 ? 's' : ''} added successfully!
</div>
)}

View file

@ -149,11 +149,11 @@ export default function RecalculateProbabilities() {
</div>
{invalidProbabilities.length > 0 && (
<Card className="border-yellow-500 bg-yellow-500/10">
<Card className="border-amber-accent/30 bg-amber-accent/10">
<CardHeader>
<div className="flex items-center gap-2">
<AlertTriangle className="h-5 w-5 text-yellow-600" />
<CardTitle className="text-yellow-600">
<AlertTriangle className="h-5 w-5 text-amber-accent" />
<CardTitle className="text-amber-accent">
Invalid Probability Data Detected
</CardTitle>
</div>
@ -192,11 +192,11 @@ export default function RecalculateProbabilities() {
)}
{actionData?.success ? (
<Card className="border-green-500 bg-green-500/10">
<Card className="border-emerald-500/30 bg-emerald-500/10">
<CardHeader>
<div className="flex items-center gap-2">
<CheckCircle className="h-5 w-5 text-green-600" />
<CardTitle className="text-green-600">
<CheckCircle className="h-5 w-5 text-emerald-400" />
<CardTitle className="text-emerald-400">
Probabilities Updated Successfully
</CardTitle>
</div>
@ -371,7 +371,7 @@ export default function RecalculateProbabilities() {
value="true"
/>
<div className="bg-blue-500/10 border border-blue-500/20 rounded-lg p-4">
<div className="bg-electric/10 border border-electric/20 rounded-lg p-4">
<h4 className="font-semibold text-sm mb-2">What happens:</h4>
<ul className="text-sm space-y-1 text-muted-foreground">
<li>

View file

@ -270,7 +270,7 @@ export default function EditSportsSeason({ loaderData, actionData }: Route.Compo
)}
{actionData?.success && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
Sports season updated successfully!
</div>
)}

View file

@ -131,19 +131,19 @@ export default function AdminStandingsSnapshots({
<Card
className={`mb-6 ${
actionData.success
? "border-green-500 bg-green-50"
: "border-red-500 bg-red-50"
? "border-emerald-500/30 bg-emerald-500/10"
: "border-destructive/30 bg-destructive/10"
}`}
>
<CardContent className="flex items-center gap-3 pt-6">
{actionData.success ? (
<CheckCircle2 className="h-5 w-5 text-green-600" />
<CheckCircle2 className="h-5 w-5 text-emerald-400" />
) : (
<AlertCircle className="h-5 w-5 text-red-600" />
<AlertCircle className="h-5 w-5 text-destructive" />
)}
<p
className={
actionData.success ? "text-green-900" : "text-red-900"
actionData.success ? "text-emerald-400" : "text-destructive"
}
>
{actionData.message}
@ -258,7 +258,7 @@ export default function AdminStandingsSnapshots({
{hasSnapshotToday && (
<Badge
variant="outline"
className="text-xs bg-green-50 text-green-700 border-green-200"
className="text-xs bg-emerald-500/15 text-emerald-400 border-emerald-500/30"
>
Today
</Badge>

View file

@ -211,7 +211,7 @@ export default function EditTemplate({ loaderData, actionData }: Route.Component
)}
{actionData?.success && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
Template updated successfully!
</div>
)}

View file

@ -125,11 +125,11 @@ export default function NewTemplate({ actionData }: Route.ComponentProps) {
</CardContent>
</Card>
<Card className="mt-6 border-blue-200 bg-blue-50 dark:bg-blue-950 dark:border-blue-800">
<Card className="mt-6 border-electric/30 bg-electric/10">
<CardHeader>
<CardTitle className="text-blue-900 dark:text-blue-100">Next Steps</CardTitle>
<CardTitle className="text-electric">Next Steps</CardTitle>
</CardHeader>
<CardContent className="text-sm text-blue-800 dark:text-blue-200">
<CardContent className="text-sm text-foreground/80">
<p>After creating the template, you'll be able to:</p>
<ul className="list-disc list-inside mt-2 space-y-1">
<li>Add sports seasons to the template</li>

View file

@ -161,7 +161,7 @@ export default function DraftBoard() {
<div className="flex items-center gap-2">
<div
className={`w-3 h-3 rounded-full ${
isConnected ? "bg-green-500" : "bg-red-500"
isConnected ? "bg-emerald-500" : "bg-coral-accent"
}`}
/>
<span className="text-sm font-medium">

View file

@ -758,14 +758,14 @@ export default function DraftRoom() {
<div className="h-screen bg-background flex flex-col overflow-hidden">
{/* Draft Completion Banner */}
{isDraftComplete && (
<div className="bg-green-500 text-white px-4 py-3 text-center font-semibold flex-shrink-0">
<div className="bg-emerald-500/20 border-b border-emerald-500/30 text-emerald-400 px-4 py-3 text-center font-semibold flex-shrink-0">
🎉 Draft Complete! The season is now active.
{season.league.isPublicDraftBoard && (
<>
{" "}
<a
href={`/leagues/${season.leagueId}/draft-board/${season.id}`}
className="underline hover:text-green-100"
className="underline hover:text-emerald-300"
>
View Draft Board
</a>
@ -841,7 +841,7 @@ export default function DraftRoom() {
<div className="flex items-center gap-2">
<div
className={`w-3 h-3 rounded-full ${
isConnected ? "bg-green-500" : "bg-red-500"
isConnected ? "bg-emerald-500" : "bg-coral-accent"
}`}
/>
<span className="text-sm font-medium">
@ -1029,7 +1029,7 @@ export default function DraftRoom() {
className={`border-t ${
isEligible
? "hover:bg-muted/50"
: "bg-red-50/30 dark:bg-red-950/20 opacity-60"
: "bg-destructive/10 opacity-60"
}`}
title={!isEligible ? ineligibleReason : undefined}
>

View file

@ -660,7 +660,7 @@ export default function LeagueSettings({ loaderData, actionData }: Route.Compone
id="isPublicDraftBoard"
name="isPublicDraftBoard"
defaultChecked={league.isPublicDraftBoard}
className="h-4 w-4 rounded border-gray-300"
className="h-4 w-4 rounded border-border"
/>
<Label htmlFor="isPublicDraftBoard" className="font-normal cursor-pointer">
Make draft board publicly accessible (no login required)
@ -919,7 +919,7 @@ export default function LeagueSettings({ loaderData, actionData }: Route.Compone
)}
{actionData?.success && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
Settings updated successfully!
</div>
)}
@ -1005,7 +1005,7 @@ export default function LeagueSettings({ loaderData, actionData }: Route.Compone
)}
{actionData?.success && actionData?.message && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
{actionData.message}
</div>
)}
@ -1135,7 +1135,7 @@ export default function LeagueSettings({ loaderData, actionData }: Route.Compone
</div>
)}
{actionData?.success && actionData?.message && (
<div className="bg-green-500/15 text-green-700 dark:text-green-400 px-4 py-3 rounded-md text-sm">
<div className="bg-emerald-500/15 text-emerald-400 px-4 py-3 rounded-md text-sm">
{actionData.message}
</div>
)}

View file

@ -326,7 +326,7 @@ export default function LeagueHome({ loaderData }: Route.ComponentProps) {
<p className="text-sm text-muted-foreground">Draft Board</p>
<Link
to={`/leagues/${league.id}/draft-board/${season.id}`}
className="text-blue-600 hover:underline font-medium"
className="text-electric hover:underline font-medium"
>
View Draft Board
</Link>
@ -335,7 +335,7 @@ export default function LeagueHome({ loaderData }: Route.ComponentProps) {
<p className="text-sm text-muted-foreground">Standings</p>
<Link
to={`/leagues/${league.id}/standings/${season.id}`}
className="text-blue-600 hover:underline font-medium"
className="text-electric hover:underline font-medium"
>
View Standings
</Link>

View file

@ -37,7 +37,7 @@ export default function TestSocket() {
<div className="flex items-center gap-2">
<div
className={`w-3 h-3 rounded-full ${
isConnected ? "bg-green-500" : "bg-red-500"
isConnected ? "bg-emerald-500" : "bg-coral-accent"
}`}
/>
<span className="font-semibold">
@ -45,7 +45,7 @@ export default function TestSocket() {
</span>
</div>
{socket && (
<p className="text-sm text-gray-600 mt-1">
<p className="text-sm text-muted-foreground mt-1">
Socket ID: {socket.id}
</p>
)}
@ -54,20 +54,20 @@ export default function TestSocket() {
<button
onClick={sendTestMessage}
disabled={!isConnected}
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 disabled:bg-gray-300 disabled:cursor-not-allowed"
className="px-4 py-2 bg-primary text-primary-foreground rounded hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground disabled:cursor-not-allowed"
>
Send Test Message
</button>
<div className="mt-6">
<h2 className="text-xl font-semibold mb-2">Messages:</h2>
<div className="bg-gray-100 p-4 rounded max-h-96 overflow-y-auto">
<div className="bg-muted p-4 rounded max-h-96 overflow-y-auto">
{messages.length === 0 ? (
<p className="text-gray-500">No messages yet...</p>
<p className="text-muted-foreground">No messages yet...</p>
) : (
<ul className="space-y-2">
{messages.map((msg, idx) => (
<li key={idx} className="text-sm font-mono bg-white p-2 rounded">
<li key={idx} className="text-sm font-mono bg-card p-2 rounded">
{msg}
</li>
))}
@ -76,7 +76,7 @@ export default function TestSocket() {
</div>
</div>
<div className="mt-6 p-4 bg-yellow-50 border border-yellow-200 rounded">
<div className="mt-6 p-4 bg-amber-accent/10 border border-amber-accent/30 rounded">
<h3 className="font-semibold mb-2">Instructions:</h3>
<ol className="list-decimal list-inside space-y-1 text-sm">
<li>Check that the status shows "Connected"</li>

View file

@ -2,7 +2,6 @@ import { Link } from "react-router";
import { Button } from "~/components/ui/button";
import logoDark from "./logo-dark.svg";
import logoLight from "./logo-light.svg";
export function Welcome({ message }: { message: string }) {
return (
@ -11,15 +10,10 @@ export function Welcome({ message }: { message: string }) {
<header className="flex flex-col items-center gap-9">
<h1 className="sr-only">{message}</h1>
<div className="w-[500px] max-w-[100vw] p-4">
<img
src={logoLight}
alt="React Router"
className="block w-full dark:hidden"
/>
<img
src={logoDark}
alt="React Router"
className="hidden w-full dark:block"
className="w-full"
/>
</div>
</header>
@ -29,15 +23,15 @@ export function Welcome({ message }: { message: string }) {
<Link to="/leagues/new">Start a League</Link>
</Button>
</div>
<nav className="rounded-3xl border border-gray-200 p-6 dark:border-gray-700 space-y-4">
<p className="leading-6 text-gray-700 dark:text-gray-200 text-center">
<nav className="rounded-3xl border border-border p-6 space-y-4">
<p className="leading-6 text-foreground text-center">
What&apos;s next?
</p>
<ul>
{resources.map(({ href, text, icon }) => (
<li key={href}>
<a
className="group flex items-center gap-3 self-stretch p-3 leading-normal text-blue-700 hover:underline dark:text-blue-500"
className="group flex items-center gap-3 self-stretch p-3 leading-normal text-electric hover:underline"
href={href}
target="_blank"
rel="noreferrer"
@ -66,7 +60,7 @@ const resources = [
height="20"
viewBox="0 0 20 20"
fill="none"
className="stroke-gray-600 group-hover:stroke-current dark:stroke-gray-300"
className="stroke-muted-foreground group-hover:stroke-current"
>
<path
d="M9.99981 10.0751V9.99992M17.4688 17.4688C15.889 19.0485 11.2645 16.9853 7.13958 12.8604C3.01467 8.73546 0.951405 4.11091 2.53116 2.53116C4.11091 0.951405 8.73546 3.01467 12.8604 7.13958C16.9853 11.2645 19.0485 15.889 17.4688 17.4688ZM2.53132 17.4688C0.951566 15.8891 3.01483 11.2645 7.13974 7.13963C11.2647 3.01471 15.8892 0.951453 17.469 2.53121C19.0487 4.11096 16.9854 8.73551 12.8605 12.8604C8.73562 16.9853 4.11107 19.0486 2.53132 17.4688Z"
@ -86,7 +80,7 @@ const resources = [
height="20"
viewBox="0 0 24 20"
fill="none"
className="stroke-gray-600 group-hover:stroke-current dark:stroke-gray-300"
className="stroke-muted-foreground group-hover:stroke-current"
>
<path
d="M15.0686 1.25995L14.5477 1.17423L14.2913 1.63578C14.1754 1.84439 14.0545 2.08275 13.9422 2.31963C12.6461 2.16488 11.3406 2.16505 10.0445 2.32014C9.92822 2.08178 9.80478 1.84975 9.67412 1.62413L9.41449 1.17584L8.90333 1.25995C7.33547 1.51794 5.80717 1.99419 4.37748 2.66939L4.19 2.75793L4.07461 2.93019C1.23864 7.16437 0.46302 11.3053 0.838165 15.3924L0.868838 15.7266L1.13844 15.9264C2.81818 17.1714 4.68053 18.1233 6.68582 18.719L7.18892 18.8684L7.50166 18.4469C7.96179 17.8268 8.36504 17.1824 8.709 16.4944L8.71099 16.4904C10.8645 17.0471 13.128 17.0485 15.2821 16.4947C15.6261 17.1826 16.0293 17.8269 16.4892 18.4469L16.805 18.8725L17.3116 18.717C19.3056 18.105 21.1876 17.1751 22.8559 15.9238L23.1224 15.724L23.1528 15.3923C23.5873 10.6524 22.3579 6.53306 19.8947 2.90714L19.7759 2.73227L19.5833 2.64518C18.1437 1.99439 16.6386 1.51826 15.0686 1.25995ZM16.6074 10.7755L16.6074 10.7756C16.5934 11.6409 16.0212 12.1444 15.4783 12.1444C14.9297 12.1444 14.3493 11.6173 14.3493 10.7877C14.3493 9.94885 14.9378 9.41192 15.4783 9.41192C16.0471 9.41192 16.6209 9.93851 16.6074 10.7755ZM8.49373 12.1444C7.94513 12.1444 7.36471 11.6173 7.36471 10.7877C7.36471 9.94885 7.95323 9.41192 8.49373 9.41192C9.06038 9.41192 9.63892 9.93712 9.6417 10.7815C9.62517 11.6239 9.05462 12.1444 8.49373 12.1444Z"

40
package-lock.json generated
View file

@ -7,6 +7,7 @@
"name": "brackt.com",
"dependencies": {
"@clerk/react-router": "^2.1.0",
"@clerk/themes": "^2.4.55",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
@ -767,13 +768,13 @@
}
},
"node_modules/@clerk/shared": {
"version": "3.27.3",
"resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-3.27.3.tgz",
"integrity": "sha512-OJqWwlQGi6XMVWJVtY1YmOESAkEAflDrynFSjwQQ/sC8c4hmUukIq07XTOlcv6j4u1i4akhtNwy40B1qiRrLdg==",
"version": "3.47.0",
"resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-3.47.0.tgz",
"integrity": "sha512-EDWFysptTc58X96MGQIZ3LlcMFKLG+rhIF9kf6n+wnyQDWnfuyA8I8ge7GbjfUXMf00c//A/CGSjg7t/oupUpw==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@clerk/types": "^4.92.0",
"csstype": "3.1.3",
"dequal": "2.0.3",
"glob-to-regexp": "0.4.1",
"js-cookie": "3.0.5",
@ -784,8 +785,8 @@
"node": ">=18.17.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0 || ^19.0.0-0",
"react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-0"
"react": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0",
"react-dom": "^18.0.0 || ~19.0.3 || ~19.1.4 || ~19.2.3 || ~19.3.0-0"
},
"peerDependenciesMeta": {
"react": {
@ -796,6 +797,19 @@
}
}
},
"node_modules/@clerk/themes": {
"version": "2.4.55",
"resolved": "https://registry.npmjs.org/@clerk/themes/-/themes-2.4.55.tgz",
"integrity": "sha512-j9q8NtAaI2f7vNBuO2RAUDmAebab2UoZCXshlTzEhsbB1UH+94fPs4KyUlsbrSNxIJNfTrM2IKxAZKos3gcCJw==",
"license": "MIT",
"dependencies": {
"@clerk/shared": "^3.47.0",
"tslib": "2.8.1"
},
"engines": {
"node": ">=18.17.0"
}
},
"node_modules/@clerk/types": {
"version": "4.92.0",
"resolved": "https://registry.npmjs.org/@clerk/types/-/types-4.92.0.tgz",
@ -11337,9 +11351,9 @@
}
},
"node_modules/react": {
"version": "19.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
"version": "19.2.4",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@ -11367,15 +11381,15 @@
}
},
"node_modules/react-dom": {
"version": "19.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
"version": "19.2.4",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
"integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
"license": "MIT",
"dependencies": {
"scheduler": "^0.27.0"
},
"peerDependencies": {
"react": "^19.2.0"
"react": "^19.2.4"
}
},
"node_modules/react-is": {

View file

@ -22,6 +22,7 @@
},
"dependencies": {
"@clerk/react-router": "^2.1.0",
"@clerk/themes": "^2.4.55",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",