diff --git a/client/src/index.css b/client/src/index.css
index 6dc1329..81a308a 100644
--- a/client/src/index.css
+++ b/client/src/index.css
@@ -82,6 +82,124 @@
--gradient-accent: hsl(282, 100%, 65%);
}
+/* Enhanced keyframes for mobile animations */
+@keyframes slideInRight {
+ from {
+ opacity: 0;
+ transform: translateX(100%);
+ }
+ to {
+ opacity: 1;
+ transform: translateX(0);
+ }
+}
+
+@keyframes slideInLeft {
+ from {
+ opacity: 0;
+ transform: translateX(-100%);
+ }
+ to {
+ opacity: 1;
+ transform: translateX(0);
+ }
+}
+
+@keyframes slideInUp {
+ from {
+ opacity: 0;
+ transform: translateY(100%);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes slideInDown {
+ from {
+ opacity: 0;
+ transform: translateY(-100%);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+@keyframes fadeInUp {
+ from {
+ opacity: 0;
+ transform: translateY(30px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes scaleIn {
+ from {
+ opacity: 0;
+ transform: scale(0.9);
+ }
+ to {
+ opacity: 1;
+ transform: scale(1);
+ }
+}
+
+@keyframes cardAppear {
+ from {
+ opacity: 0;
+ transform: translateY(20px) scale(0.95);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+}
+
+@keyframes mobileModalEnter {
+ from {
+ opacity: 0;
+ transform: translateY(100%);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+@keyframes mobileModalExit {
+ from {
+ opacity: 1;
+ transform: translateY(0);
+ }
+ to {
+ opacity: 0;
+ transform: translateY(100%);
+ }
+}
+
+@keyframes pulse {
+ 0%, 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.5;
+ }
+}
+
@layer base {
* {
@apply border-border;
@@ -91,6 +209,42 @@
@apply font-sans antialiased bg-background text-foreground;
font-feature-settings: "rlig" 1, "calt" 1;
letter-spacing: -0.01em;
+ /* Optimize for mobile */
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ /* Prevent horizontal scroll on mobile */
+ overflow-x: hidden;
+ }
+
+ /* Enhanced mobile viewport handling */
+ html {
+ /* Prevent zoom on double tap */
+ touch-action: manipulation;
+ /* Smooth scrolling */
+ scroll-behavior: smooth;
+ }
+
+ /* Disable text selection for UI elements */
+ .select-none {
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ }
+
+ /* Improve touch interactions */
+ button,
+ [role="button"],
+ input[type="submit"],
+ input[type="button"] {
+ touch-action: manipulation;
+ -webkit-tap-highlight-color: transparent;
+ }
+
+ /* Focus styles for accessibility */
+ *:focus-visible {
+ outline: 2px solid hsl(var(--ring));
+ outline-offset: 2px;
}
/* Smooth scrollbar */
@@ -113,7 +267,52 @@
}
@layer components {
- /* Modern animations */
+ /* Mobile-first responsive utilities */
+ .mobile-container {
+ @apply w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
+ }
+
+ .mobile-grid {
+ @apply grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 sm:gap-6;
+ }
+
+ .mobile-stack {
+ @apply flex flex-col space-y-4 sm:space-y-6;
+ }
+
+ .mobile-row {
+ @apply flex flex-col sm:flex-row gap-4 sm:gap-6 items-start sm:items-center;
+ }
+
+ /* Responsive spacing */
+ .mobile-spacing {
+ @apply space-y-4 sm:space-y-6 lg:space-y-8;
+ }
+
+ .mobile-padding {
+ @apply p-4 sm:p-6 lg:p-8;
+ }
+
+ .mobile-margin {
+ @apply m-4 sm:m-6 lg:m-8;
+ }
+
+ /* Touch-friendly interactions */
+ .touch-target {
+ @apply min-h-[44px] min-w-[44px] flex items-center justify-center;
+ }
+
+ .touch-button {
+ @apply touch-target px-4 py-2 sm:px-6 sm:py-3 rounded-lg font-medium transition-all duration-200 ease-out;
+ -webkit-tap-highlight-color: transparent;
+ }
+
+ .touch-input {
+ @apply h-12 sm:h-10 px-4 text-base sm:text-sm transition-all duration-200 ease-out;
+ -webkit-appearance: none;
+ }
+
+ /* Modern animations with mobile optimization */
.slide-in-right {
animation: slideInRight 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
@@ -126,10 +325,18 @@
animation: slideInUp 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
+ .slide-in-down {
+ animation: slideInDown 0.4s cubic-bezier(0.4, 0, 0.2, 1);
+ }
+
.fade-in {
animation: fadeIn 0.3s ease-out;
}
+ .fade-in-up {
+ animation: fadeInUp 0.4s cubic-bezier(0.4, 0, 0.2, 1);
+ }
+
.scale-in {
animation: scaleIn 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
@@ -137,6 +344,40 @@
.smooth-transition {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
+
+ .smooth-transform {
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ }
+
+ .mobile-smooth {
+ transition: all 0.2s ease-out;
+ }
+
+ /* Mobile-optimized states */
+ .mobile-hover {
+ @apply transition-all duration-200 ease-out;
+ }
+
+ .mobile-hover:hover {
+ @apply transform scale-[1.02];
+ }
+
+ .mobile-active {
+ @apply transition-all duration-100 ease-out;
+ }
+
+ .mobile-active:active {
+ @apply transform scale-[0.98];
+ }
+
+ /* Card animations */
+ .card-appear {
+ animation: cardAppear 0.4s cubic-bezier(0.4, 0, 0.2, 1);
+ }
+
+ .card-hover {
+ @apply transition-all duration-300 ease-out hover:shadow-lg hover:scale-[1.01];
+ }
/* Modern gradients */
.gradient-bg {
@@ -150,6 +391,85 @@
background-clip: text;
}
+ /* Mobile navigation */
+ .mobile-nav {
+ @apply fixed bottom-0 left-0 right-0 bg-white bg-opacity-95 backdrop-blur-sm border-t border-border z-50;
+ @apply flex items-center justify-around py-2 sm:hidden;
+ }
+
+ .mobile-nav-item {
+ @apply flex flex-col items-center space-y-1 px-3 py-2 rounded-lg transition-all duration-200;
+ }
+
+ .mobile-nav-item.active {
+ @apply bg-primary bg-opacity-10 text-primary;
+ }
+
+ /* Typography responsive */
+ .responsive-title {
+ @apply text-lg sm:text-xl lg:text-2xl xl:text-3xl font-bold;
+ }
+
+ .responsive-subtitle {
+ @apply text-base sm:text-lg lg:text-xl font-semibold;
+ }
+
+ .responsive-body {
+ @apply text-sm sm:text-base;
+ }
+
+ .responsive-caption {
+ @apply text-xs sm:text-sm;
+ }
+
+ /* Form responsive styles */
+ .mobile-form {
+ @apply space-y-4 sm:space-y-6;
+ }
+
+ .mobile-form-group {
+ @apply space-y-2 sm:space-y-3;
+ }
+
+ .mobile-form-row {
+ @apply grid grid-cols-1 sm:grid-cols-2 gap-4 sm:gap-6;
+ }
+
+ .mobile-form-section {
+ @apply p-4 sm:p-6 bg-muted bg-opacity-30 rounded-xl space-y-4 sm:space-y-6;
+ }
+
+ /* Table responsive */
+ .mobile-table {
+ @apply overflow-x-auto -mx-4 sm:mx-0;
+ }
+
+ .mobile-table table {
+ @apply min-w-full;
+ }
+
+ .mobile-table-cell {
+ @apply px-2 sm:px-4 py-2 sm:py-3 text-xs sm:text-sm;
+ }
+
+ /* Modal responsive */
+ .mobile-modal {
+ @apply fixed inset-0 z-50 flex items-end sm:items-center justify-center;
+ }
+
+ .mobile-modal-content {
+ @apply w-full sm:w-auto sm:max-w-lg mx-4 sm:mx-0 bg-white rounded-t-xl sm:rounded-xl;
+ @apply max-h-[90vh] overflow-y-auto;
+ }
+
+ .mobile-modal-enter {
+ animation: mobileModalEnter 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ }
+
+ .mobile-modal-exit {
+ animation: mobileModalExit 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+ }
+
/* Glass morphism */
.glass {
background: rgba(255, 255, 255, 0.05);
@@ -259,53 +579,40 @@
@apply p-4 sm:p-6 lg:p-8;
}
- /* Animation keyframes */
- @keyframes slideInRight {
- from {
- transform: translateX(100%);
- opacity: 0;
- }
- to {
- transform: translateX(0);
- opacity: 1;
- }
- }
-
- @keyframes slideInLeft {
- from {
- transform: translateX(-100%);
- opacity: 0;
- }
- to {
- transform: translateX(0);
- opacity: 1;
- }
- }
-
- @keyframes slideInUp {
- from {
- transform: translateY(30px);
- opacity: 0;
- }
- to {
- transform: translateY(0);
- opacity: 1;
- }
+ /* Additional utility classes */
+ .mobile-form-responsive {
+ @apply space-y-6 sm:space-y-8;
}
- @keyframes fadeIn {
- from { opacity: 0; }
- to { opacity: 1; }
+ .mobile-gap-responsive {
+ @apply gap-4 sm:gap-6;
}
-
- @keyframes scaleIn {
- from {
- opacity: 0;
- transform: scale(0.95);
- }
- to {
- opacity: 1;
- transform: scale(1);
- }
+
+ .mobile-header-responsive {
+ @apply text-base sm:text-lg lg:text-xl;
+ }
+
+ .touch-friendly-button {
+ @apply min-h-[44px] touch-target;
+ }
+
+ /* Modal responsive */
+ .mobile-modal-content {
+ @apply m-4 sm:m-6 max-w-[calc(100vw-2rem)] sm:max-w-[calc(100vw-3rem)];
+ }
+
+ /* Form group mobile */
+ .mobile-form-group {
+ @apply space-y-2;
+ }
+
+ /* Touch input */
+ .touch-input {
+ @apply min-h-[44px] px-3 py-2;
+ }
+
+ /* Responsive subtitle */
+ .responsive-subtitle {
+ @apply text-sm sm:text-base lg:text-lg font-semibold;
}
}