diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css index 2a20340..68d87fe 100644 --- a/apps/web/src/app/globals.css +++ b/apps/web/src/app/globals.css @@ -90,9 +90,9 @@ /* ─── Light Theme Surface Variables ─────────────────────────────────────── */ :root { - --surface-page: 246 247 251; + --surface-page: 253 251 255; --surface-card: 255 255 255; - --surface-elevated: 249 250 252; + --surface-elevated: 248 246 255; --surface-input: 255 255 255; --border-subtle: 219 224 232; --border-input: 197 205 218; @@ -108,18 +108,18 @@ .dark { color-scheme: dark; - --surface-page: 12 17 29; - --surface-card: 16 23 38; - --surface-elevated: 24 33 52; - --surface-input: 18 28 45; - --border-subtle: 41 55 78; - --border-input: 61 79 110; + --surface-page: 8 8 22; + --surface-card: 13 14 34; + --surface-elevated: 19 20 46; + --surface-input: 11 12 30; + --border-subtle: 38 42 68; + --border-input: 58 64 98; --text-primary: 237 242 247; --text-secondary: 196 207 223; --text-muted: 147 161 185; --text-very-muted: 118 133 161; - --shadow-soft: 2 6 23 / 0.38; - --shadow-strong: 2 6 23 / 0.65; + --shadow-soft: 0 0 0 / 0.45; + --shadow-strong: 0 0 0 / 0.75; } /* ─── Base Layer: Apply variables to body ────────────────────────────────── */ @@ -132,6 +132,7 @@ background-color 0.15s ease, color 0.15s ease; background-image: + radial-gradient(ellipse 80% 40% at 50% -5%, rgba(var(--accent-300), 0.05) 0%, transparent 55%), radial-gradient(ellipse at 0% 0%, rgb(var(--accent-50) / 0.15), transparent 50%), radial-gradient(ellipse at 100% 100%, rgb(var(--accent-100) / 0.08), transparent 50%), radial-gradient(circle at top left, rgb(var(--accent-100) / 0.32), transparent 24rem), @@ -141,6 +142,7 @@ .dark body { background-image: + radial-gradient(ellipse 80% 50% at 50% -10%, rgba(var(--accent-400), 0.07) 0%, transparent 60%), radial-gradient(circle at top left, rgb(var(--accent-600) / 0.16), transparent 26rem), linear-gradient(180deg, rgb(15 23 42 / 0.35), transparent 28rem); } @@ -352,33 +354,67 @@ @layer components { .app-surface { @apply rounded-2xl border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-900/90; - --tw-shadow: 0 1px 3px rgba(0, 0, 0, 0.04), 0 4px 12px rgba(0, 0, 0, 0.03); + background: linear-gradient(145deg, #ffffff 0%, #fdfbff 100%); + --tw-shadow: 0 1px 3px rgba(100, 80, 160, 0.06), 0 4px 16px rgba(100, 80, 160, 0.04); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } :is(.dark) .app-surface { - --tw-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 4px 12px rgba(0, 0, 0, 0.15); + background: linear-gradient(135deg, rgba(255,255,255,0.055) 0%, rgba(255,255,255,0.018) 100%); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + border-color: rgba(255,255,255,0.09); + --tw-shadow: 0 2px 8px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.05), inset 0 1px 0 rgba(255,255,255,0.07); + box-shadow: var(--tw-shadow); } .app-surface-strong { @apply rounded-3xl border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-900; - --tw-shadow: 0 2px 8px rgba(0, 0, 0, 0.06), 0 8px 24px rgba(0, 0, 0, 0.04); + background: linear-gradient(145deg, #ffffff 0%, #fdfbff 100%); + --tw-shadow: 0 2px 8px rgba(100, 80, 160, 0.06), 0 8px 24px rgba(100, 80, 160, 0.04); box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); } :is(.dark) .app-surface-strong { - --tw-shadow: 0 2px 8px rgba(0, 0, 0, 0.3), 0 8px 24px rgba(0, 0, 0, 0.2); + background: linear-gradient(135deg, rgba(255,255,255,0.065) 0%, rgba(255,255,255,0.022) 100%); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-color: rgba(255,255,255,0.10); + --tw-shadow: 0 4px 16px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.06), inset 0 1px 0 rgba(255,255,255,0.08); + box-shadow: var(--tw-shadow); } .app-toolbar { - @apply sticky top-0 z-10 rounded-2xl border border-gray-200 bg-white/80 p-4 shadow-sm backdrop-blur-sm; - @apply dark:border-gray-700 dark:bg-gray-900/80 dark:shadow-black/20; + @apply sticky top-0 z-10 rounded-2xl border p-4; + background: rgba(253,251,255,0.85); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-color: rgba(100,80,160,0.12); + box-shadow: 0 1px 3px rgba(100,80,160,0.06); + } + + :is(.dark) .app-toolbar { + background: rgba(13,14,34,0.82); + backdrop-filter: blur(20px); + -webkit-backdrop-filter: blur(20px); + border-color: rgba(255,255,255,0.08); + box-shadow: 0 1px 0 rgba(255,255,255,0.04); } .app-input { @apply w-full rounded-xl border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 outline-none transition; - @apply focus:border-brand-500 focus:ring-4 focus:ring-brand-100/80; - @apply dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 dark:focus:ring-brand-900/50; + @apply dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100; + } + + .app-input:focus { + border-color: rgb(var(--accent-500)); + box-shadow: 0 0 0 3px rgba(var(--accent-400), 0.25), 0 1px 2px rgba(0,0,0,0.05); + outline: none; + } + + :is(.dark) .app-input:focus { + border-color: rgb(var(--accent-400)); + box-shadow: 0 0 0 3px rgba(var(--accent-400), 0.20), inset 0 0 8px rgba(var(--accent-400), 0.08); } .app-select { @@ -403,6 +439,13 @@ @apply font-display text-3xl font-semibold text-gray-900 dark:text-gray-100; } + :is(.dark) .app-page-title { + background: linear-gradient(135deg, rgb(var(--accent-200)) 0%, #e8e4ff 50%, rgb(237 242 247) 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + } + .app-page-subtitle { @apply text-sm text-gray-500 dark:text-gray-400; } @@ -419,6 +462,10 @@ @apply bg-gray-50/90 dark:bg-gray-800/80; } + :is(.dark) .app-data-table thead tr { + background: rgba(255,255,255,0.04); + } + .app-data-table th { @apply text-[11px] font-semibold uppercase tracking-[0.16em] text-gray-500 dark:text-gray-400; } @@ -447,6 +494,32 @@ } } +/* ─── Aurora: new keyframes ──────────────────────────────────────────────── */ +@keyframes fadeSlideUp { + from { opacity: 0; transform: translateY(6px); } + to { opacity: 1; transform: translateY(0); } +} + +@keyframes scaleIn { + from { opacity: 0; transform: scale(0.96); } + to { opacity: 1; transform: scale(1); } +} + +@keyframes glowPulse { + 0%, 100% { box-shadow: 0 0 12px rgba(var(--accent-400), 0.3); } + 50% { box-shadow: 0 0 24px rgba(var(--accent-400), 0.55); } +} + +.animate-fade-slide-up { + animation: fadeSlideUp 0.12s ease-out both; +} +.animate-scale-in { + animation: scaleIn 0.12s ease-out both; +} +.animate-glow-pulse { + animation: glowPulse 2s ease-in-out infinite; +} + /* ─── Overbooking blink animation ──────────────────────────────────────────── */ @keyframes overbooking-blink { 0%, 100% { background-color: rgba(239, 68, 68, 0); } @@ -480,6 +553,12 @@ animation: shimmer 1.8s ease-in-out infinite; } +:is(.dark) .shimmer-skeleton { + background: linear-gradient(90deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.09) 50%, rgba(255,255,255,0.04) 100%); + background-size: 200% 100%; + animation: shimmer 1.5s ease-in-out infinite; +} + /* ─── Table row stagger entrance ─────────────────────────────────────────── */ @keyframes fadeSlideIn { from { @@ -493,20 +572,20 @@ } .animate-row-enter { - animation: fadeSlideIn 0.25s ease-out both; + animation: fadeSlideIn 0.12s ease-out both; } /* ─── Subtle hover lift for cards and table rows ─────────────────────────── */ .hover-lift { - transition: transform 0.15s ease-out, box-shadow 0.15s ease-out; + transition: transform 0.1s ease-out, box-shadow 0.1s ease-out; } .hover-lift:hover { transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.06); + box-shadow: 0 6px 20px rgba(var(--accent-400), 0.18), 0 2px 8px rgba(0,0,0,0.08); } :is(.dark) .hover-lift:hover { - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); + box-shadow: 0 6px 24px rgba(var(--accent-400), 0.22), 0 2px 8px rgba(0,0,0,0.35); } /* ─── Smooth scroll + reduced-motion accessibility ────────────────────────── */ @@ -530,7 +609,7 @@ html { /* ─── Table row hover accent border ──────────────────────────────────────── */ .table-row-hover { border-left: 2px solid transparent; - transition: border-color 0.15s ease-out, background-color 0.15s ease-out, transform 0.15s ease-out, box-shadow 0.15s ease-out; + transition: border-color 100ms ease-out, background-color 100ms ease-out, transform 100ms ease-out, box-shadow 100ms ease-out; } .table-row-hover:hover { border-left-color: rgb(var(--accent-400)); diff --git a/apps/web/src/components/layout/AppShell.tsx b/apps/web/src/components/layout/AppShell.tsx index cf57d7a..31ae73a 100644 --- a/apps/web/src/components/layout/AppShell.tsx +++ b/apps/web/src/components/layout/AppShell.tsx @@ -334,17 +334,17 @@ const NavItemLink = memo(function NavItemLink({ href={href as Route} {...linkProps} className={clsx( - "group relative flex items-center rounded-2xl text-sm font-medium transition-colors", + "group relative flex items-center rounded-2xl text-sm transition-colors", collapsed ? "justify-center px-2 py-2" : "gap-3 px-3 py-2", isActive - ? "text-brand-800 dark:text-brand-200" - : "text-gray-700 hover:bg-gray-100/90 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-slate-900 dark:hover:text-white", + ? "font-medium text-brand-700 dark:border-l-2 dark:border-brand-400/70 dark:text-brand-300" + : "font-medium text-gray-700 hover:bg-gray-100/90 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-white/[0.05] dark:hover:text-white", )} > {isActive && ( )} @@ -426,7 +426,7 @@ function SidebarContent({ sidebarCollapsed ? "px-3 py-4" : "px-6 py-6", )}>
@@ -551,7 +551,7 @@ function SidebarContent({