Spaces:
Sleeping
Sleeping
| @import "tailwindcss"; | |
| @import "tw-animate-css"; | |
| @custom-variant dark (&:is(.dark *)); | |
| @theme inline { | |
| --color-background: var(--background); | |
| --color-foreground: var(--foreground); | |
| --font-sans: var(--font-geist-sans); | |
| --font-mono: var(--font-geist-mono); | |
| --color-sidebar-ring: var(--sidebar-ring); | |
| --color-sidebar-border: var(--sidebar-border); | |
| --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); | |
| --color-sidebar-accent: var(--sidebar-accent); | |
| --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); | |
| --color-sidebar-primary: var(--sidebar-primary); | |
| --color-sidebar-foreground: var(--sidebar-foreground); | |
| --color-sidebar: var(--sidebar); | |
| --color-chart-5: var(--chart-5); | |
| --color-chart-4: var(--chart-4); | |
| --color-chart-3: var(--chart-3); | |
| --color-chart-2: var(--chart-2); | |
| --color-chart-1: var(--chart-1); | |
| --color-ring: var(--ring); | |
| --color-input: var(--input); | |
| --color-border: var(--border); | |
| --color-destructive: var(--destructive); | |
| --color-accent-foreground: var(--accent-foreground); | |
| --color-accent: var(--accent); | |
| --color-muted-foreground: var(--muted-foreground); | |
| --color-muted: var(--muted); | |
| --color-secondary-foreground: var(--secondary-foreground); | |
| --color-secondary: var(--secondary); | |
| --color-primary-foreground: var(--primary-foreground); | |
| --color-primary: var(--primary); | |
| --color-popover-foreground: var(--popover-foreground); | |
| --color-popover: var(--popover); | |
| --color-card-foreground: var(--card-foreground); | |
| --color-card: var(--card); | |
| --radius-sm: calc(var(--radius) - 4px); | |
| --radius-md: calc(var(--radius) - 2px); | |
| --radius-lg: var(--radius); | |
| --radius-xl: calc(var(--radius) + 4px); | |
| } | |
| :root { | |
| --radius: 0.625rem; | |
| --background: oklch(1 0 0); | |
| --foreground: oklch(0.145 0 0); | |
| --card: oklch(1 0 0); | |
| --card-foreground: oklch(0.145 0 0); | |
| --popover: oklch(1 0 0); | |
| --popover-foreground: oklch(0.145 0 0); | |
| --primary: oklch(0.205 0 0); | |
| --primary-foreground: oklch(0.985 0 0); | |
| --secondary: oklch(0.97 0 0); | |
| --secondary-foreground: oklch(0.205 0 0); | |
| --muted: oklch(0.97 0 0); | |
| --muted-foreground: oklch(0.556 0 0); | |
| --accent: oklch(0.97 0 0); | |
| --accent-foreground: oklch(0.205 0 0); | |
| --destructive: oklch(0.577 0.245 27.325); | |
| --border: oklch(0.922 0 0); | |
| --input: oklch(0.922 0 0); | |
| --ring: oklch(0.708 0 0); | |
| --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.145 0 0); | |
| --sidebar-primary: oklch(0.205 0 0); | |
| --sidebar-primary-foreground: oklch(0.985 0 0); | |
| --sidebar-accent: oklch(0.97 0 0); | |
| --sidebar-accent-foreground: oklch(0.205 0 0); | |
| --sidebar-border: oklch(0.922 0 0); | |
| --sidebar-ring: oklch(0.708 0 0); | |
| } | |
| .dark { | |
| --background: oklch(0.145 0 0); | |
| --foreground: oklch(0.985 0 0); | |
| --card: oklch(0.205 0 0); | |
| --card-foreground: oklch(0.985 0 0); | |
| --popover: oklch(0.205 0 0); | |
| --popover-foreground: oklch(0.985 0 0); | |
| --primary: oklch(0.922 0 0); | |
| --primary-foreground: oklch(0.205 0 0); | |
| --secondary: oklch(0.269 0 0); | |
| --secondary-foreground: oklch(0.985 0 0); | |
| --muted: oklch(0.269 0 0); | |
| --muted-foreground: oklch(0.708 0 0); | |
| --accent: oklch(0.269 0 0); | |
| --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.556 0 0); | |
| --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.205 0 0); | |
| --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.269 0 0); | |
| --sidebar-accent-foreground: oklch(0.985 0 0); | |
| --sidebar-border: oklch(1 0 0 / 10%); | |
| --sidebar-ring: oklch(0.556 0 0); | |
| } | |
| @layer base { | |
| * { | |
| @apply border-border outline-ring/50; | |
| } | |
| body { | |
| @apply bg-background text-foreground; | |
| } | |
| } | |
| /* IA Academy Dark Theme Override */ | |
| :root { | |
| --background: #0a0a1a; | |
| --foreground: #f8fafc; | |
| --card: #151530; | |
| --card-foreground: #f8fafc; | |
| --popover: #151530; | |
| --popover-foreground: #f8fafc; | |
| --primary: #6366f1; | |
| --primary-foreground: #ffffff; | |
| --secondary: #151530; | |
| --secondary-foreground: #f8fafc; | |
| --muted: #151530; | |
| --muted-foreground: #94a3b8; | |
| --accent: #f59e0b; | |
| --accent-foreground: #0a0a1a; | |
| --destructive: #ef4444; | |
| --border: #2a2a4a; | |
| --input: #151530; | |
| --ring: #6366f1; | |
| --chart-1: #6366f1; | |
| --chart-2: #f59e0b; | |
| --chart-3: #10b981; | |
| --chart-4: #ef4444; | |
| --chart-5: #8b5cf6; | |
| --sidebar: #151530; | |
| --sidebar-foreground: #f8fafc; | |
| --sidebar-primary: #6366f1; | |
| --sidebar-primary-foreground: #ffffff; | |
| --sidebar-accent: #151530; | |
| --sidebar-accent-foreground: #f8fafc; | |
| --sidebar-border: #2a2a4a; | |
| --sidebar-ring: #6366f1; | |
| --font-sans: 'Inter', system-ui, sans-serif; | |
| --font-mono: 'JetBrains Mono', monospace; | |
| } | |
| /* Gradient text animation - Enhanced */ | |
| .gradient-text { | |
| background: linear-gradient(135deg, #6366f1, #a855f7, #ec4899, #f59e0b, #10b981, #6366f1); | |
| background-size: 300% 300%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| animation: gradientShift 8s ease infinite; | |
| filter: drop-shadow(0 0 12px rgba(99, 102, 241, 0.3)); | |
| } | |
| @keyframes gradientShift { | |
| 0%, 100% { background-position: 0% 50%; } | |
| 25% { background-position: 50% 0%; } | |
| 50% { background-position: 100% 50%; } | |
| 75% { background-position: 50% 100%; } | |
| } | |
| /* Glassmorphism card effect - Enhanced */ | |
| .glass-card { | |
| background: rgba(15, 15, 35, 0.65); | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.05), | |
| inset 0 -1px 0 0 rgba(0, 0, 0, 0.2), | |
| 0 8px 32px rgba(0, 0, 0, 0.3), | |
| 0 0 0 1px rgba(99, 102, 241, 0.08); | |
| transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .glass-card:hover { | |
| background: rgba(20, 20, 45, 0.75); | |
| border-color: rgba(99, 102, 241, 0.35); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.08), | |
| inset 0 -1px 0 0 rgba(0, 0, 0, 0.2), | |
| 0 12px 40px rgba(0, 0, 0, 0.4), | |
| 0 0 0 1px rgba(99, 102, 241, 0.15), | |
| 0 0 30px rgba(99, 102, 241, 0.08); | |
| transform: translateY(-2px); | |
| } | |
| /* Glow effect */ | |
| .glow { | |
| box-shadow: 0 0 20px rgba(99, 102, 241, 0.15), 0 0 60px rgba(99, 102, 241, 0.05); | |
| } | |
| .glow-accent { | |
| box-shadow: 0 0 20px rgba(245, 158, 11, 0.2), 0 0 60px rgba(245, 158, 11, 0.05); | |
| } | |
| /* Particle background effect - Enhanced with mesh gradient */ | |
| .particle-bg { | |
| position: relative; | |
| overflow: hidden; | |
| background: | |
| radial-gradient(ellipse at 15% 25%, rgba(99, 102, 241, 0.12) 0%, transparent 50%), | |
| radial-gradient(ellipse at 85% 15%, rgba(168, 85, 247, 0.1) 0%, transparent 45%), | |
| radial-gradient(ellipse at 50% 80%, rgba(236, 72, 153, 0.08) 0%, transparent 50%), | |
| radial-gradient(ellipse at 75% 60%, rgba(245, 158, 11, 0.06) 0%, transparent 40%), | |
| radial-gradient(ellipse at 25% 65%, rgba(16, 185, 129, 0.07) 0%, transparent 45%), | |
| var(--background); | |
| background-size: 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 100% 100%; | |
| animation: meshGradientShift 20s ease-in-out infinite; | |
| } | |
| @keyframes meshGradientShift { | |
| 0%, 100% { | |
| background: | |
| radial-gradient(ellipse at 15% 25%, rgba(99, 102, 241, 0.12) 0%, transparent 50%), | |
| radial-gradient(ellipse at 85% 15%, rgba(168, 85, 247, 0.1) 0%, transparent 45%), | |
| radial-gradient(ellipse at 50% 80%, rgba(236, 72, 153, 0.08) 0%, transparent 50%), | |
| radial-gradient(ellipse at 75% 60%, rgba(245, 158, 11, 0.06) 0%, transparent 40%), | |
| radial-gradient(ellipse at 25% 65%, rgba(16, 185, 129, 0.07) 0%, transparent 45%), | |
| var(--background); | |
| } | |
| 33% { | |
| background: | |
| radial-gradient(ellipse at 40% 15%, rgba(99, 102, 241, 0.12) 0%, transparent 50%), | |
| radial-gradient(ellipse at 65% 40%, rgba(168, 85, 247, 0.1) 0%, transparent 45%), | |
| radial-gradient(ellipse at 20% 70%, rgba(236, 72, 153, 0.08) 0%, transparent 50%), | |
| radial-gradient(ellipse at 85% 75%, rgba(245, 158, 11, 0.06) 0%, transparent 40%), | |
| radial-gradient(ellipse at 50% 30%, rgba(16, 185, 129, 0.07) 0%, transparent 45%), | |
| var(--background); | |
| } | |
| 66% { | |
| background: | |
| radial-gradient(ellipse at 75% 50%, rgba(99, 102, 241, 0.12) 0%, transparent 50%), | |
| radial-gradient(ellipse at 25% 75%, rgba(168, 85, 247, 0.1) 0%, transparent 45%), | |
| radial-gradient(ellipse at 60% 20%, rgba(236, 72, 153, 0.08) 0%, transparent 50%), | |
| radial-gradient(ellipse at 15% 40%, rgba(245, 158, 11, 0.06) 0%, transparent 40%), | |
| radial-gradient(ellipse at 80% 85%, rgba(16, 185, 129, 0.07) 0%, transparent 45%), | |
| var(--background); | |
| } | |
| } | |
| .particle-bg::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background-image: radial-gradient(circle at 1px 1px, rgba(99, 102, 241, 0.12) 1px, transparent 0); | |
| background-size: 40px 40px; | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| .particle-bg::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background-image: radial-gradient(circle at 1px 1px, rgba(168, 85, 247, 0.06) 1px, transparent 0); | |
| background-size: 60px 60px; | |
| background-position: 20px 20px; | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| /* Custom scrollbar for dark theme */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| height: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: #0a0a1a; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: #2a2a4a; | |
| border-radius: 4px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: #6366f1; | |
| } | |
| /* Firefox scrollbar - Enhanced */ | |
| * { | |
| scrollbar-width: thin; | |
| scrollbar-color: rgba(99, 102, 241, 0.3) transparent; | |
| } | |
| /* Code block custom styling */ | |
| pre[class*="language-"], | |
| code[class*="language-"] { | |
| font-size: 0.875rem; | |
| line-height: 1.6; | |
| } | |
| /* Animated border gradient */ | |
| .border-gradient { | |
| position: relative; | |
| } | |
| .border-gradient::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| border-radius: inherit; | |
| padding: 1px; | |
| background: linear-gradient(135deg, #6366f1, #f59e0b); | |
| mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); | |
| mask-composite: exclude; | |
| -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); | |
| -webkit-mask-composite: xor; | |
| pointer-events: none; | |
| } | |
| /* Floating animation */ | |
| @keyframes float { | |
| 0%, 100% { transform: translateY(0px); } | |
| 50% { transform: translateY(-10px); } | |
| } | |
| .animate-float { | |
| animation: float 3s ease-in-out infinite; | |
| } | |
| /* Pulse glow animation */ | |
| @keyframes pulseGlow { | |
| 0%, 100% { box-shadow: 0 0 5px rgba(99, 102, 241, 0.2); } | |
| 50% { box-shadow: 0 0 20px rgba(99, 102, 241, 0.4); } | |
| } | |
| .animate-pulse-glow { | |
| animation: pulseGlow 2s ease-in-out infinite; | |
| } | |
| /* ===== Enhanced Utility Classes ===== */ | |
| /* Animated gradient border */ | |
| .gradient-border { | |
| position: relative; | |
| } | |
| .gradient-border::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -1px; | |
| border-radius: inherit; | |
| padding: 1px; | |
| background: linear-gradient(135deg, #6366f1, #a855f7, #ec4899, #6366f1); | |
| background-size: 300% 300%; | |
| animation: gradient-rotate 4s linear infinite; | |
| -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); | |
| -webkit-mask-composite: xor; | |
| mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); | |
| mask-composite: exclude; | |
| } | |
| @keyframes gradient-rotate { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| /* Pulse glow effect */ | |
| .pulse-glow { | |
| animation: pulse-glow 2s ease-in-out infinite; | |
| } | |
| @keyframes pulse-glow { | |
| 0%, 100% { box-shadow: 0 0 5px rgba(99, 102, 241, 0.3); } | |
| 50% { box-shadow: 0 0 20px rgba(99, 102, 241, 0.5), 0 0 40px rgba(99, 102, 241, 0.2); } | |
| } | |
| /* Floating animation for decorative elements */ | |
| .float-animation { | |
| animation: float 6s ease-in-out infinite; | |
| } | |
| /* Shimmer loading effect */ | |
| .shimmer { | |
| background: linear-gradient(90deg, transparent, rgba(255,255,255,0.05), transparent); | |
| background-size: 200% 100%; | |
| animation: shimmer 2s infinite; | |
| } | |
| @keyframes shimmer { | |
| 0% { background-position: -200% 0; } | |
| 100% { background-position: 200% 0; } | |
| } | |
| /* Stat counter animation */ | |
| .stat-number { | |
| font-variant-numeric: tabular-nums; | |
| } | |
| /* Scroll indicator */ | |
| .scroll-indicator { | |
| animation: bounce-subtle 2s ease-in-out infinite; | |
| } | |
| @keyframes bounce-subtle { | |
| 0%, 100% { transform: translateY(0); } | |
| 50% { transform: translateY(-4px); } | |
| } | |
| /* Better focus states for accessibility */ | |
| *:focus-visible { | |
| outline: 2px solid rgba(99, 102, 241, 0.5); | |
| outline-offset: 2px; | |
| border-radius: 4px; | |
| } | |
| /* Body base styles for smoother rendering */ | |
| body { | |
| -webkit-font-smoothing: antialiased; | |
| -moz-osx-font-smoothing: grayscale; | |
| text-rendering: optimizeLegibility; | |
| } | |
| /* Selection styling */ | |
| ::selection { | |
| background: rgba(99, 102, 241, 0.3); | |
| color: white; | |
| } | |
| /* ============================================================ | |
| IA Academy β Enhanced Visual Polish | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. Animated Noise / Grain Overlay (applies inside .particle-bg) | |
| ---------------------------------------------------------- */ | |
| .particle-bg .noise-overlay, | |
| .particle-bg > .noise-overlay { | |
| position: absolute; | |
| inset: -50%; | |
| width: 200%; | |
| height: 200%; | |
| pointer-events: none; | |
| z-index: 1; | |
| opacity: 0.035; | |
| background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); | |
| background-repeat: repeat; | |
| background-size: 200px 200px; | |
| animation: noiseShift 0.5s steps(4) infinite; | |
| will-change: transform; | |
| } | |
| @keyframes noiseShift { | |
| 0% { transform: translate(0, 0); } | |
| 25% { transform: translate(-5%, -5%); } | |
| 50% { transform: translate(3%, 2%); } | |
| 75% { transform: translate(-2%, 4%); } | |
| 100% { transform: translate(0, 0); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. Enhanced Glass Card β inner glow on hover, smoother curve | |
| ---------------------------------------------------------- */ | |
| .glass-card { | |
| transition: | |
| transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| background 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .glass-card:hover { | |
| background: rgba(20, 20, 50, 0.8); | |
| border-color: rgba(99, 102, 241, 0.4); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.1), | |
| inset 0 0 30px rgba(99, 102, 241, 0.06), | |
| inset 0 -1px 0 0 rgba(0, 0, 0, 0.25), | |
| 0 16px 48px rgba(0, 0, 0, 0.45), | |
| 0 0 0 1px rgba(99, 102, 241, 0.18), | |
| 0 0 40px rgba(99, 102, 241, 0.1), | |
| 0 0 80px rgba(139, 92, 246, 0.04); | |
| transform: translateY(-3px) scale(1.005); | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. Typing Cursor Animation | |
| ---------------------------------------------------------- */ | |
| .typing-cursor { | |
| display: inline-block; | |
| width: 2px; | |
| height: 1.1em; | |
| background: #6366f1; | |
| margin-left: 2px; | |
| vertical-align: text-bottom; | |
| border-radius: 1px; | |
| animation: cursorBlink 1s step-end infinite; | |
| box-shadow: 0 0 6px rgba(99, 102, 241, 0.5); | |
| } | |
| @keyframes cursorBlink { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. Enhanced Gradient Text β multi-layer glow behind text | |
| ---------------------------------------------------------- */ | |
| .gradient-text { | |
| position: relative; | |
| filter: drop-shadow(0 0 18px rgba(99, 102, 241, 0.35)) | |
| drop-shadow(0 0 40px rgba(168, 85, 247, 0.15)); | |
| } | |
| .gradient-text::after { | |
| content: attr(data-text); | |
| position: absolute; | |
| inset: 0; | |
| z-index: -1; | |
| background: linear-gradient(135deg, #6366f1, #a855f7, #ec4899, #f59e0b, #10b981, #6366f1); | |
| background-size: 300% 300%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| animation: gradientShift 8s ease infinite; | |
| filter: blur(18px); | |
| opacity: 0.5; | |
| pointer-events: none; | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .hover-lift β gentle lift + scale on hover | |
| ---------------------------------------------------------- */ | |
| .hover-lift { | |
| transition: | |
| transform 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.45s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .hover-lift:hover { | |
| transform: translateY(-6px) scale(1.02); | |
| box-shadow: | |
| 0 20px 40px rgba(0, 0, 0, 0.35), | |
| 0 8px 16px rgba(0, 0, 0, 0.2); | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .neon-border β neon glow border (cyan / purple) | |
| ---------------------------------------------------------- */ | |
| .neon-border { | |
| position: relative; | |
| border: 1px solid rgba(99, 102, 241, 0.35); | |
| box-shadow: | |
| 0 0 8px rgba(99, 102, 241, 0.15), | |
| 0 0 20px rgba(99, 102, 241, 0.08), | |
| inset 0 0 8px rgba(99, 102, 241, 0.05); | |
| transition: | |
| box-shadow 0.4s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: box-shadow; | |
| } | |
| .neon-border:hover { | |
| border-color: rgba(139, 92, 246, 0.6); | |
| box-shadow: | |
| 0 0 10px rgba(6, 182, 212, 0.3), | |
| 0 0 30px rgba(139, 92, 246, 0.2), | |
| 0 0 60px rgba(99, 102, 241, 0.12), | |
| inset 0 0 12px rgba(139, 92, 246, 0.08); | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. Improved Scrollbar β rounded thumb with gradient | |
| ---------------------------------------------------------- */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| height: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: rgba(10, 10, 26, 0.6); | |
| border-radius: 4px; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: linear-gradient(180deg, #6366f1, #8b5cf6, #6366f1); | |
| border-radius: 10px; | |
| border: 2px solid rgba(10, 10, 26, 0.4); | |
| background-clip: padding-box; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: linear-gradient(180deg, #818cf8, #a78bfa, #818cf8); | |
| border-radius: 10px; | |
| box-shadow: 0 0 8px rgba(99, 102, 241, 0.4); | |
| } | |
| * { | |
| scrollbar-width: thin; | |
| scrollbar-color: rgba(99, 102, 241, 0.4) rgba(10, 10, 26, 0.3); | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .hero-glow β large radial gradient glow for hero sections | |
| ---------------------------------------------------------- */ | |
| .hero-glow { | |
| position: relative; | |
| } | |
| .hero-glow::before { | |
| content: ''; | |
| position: absolute; | |
| top: -30%; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 120%; | |
| height: 80%; | |
| background: radial-gradient( | |
| ellipse 60% 50% at 50% 50%, | |
| rgba(99, 102, 241, 0.14) 0%, | |
| rgba(139, 92, 246, 0.08) 30%, | |
| rgba(168, 85, 247, 0.04) 55%, | |
| transparent 75% | |
| ); | |
| pointer-events: none; | |
| z-index: 0; | |
| animation: heroGlowPulse 8s ease-in-out infinite; | |
| } | |
| .hero-glow::after { | |
| content: ''; | |
| position: absolute; | |
| bottom: -20%; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 80%; | |
| height: 50%; | |
| background: radial-gradient( | |
| ellipse 50% 40% at 50% 50%, | |
| rgba(245, 158, 11, 0.06) 0%, | |
| rgba(16, 185, 129, 0.04) 40%, | |
| transparent 70% | |
| ); | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| @keyframes heroGlowPulse { | |
| 0%, 100% { opacity: 0.8; transform: translateX(-50%) scale(1); } | |
| 50% { opacity: 1; transform: translateX(-50%) scale(1.06); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .stat-card β stat counter card with shimmer | |
| ---------------------------------------------------------- */ | |
| .stat-card { | |
| position: relative; | |
| overflow: hidden; | |
| background: rgba(15, 15, 35, 0.6); | |
| border: 1px solid rgba(99, 102, 241, 0.15); | |
| border-radius: 12px; | |
| padding: 1.5rem; | |
| transition: | |
| transform 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.45s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .stat-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: -100%; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(99, 102, 241, 0.06) 25%, | |
| rgba(139, 92, 246, 0.08) 50%, | |
| rgba(99, 102, 241, 0.06) 75%, | |
| transparent 100% | |
| ); | |
| transition: left 0.7s ease; | |
| pointer-events: none; | |
| z-index: 1; | |
| } | |
| .stat-card:hover::before { | |
| left: 100%; | |
| } | |
| .stat-card:hover { | |
| border-color: rgba(99, 102, 241, 0.35); | |
| transform: translateY(-4px); | |
| box-shadow: | |
| 0 12px 32px rgba(0, 0, 0, 0.3), | |
| 0 0 20px rgba(99, 102, 241, 0.08); | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .badge-glow β badges with colored glow | |
| ---------------------------------------------------------- */ | |
| .badge-glow { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| padding: 0.25rem 0.75rem; | |
| border-radius: 9999px; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| letter-spacing: 0.025em; | |
| border: 1px solid rgba(99, 102, 241, 0.3); | |
| background: rgba(99, 102, 241, 0.1); | |
| color: #a5b4fc; | |
| box-shadow: 0 0 8px rgba(99, 102, 241, 0.15), 0 0 20px rgba(99, 102, 241, 0.05); | |
| transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .badge-glow.amber { | |
| border-color: rgba(245, 158, 11, 0.3); | |
| background: rgba(245, 158, 11, 0.1); | |
| color: #fbbf24; | |
| box-shadow: 0 0 8px rgba(245, 158, 11, 0.15), 0 0 20px rgba(245, 158, 11, 0.05); | |
| } | |
| .badge-glow.emerald { | |
| border-color: rgba(16, 185, 129, 0.3); | |
| background: rgba(16, 185, 129, 0.1); | |
| color: #34d399; | |
| box-shadow: 0 0 8px rgba(16, 185, 129, 0.15), 0 0 20px rgba(16, 185, 129, 0.05); | |
| } | |
| .badge-glow.rose { | |
| border-color: rgba(244, 63, 94, 0.3); | |
| background: rgba(244, 63, 94, 0.1); | |
| color: #fb7185; | |
| box-shadow: 0 0 8px rgba(244, 63, 94, 0.15), 0 0 20px rgba(244, 63, 94, 0.05); | |
| } | |
| .badge-glow.cyan { | |
| border-color: rgba(6, 182, 212, 0.3); | |
| background: rgba(6, 182, 212, 0.1); | |
| color: #22d3ee; | |
| box-shadow: 0 0 8px rgba(6, 182, 212, 0.15), 0 0 20px rgba(6, 182, 212, 0.05); | |
| } | |
| .badge-glow:hover { | |
| transform: scale(1.05); | |
| box-shadow: 0 0 14px rgba(99, 102, 241, 0.25), 0 0 30px rgba(99, 102, 241, 0.08); | |
| } | |
| .badge-glow.amber:hover { | |
| box-shadow: 0 0 14px rgba(245, 158, 11, 0.25), 0 0 30px rgba(245, 158, 11, 0.08); | |
| } | |
| .badge-glow.emerald:hover { | |
| box-shadow: 0 0 14px rgba(16, 185, 129, 0.25), 0 0 30px rgba(16, 185, 129, 0.08); | |
| } | |
| .badge-glow.rose:hover { | |
| box-shadow: 0 0 14px rgba(244, 63, 94, 0.25), 0 0 30px rgba(244, 63, 94, 0.08); | |
| } | |
| .badge-glow.cyan:hover { | |
| box-shadow: 0 0 14px rgba(6, 182, 212, 0.25), 0 0 30px rgba(6, 182, 212, 0.08); | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .section-divider β gradient horizontal line | |
| ---------------------------------------------------------- */ | |
| .section-divider { | |
| border: none; | |
| height: 1px; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(99, 102, 241, 0.15) 15%, | |
| rgba(139, 92, 246, 0.3) 50%, | |
| rgba(99, 102, 241, 0.15) 85%, | |
| transparent 100% | |
| ); | |
| margin: 3rem 0; | |
| position: relative; | |
| } | |
| .section-divider::before { | |
| content: ''; | |
| position: absolute; | |
| top: -2px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 60px; | |
| height: 5px; | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6); | |
| border-radius: 999px; | |
| box-shadow: 0 0 12px rgba(99, 102, 241, 0.4); | |
| } | |
| .section-divider.amber::before { | |
| background: linear-gradient(90deg, #f59e0b, #fbbf24); | |
| box-shadow: 0 0 12px rgba(245, 158, 11, 0.4); | |
| } | |
| .section-divider.emerald::before { | |
| background: linear-gradient(90deg, #10b981, #34d399); | |
| box-shadow: 0 0 12px rgba(16, 185, 129, 0.4); | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. will-change Hints for animated elements | |
| ---------------------------------------------------------- */ | |
| .particle-bg, | |
| .gradient-border, | |
| .border-gradient, | |
| .animate-float, | |
| .float-animation, | |
| .animate-pulse-glow, | |
| .pulse-glow, | |
| .shimmer { | |
| will-change: transform, opacity, box-shadow; | |
| } | |
| /* ---------------------------------------------------------- | |
| 13. .text-glow β glowing text utility (color variants) | |
| ---------------------------------------------------------- */ | |
| .text-glow { | |
| text-shadow: 0 0 10px currentColor, 0 0 20px currentColor; | |
| } | |
| .text-glow-indigo { | |
| color: #a5b4fc; | |
| text-shadow: | |
| 0 0 7px rgba(99, 102, 241, 0.6), | |
| 0 0 20px rgba(99, 102, 241, 0.3), | |
| 0 0 40px rgba(99, 102, 241, 0.15); | |
| } | |
| .text-glow-purple { | |
| color: #c4b5fd; | |
| text-shadow: | |
| 0 0 7px rgba(139, 92, 246, 0.6), | |
| 0 0 20px rgba(139, 92, 246, 0.3), | |
| 0 0 40px rgba(139, 92, 246, 0.15); | |
| } | |
| .text-glow-amber { | |
| color: #fcd34d; | |
| text-shadow: | |
| 0 0 7px rgba(245, 158, 11, 0.6), | |
| 0 0 20px rgba(245, 158, 11, 0.3), | |
| 0 0 40px rgba(245, 158, 11, 0.15); | |
| } | |
| .text-glow-emerald { | |
| color: #6ee7b7; | |
| text-shadow: | |
| 0 0 7px rgba(16, 185, 129, 0.6), | |
| 0 0 20px rgba(16, 185, 129, 0.3), | |
| 0 0 40px rgba(16, 185, 129, 0.15); | |
| } | |
| .text-glow-cyan { | |
| color: #67e8f9; | |
| text-shadow: | |
| 0 0 7px rgba(6, 182, 212, 0.6), | |
| 0 0 20px rgba(6, 182, 212, 0.3), | |
| 0 0 40px rgba(6, 182, 212, 0.15); | |
| } | |
| .text-glow-rose { | |
| color: #fda4af; | |
| text-shadow: | |
| 0 0 7px rgba(244, 63, 94, 0.6), | |
| 0 0 20px rgba(244, 63, 94, 0.3), | |
| 0 0 40px rgba(244, 63, 94, 0.15); | |
| } | |
| /* ---------------------------------------------------------- | |
| 14. .btn-glow β gradient button with hover glow | |
| ---------------------------------------------------------- */ | |
| .btn-glow { | |
| position: relative; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.5rem; | |
| padding: 0.625rem 1.5rem; | |
| font-weight: 600; | |
| font-size: 0.875rem; | |
| border: none; | |
| border-radius: 10px; | |
| color: #ffffff; | |
| background: linear-gradient(135deg, #6366f1, #8b5cf6); | |
| background-size: 200% 200%; | |
| cursor: pointer; | |
| transition: | |
| transform 0.35s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.35s cubic-bezier(0.23, 1, 0.32, 1), | |
| background-position 0.5s ease; | |
| will-change: transform, box-shadow; | |
| box-shadow: | |
| 0 4px 14px rgba(99, 102, 241, 0.25), | |
| 0 0 0 1px rgba(99, 102, 241, 0.1); | |
| } | |
| .btn-glow:hover { | |
| background-position: 100% 100%; | |
| transform: translateY(-2px) scale(1.03); | |
| box-shadow: | |
| 0 8px 24px rgba(99, 102, 241, 0.35), | |
| 0 0 30px rgba(99, 102, 241, 0.15), | |
| 0 0 60px rgba(139, 92, 246, 0.08), | |
| 0 0 0 1px rgba(139, 92, 246, 0.2); | |
| } | |
| .btn-glow:active { | |
| transform: translateY(0) scale(0.98); | |
| box-shadow: 0 2px 8px rgba(99, 102, 241, 0.2); | |
| } | |
| .btn-glow.amber { | |
| background: linear-gradient(135deg, #f59e0b, #f97316); | |
| box-shadow: 0 4px 14px rgba(245, 158, 11, 0.25), 0 0 0 1px rgba(245, 158, 11, 0.1); | |
| } | |
| .btn-glow.amber:hover { | |
| box-shadow: | |
| 0 8px 24px rgba(245, 158, 11, 0.35), | |
| 0 0 30px rgba(245, 158, 11, 0.15), | |
| 0 0 60px rgba(249, 115, 22, 0.08), | |
| 0 0 0 1px rgba(245, 158, 11, 0.2); | |
| } | |
| .btn-glow.emerald { | |
| background: linear-gradient(135deg, #10b981, #14b8a6); | |
| box-shadow: 0 4px 14px rgba(16, 185, 129, 0.25), 0 0 0 1px rgba(16, 185, 129, 0.1); | |
| } | |
| .btn-glow.emerald:hover { | |
| box-shadow: | |
| 0 8px 24px rgba(16, 185, 129, 0.35), | |
| 0 0 30px rgba(16, 185, 129, 0.15), | |
| 0 0 60px rgba(20, 184, 166, 0.08), | |
| 0 0 0 1px rgba(16, 185, 129, 0.2); | |
| } | |
| /* ---------------------------------------------------------- | |
| 15. .timeline-dot β pulsing timeline dot | |
| ---------------------------------------------------------- */ | |
| .timeline-dot { | |
| position: relative; | |
| width: 14px; | |
| height: 14px; | |
| border-radius: 50%; | |
| background: #6366f1; | |
| border: 2px solid #818cf8; | |
| flex-shrink: 0; | |
| box-shadow: 0 0 8px rgba(99, 102, 241, 0.3); | |
| will-change: box-shadow, transform; | |
| } | |
| .timeline-dot::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -6px; | |
| border-radius: 50%; | |
| border: 1px solid rgba(99, 102, 241, 0.25); | |
| animation: timelineDotPulse 2.5s ease-in-out infinite; | |
| } | |
| .timeline-dot::after { | |
| content: ''; | |
| position: absolute; | |
| inset: -12px; | |
| border-radius: 50%; | |
| border: 1px solid rgba(99, 102, 241, 0.1); | |
| animation: timelineDotPulse 2.5s ease-in-out infinite 0.3s; | |
| } | |
| @keyframes timelineDotPulse { | |
| 0%, 100% { | |
| transform: scale(1); | |
| opacity: 0.6; | |
| } | |
| 50% { | |
| transform: scale(1.5); | |
| opacity: 0; | |
| } | |
| } | |
| /* Color variants for timeline dots */ | |
| .timeline-dot.amber { | |
| background: #f59e0b; | |
| border-color: #fbbf24; | |
| box-shadow: 0 0 8px rgba(245, 158, 11, 0.3); | |
| } | |
| .timeline-dot.amber::before { | |
| border-color: rgba(245, 158, 11, 0.25); | |
| } | |
| .timeline-dot.amber::after { | |
| border-color: rgba(245, 158, 11, 0.1); | |
| } | |
| .timeline-dot.emerald { | |
| background: #10b981; | |
| border-color: #34d399; | |
| box-shadow: 0 0 8px rgba(16, 185, 129, 0.3); | |
| } | |
| .timeline-dot.emerald::before { | |
| border-color: rgba(16, 185, 129, 0.25); | |
| } | |
| .timeline-dot.emerald::after { | |
| border-color: rgba(16, 185, 129, 0.1); | |
| } | |
| /* ============================================================ | |
| IA Academy β Advanced Visual Enhancement Classes | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .card-shine β Holographic diagonal shine sweep on hover | |
| ---------------------------------------------------------- | |
| A pseudo-element slides diagonally across the card on hover, | |
| creating a light/glare sweep effect similar to a holographic | |
| card catch-light. | |
| Usage: | |
| <div class="glass-card card-shine">Card content</div> | |
| Requires: | |
| - Parent must have overflow: hidden (handled here) | |
| - Works best on cards with a slightly reflective background | |
| ---------------------------------------------------------- */ | |
| .card-shine { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .card-shine::after { | |
| content: ''; | |
| position: absolute; | |
| top: -50%; | |
| left: -75%; | |
| width: 50%; | |
| height: 200%; | |
| background: linear-gradient( | |
| 105deg, | |
| transparent 20%, | |
| rgba(255, 255, 255, 0.03) 30%, | |
| rgba(255, 255, 255, 0.08) 38%, | |
| rgba(255, 255, 255, 0.12) 42%, | |
| rgba(255, 255, 255, 0.08) 46%, | |
| rgba(255, 255, 255, 0.03) 55%, | |
| transparent 70% | |
| ); | |
| transform: skewX(-25deg); | |
| transition: left 0.75s cubic-bezier(0.23, 1, 0.32, 1); | |
| pointer-events: none; | |
| z-index: 2; | |
| } | |
| .card-shine:hover::after { | |
| left: 125%; | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .border-beam β Animated light beam traveling the border | |
| ---------------------------------------------------------- | |
| Uses a conic-gradient that rotates continuously, masked to | |
| only the border area. Creates a "beam of light" that orbits | |
| the perimeter of the element. | |
| Usage: | |
| <div class="border-beam">Content</div> | |
| Customize: | |
| - Speed: adjust the animation duration in @keyframes borderBeamSpin | |
| - Colors: change the conic-gradient color stops | |
| ---------------------------------------------------------- */ | |
| .border-beam { | |
| position: relative; | |
| overflow: hidden; | |
| border-radius: 12px; | |
| isolation: isolate; | |
| } | |
| .border-beam::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -2px; | |
| border-radius: inherit; | |
| background: conic-gradient( | |
| from 0deg, | |
| transparent 0%, | |
| rgba(99, 102, 241, 0.6) 5%, | |
| rgba(139, 92, 246, 0.8) 10%, | |
| rgba(168, 85, 247, 0.6) 15%, | |
| transparent 20%, | |
| transparent 100% | |
| ); | |
| animation: borderBeamSpin 4s linear infinite; | |
| z-index: -2; | |
| } | |
| .border-beam::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 2px; | |
| border-radius: inherit; | |
| background: var(--card, #151530); | |
| z-index: -1; | |
| } | |
| @keyframes borderBeamSpin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .gradient-mesh β Animated gradient mesh background | |
| ---------------------------------------------------------- | |
| Multiple overlapping radial gradients that slowly morph and | |
| shift positions, creating an organic, flowing background | |
| effect ideal for full-width sections. | |
| Usage: | |
| <section class="gradient-mesh">Section content</section> | |
| Note: | |
| - Content inside should have position: relative; z-index: 1 | |
| to sit above the gradient layers | |
| - Adjust animation duration to control morph speed | |
| ---------------------------------------------------------- */ | |
| .gradient-mesh { | |
| position: relative; | |
| overflow: hidden; | |
| background-color: var(--background, #0a0a1a); | |
| } | |
| .gradient-mesh::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -10%; | |
| background: | |
| radial-gradient(ellipse 600px 400px at 20% 30%, rgba(99, 102, 241, 0.2) 0%, transparent 70%), | |
| radial-gradient(ellipse 500px 500px at 70% 20%, rgba(168, 85, 247, 0.15) 0%, transparent 70%), | |
| radial-gradient(ellipse 700px 300px at 50% 70%, rgba(236, 72, 153, 0.12) 0%, transparent 70%), | |
| radial-gradient(ellipse 400px 600px at 80% 80%, rgba(16, 185, 129, 0.1) 0%, transparent 70%), | |
| radial-gradient(ellipse 500px 400px at 30% 80%, rgba(245, 158, 11, 0.08) 0%, transparent 70%), | |
| radial-gradient(ellipse 300px 300px at 60% 50%, rgba(6, 182, 212, 0.1) 0%, transparent 70%); | |
| animation: gradientMeshMorph 16s ease-in-out infinite; | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| .gradient-mesh::after { | |
| content: ''; | |
| position: absolute; | |
| inset: -10%; | |
| background: | |
| radial-gradient(ellipse 500px 350px at 60% 40%, rgba(139, 92, 246, 0.12) 0%, transparent 70%), | |
| radial-gradient(ellipse 600px 450px at 25% 60%, rgba(99, 102, 241, 0.15) 0%, transparent 70%), | |
| radial-gradient(ellipse 450px 550px at 75% 55%, rgba(245, 158, 11, 0.08) 0%, transparent 70%), | |
| radial-gradient(ellipse 550px 400px at 40% 20%, rgba(236, 72, 153, 0.1) 0%, transparent 70%), | |
| radial-gradient(ellipse 350px 500px at 85% 30%, rgba(16, 185, 129, 0.08) 0%, transparent 70%); | |
| animation: gradientMeshMorph2 20s ease-in-out infinite; | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| @keyframes gradientMeshMorph { | |
| 0%, 100% { | |
| transform: translate(0, 0) scale(1); | |
| opacity: 1; | |
| } | |
| 25% { | |
| transform: translate(3%, -2%) scale(1.05); | |
| opacity: 0.85; | |
| } | |
| 50% { | |
| transform: translate(-2%, 3%) scale(0.97); | |
| opacity: 1; | |
| } | |
| 75% { | |
| transform: translate(-3%, -1%) scale(1.03); | |
| opacity: 0.9; | |
| } | |
| } | |
| @keyframes gradientMeshMorph2 { | |
| 0%, 100% { | |
| transform: translate(0, 0) scale(1); | |
| opacity: 0.7; | |
| } | |
| 33% { | |
| transform: translate(-4%, 2%) scale(1.04); | |
| opacity: 0.9; | |
| } | |
| 66% { | |
| transform: translate(3%, -3%) scale(0.96); | |
| opacity: 0.75; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .text-reveal β Bottom-to-top clip-path text reveal | |
| ---------------------------------------------------------- | |
| Text is hidden by default using clip-path. When the .active | |
| class is added (typically via JS IntersectionObserver), the | |
| text reveals itself from bottom to top with a smooth transition. | |
| Usage: | |
| <h2 class="text-reveal">Hidden heading</h2> | |
| // Then in JS: element.classList.add('active') | |
| States: | |
| - Default: clip-path hides text, opacity 0 | |
| - .active: clip-path reveals text, opacity 1 | |
| ---------------------------------------------------------- */ | |
| .text-reveal { | |
| clip-path: inset(100% 0 0 0); | |
| opacity: 0; | |
| transition: | |
| clip-path 0.8s cubic-bezier(0.23, 1, 0.32, 1), | |
| opacity 0.8s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: clip-path, opacity; | |
| } | |
| .text-reveal.active { | |
| clip-path: inset(0 0 0 0); | |
| opacity: 1; | |
| } | |
| /* Stagger delay variants for lists of .text-reveal elements */ | |
| .text-reveal.active.delay-1 { transition-delay: 0.1s; } | |
| .text-reveal.active.delay-2 { transition-delay: 0.2s; } | |
| .text-reveal.active.delay-3 { transition-delay: 0.3s; } | |
| .text-reveal.active.delay-4 { transition-delay: 0.4s; } | |
| .text-reveal.active.delay-5 { transition-delay: 0.5s; } | |
| /* ---------------------------------------------------------- | |
| 5. .magnetic-button β CSS foundation for magnetic effect | |
| ---------------------------------------------------------- | |
| Provides the smooth cubic-bezier transition for the magnetic | |
| cursor-following effect. The actual mousemove JS would | |
| apply a small translateX/Y to nudge the button toward the | |
| cursor on hover. | |
| Usage: | |
| <button class="magnetic-button">Hover me</button> | |
| JS companion: | |
| button.addEventListener('mousemove', (e) => { | |
| const rect = button.getBoundingClientRect(); | |
| const x = e.clientX - rect.left - rect.width / 2; | |
| const y = e.clientY - rect.top - rect.height / 2; | |
| button.style.transform = `translate(${x * 0.3}px, ${y * 0.3}px)`; | |
| }); | |
| button.addEventListener('mouseleave', () => { | |
| button.style.transform = 'translate(0, 0)'; | |
| }); | |
| ---------------------------------------------------------- */ | |
| .magnetic-button { | |
| transition: transform 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .stacked-cards β Visually offset/stacked card container | |
| ---------------------------------------------------------- | |
| Container class that makes direct child cards appear stacked | |
| with each subsequent card offset 4px down and 4px right, | |
| with decreasing opacity for a depth illusion. | |
| Usage: | |
| <div class="stacked-cards"> | |
| <div class="glass-card">Card 1</div> | |
| <div class="glass-card">Card 2</div> | |
| <div class="glass-card">Card 3</div> | |
| </div> | |
| Note: | |
| - Best with 2-5 child cards; excessive stacking may look odd | |
| - Children should be absolutely positioned or the container | |
| should have appropriate spacing | |
| ---------------------------------------------------------- */ | |
| .stacked-cards { | |
| position: relative; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .stacked-cards > :first-child { | |
| z-index: 3; | |
| opacity: 1; | |
| } | |
| .stacked-cards > :nth-child(2) { | |
| z-index: 2; | |
| opacity: 0.75; | |
| transform: translate(4px, 4px); | |
| } | |
| .stacked-cards > :nth-child(3) { | |
| z-index: 1; | |
| opacity: 0.5; | |
| transform: translate(8px, 8px); | |
| } | |
| .stacked-cards > :nth-child(4) { | |
| z-index: 0; | |
| opacity: 0.3; | |
| transform: translate(12px, 12px); | |
| } | |
| .stacked-cards > :nth-child(n+5) { | |
| z-index: -1; | |
| opacity: 0.15; | |
| transform: translate(16px, 16px); | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .glow-line β Pulsing gradient glow separator line | |
| ---------------------------------------------------------- | |
| A thin horizontal line with a centered gradient glow that | |
| pulses gently. Ideal as a section separator between content | |
| blocks. | |
| Usage: | |
| <hr class="glow-line" /> | |
| Variants: | |
| .glow-line.amber β amber/gold glow | |
| .glow-line.emerald β green glow | |
| .glow-line.rose β pink/rose glow | |
| ---------------------------------------------------------- */ | |
| .glow-line { | |
| border: none; | |
| height: 1px; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(99, 102, 241, 0.08) 20%, | |
| rgba(99, 102, 241, 0.5) 45%, | |
| rgba(139, 92, 246, 0.6) 50%, | |
| rgba(99, 102, 241, 0.5) 55%, | |
| rgba(99, 102, 241, 0.08) 80%, | |
| transparent 100% | |
| ); | |
| position: relative; | |
| margin: 2.5rem 0; | |
| animation: glowLinePulse 3s ease-in-out infinite; | |
| box-shadow: | |
| 0 0 6px rgba(99, 102, 241, 0.15), | |
| 0 0 12px rgba(99, 102, 241, 0.05); | |
| } | |
| .glow-line.amber { | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(245, 158, 11, 0.08) 20%, | |
| rgba(245, 158, 11, 0.5) 45%, | |
| rgba(251, 191, 36, 0.6) 50%, | |
| rgba(245, 158, 11, 0.5) 55%, | |
| rgba(245, 158, 11, 0.08) 80%, | |
| transparent 100% | |
| ); | |
| box-shadow: | |
| 0 0 6px rgba(245, 158, 11, 0.15), | |
| 0 0 12px rgba(245, 158, 11, 0.05); | |
| } | |
| .glow-line.emerald { | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(16, 185, 129, 0.08) 20%, | |
| rgba(16, 185, 129, 0.5) 45%, | |
| rgba(52, 211, 153, 0.6) 50%, | |
| rgba(16, 185, 129, 0.5) 55%, | |
| rgba(16, 185, 129, 0.08) 80%, | |
| transparent 100% | |
| ); | |
| box-shadow: | |
| 0 0 6px rgba(16, 185, 129, 0.15), | |
| 0 0 12px rgba(16, 185, 129, 0.05); | |
| } | |
| .glow-line.rose { | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(244, 63, 94, 0.08) 20%, | |
| rgba(244, 63, 94, 0.5) 45%, | |
| rgba(251, 113, 133, 0.6) 50%, | |
| rgba(244, 63, 94, 0.5) 55%, | |
| rgba(244, 63, 94, 0.08) 80%, | |
| transparent 100% | |
| ); | |
| box-shadow: | |
| 0 0 6px rgba(244, 63, 94, 0.15), | |
| 0 0 12px rgba(244, 63, 94, 0.05); | |
| } | |
| @keyframes glowLinePulse { | |
| 0%, 100% { opacity: 0.7; filter: brightness(1); } | |
| 50% { opacity: 1; filter: brightness(1.4); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .card-spotlight β Radial gradient spotlight (fixed pos) | |
| ---------------------------------------------------------- | |
| A card with a soft radial-gradient spotlight effect. This | |
| pure-CSS version places the spotlight at the top-right corner | |
| for a consistent "light source" feel. | |
| Usage: | |
| <div class="card-spotlight glass-card">Card content</div> | |
| For a cursor-following version, add JS to update | |
| the background-position via CSS custom properties. | |
| ---------------------------------------------------------- */ | |
| .card-spotlight { | |
| position: relative; | |
| overflow: hidden; | |
| background: | |
| radial-gradient( | |
| 350px circle at 85% 15%, | |
| rgba(99, 102, 241, 0.12) 0%, | |
| rgba(139, 92, 246, 0.06) 40%, | |
| transparent 70% | |
| ), | |
| var(--card, rgba(15, 15, 35, 0.65)); | |
| transition: | |
| background 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .card-spotlight:hover { | |
| background: | |
| radial-gradient( | |
| 400px circle at 85% 15%, | |
| rgba(99, 102, 241, 0.2) 0%, | |
| rgba(139, 92, 246, 0.1) 35%, | |
| transparent 70% | |
| ), | |
| var(--card, rgba(20, 20, 45, 0.75)); | |
| box-shadow: | |
| 0 8px 32px rgba(0, 0, 0, 0.3), | |
| 0 0 20px rgba(99, 102, 241, 0.06); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .morph-bg β Slowly morphing background blob | |
| ---------------------------------------------------------- | |
| Decorative background element that continuously morphs its | |
| shape using border-radius animation. Creates an organic, | |
| flowing blob effect. | |
| Usage: | |
| <div class="morph-bg"></div> | |
| <div class="morph-bg morph-bg-alt"></div> | |
| Tips: | |
| - Set width/height and background-color on the element | |
| - Use opacity: 0.2-0.5 and blur for soft decoration | |
| - position: absolute inside a relative container | |
| - The .morph-bg-alt variant uses a different animation | |
| phase for visual variety when layering multiple blobs | |
| ---------------------------------------------------------- */ | |
| .morph-bg { | |
| width: 300px; | |
| height: 300px; | |
| border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; | |
| background: rgba(99, 102, 241, 0.15); | |
| animation: morphBlob1 12s ease-in-out infinite; | |
| will-change: border-radius, transform; | |
| filter: blur(40px); | |
| } | |
| .morph-bg-alt { | |
| border-radius: 30% 70% 70% 30% / 30% 52% 48% 70%; | |
| background: rgba(139, 92, 246, 0.12); | |
| animation: morphBlob2 14s ease-in-out infinite; | |
| } | |
| .morph-bg-amber { | |
| background: rgba(245, 158, 11, 0.1); | |
| animation: morphBlob1 16s ease-in-out infinite; | |
| } | |
| .morph-bg-emerald { | |
| background: rgba(16, 185, 129, 0.1); | |
| animation: morphBlob2 18s ease-in-out infinite; | |
| } | |
| @keyframes morphBlob1 { | |
| 0%, 100% { | |
| border-radius: 60% 40% 30% 70% / 60% 30% 70% 40%; | |
| transform: rotate(0deg) scale(1); | |
| } | |
| 25% { | |
| border-radius: 30% 60% 70% 40% / 50% 60% 30% 60%; | |
| transform: rotate(90deg) scale(1.05); | |
| } | |
| 50% { | |
| border-radius: 50% 60% 30% 60% / 30% 40% 70% 60%; | |
| transform: rotate(180deg) scale(0.95); | |
| } | |
| 75% { | |
| border-radius: 60% 30% 60% 40% / 70% 50% 40% 60%; | |
| transform: rotate(270deg) scale(1.03); | |
| } | |
| } | |
| @keyframes morphBlob2 { | |
| 0%, 100% { | |
| border-radius: 30% 70% 70% 30% / 30% 52% 48% 70%; | |
| transform: rotate(0deg) scale(1); | |
| } | |
| 25% { | |
| border-radius: 58% 42% 55% 45% / 56% 60% 40% 44%; | |
| transform: rotate(-90deg) scale(1.08); | |
| } | |
| 50% { | |
| border-radius: 45% 55% 40% 60% / 65% 35% 60% 40%; | |
| transform: rotate(-180deg) scale(0.97); | |
| } | |
| 75% { | |
| border-radius: 70% 30% 50% 50% / 40% 65% 35% 55%; | |
| transform: rotate(-270deg) scale(1.04); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .number-ticker β Animated number counter styling | |
| ---------------------------------------------------------- | |
| Styling for number counters/odometer displays. Uses | |
| tabular-nums for stable digit widths and a subtle glow | |
| effect. The actual counting animation is handled by JS. | |
| Usage: | |
| <span class="number-ticker">12,847</span> | |
| Pair with JS that animates innerText from 0 β target. | |
| The tabular-nums ensures digits don't shift as numbers change. | |
| ---------------------------------------------------------- */ | |
| .number-ticker { | |
| font-variant-numeric: tabular-nums; | |
| font-feature-settings: 'tnum'; | |
| letter-spacing: -0.02em; | |
| color: #f8fafc; | |
| text-shadow: | |
| 0 0 8px rgba(99, 102, 241, 0.25), | |
| 0 0 20px rgba(99, 102, 241, 0.08); | |
| display: inline-block; | |
| overflow: hidden; | |
| } | |
| .number-ticker.glow-amber { | |
| color: #fcd34d; | |
| text-shadow: | |
| 0 0 8px rgba(245, 158, 11, 0.3), | |
| 0 0 20px rgba(245, 158, 11, 0.1); | |
| } | |
| .number-ticker.glow-emerald { | |
| color: #6ee7b7; | |
| text-shadow: | |
| 0 0 8px rgba(16, 185, 129, 0.3), | |
| 0 0 20px rgba(16, 185, 129, 0.1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .scroll-reveal β Fade-up on scroll reveal | |
| ---------------------------------------------------------- | |
| Default state: invisible, shifted down 20px. When the | |
| .visible class is added (via JS IntersectionObserver), the | |
| element fades in and slides up into place. | |
| Usage: | |
| <div class="scroll-reveal">Content</div> | |
| JS companion: | |
| const observer = new IntersectionObserver((entries) => { | |
| entries.forEach(entry => { | |
| if (entry.isIntersecting) { | |
| entry.target.classList.add('visible'); | |
| } | |
| }); | |
| }, { threshold: 0.1 }); | |
| document.querySelectorAll('.scroll-reveal').forEach(el => observer.observe(el)); | |
| Stagger variants: | |
| .scroll-reveal.stagger-1 β 0.1s delay | |
| .scroll-reveal.stagger-2 β 0.2s delay | |
| .scroll-reveal.stagger-3 β 0.3s delay | |
| ---------------------------------------------------------- */ | |
| .scroll-reveal { | |
| opacity: 0; | |
| transform: translateY(20px); | |
| transition: | |
| opacity 0.7s cubic-bezier(0.23, 1, 0.32, 1), | |
| transform 0.7s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: opacity, transform; | |
| } | |
| .scroll-reveal.visible { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| /* Stagger delay variants for sequential reveals */ | |
| .scroll-reveal.visible.stagger-1 { transition-delay: 0.1s; } | |
| .scroll-reveal.visible.stagger-2 { transition-delay: 0.2s; } | |
| .scroll-reveal.visible.stagger-3 { transition-delay: 0.3s; } | |
| .scroll-reveal.visible.stagger-4 { transition-delay: 0.4s; } | |
| .scroll-reveal.visible.stagger-5 { transition-delay: 0.5s; } | |
| .scroll-reveal.visible.stagger-6 { transition-delay: 0.6s; } | |
| /* ---------------------------------------------------------- | |
| 12. Enhanced Input & Textarea Focus States | |
| ---------------------------------------------------------- | |
| Custom focus ring styles for inputs and textareas that | |
| match the IA Academy indigo theme. On focus, the input | |
| gets a subtle indigo glow border and box-shadow, replacing | |
| the default browser focus outline with a polished look. | |
| Usage: | |
| These styles apply automatically to all <input> and | |
| <textarea> elements within the theme. | |
| Behavior: | |
| - Default: dark themed input with subtle border | |
| - Focus: indigo border + outer glow + slight bg shift | |
| - Placeholder: muted color that transitions on focus | |
| ---------------------------------------------------------- */ | |
| input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="reset"]):not([type="button"]), | |
| textarea, | |
| select { | |
| background: rgba(15, 15, 35, 0.6); | |
| border: 1px solid var(--border, #2a2a4a); | |
| border-radius: 8px; | |
| padding: 0.625rem 0.875rem; | |
| color: var(--foreground, #f8fafc); | |
| font-size: 0.875rem; | |
| line-height: 1.5; | |
| outline: none; | |
| transition: | |
| border-color 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| background 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: border-color, box-shadow; | |
| } | |
| input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="reset"]):not([type="button"]):focus, | |
| textarea:focus, | |
| select:focus { | |
| border-color: rgba(99, 102, 241, 0.6); | |
| box-shadow: | |
| 0 0 0 3px rgba(99, 102, 241, 0.15), | |
| 0 0 12px rgba(99, 102, 241, 0.1), | |
| 0 0 24px rgba(99, 102, 241, 0.05); | |
| background: rgba(20, 20, 50, 0.8); | |
| } | |
| input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="reset"]):not([type="button"])::placeholder, | |
| textarea::placeholder { | |
| color: rgba(148, 163, 184, 0.5); | |
| transition: color 0.3s ease; | |
| } | |
| input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="reset"]):not([type="button"]):focus::placeholder, | |
| textarea:focus::placeholder { | |
| color: rgba(148, 163, 184, 0.3); | |
| } | |
| /* Textarea specific: larger default size and resize handle styling */ | |
| textarea { | |
| min-height: 100px; | |
| resize: vertical; | |
| } | |
| textarea:focus { | |
| min-height: 100px; | |
| } | |
| /* ============================================================ | |
| IA Academy β Extended Visual Effect Classes (Task 9) | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .aurora-bg β Aurora borealis animated background | |
| ---------------------------------------------------------- | |
| Multiple layered radial gradients that slowly shift color | |
| and position, simulating the Northern Lights. Designed for | |
| full-width sections behind content. | |
| Usage: | |
| <section class="aurora-bg"> | |
| <div style="position:relative;z-index:1">Content</div> | |
| </section> | |
| Note: | |
| - Content needs position:relative; z-index:1 to sit above | |
| - Uses both ::before and ::after for layered depth | |
| - Colors cycle through indigo, purple, emerald, cyan | |
| ---------------------------------------------------------- */ | |
| .aurora-bg { | |
| position: relative; | |
| overflow: hidden; | |
| background-color: var(--background, #0a0a1a); | |
| } | |
| .aurora-bg::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -20%; | |
| background: | |
| radial-gradient(ellipse 80% 50% at 20% 40%, rgba(99, 102, 241, 0.25) 0%, transparent 60%), | |
| radial-gradient(ellipse 60% 70% at 70% 20%, rgba(139, 92, 246, 0.2) 0%, transparent 55%), | |
| radial-gradient(ellipse 90% 40% at 50% 80%, rgba(16, 185, 129, 0.15) 0%, transparent 50%), | |
| radial-gradient(ellipse 50% 60% at 85% 60%, rgba(6, 182, 212, 0.12) 0%, transparent 55%); | |
| animation: auroraShift1 18s ease-in-out infinite; | |
| pointer-events: none; | |
| z-index: 0; | |
| filter: blur(60px); | |
| } | |
| .aurora-bg::after { | |
| content: ''; | |
| position: absolute; | |
| inset: -15%; | |
| background: | |
| radial-gradient(ellipse 70% 45% at 60% 30%, rgba(168, 85, 247, 0.18) 0%, transparent 55%), | |
| radial-gradient(ellipse 55% 65% at 30% 70%, rgba(99, 102, 241, 0.15) 0%, transparent 50%), | |
| radial-gradient(ellipse 65% 35% at 80% 50%, rgba(16, 185, 129, 0.1) 0%, transparent 50%), | |
| radial-gradient(ellipse 45% 55% at 15% 25%, rgba(245, 158, 11, 0.08) 0%, transparent 50%); | |
| animation: auroraShift2 24s ease-in-out infinite; | |
| pointer-events: none; | |
| z-index: 0; | |
| filter: blur(80px); | |
| } | |
| @keyframes auroraShift1 { | |
| 0%, 100% { | |
| transform: translate(0, 0) rotate(0deg) scale(1); | |
| opacity: 1; | |
| } | |
| 25% { | |
| transform: translate(5%, -3%) rotate(2deg) scale(1.05); | |
| opacity: 0.8; | |
| } | |
| 50% { | |
| transform: translate(-3%, 5%) rotate(-1deg) scale(0.98); | |
| opacity: 1; | |
| } | |
| 75% { | |
| transform: translate(-5%, -2%) rotate(1deg) scale(1.03); | |
| opacity: 0.85; | |
| } | |
| } | |
| @keyframes auroraShift2 { | |
| 0%, 100% { | |
| transform: translate(0, 0) rotate(0deg) scale(1); | |
| opacity: 0.7; | |
| } | |
| 33% { | |
| transform: translate(-4%, 4%) rotate(-2deg) scale(1.06); | |
| opacity: 0.9; | |
| } | |
| 66% { | |
| transform: translate(4%, -3%) rotate(2deg) scale(0.95); | |
| opacity: 0.75; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .ripple-effect β Click ripple/pulse emanation | |
| ---------------------------------------------------------- | |
| On click, a circle expands from the center of the element | |
| and fades out, creating a Material Design-style ripple. | |
| Uses ::after pseudo-element with scale animation. | |
| Usage: | |
| <button class="ripple-effect">Click me</button> | |
| Note: | |
| - Pure CSS approach: ripple plays once per click via | |
| the :active pseudo-class | |
| - For JS-driven multi-ripple, use additional spans | |
| ---------------------------------------------------------- */ | |
| .ripple-effect { | |
| position: relative; | |
| overflow: hidden; | |
| cursor: pointer; | |
| } | |
| .ripple-effect::after { | |
| content: ''; | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| width: 10px; | |
| height: 10px; | |
| border-radius: 50%; | |
| background: radial-gradient(circle, rgba(99, 102, 241, 0.4), rgba(139, 92, 246, 0.2), transparent); | |
| transform: translate(-50%, -50%) scale(0); | |
| opacity: 0; | |
| pointer-events: none; | |
| z-index: 10; | |
| transition: none; | |
| } | |
| .ripple-effect:active::after { | |
| animation: rippleExpand 0.6s ease-out forwards; | |
| } | |
| @keyframes rippleExpand { | |
| 0% { | |
| transform: translate(-50%, -50%) scale(0); | |
| opacity: 1; | |
| } | |
| 100% { | |
| transform: translate(-50%, -50%) scale(40); | |
| opacity: 0; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .glass-input β Enhanced glassmorphism input field | |
| ---------------------------------------------------------- | |
| Semi-transparent background with subtle border and inner | |
| glow on focus. Smooth transitions for a polished dark-theme | |
| input experience that pairs well with .glass-card containers. | |
| Usage: | |
| <input class="glass-input" placeholder="Search..." /> | |
| States: | |
| - Default: frosted glass background, muted border | |
| - Focus: indigo inner glow, brighter border, bg shift | |
| - Disabled: dimmed with reduced opacity | |
| ---------------------------------------------------------- */ | |
| .glass-input { | |
| background: rgba(15, 15, 35, 0.5); | |
| backdrop-filter: blur(12px); | |
| -webkit-backdrop-filter: blur(12px); | |
| border: 1px solid rgba(99, 102, 241, 0.15); | |
| border-radius: 10px; | |
| padding: 0.75rem 1rem; | |
| color: var(--foreground, #f8fafc); | |
| font-size: 0.875rem; | |
| line-height: 1.5; | |
| outline: none; | |
| transition: | |
| border-color 0.35s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.35s cubic-bezier(0.23, 1, 0.32, 1), | |
| background 0.35s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: border-color, box-shadow; | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.04), | |
| inset 0 0 0 0 transparent; | |
| } | |
| .glass-input::placeholder { | |
| color: rgba(148, 163, 184, 0.45); | |
| transition: color 0.3s ease; | |
| } | |
| .glass-input:hover { | |
| border-color: rgba(99, 102, 241, 0.3); | |
| background: rgba(18, 18, 42, 0.6); | |
| } | |
| .glass-input:focus { | |
| border-color: rgba(99, 102, 241, 0.55); | |
| background: rgba(20, 20, 50, 0.7); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.06), | |
| inset 0 0 20px rgba(99, 102, 241, 0.06), | |
| 0 0 0 3px rgba(99, 102, 241, 0.12), | |
| 0 0 16px rgba(99, 102, 241, 0.08); | |
| } | |
| .glass-input:focus::placeholder { | |
| color: rgba(148, 163, 184, 0.25); | |
| } | |
| .glass-input:disabled { | |
| opacity: 0.5; | |
| cursor: not-allowed; | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .tag-chip β Small rounded tag/chip pill | |
| ---------------------------------------------------------- | |
| Compact tag styling for labeling content (TP tags, categories, | |
| skill badges). Pill-shaped with semi-transparent background | |
| and a hover lift effect. | |
| Usage: | |
| <span class="tag-chip">Python</span> | |
| <span class="tag-chip indigo">Classification</span> | |
| <span class="tag-chip amber">IntermΓ©diaire</span> | |
| Color variants: | |
| (default) β indigo tones | |
| .indigo β indigo | |
| .amber β amber/gold | |
| .emerald β green | |
| .rose β pink/rose | |
| ---------------------------------------------------------- */ | |
| .tag-chip { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| padding: 0.2rem 0.65rem; | |
| border-radius: 9999px; | |
| font-size: 0.7rem; | |
| font-weight: 600; | |
| letter-spacing: 0.02em; | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| background: rgba(99, 102, 241, 0.08); | |
| color: #a5b4fc; | |
| cursor: default; | |
| transition: | |
| transform 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform; | |
| } | |
| .tag-chip:hover { | |
| transform: translateY(-2px); | |
| border-color: rgba(99, 102, 241, 0.4); | |
| box-shadow: 0 4px 12px rgba(99, 102, 241, 0.12); | |
| } | |
| .tag-chip.indigo { | |
| border-color: rgba(99, 102, 241, 0.2); | |
| background: rgba(99, 102, 241, 0.08); | |
| color: #a5b4fc; | |
| } | |
| .tag-chip.indigo:hover { | |
| border-color: rgba(99, 102, 241, 0.4); | |
| box-shadow: 0 4px 12px rgba(99, 102, 241, 0.12); | |
| } | |
| .tag-chip.amber { | |
| border-color: rgba(245, 158, 11, 0.2); | |
| background: rgba(245, 158, 11, 0.08); | |
| color: #fbbf24; | |
| } | |
| .tag-chip.amber:hover { | |
| border-color: rgba(245, 158, 11, 0.4); | |
| box-shadow: 0 4px 12px rgba(245, 158, 11, 0.12); | |
| } | |
| .tag-chip.emerald { | |
| border-color: rgba(16, 185, 129, 0.2); | |
| background: rgba(16, 185, 129, 0.08); | |
| color: #34d399; | |
| } | |
| .tag-chip.emerald:hover { | |
| border-color: rgba(16, 185, 129, 0.4); | |
| box-shadow: 0 4px 12px rgba(16, 185, 129, 0.12); | |
| } | |
| .tag-chip.rose { | |
| border-color: rgba(244, 63, 94, 0.2); | |
| background: rgba(244, 63, 94, 0.08); | |
| color: #fb7185; | |
| } | |
| .tag-chip.rose:hover { | |
| border-color: rgba(244, 63, 94, 0.4); | |
| box-shadow: 0 4px 12px rgba(244, 63, 94, 0.12); | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .card-3d β 3D tilt card with perspective | |
| ---------------------------------------------------------- | |
| Adds a CSS perspective container so the card subtly tilts | |
| on hover using rotateX/Y transforms. The transform-style: | |
| preserve-3d ensures children participate in the 3D space. | |
| Usage: | |
| <div class="card-3d"> | |
| <div class="glass-card">Card content</div> | |
| </div> | |
| Note: | |
| - Pure CSS version uses a fixed tilt angle on hover | |
| - For cursor-following tilt, add JS mousemove handler | |
| that sets --rotateX / --rotateY CSS custom properties | |
| ---------------------------------------------------------- */ | |
| .card-3d { | |
| perspective: 800px; | |
| perspective-origin: center; | |
| } | |
| .card-3d > * { | |
| transform-style: preserve-3d; | |
| transition: | |
| transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .card-3d:hover > * { | |
| transform: rotateX(3deg) rotateY(-3deg) translateZ(8px); | |
| box-shadow: | |
| 0 20px 40px rgba(0, 0, 0, 0.35), | |
| 0 0 30px rgba(99, 102, 241, 0.08); | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .gradient-text-reveal β Gradient sweep text reveal | |
| ---------------------------------------------------------- | |
| Text reveals with a gradient sweep from left to right using | |
| clip-path animation. The text background uses a gradient | |
| that slides in, creating a colorful wipe-reveal effect. | |
| Usage: | |
| <h2 class="gradient-text-reveal">Revealing heading</h2> | |
| Activation: | |
| - Add .active class via JS/IntersectionObserver to trigger | |
| - Text is invisible by default (clip-path: inset) | |
| - On .active, gradient sweeps in from left to right | |
| ---------------------------------------------------------- */ | |
| .gradient-text-reveal { | |
| background: linear-gradient( | |
| 90deg, | |
| #6366f1 0%, | |
| #a855f7 25%, | |
| #ec4899 50%, | |
| #f59e0b 75%, | |
| #10b981 100% | |
| ); | |
| background-size: 200% 100%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| clip-path: inset(0 100% 0 0); | |
| opacity: 0; | |
| transition: | |
| clip-path 1s cubic-bezier(0.23, 1, 0.32, 1), | |
| opacity 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: clip-path, opacity; | |
| } | |
| .gradient-text-reveal.active { | |
| clip-path: inset(0 0% 0 0); | |
| opacity: 1; | |
| animation: gradientTextRevealSweep 1.5s ease-in-out 0.3s; | |
| } | |
| @keyframes gradientTextRevealSweep { | |
| 0% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .pulse-ring β Notification-style pulsing ring | |
| ---------------------------------------------------------- | |
| Multiple expanding rings that emanate from an element and | |
| fade out. Ideal for notification indicators, unread badges, | |
| or the "Quiz" button attention effect. | |
| Usage: | |
| <div class="pulse-ring">Icon or dot</div> | |
| Note: | |
| - Uses ::before and ::after for two staggered rings | |
| - The element itself should be small (dot, icon) | |
| - Rings expand to 3x the element size and fade out | |
| ---------------------------------------------------------- */ | |
| .pulse-ring { | |
| position: relative; | |
| z-index: 1; | |
| } | |
| .pulse-ring::before, | |
| .pulse-ring::after { | |
| content: ''; | |
| position: absolute; | |
| inset: -4px; | |
| border-radius: inherit; | |
| border: 2px solid rgba(99, 102, 241, 0.6); | |
| pointer-events: none; | |
| z-index: -1; | |
| animation: pulseRingExpand 2.5s cubic-bezier(0.215, 0.61, 0.355, 1) infinite; | |
| } | |
| .pulse-ring::after { | |
| animation-delay: 0.8s; | |
| border-color: rgba(139, 92, 246, 0.4); | |
| } | |
| @keyframes pulseRingExpand { | |
| 0% { | |
| transform: scale(1); | |
| opacity: 0.8; | |
| } | |
| 80% { | |
| transform: scale(2.5); | |
| opacity: 0; | |
| } | |
| 100% { | |
| transform: scale(2.5); | |
| opacity: 0; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .grid-pattern β Subtle grid/dot pattern overlay | |
| ---------------------------------------------------------- | |
| A repeating dot-grid background overlay (like graph paper) | |
| that adds subtle texture to sections. Uses CSS repeating | |
| gradients to create a precise, lightweight dot pattern. | |
| Usage: | |
| <div class="grid-pattern">Content</div> | |
| Note: | |
| - Semi-transparent dots on dark background | |
| - Content should have position:relative; z-index:1 | |
| - Dots are 1px at 24px intervals, very subtle | |
| ---------------------------------------------------------- */ | |
| .grid-pattern { | |
| position: relative; | |
| } | |
| .grid-pattern::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background-image: | |
| radial-gradient(circle, rgba(99, 102, 241, 0.12) 1px, transparent 1px); | |
| background-size: 24px 24px; | |
| pointer-events: none; | |
| z-index: 0; | |
| mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.2) 80%, transparent 100%); | |
| -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.2) 80%, transparent 100%); | |
| } | |
| .grid-pattern::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background-image: | |
| linear-gradient(rgba(99, 102, 241, 0.03) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(99, 102, 241, 0.03) 1px, transparent 1px); | |
| background-size: 24px 24px; | |
| pointer-events: none; | |
| z-index: 0; | |
| mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0.1) 70%, transparent 100%); | |
| -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0.1) 70%, transparent 100%); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .floating-orbs β Decorative floating background orbs | |
| ---------------------------------------------------------- | |
| Two or three small circular orbs that float around slowly | |
| using keyframe animations with different speeds and paths. | |
| Purely decorative background elements. | |
| Usage: | |
| <div class="floating-orbs"> | |
| <div class="orb orb-1"></div> | |
| <div class="orb orb-2"></div> | |
| <div class="orb orb-3"></div> | |
| </div> | |
| Note: | |
| - Orbs are position:absolute; container must be relative | |
| - Each orb has a unique animation path and speed | |
| - Apply filter:blur() for soft glowing effect | |
| ---------------------------------------------------------- */ | |
| .floating-orbs { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .floating-orbs .orb { | |
| position: absolute; | |
| border-radius: 50%; | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| .floating-orbs .orb-1 { | |
| width: 120px; | |
| height: 120px; | |
| top: 15%; | |
| left: 10%; | |
| background: radial-gradient(circle, rgba(99, 102, 241, 0.25), rgba(99, 102, 241, 0.05), transparent); | |
| filter: blur(30px); | |
| animation: orbFloat1 20s ease-in-out infinite; | |
| } | |
| .floating-orbs .orb-2 { | |
| width: 80px; | |
| height: 80px; | |
| top: 60%; | |
| right: 15%; | |
| background: radial-gradient(circle, rgba(139, 92, 246, 0.3), rgba(139, 92, 246, 0.05), transparent); | |
| filter: blur(25px); | |
| animation: orbFloat2 16s ease-in-out infinite; | |
| } | |
| .floating-orbs .orb-3 { | |
| width: 60px; | |
| height: 60px; | |
| bottom: 20%; | |
| left: 40%; | |
| background: radial-gradient(circle, rgba(245, 158, 11, 0.2), rgba(245, 158, 11, 0.05), transparent); | |
| filter: blur(20px); | |
| animation: orbFloat3 24s ease-in-out infinite; | |
| } | |
| @keyframes orbFloat1 { | |
| 0%, 100% { | |
| transform: translate(0, 0) scale(1); | |
| opacity: 0.7; | |
| } | |
| 20% { | |
| transform: translate(60px, -30px) scale(1.1); | |
| opacity: 0.9; | |
| } | |
| 40% { | |
| transform: translate(30px, 40px) scale(0.9); | |
| opacity: 0.6; | |
| } | |
| 60% { | |
| transform: translate(-40px, 20px) scale(1.05); | |
| opacity: 0.85; | |
| } | |
| 80% { | |
| transform: translate(20px, -50px) scale(0.95); | |
| opacity: 0.5; | |
| } | |
| } | |
| @keyframes orbFloat2 { | |
| 0%, 100% { | |
| transform: translate(0, 0) scale(1); | |
| opacity: 0.8; | |
| } | |
| 25% { | |
| transform: translate(-50px, -40px) scale(1.15); | |
| opacity: 0.6; | |
| } | |
| 50% { | |
| transform: translate(40px, 30px) scale(0.85); | |
| opacity: 1; | |
| } | |
| 75% { | |
| transform: translate(-20px, 50px) scale(1.1); | |
| opacity: 0.5; | |
| } | |
| } | |
| @keyframes orbFloat3 { | |
| 0%, 100% { | |
| transform: translate(0, 0) scale(1); | |
| opacity: 0.6; | |
| } | |
| 33% { | |
| transform: translate(50px, -20px) scale(1.2); | |
| opacity: 0.9; | |
| } | |
| 66% { | |
| transform: translate(-30px, 40px) scale(0.8); | |
| opacity: 0.4; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .text-gradient-border β Gradient border/outline text | |
| ---------------------------------------------------------- | |
| Text with a gradient outline effect achieved using the | |
| background-clip trick with -webkit-text-stroke. The text | |
| fill is transparent while the stroke shows the gradient. | |
| Usage: | |
| <span class="text-gradient-border">Outlined text</span> | |
| Note: | |
| - Uses -webkit-text-stroke for the gradient outline | |
| - Background is clipped to text for gradient stroke | |
| - Works best on larger text (headings, display text) | |
| ---------------------------------------------------------- */ | |
| .text-gradient-border { | |
| background: linear-gradient(135deg, #6366f1, #a855f7, #ec4899, #f59e0b); | |
| background-size: 300% 300%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| -webkit-text-stroke: 1.5px transparent; | |
| position: relative; | |
| animation: gradientBorderShift 6s ease infinite; | |
| filter: drop-shadow(0 0 8px rgba(99, 102, 241, 0.2)); | |
| } | |
| .text-gradient-border::before { | |
| content: attr(data-text); | |
| position: absolute; | |
| inset: 0; | |
| background: linear-gradient(135deg, #6366f1, #a855f7, #ec4899, #f59e0b); | |
| background-size: 300% 300%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| -webkit-text-stroke: 1.5px rgba(99, 102, 241, 0.6); | |
| animation: gradientBorderShift 6s ease infinite; | |
| pointer-events: none; | |
| } | |
| @keyframes gradientBorderShift { | |
| 0%, 100% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .icon-glow β Subtle glow effect for icons | |
| ---------------------------------------------------------- | |
| Adds a soft, color-matched text-shadow glow to icons. | |
| Scales up slightly on hover for interactive feedback. | |
| Usage: | |
| <i class="icon-glow lucide-brain"></i> | |
| Color variants (via CSS custom property): | |
| Default: indigo glow | |
| Set --glow-color to customize (e.g., amber, emerald) | |
| ---------------------------------------------------------- */ | |
| .icon-glow { | |
| display: inline-block; | |
| color: #a5b4fc; | |
| text-shadow: | |
| 0 0 6px rgba(99, 102, 241, 0.4), | |
| 0 0 14px rgba(99, 102, 241, 0.15); | |
| transition: | |
| transform 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| text-shadow 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, text-shadow; | |
| } | |
| .icon-glow:hover { | |
| transform: scale(1.15); | |
| text-shadow: | |
| 0 0 10px rgba(99, 102, 241, 0.6), | |
| 0 0 24px rgba(99, 102, 241, 0.25), | |
| 0 0 40px rgba(99, 102, 241, 0.1); | |
| } | |
| .icon-glow[style*="--glow-amber"], | |
| .icon-glow.amber { | |
| color: #fbbf24; | |
| text-shadow: | |
| 0 0 6px rgba(245, 158, 11, 0.4), | |
| 0 0 14px rgba(245, 158, 11, 0.15); | |
| } | |
| .icon-glow.amber:hover { | |
| text-shadow: | |
| 0 0 10px rgba(245, 158, 11, 0.6), | |
| 0 0 24px rgba(245, 158, 11, 0.25), | |
| 0 0 40px rgba(245, 158, 11, 0.1); | |
| } | |
| .icon-glow[style*="--glow-emerald"], | |
| .icon-glow.emerald { | |
| color: #34d399; | |
| text-shadow: | |
| 0 0 6px rgba(16, 185, 129, 0.4), | |
| 0 0 14px rgba(16, 185, 129, 0.15); | |
| } | |
| .icon-glow.emerald:hover { | |
| text-shadow: | |
| 0 0 10px rgba(16, 185, 129, 0.6), | |
| 0 0 24px rgba(16, 185, 129, 0.25), | |
| 0 0 40px rgba(16, 185, 129, 0.1); | |
| } | |
| .icon-glow[style*="--glow-rose"], | |
| .icon-glow.rose { | |
| color: #fb7185; | |
| text-shadow: | |
| 0 0 6px rgba(244, 63, 94, 0.4), | |
| 0 0 14px rgba(244, 63, 94, 0.15); | |
| } | |
| .icon-glow.rose:hover { | |
| text-shadow: | |
| 0 0 10px rgba(244, 63, 94, 0.6), | |
| 0 0 24px rgba(244, 63, 94, 0.25), | |
| 0 0 40px rgba(244, 63, 94, 0.1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .progress-shimmer β Progress bar with shimmer animation | |
| ---------------------------------------------------------- | |
| An enhanced progress bar with a moving gradient highlight | |
| (shimmer) that sweeps across the fill, giving a sense of | |
| activity and progress. | |
| Usage: | |
| <div class="progress-shimmer" style="--progress: 65%"> | |
| <div class="progress-shimmer-fill"></div> | |
| </div> | |
| Structure: | |
| - Outer div: background track, set width via --progress | |
| - Inner div: colored fill with shimmer animation | |
| ---------------------------------------------------------- */ | |
| .progress-shimmer { | |
| position: relative; | |
| width: 100%; | |
| height: 8px; | |
| background: rgba(99, 102, 241, 0.08); | |
| border-radius: 999px; | |
| overflow: hidden; | |
| border: 1px solid rgba(99, 102, 241, 0.1); | |
| } | |
| .progress-shimmer-fill { | |
| height: 100%; | |
| width: var(--progress, 50%); | |
| min-width: 2%; | |
| border-radius: 999px; | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6, #6366f1); | |
| position: relative; | |
| overflow: hidden; | |
| transition: width 0.6s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .progress-shimmer-fill::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(255, 255, 255, 0.15) 25%, | |
| rgba(255, 255, 255, 0.35) 50%, | |
| rgba(255, 255, 255, 0.15) 75%, | |
| transparent 100% | |
| ); | |
| background-size: 200% 100%; | |
| animation: progressShimmerSweep 2s ease-in-out infinite; | |
| border-radius: inherit; | |
| } | |
| @keyframes progressShimmerSweep { | |
| 0% { background-position: 200% 0; } | |
| 100% { background-position: -200% 0; } | |
| } | |
| /* Progress color variants */ | |
| .progress-shimmer.amber .progress-shimmer-fill { | |
| background: linear-gradient(90deg, #f59e0b, #fbbf24, #f59e0b); | |
| } | |
| .progress-shimmer.emerald .progress-shimmer-fill { | |
| background: linear-gradient(90deg, #10b981, #34d399, #10b981); | |
| } | |
| .progress-shimmer.rose .progress-shimmer-fill { | |
| background: linear-gradient(90deg, #f43f5e, #fb7185, #f43f5e); | |
| } | |
| /* ============================================================ | |
| IA Academy β Interactive & Polish Utility Classes (Task 5-a) | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .tooltip-trigger / .tooltip-content β Hover tooltip | |
| ---------------------------------------------------------- | |
| Wrap an element in .tooltip-trigger; a child .tooltip-content | |
| will appear on hover with a fade-in + slide-up animation. | |
| Usage: | |
| <span class="tooltip-trigger"> | |
| Hover me | |
| <span class="tooltip-content">Tooltip text</span> | |
| </span> | |
| Note: | |
| - .tooltip-trigger must have position: relative | |
| - .tooltip-content is absolutely positioned at top center | |
| ---------------------------------------------------------- */ | |
| .tooltip-trigger { | |
| position: relative; | |
| display: inline-flex; | |
| } | |
| .tooltip-content { | |
| position: absolute; | |
| bottom: calc(100% + 8px); | |
| left: 50%; | |
| transform: translateX(-50%) translateY(4px); | |
| padding: 0.375rem 0.75rem; | |
| border-radius: 8px; | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| white-space: nowrap; | |
| pointer-events: none; | |
| opacity: 0; | |
| transition: | |
| opacity 0.2s cubic-bezier(0.23, 1, 0.32, 1), | |
| transform 0.2s cubic-bezier(0.23, 1, 0.32, 1); | |
| background: rgba(21, 21, 48, 0.9); | |
| backdrop-filter: blur(12px); | |
| -webkit-backdrop-filter: blur(12px); | |
| border: 1px solid rgba(99, 102, 241, 0.25); | |
| color: #e2e8f0; | |
| box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(99, 102, 241, 0.1); | |
| z-index: 50; | |
| } | |
| .tooltip-content::after { | |
| content: ''; | |
| position: absolute; | |
| top: 100%; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| border: 5px solid transparent; | |
| border-top-color: rgba(99, 102, 241, 0.25); | |
| } | |
| .tooltip-trigger:hover .tooltip-content { | |
| opacity: 1; | |
| transform: translateX(-50%) translateY(0); | |
| pointer-events: auto; | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .hover-card-lift β Card with enhanced lift on hover | |
| ---------------------------------------------------------- | |
| Applies a smooth lift + scale + shadow enhancement on hover. | |
| Works great with .glass-card for a premium card feel. | |
| Usage: | |
| <Card className="glass-card hover-card-lift">Content</Card> | |
| ---------------------------------------------------------- */ | |
| .hover-card-lift { | |
| transition: | |
| transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .hover-card-lift:hover { | |
| transform: translateY(-8px) scale(1.015); | |
| box-shadow: | |
| 0 24px 48px rgba(0, 0, 0, 0.35), | |
| 0 12px 24px rgba(0, 0, 0, 0.2), | |
| 0 0 0 1px rgba(99, 102, 241, 0.12), | |
| 0 0 40px rgba(99, 102, 241, 0.06); | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .shimmer-text β Text with shimmer/gradient sweep animation | |
| ---------------------------------------------------------- | |
| A gradient highlight sweeps across the text from left to | |
| right, creating a metallic shimmer effect. | |
| Usage: | |
| <span class="shimmer-text">Shimmering text</span> | |
| Note: | |
| - Works best on bold/large headings | |
| - Uses -webkit-background-clip for broad browser support | |
| ---------------------------------------------------------- */ | |
| .shimmer-text { | |
| background: linear-gradient( | |
| 90deg, | |
| #e2e8f0 0%, | |
| #e2e8f0 40%, | |
| #a5b4fc 50%, | |
| #e2e8f0 60%, | |
| #e2e8f0 100% | |
| ); | |
| background-size: 200% 100%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| animation: shimmerTextSweep 3s ease-in-out infinite; | |
| } | |
| @keyframes shimmerTextSweep { | |
| 0% { background-position: 200% 0; } | |
| 100% { background-position: -200% 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .slide-in-left β Enter from left with spring-like anim | |
| ---------------------------------------------------------- | |
| Element starts off-screen to the left and slides in with | |
| a spring easing curve. Good for staggered list items. | |
| Usage: | |
| <div class="slide-in-left">Slide from left</div> | |
| JS companion: | |
| Add class via IntersectionObserver for scroll-triggered entry. | |
| ---------------------------------------------------------- */ | |
| .slide-in-left { | |
| opacity: 0; | |
| transform: translateX(-40px); | |
| transition: | |
| opacity 0.6s cubic-bezier(0.34, 1.56, 0.64, 1), | |
| transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| will-change: opacity, transform; | |
| } | |
| .slide-in-left.visible { | |
| opacity: 1; | |
| transform: translateX(0); | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .slide-in-right β Enter from right with spring-like anim | |
| ---------------------------------------------------------- | |
| Mirror of .slide-in-left. Element enters from the right side. | |
| Usage: | |
| <div class="slide-in-right">Slide from right</div> | |
| ---------------------------------------------------------- */ | |
| .slide-in-right { | |
| opacity: 0; | |
| transform: translateX(40px); | |
| transition: | |
| opacity 0.6s cubic-bezier(0.34, 1.56, 0.64, 1), | |
| transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| will-change: opacity, transform; | |
| } | |
| .slide-in-right.visible { | |
| opacity: 1; | |
| transform: translateX(0); | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .bounce-in β Scale bounce-in animation on mount | |
| ---------------------------------------------------------- | |
| Element starts at scale(0.8) with opacity 0, then bounces | |
| to full size with a spring overshoot. | |
| Usage: | |
| <div class="bounce-in">Bounce in content</div> | |
| JS companion: | |
| Add .active or .visible to trigger the animation. | |
| ---------------------------------------------------------- */ | |
| .bounce-in { | |
| opacity: 0; | |
| transform: scale(0.8); | |
| transition: | |
| opacity 0.5s cubic-bezier(0.34, 1.56, 0.64, 1), | |
| transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| will-change: opacity, transform; | |
| } | |
| .bounce-in.visible, | |
| .bounce-in.active { | |
| opacity: 1; | |
| transform: scale(1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .stagger-children > * β Staggered child animation delays | |
| ---------------------------------------------------------- | |
| Apply to a container; each direct child receives an incremental | |
| transition-delay based on its index (up to 8 children). | |
| Usage: | |
| <div class="stagger-children"> | |
| <div>Item 1</div> <!-- 0ms delay --> | |
| <div>Item 2</div> <!-- 80ms delay --> | |
| <div>Item 3</div> <!-- 160ms delay --> | |
| </div> | |
| Note: | |
| - Children must already have a transition property set | |
| - Works best with opacity/transform transitions | |
| ---------------------------------------------------------- */ | |
| .stagger-children > *:nth-child(1) { transition-delay: 0ms; } | |
| .stagger-children > *:nth-child(2) { transition-delay: 80ms; } | |
| .stagger-children > *:nth-child(3) { transition-delay: 160ms; } | |
| .stagger-children > *:nth-child(4) { transition-delay: 240ms; } | |
| .stagger-children > *:nth-child(5) { transition-delay: 320ms; } | |
| .stagger-children > *:nth-child(6) { transition-delay: 400ms; } | |
| .stagger-children > *:nth-child(7) { transition-delay: 480ms; } | |
| .stagger-children > *:nth-child(8) { transition-delay: 560ms; } | |
| /* ---------------------------------------------------------- | |
| 8. .gradient-divider β Horizontal gradient line with variants | |
| ---------------------------------------------------------- | |
| A thin horizontal divider with a gradient fade effect. | |
| Available color variants: .indigo, .purple, .amber, | |
| .emerald, .rose, .cyan | |
| Usage: | |
| <hr class="gradient-divider" /> | |
| <hr class="gradient-divider amber" /> | |
| ---------------------------------------------------------- */ | |
| .gradient-divider { | |
| border: none; | |
| height: 1px; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(99, 102, 241, 0.4) 20%, | |
| rgba(99, 102, 241, 0.4) 80%, | |
| transparent 100% | |
| ); | |
| margin: 2rem 0; | |
| } | |
| .gradient-divider.purple { | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(139, 92, 246, 0.4) 20%, | |
| rgba(139, 92, 246, 0.4) 80%, | |
| transparent 100% | |
| ); | |
| } | |
| .gradient-divider.amber { | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(245, 158, 11, 0.4) 20%, | |
| rgba(245, 158, 11, 0.4) 80%, | |
| transparent 100% | |
| ); | |
| } | |
| .gradient-divider.emerald { | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(16, 185, 129, 0.4) 20%, | |
| rgba(16, 185, 129, 0.4) 80%, | |
| transparent 100% | |
| ); | |
| } | |
| .gradient-divider.rose { | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(244, 63, 94, 0.4) 20%, | |
| rgba(244, 63, 94, 0.4) 80%, | |
| transparent 100% | |
| ); | |
| } | |
| .gradient-divider.cyan { | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(6, 182, 212, 0.4) 20%, | |
| rgba(6, 182, 212, 0.4) 80%, | |
| transparent 100% | |
| ); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .glass-badge β Glass-effect badge with backdrop-filter | |
| ---------------------------------------------------------- | |
| A small badge with glass morphism styling and colored variants. | |
| Available color variants: .indigo, .amber, .emerald, .rose, .purple | |
| Usage: | |
| <span class="glass-badge indigo">New</span> | |
| <span class="glass-badge emerald">Active</span> | |
| ---------------------------------------------------------- */ | |
| .glass-badge { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| padding: 0.25rem 0.75rem; | |
| border-radius: 9999px; | |
| font-size: 0.7rem; | |
| font-weight: 600; | |
| letter-spacing: 0.03em; | |
| text-transform: uppercase; | |
| backdrop-filter: blur(10px); | |
| -webkit-backdrop-filter: blur(10px); | |
| border: 1px solid rgba(99, 102, 241, 0.25); | |
| background: rgba(99, 102, 241, 0.12); | |
| color: #a5b4fc; | |
| transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .glass-badge:hover { | |
| background: rgba(99, 102, 241, 0.2); | |
| border-color: rgba(99, 102, 241, 0.4); | |
| transform: translateY(-1px); | |
| } | |
| .glass-badge.amber { | |
| border-color: rgba(245, 158, 11, 0.25); | |
| background: rgba(245, 158, 11, 0.12); | |
| color: #fbbf24; | |
| } | |
| .glass-badge.amber:hover { | |
| background: rgba(245, 158, 11, 0.2); | |
| border-color: rgba(245, 158, 11, 0.4); | |
| } | |
| .glass-badge.emerald { | |
| border-color: rgba(16, 185, 129, 0.25); | |
| background: rgba(16, 185, 129, 0.12); | |
| color: #34d399; | |
| } | |
| .glass-badge.emerald:hover { | |
| background: rgba(16, 185, 129, 0.2); | |
| border-color: rgba(16, 185, 129, 0.4); | |
| } | |
| .glass-badge.rose { | |
| border-color: rgba(244, 63, 94, 0.25); | |
| background: rgba(244, 63, 94, 0.12); | |
| color: #fb7185; | |
| } | |
| .glass-badge.rose:hover { | |
| background: rgba(244, 63, 94, 0.2); | |
| border-color: rgba(244, 63, 94, 0.4); | |
| } | |
| .glass-badge.purple { | |
| border-color: rgba(139, 92, 246, 0.25); | |
| background: rgba(139, 92, 246, 0.12); | |
| color: #c4b5fd; | |
| } | |
| .glass-badge.purple:hover { | |
| background: rgba(139, 92, 246, 0.2); | |
| border-color: rgba(139, 92, 246, 0.4); | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .pulse-dot β Small pulsing dot indicator | |
| ---------------------------------------------------------- | |
| A small circle that pulses (scales + fades) continuously. | |
| Available color variants: .green, .amber, .red | |
| Usage: | |
| <span class="pulse-dot green"></span> Online | |
| <span class="pulse-dot red"></span> Offline | |
| ---------------------------------------------------------- */ | |
| .pulse-dot { | |
| position: relative; | |
| display: inline-block; | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 50%; | |
| background: #6366f1; | |
| flex-shrink: 0; | |
| } | |
| .pulse-dot::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -3px; | |
| border-radius: 50%; | |
| background: inherit; | |
| opacity: 0.4; | |
| animation: pulseDotPulse 2s ease-in-out infinite; | |
| } | |
| @keyframes pulseDotPulse { | |
| 0%, 100% { transform: scale(1); opacity: 0.4; } | |
| 50% { transform: scale(1.8); opacity: 0; } | |
| } | |
| .pulse-dot.green { | |
| background: #10b981; | |
| } | |
| .pulse-dot.amber { | |
| background: #f59e0b; | |
| } | |
| .pulse-dot.red { | |
| background: #ef4444; | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .text-shadow-glow β Text with subtle glow shadow | |
| ---------------------------------------------------------- | |
| Applies a subtle colored text-shadow glow to text elements. | |
| Available color variants: .indigo, .purple, .amber, .emerald | |
| Usage: | |
| <h3 class="text-shadow-glow indigo">Glowing heading</h3> | |
| ---------------------------------------------------------- */ | |
| .text-shadow-glow { | |
| text-shadow: 0 0 12px rgba(99, 102, 241, 0.3), 0 0 30px rgba(99, 102, 241, 0.1); | |
| } | |
| .text-shadow-glow.indigo { | |
| text-shadow: | |
| 0 0 8px rgba(99, 102, 241, 0.5), | |
| 0 0 20px rgba(99, 102, 241, 0.2), | |
| 0 0 40px rgba(99, 102, 241, 0.1); | |
| } | |
| .text-shadow-glow.purple { | |
| text-shadow: | |
| 0 0 8px rgba(139, 92, 246, 0.5), | |
| 0 0 20px rgba(139, 92, 246, 0.2), | |
| 0 0 40px rgba(139, 92, 246, 0.1); | |
| } | |
| .text-shadow-glow.amber { | |
| text-shadow: | |
| 0 0 8px rgba(245, 158, 11, 0.5), | |
| 0 0 20px rgba(245, 158, 11, 0.2), | |
| 0 0 40px rgba(245, 158, 11, 0.1); | |
| } | |
| .text-shadow-glow.emerald { | |
| text-shadow: | |
| 0 0 8px rgba(16, 185, 129, 0.5), | |
| 0 0 20px rgba(16, 185, 129, 0.2), | |
| 0 0 40px rgba(16, 185, 129, 0.1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .card-gradient-border β Card with animated gradient border | |
| ---------------------------------------------------------- | |
| Uses a ::before pseudo-element to render an animated gradient | |
| border around the card. The border rotates/shifts continuously. | |
| Usage: | |
| <div class="card-gradient-border glass-card p-6">Content</div> | |
| Note: | |
| - Card must have position: relative (handled here) | |
| - Padding is increased by 2px to accommodate the border | |
| ---------------------------------------------------------- */ | |
| .card-gradient-border { | |
| position: relative; | |
| z-index: 0; | |
| } | |
| .card-gradient-border::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| border-radius: inherit; | |
| padding: 2px; | |
| background: linear-gradient( | |
| 135deg, | |
| #6366f1, #8b5cf6, #ec4899, #f59e0b, #10b981, #6366f1 | |
| ); | |
| background-size: 400% 400%; | |
| animation: cardGradientBorderShift 6s linear infinite; | |
| -webkit-mask: | |
| linear-gradient(#fff 0 0) content-box, | |
| linear-gradient(#fff 0 0); | |
| -webkit-mask-composite: xor; | |
| mask: | |
| linear-gradient(#fff 0 0) content-box, | |
| linear-gradient(#fff 0 0); | |
| mask-composite: exclude; | |
| pointer-events: none; | |
| z-index: -1; | |
| } | |
| @keyframes cardGradientBorderShift { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 13. .scroll-progress β Top scroll progress bar indicator | |
| ---------------------------------------------------------- | |
| A thin fixed bar at the very top of the viewport that fills | |
| with a gradient as the user scrolls down the page. | |
| Usage: | |
| <div class="scroll-progress" id="scrollProgress" /> | |
| JS companion: | |
| window.addEventListener('scroll', () => { | |
| const pct = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100; | |
| document.getElementById('scrollProgress').style.width = pct + '%'; | |
| }); | |
| ---------------------------------------------------------- */ | |
| .scroll-progress { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| height: 3px; | |
| width: 0%; | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6, #ec4899, #f59e0b); | |
| background-size: 300% 100%; | |
| animation: scrollProgressGradient 4s linear infinite; | |
| z-index: 9999; | |
| pointer-events: none; | |
| border-radius: 0 2px 2px 0; | |
| transition: width 0.1s linear; | |
| box-shadow: 0 0 8px rgba(99, 102, 241, 0.4); | |
| } | |
| @keyframes scrollProgressGradient { | |
| 0% { background-position: 0% 0; } | |
| 100% { background-position: 300% 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 14. .hover-underline β Text with animated underline on hover | |
| ---------------------------------------------------------- | |
| Adds an animated underline that sweeps from left to right | |
| on hover using a ::after pseudo-element. | |
| Usage: | |
| <a href="#" class="hover-underline">Link text</a> | |
| Note: | |
| - Element must be display: inline-block or inline | |
| - Underline color defaults to indigo | |
| ---------------------------------------------------------- */ | |
| .hover-underline { | |
| position: relative; | |
| display: inline-block; | |
| text-decoration: none; | |
| } | |
| .hover-underline::after { | |
| content: ''; | |
| position: absolute; | |
| bottom: -2px; | |
| left: 0; | |
| width: 100%; | |
| height: 2px; | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6); | |
| border-radius: 1px; | |
| transform: scaleX(0); | |
| transform-origin: left; | |
| transition: transform 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .hover-underline:hover::after { | |
| transform: scaleX(1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 15. .icon-float β Icon that gently floats up/down | |
| ---------------------------------------------------------- | |
| A gentle continuous floating animation for decorative icons. | |
| Different from .animate-float: uses a softer, more organic | |
| timing function. | |
| Usage: | |
| <Brain className="w-8 h-8 icon-float" /> | |
| ---------------------------------------------------------- */ | |
| .icon-float { | |
| animation: iconFloat 4s ease-in-out infinite; | |
| will-change: transform; | |
| } | |
| @keyframes iconFloat { | |
| 0%, 100% { transform: translateY(0px); } | |
| 25% { transform: translateY(-6px); } | |
| 50% { transform: translateY(-2px); } | |
| 75% { transform: translateY(-8px); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 16. .dot-pattern-bg β Dotted pattern background for sections | |
| ---------------------------------------------------------- | |
| Adds a subtle repeating dot pattern to section backgrounds. | |
| Ideal for adding texture to large content areas. | |
| Usage: | |
| <section className="dot-pattern-bg relative"> | |
| <div className="relative z-10">Content here</div> | |
| </section> | |
| Note: | |
| - Content should have position: relative; z-index: 1 | |
| - Pattern is semi-transparent and non-intrusive | |
| ---------------------------------------------------------- */ | |
| .dot-pattern-bg { | |
| position: relative; | |
| } | |
| .dot-pattern-bg::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background-image: | |
| radial-gradient(circle at 1px 1px, rgba(99, 102, 241, 0.08) 1px, transparent 0); | |
| background-size: 32px 32px; | |
| pointer-events: none; | |
| z-index: 0; | |
| mask-image: radial-gradient(ellipse 70% 60% at 50% 50%, black 30%, transparent 100%); | |
| -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 50%, black 30%, transparent 100%); | |
| } | |
| /* ============================================================ | |
| IA Academy β UI Component & Enhancement Classes (Task 6-b) | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .glass-panel β Elevated glass panel with strong blur | |
| ---------------------------------------------------------- | |
| A heavier glassmorphism panel with stronger backdrop blur | |
| and inner shadow depth. Good for sidebar panels, stat bars, | |
| and elevated container sections. | |
| Usage: | |
| <aside class="glass-panel rounded-xl p-4">Sidebar content</aside> | |
| ---------------------------------------------------------- */ | |
| .glass-panel { | |
| background: rgba(12, 12, 30, 0.75); | |
| backdrop-filter: blur(24px) saturate(1.4); | |
| -webkit-backdrop-filter: blur(24px) saturate(1.4); | |
| border: 1px solid rgba(99, 102, 241, 0.18); | |
| border-radius: 16px; | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.06), | |
| inset 0 0 20px rgba(99, 102, 241, 0.04), | |
| 0 4px 24px rgba(0, 0, 0, 0.35), | |
| 0 0 0 1px rgba(99, 102, 241, 0.06); | |
| transition: | |
| border-color 0.4s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: box-shadow, border-color; | |
| } | |
| .glass-panel:hover { | |
| border-color: rgba(99, 102, 241, 0.3); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.08), | |
| inset 0 0 30px rgba(99, 102, 241, 0.06), | |
| 0 8px 32px rgba(0, 0, 0, 0.4), | |
| 0 0 0 1px rgba(99, 102, 241, 0.12), | |
| 0 0 20px rgba(99, 102, 241, 0.05); | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .stat-bar β Thin horizontal stats display bar | |
| ---------------------------------------------------------- | |
| Thin glass bar for top-of-page stats with small text and | |
| a subtle gradient bottom border accent. | |
| Usage: | |
| <div class="stat-bar"> | |
| <span>8 Algorithmes</span> | |
| <span>4 TPs Complets</span> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .stat-bar { | |
| display: flex; | |
| align-items: center; | |
| gap: 1.5rem; | |
| padding: 0.5rem 1.25rem; | |
| background: rgba(15, 15, 35, 0.5); | |
| backdrop-filter: blur(12px); | |
| -webkit-backdrop-filter: blur(12px); | |
| border: 1px solid rgba(99, 102, 241, 0.1); | |
| border-radius: 8px; | |
| font-size: 0.75rem; | |
| color: var(--muted-foreground, #94a3b8); | |
| border-bottom: 2px solid transparent; | |
| border-image: linear-gradient(90deg, #6366f1, #8b5cf6, #ec4899) 1; | |
| } | |
| .stat-bar span { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .timer-ring β Container for SVG circular progress ring | |
| ---------------------------------------------------------- | |
| Centered flex container for SVG-based circular timer. | |
| Usage: | |
| <div class="timer-ring"> | |
| <svg width="80" height="80">...</svg> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .timer-ring { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| position: relative; | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .timer-ring svg β SVG progress ring styling | |
| ---------------------------------------------------------- | |
| Rotates the ring -90deg so progress starts from top, | |
| and adds smooth transition for stroke-dashoffset animation. | |
| Usage: | |
| Applied automatically inside .timer-ring | |
| ---------------------------------------------------------- */ | |
| .timer-ring svg { | |
| transform: rotate(-90deg); | |
| } | |
| .timer-ring svg circle { | |
| transition: stroke-dashoffset 0.6s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .btn-icon-float β Floating action button (circular) | |
| ---------------------------------------------------------- | |
| Circular floating button with glass bg, shadow, and | |
| hover scale. For floating buttons like back-to-top. | |
| Usage: | |
| <button class="btn-icon-float" aria-label="Action"> | |
| <Icon className="w-5 h-5" /> | |
| </button> | |
| ---------------------------------------------------------- */ | |
| .btn-icon-float { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 2.75rem; | |
| height: 2.75rem; | |
| border-radius: 9999px; | |
| border: 1px solid rgba(255, 255, 255, 0.12); | |
| background: rgba(99, 102, 241, 0.2); | |
| backdrop-filter: blur(12px); | |
| -webkit-backdrop-filter: blur(12px); | |
| color: #ffffff; | |
| cursor: pointer; | |
| box-shadow: | |
| 0 4px 16px rgba(0, 0, 0, 0.3), | |
| 0 0 0 1px rgba(99, 102, 241, 0.15), | |
| 0 0 20px rgba(99, 102, 241, 0.08); | |
| transition: | |
| transform 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| background 0.3s ease; | |
| will-change: transform, box-shadow; | |
| } | |
| .btn-icon-float:hover { | |
| transform: scale(1.1); | |
| background: rgba(99, 102, 241, 0.35); | |
| box-shadow: | |
| 0 8px 24px rgba(0, 0, 0, 0.4), | |
| 0 0 0 1px rgba(99, 102, 241, 0.25), | |
| 0 0 30px rgba(99, 102, 241, 0.15); | |
| } | |
| .btn-icon-float:active { | |
| transform: scale(0.95); | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .shortcut-key β Keyboard shortcut display badge | |
| ---------------------------------------------------------- | |
| Styled <kbd> replacement with monospace font, border, and | |
| glass bg. Three size variants available. | |
| Usage: | |
| <kbd class="shortcut-key">Ctrl</kbd> | |
| <kbd class="shortcut-key sm">Esc</kbd> | |
| <kbd class="shortcut-key lg">Cmd+K</kbd> | |
| ---------------------------------------------------------- */ | |
| .shortcut-key { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-family: var(--font-mono, 'JetBrains Mono', monospace); | |
| font-size: 0.6875rem; | |
| font-weight: 500; | |
| line-height: 1; | |
| padding: 0.2rem 0.45rem; | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| border-radius: 5px; | |
| background: rgba(21, 21, 48, 0.7); | |
| color: #a5b4fc; | |
| box-shadow: | |
| 0 1px 2px rgba(0, 0, 0, 0.3), | |
| inset 0 1px 0 rgba(255, 255, 255, 0.04); | |
| white-space: nowrap; | |
| user-select: none; | |
| } | |
| .shortcut-key.sm { | |
| font-size: 0.625rem; | |
| padding: 0.125rem 0.35rem; | |
| border-radius: 4px; | |
| } | |
| .shortcut-key.lg { | |
| font-size: 0.8125rem; | |
| padding: 0.3rem 0.65rem; | |
| border-radius: 6px; | |
| border-color: rgba(99, 102, 241, 0.3); | |
| box-shadow: | |
| 0 2px 4px rgba(0, 0, 0, 0.3), | |
| inset 0 1px 0 rgba(255, 255, 255, 0.06), | |
| 0 0 8px rgba(99, 102, 241, 0.06); | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .resource-card β Resource link card with hover glow | |
| ---------------------------------------------------------- | |
| Resource link card with gradient top border and icon | |
| float animation on hover. | |
| Usage: | |
| <a href="#" class="resource-card"> | |
| <Icon className="w-5 h-5" /> | |
| <span>Resource Name</span> | |
| </a> | |
| ---------------------------------------------------------- */ | |
| .resource-card { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.75rem; | |
| padding: 1rem 1.25rem; | |
| background: rgba(15, 15, 35, 0.5); | |
| border: 1px solid rgba(99, 102, 241, 0.12); | |
| border-top: 3px solid transparent; | |
| border-image: linear-gradient(90deg, #6366f1, #8b5cf6) 1; | |
| border-radius: 12px; | |
| color: #f8fafc; | |
| text-decoration: none; | |
| transition: | |
| transform 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.3s ease, | |
| background 0.3s ease; | |
| will-change: transform, box-shadow; | |
| } | |
| .resource-card:hover { | |
| transform: translateY(-2px); | |
| background: rgba(20, 20, 50, 0.7); | |
| box-shadow: | |
| 0 8px 24px rgba(0, 0, 0, 0.3), | |
| 0 0 16px rgba(99, 102, 241, 0.08); | |
| } | |
| .resource-card:hover svg, | |
| .resource-card:hover .resource-icon { | |
| transform: translateY(-2px); | |
| transition: transform 0.3s ease; | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .category-tab β Active/inactive category filter tab | |
| ---------------------------------------------------------- | |
| Glass-background tab with .active and .inactive variants. | |
| Active tab gets gradient bg + glow; inactive is transparent. | |
| Usage: | |
| <button class="category-tab active">All</button> | |
| <button class="category-tab inactive">Category</button> | |
| ---------------------------------------------------------- */ | |
| .category-tab { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| padding: 0.375rem 0.875rem; | |
| border-radius: 8px; | |
| font-size: 0.8125rem; | |
| font-weight: 500; | |
| cursor: pointer; | |
| border: 1px solid transparent; | |
| transition: | |
| all 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| white-space: nowrap; | |
| } | |
| .category-tab.active { | |
| background: linear-gradient(135deg, rgba(99, 102, 241, 0.2), rgba(139, 92, 246, 0.15)); | |
| border-color: rgba(99, 102, 241, 0.3); | |
| color: #c7d2fe; | |
| box-shadow: | |
| 0 0 12px rgba(99, 102, 241, 0.1), | |
| inset 0 1px 0 rgba(255, 255, 255, 0.05); | |
| } | |
| .category-tab.inactive { | |
| background: transparent; | |
| border-color: rgba(99, 102, 241, 0.1); | |
| color: var(--muted-foreground, #94a3b8); | |
| } | |
| .category-tab.inactive:hover { | |
| background: rgba(99, 102, 241, 0.08); | |
| border-color: rgba(99, 102, 241, 0.2); | |
| color: #e2e8f0; | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .progress-ring-bg β Background ring for circular progress | |
| ---------------------------------------------------------- | |
| Thin stroke ring with muted color for SVG circular progress. | |
| Usage: | |
| <circle class="progress-ring-bg" cx="40" cy="40" r="34" /> | |
| ---------------------------------------------------------- */ | |
| .progress-ring-bg { | |
| fill: none; | |
| stroke: rgba(99, 102, 241, 0.12); | |
| stroke-width: 4; | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .progress-ring-fill β Animated fill ring | |
| ---------------------------------------------------------- | |
| Animated SVG circle fill for circular progress indicators. | |
| Uses stroke-dasharray/dashoffset for percentage animation. | |
| 4 color variants: .indigo, .emerald, .amber, .rose | |
| Usage: | |
| <circle class="progress-ring-fill indigo" cx="40" cy="40" r="34" | |
| style={{ strokeDasharray: 213.6, strokeDashoffset: 53.4 }} /> | |
| ---------------------------------------------------------- */ | |
| .progress-ring-fill { | |
| fill: none; | |
| stroke-width: 4; | |
| stroke-linecap: round; | |
| transition: stroke-dashoffset 0.8s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .progress-ring-fill.indigo { | |
| stroke: #6366f1; | |
| filter: drop-shadow(0 0 4px rgba(99, 102, 241, 0.4)); | |
| } | |
| .progress-ring-fill.emerald { | |
| stroke: #10b981; | |
| filter: drop-shadow(0 0 4px rgba(16, 185, 129, 0.4)); | |
| } | |
| .progress-ring-fill.amber { | |
| stroke: #f59e0b; | |
| filter: drop-shadow(0 0 4px rgba(245, 158, 11, 0.4)); | |
| } | |
| .progress-ring-fill.rose { | |
| stroke: #f43f5e; | |
| filter: drop-shadow(0 0 4px rgba(244, 63, 94, 0.4)); | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .text-balance β Improved heading typography | |
| ---------------------------------------------------------- | |
| Simple text-wrap: balance for better multi-line headings. | |
| Usage: | |
| <h2 className="text-balance">Long heading text that wraps</h2> | |
| ---------------------------------------------------------- */ | |
| .text-balance { | |
| text-wrap: balance; | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .glass-scrollbar-thin β Thin custom scrollbar | |
| ---------------------------------------------------------- | |
| Ultra-thin (4px) scrollbar with glass appearance for | |
| sidebar panels and scroll areas. | |
| Usage: | |
| <div class="glass-scrollbar-thin overflow-y-auto" style="max-height: 70vh"> | |
| ...content... | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .glass-scrollbar-thin { | |
| scrollbar-width: thin; | |
| scrollbar-color: rgba(99, 102, 241, 0.25) transparent; | |
| } | |
| .glass-scrollbar-thin::-webkit-scrollbar { | |
| width: 4px; | |
| } | |
| .glass-scrollbar-thin::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| .glass-scrollbar-thin::-webkit-scrollbar-thumb { | |
| background: rgba(99, 102, 241, 0.2); | |
| border-radius: 10px; | |
| border: none; | |
| } | |
| .glass-scrollbar-thin::-webkit-scrollbar-thumb:hover { | |
| background: rgba(99, 102, 241, 0.35); | |
| box-shadow: 0 0 6px rgba(99, 102, 241, 0.2); | |
| } | |
| /* ---------------------------------------------------------- | |
| 13. .fade-mask-bottom β Gradient fade at bottom | |
| ---------------------------------------------------------- | |
| Gradient mask that fades content to transparent at the | |
| bottom edge. For content areas that extend beyond visible. | |
| Usage: | |
| <div class="fade-mask-bottom overflow-hidden" style="max-height: 200px"> | |
| ...long content... | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .fade-mask-bottom { | |
| -webkit-mask-image: linear-gradient(to bottom, black 50%, transparent 100%); | |
| mask-image: linear-gradient(to bottom, black 50%, transparent 100%); | |
| } | |
| /* ---------------------------------------------------------- | |
| 14. .badge-dot β Badge with colored dot indicator | |
| ---------------------------------------------------------- | |
| Badge with a small colored dot via ::before pseudo-element. | |
| 4 color variants: .green, .amber, .red, .blue | |
| Usage: | |
| <span class="badge-dot green">Active</span> | |
| <span class="badge-dot red">Offline</span> | |
| ---------------------------------------------------------- */ | |
| .badge-dot { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| padding: 0.25rem 0.625rem; | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| border-radius: 9999px; | |
| background: rgba(21, 21, 48, 0.6); | |
| color: #e2e8f0; | |
| } | |
| .badge-dot::before { | |
| content: ''; | |
| width: 6px; | |
| height: 6px; | |
| border-radius: 50%; | |
| flex-shrink: 0; | |
| } | |
| .badge-dot.green::before { | |
| background: #10b981; | |
| box-shadow: 0 0 6px rgba(16, 185, 129, 0.5); | |
| } | |
| .badge-dot.amber::before { | |
| background: #f59e0b; | |
| box-shadow: 0 0 6px rgba(245, 158, 11, 0.5); | |
| } | |
| .badge-dot.red::before { | |
| background: #ef4444; | |
| box-shadow: 0 0 6px rgba(239, 68, 68, 0.5); | |
| } | |
| .badge-dot.blue::before { | |
| background: #6366f1; | |
| box-shadow: 0 0 6px rgba(99, 102, 241, 0.5); | |
| } | |
| /* ---------------------------------------------------------- | |
| 15. .hover-glow-sm β Subtle hover glow effect | |
| ---------------------------------------------------------- | |
| Smaller/softer hover glow compared to .glow. For subtle | |
| interactive elements like stat cards and small buttons. | |
| Usage: | |
| <div className="glass-card hover-glow-sm">Subtle hover</div> | |
| ---------------------------------------------------------- */ | |
| .hover-glow-sm { | |
| transition: | |
| box-shadow 0.4s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .hover-glow-sm:hover { | |
| box-shadow: | |
| 0 0 10px rgba(99, 102, 241, 0.1), | |
| 0 0 25px rgba(99, 102, 241, 0.04); | |
| border-color: rgba(99, 102, 241, 0.25); | |
| } | |
| /* ---------------------------------------------------------- | |
| 16. .glass-divider-v β Vertical glass divider | |
| ---------------------------------------------------------- | |
| Vertical divider line with gradient for separating sidebar | |
| content into sections. | |
| Usage: | |
| <div className="glass-divider-v h-8" /> | |
| ---------------------------------------------------------- */ | |
| .glass-divider-v { | |
| width: 1px; | |
| background: linear-gradient( | |
| 180deg, | |
| transparent 0%, | |
| rgba(99, 102, 241, 0.2) 20%, | |
| rgba(139, 92, 246, 0.3) 50%, | |
| rgba(99, 102, 241, 0.2) 80%, | |
| transparent 100% | |
| ); | |
| align-self: stretch; | |
| flex-shrink: 0; | |
| } | |
| /* ---------------------------------------------------------- | |
| 17. .text-gradient-animate β Animated gradient text | |
| ---------------------------------------------------------- | |
| Text with a slowly shifting gradient color animation. | |
| Uses background-size animation for continuous color sweep. | |
| Usage: | |
| <h2 className="text-gradient-animate">Animated Text</h2> | |
| ---------------------------------------------------------- */ | |
| .text-gradient-animate { | |
| background: linear-gradient( | |
| 90deg, | |
| #6366f1, #8b5cf6, #ec4899, #f59e0b, #10b981, #06b6d4, #6366f1 | |
| ); | |
| background-size: 300% 100%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| animation: gradientTextSweep 6s ease-in-out infinite; | |
| } | |
| @keyframes gradientTextSweep { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| /* ============================================================ | |
| IA Academy β Styling Enhancements (Task 7-b) | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .light-theme β Light mode override selector | |
| ---------------------------------------------------------- | |
| Applies light theme overrides on all CSS variables and child | |
| components when the .light-theme class is added to a parent | |
| (typically the <body> or <main> wrapper). | |
| Usage: | |
| <div class="light-theme"> | |
| <Card>Light mode card</Card> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .light-theme { | |
| --background: #f8fafc; | |
| --foreground: #0f172a; | |
| --card: #ffffff; | |
| --card-foreground: #0f172a; | |
| --popover: #ffffff; | |
| --popover-foreground: #0f172a; | |
| --primary: #6366f1; | |
| --primary-foreground: #ffffff; | |
| --secondary: #f1f5f9; | |
| --secondary-foreground: #0f172a; | |
| --muted: #f1f5f9; | |
| --muted-foreground: #64748b; | |
| --accent: #f1f5f9; | |
| --accent-foreground: #0f172a; | |
| --destructive: #ef4444; | |
| --border: #e2e8f0; | |
| --input: #e2e8f0; | |
| --ring: #6366f1; | |
| } | |
| .light-theme .glass-card { | |
| background: rgba(255, 255, 255, 0.7); | |
| border-color: rgba(255, 255, 255, 0.2); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.8), | |
| 0 8px 32px rgba(0, 0, 0, 0.08); | |
| } | |
| .light-theme .glass-card:hover { | |
| background: rgba(255, 255, 255, 0.85); | |
| border-color: rgba(99, 102, 241, 0.2); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.9), | |
| 0 12px 40px rgba(0, 0, 0, 0.12); | |
| } | |
| .light-theme .particle-bg { | |
| background: | |
| radial-gradient(ellipse at 15% 25%, rgba(99, 102, 241, 0.06) 0%, transparent 50%), | |
| radial-gradient(ellipse at 85% 15%, rgba(168, 85, 247, 0.04) 0%, transparent 45%), | |
| radial-gradient(ellipse at 50% 80%, rgba(236, 72, 153, 0.03) 0%, transparent 50%), | |
| #f8fafc; | |
| } | |
| .light-theme .gradient-text { | |
| background: linear-gradient(135deg, #4f46e5, #7c3aed, #db2777, #4f46e5); | |
| background-size: 300% 300%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| filter: drop-shadow(0 0 8px rgba(79, 70, 229, 0.2)); | |
| } | |
| .light-theme .gradient-text::after { | |
| background: linear-gradient(135deg, #4f46e5, #7c3aed, #db2777, #4f46e5); | |
| background-size: 300% 300%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| filter: blur(12px); | |
| opacity: 0.3; | |
| } | |
| /* βββ html.light alias for JS-driven theme toggle ββββββββ */ | |
| html.light, | |
| html.light body, | |
| html.light * { | |
| transition: background-color 300ms ease, color 300ms ease, border-color 300ms ease, box-shadow 300ms ease; | |
| } | |
| html.light { | |
| --background: #faf8f5; | |
| --foreground: #1c1917; | |
| --card: #ffffff; | |
| --card-foreground: #1c1917; | |
| --popover: #ffffff; | |
| --popover-foreground: #1c1917; | |
| --primary: #7c3aed; | |
| --primary-foreground: #ffffff; | |
| --secondary: #f5f0eb; | |
| --secondary-foreground: #1c1917; | |
| --muted: #f5f0eb; | |
| --muted-foreground: #78716c; | |
| --accent: #f5f0eb; | |
| --accent-foreground: #1c1917; | |
| --destructive: #ef4444; | |
| --border: #e7e0d8; | |
| --input: #e7e0d8; | |
| --ring: #7c3aed; | |
| } | |
| html.light body { | |
| background: linear-gradient(135deg, #faf8f5 0%, #f5f0eb 50%, #faf8f5 100%); | |
| } | |
| html.light .glass-card { | |
| background: rgba(255, 255, 255, 0.75); | |
| border-color: rgba(231, 224, 216, 0.6); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.9), | |
| 0 4px 24px rgba(0, 0, 0, 0.06); | |
| } | |
| html.light .glass-card:hover { | |
| background: rgba(255, 255, 255, 0.9); | |
| border-color: rgba(124, 58, 237, 0.15); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 1), | |
| 0 8px 32px rgba(0, 0, 0, 0.08); | |
| } | |
| html.light .particle-bg { | |
| background: | |
| radial-gradient(ellipse at 15% 25%, rgba(124, 58, 237, 0.04) 0%, transparent 50%), | |
| radial-gradient(ellipse at 85% 15%, rgba(217, 119, 6, 0.03) 0%, transparent 45%), | |
| radial-gradient(ellipse at 50% 80%, rgba(16, 185, 129, 0.02) 0%, transparent 50%), | |
| #faf8f5; | |
| } | |
| html.light .gradient-text { | |
| background: linear-gradient(135deg, #7c3aed, #d97706, #059669, #7c3aed); | |
| background-size: 300% 300%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| filter: drop-shadow(0 0 6px rgba(124, 58, 237, 0.15)); | |
| } | |
| html.light .gradient-text::after { | |
| background: linear-gradient(135deg, #7c3aed, #d97706, #059669, #7c3aed); | |
| background-size: 300% 300%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| filter: blur(12px); | |
| opacity: 0.2; | |
| } | |
| html.light .neon-text.emerald { | |
| text-shadow: none; | |
| } | |
| html.light .streak-badge { | |
| background: rgba(217, 119, 6, 0.1); | |
| color: #d97706; | |
| border: 1px solid rgba(217, 119, 6, 0.2); | |
| } | |
| /* Warm accent stats bar gradient in light mode */ | |
| html.light .stats-bar-gradient { | |
| background: linear-gradient(90deg, rgba(124, 58, 237, 0.06) 0%, rgba(217, 119, 6, 0.08) 50%, rgba(16, 185, 129, 0.06) 100%); | |
| } | |
| /* Light mode footer */ | |
| html.light footer { | |
| background: rgba(255, 255, 255, 0.6) ; | |
| } | |
| /* Light mode study timer */ | |
| html.light .study-timer-widget { | |
| background: rgba(255, 255, 255, 0.85); | |
| border-color: rgba(231, 224, 216, 0.6); | |
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.08); | |
| } | |
| /* βββ Theme transition base βββββββββββββββββββββββββββββββ */ | |
| html.theme-transitioning, | |
| html.theme-transitioning *, | |
| html.theme-transitioning *::before, | |
| html.theme-transitioning *::after { | |
| transition: background-color 300ms ease, color 300ms ease, border-color 300ms ease, box-shadow 300ms ease, fill 300ms ease, stroke 300ms ease ; | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .confetti-burst β Confetti particle animation | |
| ---------------------------------------------------------- | |
| Keyframe animation that simulates confetti particles bursting | |
| outward with scale, rotation, and fade effects. Apply to small | |
| decorative elements or pseudo-elements. | |
| Usage: | |
| <div class="confetti-burst">(confetti)</div> | |
| ---------------------------------------------------------- */ | |
| @keyframes confettiBurst { | |
| 0% { | |
| transform: scale(0) rotate(0deg) translateY(0); | |
| opacity: 1; | |
| } | |
| 50% { | |
| transform: scale(1.2) rotate(180deg) translateY(-20px); | |
| opacity: 0.8; | |
| } | |
| 100% { | |
| transform: scale(0.5) rotate(360deg) translateY(40px); | |
| opacity: 0; | |
| } | |
| } | |
| @keyframes confettiBurst2 { | |
| 0% { | |
| transform: scale(0) rotate(45deg) translateX(0); | |
| opacity: 1; | |
| } | |
| 60% { | |
| transform: scale(1.1) rotate(200deg) translateX(30px); | |
| opacity: 0.7; | |
| } | |
| 100% { | |
| transform: scale(0.3) rotate(400deg) translateX(-15px); | |
| opacity: 0; | |
| } | |
| } | |
| @keyframes confettiBurst3 { | |
| 0% { | |
| transform: scale(0) rotate(-30deg) translateY(0) translateX(0); | |
| opacity: 1; | |
| } | |
| 40% { | |
| transform: scale(1.3) rotate(-150deg) translateY(-30px) translateX(20px); | |
| opacity: 0.9; | |
| } | |
| 100% { | |
| transform: scale(0.2) rotate(-360deg) translateY(20px) translateX(-25px); | |
| opacity: 0; | |
| } | |
| } | |
| .confetti-burst { | |
| animation: confettiBurst 1.2s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards; | |
| pointer-events: none; | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .onboarding-card β Centered onboarding overlay card | |
| ---------------------------------------------------------- | |
| A large, centered card for onboarding overlays. Uses glass | |
| background, generous rounding, max-width constraint, deep | |
| shadow, and a fade-scale entrance animation. | |
| Usage: | |
| <div class="onboarding-card"> | |
| <h2>Welcome!</h2> | |
| <p>Get started with...</p> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| @keyframes onboardingEntrance { | |
| 0% { | |
| opacity: 0; | |
| transform: scale(0.9) translateY(20px); | |
| } | |
| 100% { | |
| opacity: 1; | |
| transform: scale(1) translateY(0); | |
| } | |
| } | |
| .onboarding-card { | |
| background: rgba(15, 15, 35, 0.75); | |
| backdrop-filter: blur(24px); | |
| -webkit-backdrop-filter: blur(24px); | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| border-radius: 1.5rem; | |
| max-width: 32rem; | |
| width: 90%; | |
| margin: auto; | |
| padding: 2.5rem; | |
| box-shadow: | |
| 0 25px 60px rgba(0, 0, 0, 0.5), | |
| 0 0 0 1px rgba(99, 102, 241, 0.1), | |
| 0 0 80px rgba(99, 102, 241, 0.06); | |
| animation: onboardingEntrance 0.5s cubic-bezier(0.23, 1, 0.32, 1) forwards; | |
| position: relative; | |
| z-index: 10; | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .step-dot β Step indicator dots | |
| ---------------------------------------------------------- | |
| Small circular dots for step/wizard indicators. Active state | |
| is filled with the primary color and slightly scaled up. | |
| Inactive state uses a muted border. | |
| Usage: | |
| <span class="step-dot active">1</span> | |
| <span class="step-dot inactive">2</span> | |
| ---------------------------------------------------------- */ | |
| .step-dot { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 32px; | |
| height: 32px; | |
| border-radius: 50%; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| transition: | |
| transform 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| background 0.3s ease, | |
| border-color 0.3s ease, | |
| color 0.3s ease; | |
| } | |
| .step-dot.active { | |
| background: #6366f1; | |
| border: 2px solid #818cf8; | |
| color: #ffffff; | |
| transform: scale(1.1); | |
| box-shadow: 0 0 12px rgba(99, 102, 241, 0.35); | |
| } | |
| .step-dot.inactive { | |
| background: transparent; | |
| border: 2px solid rgba(148, 163, 184, 0.3); | |
| color: #94a3b8; | |
| } | |
| .step-dot.inactive:hover { | |
| border-color: rgba(148, 163, 184, 0.6); | |
| color: #cbd5e1; | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .theme-toggle β Theme toggle button | |
| ---------------------------------------------------------- | |
| A circular button with glass background for toggling between | |
| light/dark themes. The icon rotates 180Β° on hover for a | |
| smooth transition effect. | |
| Usage: | |
| <button class="theme-toggle" aria-label="Toggle theme"> | |
| <Sun className="w-5 h-5" /> | |
| </button> | |
| ---------------------------------------------------------- */ | |
| .theme-toggle { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 50%; | |
| background: rgba(15, 15, 35, 0.6); | |
| backdrop-filter: blur(12px); | |
| -webkit-backdrop-filter: blur(12px); | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| color: #f8fafc; | |
| cursor: pointer; | |
| transition: | |
| background 0.3s ease, | |
| border-color 0.3s ease, | |
| box-shadow 0.3s ease; | |
| } | |
| .theme-toggle:hover { | |
| background: rgba(99, 102, 241, 0.15); | |
| border-color: rgba(99, 102, 241, 0.4); | |
| box-shadow: 0 0 16px rgba(99, 102, 241, 0.2); | |
| } | |
| .theme-toggle svg, | |
| .theme-toggle > * { | |
| transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .theme-toggle:hover svg, | |
| .theme-toggle:hover > * { | |
| transform: rotate(180deg); | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .card-hover-glow β Card with colored glow on hover | |
| ---------------------------------------------------------- | |
| Card that gets a colored glow shadow on hover. Four color | |
| variants: indigo, emerald, amber, rose. | |
| Usage: | |
| <div class="card-hover-glow indigo">Card</div> | |
| <div class="card-hover-glow emerald">Card</div> | |
| ---------------------------------------------------------- */ | |
| .card-hover-glow { | |
| transition: | |
| box-shadow 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| transform 0.45s cubic-bezier(0.23, 1, 0.32, 1); | |
| border-radius: 0.75rem; | |
| } | |
| .card-hover-glow:hover { | |
| transform: translateY(-2px); | |
| } | |
| .card-hover-glow.indigo:hover { | |
| box-shadow: | |
| 0 0 20px rgba(99, 102, 241, 0.2), | |
| 0 0 50px rgba(99, 102, 241, 0.1), | |
| 0 8px 24px rgba(0, 0, 0, 0.15); | |
| } | |
| .card-hover-glow.emerald:hover { | |
| box-shadow: | |
| 0 0 20px rgba(16, 185, 129, 0.2), | |
| 0 0 50px rgba(16, 185, 129, 0.1), | |
| 0 8px 24px rgba(0, 0, 0, 0.15); | |
| } | |
| .card-hover-glow.amber:hover { | |
| box-shadow: | |
| 0 0 20px rgba(245, 158, 11, 0.2), | |
| 0 0 50px rgba(245, 158, 11, 0.1), | |
| 0 8px 24px rgba(0, 0, 0, 0.15); | |
| } | |
| .card-hover-glow.rose:hover { | |
| box-shadow: | |
| 0 0 20px rgba(244, 63, 94, 0.2), | |
| 0 0 50px rgba(244, 63, 94, 0.1), | |
| 0 8px 24px rgba(0, 0, 0, 0.15); | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .text-stroke β Text with outline/stroke effect | |
| ---------------------------------------------------------- | |
| Text with a visible outline/stroke using -webkit-text-stroke. | |
| Three weight variants: thin, medium, thick. | |
| Usage: | |
| <h1 class="text-stroke thin">Outline Text</h1> | |
| <h1 class="text-stroke medium">Outline Text</h1> | |
| <h1 class="text-stroke thick">Outline Text</h1> | |
| ---------------------------------------------------------- */ | |
| .text-stroke { | |
| -webkit-text-fill-color: transparent; | |
| color: transparent; | |
| } | |
| .text-stroke.thin { | |
| -webkit-text-stroke: 1px #6366f1; | |
| paint-order: stroke fill; | |
| } | |
| .text-stroke.medium { | |
| -webkit-text-stroke: 2px #8b5cf6; | |
| paint-order: stroke fill; | |
| } | |
| .text-stroke.thick { | |
| -webkit-text-stroke: 3px #ec4899; | |
| paint-order: stroke fill; | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .scroll-indicator-dots β Horizontal scroll dots | |
| ---------------------------------------------------------- | |
| Horizontal scroll indicator with dot elements. Uses flex | |
| layout with gap and centered alignment. | |
| Usage: | |
| <div class="scroll-indicator-dots"> | |
| <span class="w-2 h-2 rounded-full bg-primary" /> | |
| <span class="w-2 h-2 rounded-full bg-muted" /> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .scroll-indicator-dots { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.5rem; | |
| padding: 0.75rem 0; | |
| } | |
| .scroll-indicator-dots > * { | |
| transition: | |
| transform 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| opacity 0.3s ease; | |
| } | |
| .scroll-indicator-dots > *.active { | |
| transform: scale(1.3); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .glass-tooltip β Glass tooltip with arrow | |
| ---------------------------------------------------------- | |
| Small tooltip with glass background, rounded corners, | |
| and a fade-in animation. Uses a ::after pseudo-element | |
| for the bottom arrow indicator. | |
| Usage: | |
| <span class="glass-tooltip">Tooltip text</span> | |
| ---------------------------------------------------------- */ | |
| @keyframes tooltipFadeIn { | |
| 0% { | |
| opacity: 0; | |
| transform: translateY(4px) scale(0.95); | |
| } | |
| 100% { | |
| opacity: 1; | |
| transform: translateY(0) scale(1); | |
| } | |
| } | |
| .glass-tooltip { | |
| display: inline-block; | |
| position: relative; | |
| background: rgba(15, 15, 35, 0.85); | |
| backdrop-filter: blur(16px); | |
| -webkit-backdrop-filter: blur(16px); | |
| border: 1px solid rgba(99, 102, 241, 0.25); | |
| border-radius: 8px; | |
| padding: 0.375rem 0.75rem; | |
| font-size: 0.75rem; | |
| color: #f8fafc; | |
| white-space: nowrap; | |
| animation: tooltipFadeIn 0.25s cubic-bezier(0.23, 1, 0.32, 1) forwards; | |
| box-shadow: | |
| 0 4px 16px rgba(0, 0, 0, 0.3), | |
| 0 0 0 1px rgba(99, 102, 241, 0.08); | |
| } | |
| .glass-tooltip::after { | |
| content: ''; | |
| position: absolute; | |
| bottom: -5px; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 10px; | |
| height: 10px; | |
| background: rgba(15, 15, 35, 0.85); | |
| border-right: 1px solid rgba(99, 102, 241, 0.25); | |
| border-bottom: 1px solid rgba(99, 102, 241, 0.25); | |
| rotate: 45deg; | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .skeleton-shimmer β Skeleton loading shimmer | |
| ---------------------------------------------------------- | |
| Skeleton loading placeholder with a shimmer sweep animation. | |
| Uses a linear-gradient that moves across the element. | |
| Usage: | |
| <div class="skeleton-shimmer h-4 w-full rounded" /> | |
| ---------------------------------------------------------- */ | |
| @keyframes skeletonShimmer { | |
| 0% { | |
| background-position: -200% 0; | |
| } | |
| 100% { | |
| background-position: 200% 0; | |
| } | |
| } | |
| .skeleton-shimmer { | |
| background: linear-gradient( | |
| 90deg, | |
| rgba(99, 102, 241, 0.05) 0%, | |
| rgba(99, 102, 241, 0.1) 25%, | |
| rgba(139, 92, 246, 0.15) 50%, | |
| rgba(99, 102, 241, 0.1) 75%, | |
| rgba(99, 102, 241, 0.05) 100% | |
| ); | |
| background-size: 200% 100%; | |
| animation: skeletonShimmer 1.5s ease-in-out infinite; | |
| border-radius: 6px; | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .gradient-border-anim β Animated gradient border | |
| ---------------------------------------------------------- | |
| Animated gradient border using CSS @property for --angle, | |
| a conic-gradient background, and hue-rotate animation to | |
| create a rotating rainbow border effect. | |
| Usage: | |
| <div class="gradient-border-anim rounded-xl p-6"> | |
| Content with animated border | |
| </div> | |
| ---------------------------------------------------------- */ | |
| @property --angle { | |
| syntax: '<angle>'; | |
| initial-value: 0deg; | |
| inherits: false; | |
| } | |
| @keyframes gradientBorderSpin { | |
| 0% { --angle: 0deg; } | |
| 100% { --angle: 360deg; } | |
| } | |
| .gradient-border-anim { | |
| position: relative; | |
| border-radius: inherit; | |
| isolation: isolate; | |
| } | |
| .gradient-border-anim::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -2px; | |
| border-radius: inherit; | |
| background: conic-gradient( | |
| from var(--angle), | |
| #6366f1, #8b5cf6, #ec4899, #f59e0b, #10b981, #06b6d4, #6366f1 | |
| ); | |
| animation: gradientBorderSpin 4s linear infinite; | |
| z-index: -2; | |
| } | |
| .gradient-border-anim::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 2px; | |
| border-radius: inherit; | |
| background: var(--card, #151530); | |
| z-index: -1; | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .icon-bounce β Icon bounce animation on interaction | |
| ---------------------------------------------------------- | |
| Bounce animation for icons on click/interaction. Uses a | |
| scaleY squash then stretch effect for a playful feel. | |
| Typically triggered via JS by adding the .active class. | |
| Usage: | |
| <span class="icon-bounce" onClick={() => el.classList.add('active')}> | |
| <Icon /> | |
| </span> | |
| ---------------------------------------------------------- */ | |
| @keyframes iconBounce { | |
| 0% { transform: scale(1, 1); } | |
| 20% { transform: scale(1, 0.85); } | |
| 40% { transform: scale(0.9, 1.1); } | |
| 60% { transform: scale(1.05, 0.95); } | |
| 80% { transform: scale(0.98, 1.02); } | |
| 100% { transform: scale(1, 1); } | |
| } | |
| .icon-bounce { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .icon-bounce.active { | |
| animation: iconBounce 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 13. .text-gradient-static β Static gradient text | |
| ---------------------------------------------------------- | |
| Non-animated gradient text using background-clip. Five | |
| color pair variants for different contexts. | |
| Usage: | |
| <h2 class="text-gradient-static indigo-purple">Text</h2> | |
| <span class="text-gradient-static emerald-cyan">Text</span> | |
| ---------------------------------------------------------- */ | |
| .text-gradient-static { | |
| display: inline-block; | |
| -webkit-background-clip: text ; | |
| background-clip: text ; | |
| -webkit-text-fill-color: transparent ; | |
| font-weight: 700; | |
| background-size: 100% 100% ; | |
| animation: none ; | |
| position: static ; | |
| filter: none ; | |
| } | |
| .text-gradient-static::after { | |
| display: none ; | |
| } | |
| .text-gradient-static.indigo-purple { | |
| background-image: linear-gradient(135deg, #6366f1, #8b5cf6); | |
| } | |
| .text-gradient-static.emerald-cyan { | |
| background-image: linear-gradient(135deg, #10b981, #06b6d4); | |
| } | |
| .text-gradient-static.amber-rose { | |
| background-image: linear-gradient(135deg, #f59e0b, #ec4899); | |
| } | |
| .text-gradient-static.blue-indigo { | |
| background-image: linear-gradient(135deg, #3b82f6, #6366f1); | |
| } | |
| .text-gradient-static.rose-pink { | |
| background-image: linear-gradient(135deg, #ef4444, #ec4899); | |
| } | |
| /* ---------------------------------------------------------- | |
| 14. .glass-chip β Small inline glass chip/pill | |
| ---------------------------------------------------------- | |
| Small inline chip/pill with glass background, rounded-full, | |
| subtle border, and a hover lift effect. | |
| Usage: | |
| <span class="glass-chip">Tag</span> | |
| <span class="glass-chip">Category</span> | |
| ---------------------------------------------------------- */ | |
| .glass-chip { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| padding: 0.25rem 0.75rem; | |
| border-radius: 9999px; | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| background: rgba(15, 15, 35, 0.6); | |
| backdrop-filter: blur(8px); | |
| -webkit-backdrop-filter: blur(8px); | |
| border: 1px solid rgba(99, 102, 241, 0.15); | |
| color: #a5b4fc; | |
| cursor: pointer; | |
| transition: | |
| transform 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.3s ease; | |
| will-change: transform; | |
| } | |
| .glass-chip:hover { | |
| transform: translateY(-2px); | |
| box-shadow: | |
| 0 4px 12px rgba(0, 0, 0, 0.2), | |
| 0 0 12px rgba(99, 102, 241, 0.1); | |
| border-color: rgba(99, 102, 241, 0.3); | |
| } | |
| .glass-chip:active { | |
| transform: translateY(0); | |
| } | |
| /* ---------------------------------------------------------- | |
| 15. .progress-bar-animated β Animated striped progress bar | |
| ---------------------------------------------------------- | |
| Animated progress bar with a striped pattern and sweep | |
| animation. Three color variants: indigo, emerald, amber. | |
| Usage: | |
| <div class="progress-bar-animated indigo" style="--progress: 65%"> | |
| <div class="progress-bar-animated__fill" /> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| @keyframes progressStripe { | |
| 0% { background-position: 1rem 0; } | |
| 100% { background-position: 0 0; } | |
| } | |
| @keyframes progressSweep { | |
| 0% { left: -40%; } | |
| 100% { left: 100%; } | |
| } | |
| .progress-bar-animated { | |
| position: relative; | |
| width: 100%; | |
| height: 8px; | |
| border-radius: 9999px; | |
| overflow: hidden; | |
| background: rgba(99, 102, 241, 0.1); | |
| } | |
| .progress-bar-animated__fill { | |
| position: relative; | |
| height: 100%; | |
| border-radius: 9999px; | |
| width: var(--progress, 0%); | |
| transition: width 0.6s cubic-bezier(0.23, 1, 0.32, 1); | |
| background-image: linear-gradient( | |
| -45deg, | |
| rgba(255, 255, 255, 0.15) 25%, | |
| transparent 25%, | |
| transparent 50%, | |
| rgba(255, 255, 255, 0.15) 50%, | |
| rgba(255, 255, 255, 0.15) 75%, | |
| transparent 75% | |
| ); | |
| background-size: 1rem 1rem; | |
| animation: progressStripe 0.75s linear infinite; | |
| } | |
| .progress-bar-animated__fill::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: -40%; | |
| width: 40%; | |
| height: 100%; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent, | |
| rgba(255, 255, 255, 0.2), | |
| transparent | |
| ); | |
| animation: progressSweep 1.5s ease-in-out infinite; | |
| } | |
| .progress-bar-animated.indigo .progress-bar-animated__fill { | |
| background-color: #6366f1; | |
| } | |
| .progress-bar-animated.emerald .progress-bar-animated__fill { | |
| background-color: #10b981; | |
| } | |
| .progress-bar-animated.amber .progress-bar-animated__fill { | |
| background-color: #f59e0b; | |
| } | |
| /* ---------------------------------------------------------- | |
| 16. .hover-scale-sm β Subtle scale on hover | |
| ---------------------------------------------------------- | |
| A subtle scale transform (1.02) on hover with a smooth | |
| 200ms transition. Ideal for cards and interactive elements | |
| where a gentle size change provides feedback. | |
| Usage: | |
| <Card className="hover-scale-sm">Card content</Card> | |
| ---------------------------------------------------------- */ | |
| .hover-scale-sm { | |
| transition: transform 0.2s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .hover-scale-sm:hover { | |
| transform: scale(1.02); | |
| } | |
| /* ============================================================ | |
| IA Academy β Gamification & Interaction Enhancement Classes | |
| ============================================================ | |
| 18 new classes for achievements, learning paths, streaks, | |
| celebrations, onboarding, and enhanced UI components. | |
| Color palette: #6366f1 (indigo), #8b5cf6 (purple), | |
| #f59e0b (amber), #10b981 (emerald), #ef4444 (red), | |
| #ec4899 (pink), #06b6d4 (cyan) | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .confetti-canvas β Full-screen fixed canvas overlay | |
| ---------------------------------------------------------- | |
| A transparent canvas overlay positioned over the entire | |
| viewport for rendering confetti particle effects. Uses | |
| z-[9999] to sit above all other content and pointer-events: | |
| none so it never blocks interaction. | |
| Usage: | |
| <canvas className="confetti-canvas" ref={canvasRef} /> | |
| Note: | |
| - The canvas element itself should be controlled by JS | |
| (e.g., canvas-confetti library or custom particle system) | |
| - Ensure the parent doesn't set overflow: hidden | |
| ---------------------------------------------------------- */ | |
| .confetti-canvas { | |
| position: fixed; | |
| inset: 0; | |
| width: 100vw; | |
| height: 100vh; | |
| z-index: 9999; | |
| pointer-events: none; | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .achievement-badge β Achievement badge card | |
| ---------------------------------------------------------- | |
| A compact badge card with glass background, rounded-full | |
| icon area, and subtle border. Default state is ready for | |
| unlock. Combine with .unlocked or .locked for states. | |
| Usage: | |
| <div className="achievement-badge unlocked"> | |
| <div className="w-12 h-12 rounded-full ...">(trophy)</div> | |
| <h4>First Quiz</h4> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .achievement-badge { | |
| position: relative; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 0.75rem; | |
| padding: 1.5rem 1.25rem; | |
| background: rgba(15, 15, 35, 0.65); | |
| backdrop-filter: blur(16px); | |
| -webkit-backdrop-filter: blur(16px); | |
| border: 1px solid rgba(99, 102, 241, 0.15); | |
| border-radius: 16px; | |
| text-align: center; | |
| transition: | |
| transform 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| filter 0.45s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow, filter; | |
| } | |
| .achievement-badge .achievement-badge__icon { | |
| width: 3.5rem; | |
| height: 3.5rem; | |
| border-radius: 9999px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 1.5rem; | |
| background: rgba(99, 102, 241, 0.1); | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| } | |
| .achievement-badge .achievement-badge__title { | |
| font-size: 0.875rem; | |
| font-weight: 600; | |
| color: var(--foreground, #f8fafc); | |
| } | |
| .achievement-badge .achievement-badge__desc { | |
| font-size: 0.75rem; | |
| color: var(--muted-foreground, #94a3b8); | |
| line-height: 1.4; | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .achievement-badge.unlocked β Full color unlocked state | |
| ---------------------------------------------------------- | |
| Glowing border, scale bump on hover, emerald/gold accents. | |
| Applied when the achievement has been earned. | |
| Usage: | |
| <div className="achievement-badge unlocked">...</div> | |
| ---------------------------------------------------------- */ | |
| .achievement-badge.unlocked { | |
| border-color: rgba(245, 158, 11, 0.3); | |
| box-shadow: | |
| 0 0 16px rgba(245, 158, 11, 0.12), | |
| 0 0 40px rgba(245, 158, 11, 0.06), | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.08); | |
| animation: achievementUnlock 0.6s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; | |
| } | |
| .achievement-badge.unlocked:hover { | |
| transform: translateY(-4px) scale(1.04); | |
| box-shadow: | |
| 0 0 24px rgba(245, 158, 11, 0.2), | |
| 0 0 60px rgba(245, 158, 11, 0.1), | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.1); | |
| } | |
| .achievement-badge.unlocked .achievement-badge__icon { | |
| background: linear-gradient(135deg, rgba(245, 158, 11, 0.2), rgba(249, 115, 22, 0.15)); | |
| border-color: rgba(245, 158, 11, 0.35); | |
| box-shadow: 0 0 12px rgba(245, 158, 11, 0.2); | |
| } | |
| @keyframes achievementUnlock { | |
| 0% { transform: scale(0.8); opacity: 0.5; } | |
| 50% { transform: scale(1.08); } | |
| 100% { transform: scale(1); opacity: 1; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .achievement-badge.locked β Grayed out locked state | |
| ---------------------------------------------------------- | |
| Desaturated, reduced opacity, and grayscale filter. | |
| Applied for achievements not yet earned. | |
| Usage: | |
| <div className="achievement-badge locked">...</div> | |
| ---------------------------------------------------------- */ | |
| .achievement-badge.locked { | |
| filter: grayscale(0.7) brightness(0.7); | |
| opacity: 0.55; | |
| border-color: rgba(255, 255, 255, 0.05); | |
| } | |
| .achievement-badge.locked:hover { | |
| filter: grayscale(0.5) brightness(0.8); | |
| opacity: 0.7; | |
| transform: translateY(-2px); | |
| } | |
| .achievement-badge.locked .achievement-badge__icon { | |
| background: rgba(255, 255, 255, 0.03); | |
| border-color: rgba(255, 255, 255, 0.08); | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .learning-path β Flex container for TP roadmap | |
| ---------------------------------------------------------- | |
| Horizontal layout on desktop (lg+) with wrapping and gap, | |
| vertical stack on mobile. Used as the parent for .path-node | |
| and .path-connector elements. | |
| Usage: | |
| <div className="learning-path"> | |
| <div className="path-node">1</div> | |
| <div className="path-connector" /> | |
| <div className="path-node">2</div> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .learning-path { | |
| display: flex; | |
| flex-direction: row; | |
| flex-wrap: wrap; | |
| align-items: center; | |
| gap: 0; | |
| width: 100%; | |
| padding: 1rem 0; | |
| } | |
| @media (max-width: 1023px) { | |
| .learning-path { | |
| flex-direction: column; | |
| align-items: flex-start; | |
| padding-left: 1.5rem; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .path-node β Individual node in the learning path | |
| ---------------------------------------------------------- | |
| A circle with a step number inside, connected to siblings | |
| by .path-connector lines. Default muted style. | |
| Usage: | |
| <div className="path-node active"> | |
| <span>1</span> | |
| <p>Introduction</p> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .path-node { | |
| position: relative; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 0.5rem; | |
| z-index: 2; | |
| flex-shrink: 0; | |
| } | |
| .path-node .path-node__circle { | |
| width: 2.5rem; | |
| height: 2.5rem; | |
| border-radius: 9999px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 0.8125rem; | |
| font-weight: 700; | |
| color: var(--muted-foreground, #94a3b8); | |
| background: rgba(15, 15, 35, 0.8); | |
| border: 2px solid rgba(99, 102, 241, 0.15); | |
| box-shadow: 0 0 0 4px rgba(10, 10, 26, 1); | |
| transition: | |
| border-color 0.35s ease, | |
| background 0.35s ease, | |
| box-shadow 0.35s ease, | |
| color 0.35s ease; | |
| } | |
| .path-node .path-node__label { | |
| font-size: 0.75rem; | |
| color: var(--muted-foreground, #94a3b8); | |
| text-align: center; | |
| max-width: 5rem; | |
| line-height: 1.3; | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .path-node.active β Highlighted active node | |
| ---------------------------------------------------------- | |
| Pulsing glow ring animation and indigo accent for the | |
| currently active learning step. | |
| Usage: | |
| <div className="path-node active"> | |
| <div className="path-node__circle">3</div> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .path-node.active .path-node__circle { | |
| border-color: #6366f1; | |
| background: rgba(99, 102, 241, 0.15); | |
| color: #a5b4fc; | |
| box-shadow: | |
| 0 0 0 4px rgba(10, 10, 26, 1), | |
| 0 0 0 6px rgba(99, 102, 241, 0.25), | |
| 0 0 16px rgba(99, 102, 241, 0.15); | |
| animation: pathNodePulse 2.5s ease-in-out infinite; | |
| } | |
| .path-node.active .path-node__label { | |
| color: var(--foreground, #f8fafc); | |
| font-weight: 500; | |
| } | |
| @keyframes pathNodePulse { | |
| 0%, 100% { | |
| box-shadow: | |
| 0 0 0 4px rgba(10, 10, 26, 1), | |
| 0 0 0 6px rgba(99, 102, 241, 0.25), | |
| 0 0 16px rgba(99, 102, 241, 0.15); | |
| } | |
| 50% { | |
| box-shadow: | |
| 0 0 0 4px rgba(10, 10, 26, 1), | |
| 0 0 0 10px rgba(99, 102, 241, 0.15), | |
| 0 0 24px rgba(99, 102, 241, 0.1); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .path-node.completed β Completed node with checkmark | |
| ---------------------------------------------------------- | |
| Emerald accent and a checkmark indicator for steps | |
| that the user has already finished. | |
| Usage: | |
| <div className="path-node completed"> | |
| <div className="path-node__circle">(check)</div> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .path-node.completed .path-node__circle { | |
| border-color: #10b981; | |
| background: rgba(16, 185, 129, 0.15); | |
| color: #34d399; | |
| box-shadow: | |
| 0 0 0 4px rgba(10, 10, 26, 1), | |
| 0 0 8px rgba(16, 185, 129, 0.15); | |
| } | |
| .path-node.completed .path-node__label { | |
| color: #6ee7b7; | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .path-connector β Dashed line connector | |
| ---------------------------------------------------------- | |
| Gradient-colored dashed line connecting path nodes. | |
| Horizontal on desktop, vertical on mobile. Animated | |
| dash movement via stroke-dashoffset. | |
| Usage: | |
| <div className="path-connector" /> | |
| β or β | |
| <svg className="path-connector"><line ... /></svg> | |
| ---------------------------------------------------------- */ | |
| .path-connector { | |
| flex: 1; | |
| min-width: 2rem; | |
| height: 2px; | |
| background: linear-gradient( | |
| 90deg, | |
| rgba(99, 102, 241, 0.3) 0%, | |
| rgba(139, 92, 246, 0.4) 50%, | |
| rgba(99, 102, 241, 0.3) 100% | |
| ); | |
| background-size: 200% 100%; | |
| border-radius: 1px; | |
| animation: pathConnectorFlow 3s linear infinite; | |
| mask-image: repeating-linear-gradient( | |
| 90deg, | |
| black 0px, | |
| black 6px, | |
| transparent 6px, | |
| transparent 12px | |
| ); | |
| -webkit-mask-image: repeating-linear-gradient( | |
| 90deg, | |
| black 0px, | |
| black 6px, | |
| transparent 6px, | |
| transparent 12px | |
| ); | |
| } | |
| @media (max-width: 1023px) { | |
| .path-connector { | |
| flex: 0; | |
| min-width: 2px; | |
| width: 2px; | |
| min-height: 2rem; | |
| height: 2rem; | |
| background: linear-gradient( | |
| 180deg, | |
| rgba(99, 102, 241, 0.3) 0%, | |
| rgba(139, 92, 246, 0.4) 50%, | |
| rgba(99, 102, 241, 0.3) 100% | |
| ); | |
| background-size: 100% 200%; | |
| mask-image: repeating-linear-gradient( | |
| 180deg, | |
| black 0px, | |
| black 6px, | |
| transparent 6px, | |
| transparent 12px | |
| ); | |
| -webkit-mask-image: repeating-linear-gradient( | |
| 180deg, | |
| black 0px, | |
| black 6px, | |
| transparent 6px, | |
| transparent 12px | |
| ); | |
| } | |
| } | |
| @keyframes pathConnectorFlow { | |
| 0% { background-position: 0% 0; } | |
| 100% { background-position: 200% 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .streak-fire β Fire/streak indicator with flicker glow | |
| ---------------------------------------------------------- | |
| Animated flickering glow effect using amber/orange gradient. | |
| For streak counters, daily activity indicators, and hot | |
| streaks. Text inside gets an amber glow. | |
| Usage: | |
| <div className="streak-fire"> | |
| <span className="text-2xl">(fire)</span> | |
| <span>7 jours</span> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .streak-fire { | |
| position: relative; | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| padding: 0.375rem 0.875rem; | |
| border-radius: 9999px; | |
| background: linear-gradient(135deg, rgba(245, 158, 11, 0.12), rgba(249, 115, 22, 0.08)); | |
| border: 1px solid rgba(245, 158, 11, 0.25); | |
| color: #fbbf24; | |
| font-weight: 600; | |
| font-size: 0.875rem; | |
| animation: streakFlicker 2s ease-in-out infinite; | |
| will-change: box-shadow; | |
| } | |
| @keyframes streakFlicker { | |
| 0%, 100% { | |
| box-shadow: | |
| 0 0 8px rgba(245, 158, 11, 0.15), | |
| 0 0 20px rgba(245, 158, 11, 0.05); | |
| } | |
| 25% { | |
| box-shadow: | |
| 0 0 12px rgba(249, 115, 22, 0.25), | |
| 0 0 30px rgba(245, 158, 11, 0.1); | |
| } | |
| 50% { | |
| box-shadow: | |
| 0 0 6px rgba(245, 158, 11, 0.12), | |
| 0 0 16px rgba(249, 115, 22, 0.04); | |
| } | |
| 75% { | |
| box-shadow: | |
| 0 0 14px rgba(249, 115, 22, 0.3), | |
| 0 0 36px rgba(245, 158, 11, 0.12); | |
| } | |
| } | |
| .streak-fire .streak-fire__icon { | |
| font-size: 1.25rem; | |
| animation: streakFireWiggle 1.5s ease-in-out infinite; | |
| } | |
| @keyframes streakFireWiggle { | |
| 0%, 100% { transform: rotate(0deg) scale(1); } | |
| 25% { transform: rotate(-4deg) scale(1.1); } | |
| 75% { transform: rotate(4deg) scale(1.05); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .toast-celebration β Enhanced celebration toast | |
| ---------------------------------------------------------- | |
| A more prominent toast variant for celebrations with a | |
| gold/amber border, sparkle animation, and slightly larger | |
| text. Wraps around the existing toast container. | |
| Usage: | |
| <div className="toast-celebration"> | |
| <span>(celebration)</span> | |
| <span>Quiz complΓ©tΓ© ! Score: 3/3</span> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .toast-celebration { | |
| position: relative; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.625rem; | |
| padding: 0.875rem 1.25rem; | |
| background: rgba(15, 15, 35, 0.85); | |
| backdrop-filter: blur(16px); | |
| -webkit-backdrop-filter: blur(16px); | |
| border: 1px solid rgba(245, 158, 11, 0.35); | |
| border-radius: 12px; | |
| box-shadow: | |
| 0 0 20px rgba(245, 158, 11, 0.1), | |
| 0 0 40px rgba(245, 158, 11, 0.05), | |
| 0 8px 24px rgba(0, 0, 0, 0.3); | |
| color: #fcd34d; | |
| font-size: 0.9375rem; | |
| font-weight: 600; | |
| animation: toastCelebrationIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; | |
| overflow: hidden; | |
| } | |
| .toast-celebration::before { | |
| content: ''; | |
| position: absolute; | |
| top: -50%; | |
| left: -75%; | |
| width: 50%; | |
| height: 200%; | |
| background: linear-gradient( | |
| 105deg, | |
| transparent 20%, | |
| rgba(245, 158, 11, 0.06) 35%, | |
| rgba(255, 255, 255, 0.08) 42%, | |
| rgba(245, 158, 11, 0.06) 50%, | |
| transparent 65% | |
| ); | |
| transform: skewX(-25deg); | |
| animation: toastSparkle 2.5s ease-in-out infinite; | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| .toast-celebration > * { | |
| position: relative; | |
| z-index: 1; | |
| } | |
| @keyframes toastCelebrationIn { | |
| 0% { transform: translateY(20px) scale(0.9); opacity: 0; } | |
| 100% { transform: translateY(0) scale(1); opacity: 1; } | |
| } | |
| @keyframes toastSparkle { | |
| 0%, 100% { left: -75%; } | |
| 50% { left: 125%; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .glass-chip β Small glass chip/tag component | |
| ---------------------------------------------------------- | |
| Pill-shaped tag with glass background, backdrop blur, | |
| subtle border, and a gentle lift on hover. Ideal for | |
| filter badges, category tags, and metadata chips. | |
| Usage: | |
| <button className="glass-chip">DΓ©butant</button> | |
| <span className="glass-chip">Classification</span> | |
| ---------------------------------------------------------- */ | |
| .glass-chip { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| padding: 0.25rem 0.75rem; | |
| border-radius: 9999px; | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| line-height: 1.5; | |
| white-space: nowrap; | |
| background: rgba(15, 15, 35, 0.5); | |
| backdrop-filter: blur(8px); | |
| -webkit-backdrop-filter: blur(8px); | |
| border: 1px solid rgba(255, 255, 255, 0.06); | |
| color: var(--muted-foreground, #94a3b8); | |
| cursor: pointer; | |
| transition: | |
| transform 0.25s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.25s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.25s ease, | |
| background 0.25s ease, | |
| color 0.25s ease; | |
| will-change: transform, box-shadow; | |
| } | |
| .glass-chip:hover { | |
| transform: translateY(-1px); | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
| border-color: rgba(99, 102, 241, 0.2); | |
| background: rgba(20, 20, 45, 0.6); | |
| color: var(--foreground, #f8fafc); | |
| } | |
| .glass-chip:active { | |
| transform: translateY(0); | |
| box-shadow: none; | |
| } | |
| /* ---------------------------------------------------------- | |
| 13. .card-glow-emerald β Emerald glow on hover | |
| ---------------------------------------------------------- | |
| Card wrapper that produces an emerald/green glow effect | |
| on hover. For success states, completed items, and positive | |
| feedback cards. | |
| Usage: | |
| <div className="glass-card card-glow-emerald"> | |
| <CheckCircle2 className="text-emerald-400" /> | |
| <p>Module complΓ©tΓ©</p> | |
| </div> | |
| Note: | |
| - Combine with .glass-card for glass background | |
| - Uses transition for smooth glow appearance | |
| ---------------------------------------------------------- */ | |
| .card-glow-emerald { | |
| transition: | |
| box-shadow 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.45s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .card-glow-emerald:hover { | |
| border-color: rgba(16, 185, 129, 0.3); | |
| box-shadow: | |
| 0 0 16px rgba(16, 185, 129, 0.12), | |
| 0 0 40px rgba(16, 185, 129, 0.06), | |
| 0 0 80px rgba(16, 185, 129, 0.03), | |
| 0 8px 24px rgba(0, 0, 0, 0.2); | |
| } | |
| /* ---------------------------------------------------------- | |
| 14. .card-glow-rose β Rose/pink glow on hover | |
| ---------------------------------------------------------- | |
| Card wrapper that produces a rose/pink glow effect on | |
| hover. For achievements, celebrations, and premium | |
| feature cards. | |
| Usage: | |
| <div className="glass-card card-glow-rose"> | |
| <Trophy className="text-pink-400" /> | |
| <p>Achievement Unlocked!</p> | |
| </div> | |
| ---------------------------------------------------------- */ | |
| .card-glow-rose { | |
| transition: | |
| box-shadow 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.45s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .card-glow-rose:hover { | |
| border-color: rgba(236, 72, 153, 0.3); | |
| box-shadow: | |
| 0 0 16px rgba(236, 72, 153, 0.12), | |
| 0 0 40px rgba(236, 72, 153, 0.06), | |
| 0 0 80px rgba(236, 72, 153, 0.03), | |
| 0 8px 24px rgba(0, 0, 0, 0.2); | |
| } | |
| /* ---------------------------------------------------------- | |
| 15. .text-glow-amber β Enhanced amber/gold glowing text | |
| ---------------------------------------------------------- | |
| Amber/gold glowing text effect with multi-layer text-shadow. | |
| For streaks, achievements, scores, and premium content. | |
| Note: This extends the existing .text-glow-amber from section 13 | |
| with additional intensity and a subtle animation. | |
| Usage: | |
| <span className="text-glow-amber">7 jours</span> | |
| <h3 className="text-glow-amber">Score Parfait !</h3> | |
| ---------------------------------------------------------- */ | |
| .text-glow-amber { | |
| text-shadow: | |
| 0 0 7px rgba(245, 158, 11, 0.6), | |
| 0 0 20px rgba(245, 158, 11, 0.3), | |
| 0 0 40px rgba(245, 158, 11, 0.15), | |
| 0 0 80px rgba(249, 115, 22, 0.08); | |
| animation: textGlowAmberPulse 3s ease-in-out infinite; | |
| } | |
| @keyframes textGlowAmberPulse { | |
| 0%, 100% { | |
| text-shadow: | |
| 0 0 7px rgba(245, 158, 11, 0.6), | |
| 0 0 20px rgba(245, 158, 11, 0.3), | |
| 0 0 40px rgba(245, 158, 11, 0.15), | |
| 0 0 80px rgba(249, 115, 22, 0.08); | |
| } | |
| 50% { | |
| text-shadow: | |
| 0 0 10px rgba(245, 158, 11, 0.8), | |
| 0 0 28px rgba(245, 158, 11, 0.4), | |
| 0 0 56px rgba(245, 158, 11, 0.2), | |
| 0 0 100px rgba(249, 115, 22, 0.1); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 16. .scroll-indicator-dots β Horizontal scroll indicator | |
| ---------------------------------------------------------- | |
| Animated dots that indicate scrollable content on mobile | |
| swipe sections. Dots highlight based on active scroll | |
| position (controlled via .active class on individual dots). | |
| Usage: | |
| <div className="scroll-indicator-dots"> | |
| <span className="scroll-indicator-dots__dot active" /> | |
| <span className="scroll-indicator-dots__dot" /> | |
| <span className="scroll-indicator-dots__dot" /> | |
| </div> | |
| Customize: | |
| - Dot count should match number of scrollable sections | |
| - Add .active to current dot via JS scroll listener | |
| ---------------------------------------------------------- */ | |
| .scroll-indicator-dots { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.5rem; | |
| padding: 0.75rem 0; | |
| } | |
| .scroll-indicator-dots__dot { | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 9999px; | |
| background: rgba(99, 102, 241, 0.2); | |
| border: 1px solid rgba(99, 102, 241, 0.15); | |
| transition: | |
| width 0.35s cubic-bezier(0.23, 1, 0.32, 1), | |
| background 0.35s ease, | |
| box-shadow 0.35s ease; | |
| cursor: pointer; | |
| } | |
| .scroll-indicator-dots__dot:hover { | |
| background: rgba(99, 102, 241, 0.35); | |
| } | |
| .scroll-indicator-dots__dot.active { | |
| width: 24px; | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6); | |
| border-color: transparent; | |
| box-shadow: 0 0 8px rgba(99, 102, 241, 0.3); | |
| animation: scrollDotPulse 2s ease-in-out infinite; | |
| } | |
| @keyframes scrollDotPulse { | |
| 0%, 100% { box-shadow: 0 0 8px rgba(99, 102, 241, 0.3); } | |
| 50% { box-shadow: 0 0 14px rgba(99, 102, 241, 0.5), 0 0 24px rgba(99, 102, 241, 0.15); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 17. .sidebar-section-title β Sidebar section heading | |
| ---------------------------------------------------------- | |
| Styled sidebar section title with a left accent border | |
| (indigo gradient) and subtle gradient text. For section | |
| labels like "CHAPITRES", "QUIZ", "RESSOURCES" in the | |
| Cours sidebar. | |
| Usage: | |
| <h3 className="sidebar-section-title">CHAPITRES</h3> | |
| <h3 className="sidebar-section-title">QUIZ</h3> | |
| ---------------------------------------------------------- */ | |
| .sidebar-section-title { | |
| position: relative; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| font-size: 0.6875rem; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: 0.1em; | |
| color: var(--muted-foreground, #94a3b8); | |
| padding-left: 0.75rem; | |
| margin-bottom: 0.75rem; | |
| } | |
| .sidebar-section-title::before { | |
| content: ''; | |
| position: absolute; | |
| left: 0; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| width: 3px; | |
| height: 60%; | |
| border-radius: 9999px; | |
| background: linear-gradient(180deg, #6366f1, #8b5cf6); | |
| box-shadow: 0 0 6px rgba(99, 102, 241, 0.3); | |
| } | |
| /* ---------------------------------------------------------- | |
| 18. .onboarding-highlight β Pulsing highlight overlay | |
| ---------------------------------------------------------- | |
| Animated border highlight for onboarding tooltips and | |
| element callouts. Uses a pulsing ring border animation | |
| to draw user attention. pointer-events-none prevents | |
| blocking interaction with the highlighted element. | |
| Usage: | |
| <div className="onboarding-highlight" style="position: absolute; inset: -4px;"> | |
| </div> | |
| Note: | |
| - Apply as an overlay on top of the target element | |
| - Set border-radius to match the target's corners | |
| - Remove class after onboarding step completes | |
| ---------------------------------------------------------- */ | |
| .onboarding-highlight { | |
| position: absolute; | |
| inset: -4px; | |
| border: 2px solid rgba(99, 102, 241, 0.6); | |
| border-radius: inherit; | |
| pointer-events: none; | |
| z-index: 50; | |
| animation: onboardingPulse 2s ease-in-out infinite; | |
| } | |
| .onboarding-highlight::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -4px; | |
| border: 2px solid rgba(99, 102, 241, 0.2); | |
| border-radius: inherit; | |
| animation: onboardingRingExpand 2s ease-out infinite; | |
| } | |
| @keyframes onboardingPulse { | |
| 0%, 100% { | |
| border-color: rgba(99, 102, 241, 0.6); | |
| box-shadow: 0 0 8px rgba(99, 102, 241, 0.15), 0 0 16px rgba(99, 102, 241, 0.05); | |
| } | |
| 50% { | |
| border-color: rgba(139, 92, 246, 0.8); | |
| box-shadow: 0 0 16px rgba(139, 92, 246, 0.25), 0 0 32px rgba(99, 102, 241, 0.1); | |
| } | |
| } | |
| @keyframes onboardingRingExpand { | |
| 0% { | |
| inset: -4px; | |
| opacity: 0.6; | |
| border-color: rgba(99, 102, 241, 0.4); | |
| } | |
| 100% { | |
| inset: -14px; | |
| opacity: 0; | |
| border-color: rgba(99, 102, 241, 0); | |
| } | |
| } | |
| /* ============================================================ | |
| IA Academy β Phase 8 Enhancement Classes | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .confetti-canvas β Full-screen overlay for confetti effect | |
| ---------------------------------------------------------- */ | |
| .confetti-canvas { | |
| position: fixed; | |
| inset: 0; | |
| z-index: 9999; | |
| pointer-events: none; | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .achievement-badge β Achievement badge card | |
| ---------------------------------------------------------- */ | |
| .achievement-badge { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 0.5rem; | |
| padding: 1rem; | |
| border-radius: 12px; | |
| background: rgba(15, 15, 35, 0.6); | |
| backdrop-filter: blur(12px); | |
| border: 1px solid rgba(99, 102, 241, 0.15); | |
| transition: all 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| text-align: center; | |
| } | |
| .achievement-badge .badge-icon { | |
| width: 48px; | |
| height: 48px; | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| background: rgba(99, 102, 241, 0.1); | |
| border: 2px solid rgba(99, 102, 241, 0.2); | |
| font-size: 1.25rem; | |
| transition: all 0.4s ease; | |
| } | |
| .achievement-badge.unlocked { | |
| border-color: rgba(99, 102, 241, 0.35); | |
| background: rgba(99, 102, 241, 0.08); | |
| box-shadow: 0 0 20px rgba(99, 102, 241, 0.1), 0 4px 16px rgba(0, 0, 0, 0.2); | |
| animation: achievementUnlock 0.6s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .achievement-badge.unlocked .badge-icon { | |
| background: linear-gradient(135deg, rgba(99, 102, 241, 0.2), rgba(139, 92, 246, 0.2)); | |
| border-color: rgba(139, 92, 246, 0.4); | |
| box-shadow: 0 0 12px rgba(139, 92, 246, 0.3); | |
| transform: scale(1.05); | |
| } | |
| @keyframes achievementUnlock { | |
| 0% { transform: scale(0.8); opacity: 0.5; } | |
| 50% { transform: scale(1.08); } | |
| 100% { transform: scale(1); opacity: 1; } | |
| } | |
| .achievement-badge.locked { | |
| opacity: 0.4; | |
| filter: grayscale(1); | |
| } | |
| .achievement-badge.locked .badge-icon { | |
| background: rgba(100, 100, 120, 0.1); | |
| border-color: rgba(100, 100, 120, 0.2); | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .learning-path β TP learning path container | |
| ---------------------------------------------------------- */ | |
| .learning-path { | |
| display: flex; | |
| align-items: center; | |
| gap: 0; | |
| overflow-x: auto; | |
| padding: 1rem 0; | |
| } | |
| @media (max-width: 640px) { | |
| .learning-path { | |
| flex-direction: column; | |
| align-items: stretch; | |
| overflow-x: visible; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .path-node β Individual node in learning path | |
| ---------------------------------------------------------- */ | |
| .path-node { | |
| display: flex; | |
| flex-shrink: 0; | |
| align-items: center; | |
| gap: 0.75rem; | |
| padding: 0.75rem 1rem; | |
| border-radius: 12px; | |
| background: rgba(15, 15, 35, 0.5); | |
| border: 1px solid rgba(99, 102, 241, 0.12); | |
| transition: all 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| position: relative; | |
| } | |
| .path-node:hover { | |
| border-color: rgba(99, 102, 241, 0.3); | |
| background: rgba(20, 20, 50, 0.7); | |
| transform: translateY(-2px); | |
| box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); | |
| } | |
| .path-node .node-number { | |
| width: 36px; | |
| height: 36px; | |
| border-radius: 50%; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-weight: 700; | |
| font-size: 0.875rem; | |
| background: linear-gradient(135deg, rgba(99, 102, 241, 0.2), rgba(139, 92, 246, 0.2)); | |
| border: 2px solid rgba(99, 102, 241, 0.3); | |
| color: #a5b4fc; | |
| flex-shrink: 0; | |
| } | |
| .path-node.active { | |
| border-color: rgba(99, 102, 241, 0.4); | |
| box-shadow: 0 0 20px rgba(99, 102, 241, 0.12), 0 0 40px rgba(99, 102, 241, 0.06); | |
| } | |
| .path-node.active .node-number { | |
| background: linear-gradient(135deg, #6366f1, #8b5cf6); | |
| border-color: #818cf8; | |
| color: white; | |
| box-shadow: 0 0 12px rgba(99, 102, 241, 0.4); | |
| animation: pathNodePulse 2s ease-in-out infinite; | |
| } | |
| @keyframes pathNodePulse { | |
| 0%, 100% { box-shadow: 0 0 12px rgba(99, 102, 241, 0.4); } | |
| 50% { box-shadow: 0 0 20px rgba(99, 102, 241, 0.6), 0 0 32px rgba(99, 102, 241, 0.2); } | |
| } | |
| .path-node.completed .node-number { | |
| background: linear-gradient(135deg, #10b981, #14b8a6); | |
| border-color: #34d399; | |
| color: white; | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .path-connector β Dashed line between path nodes | |
| ---------------------------------------------------------- */ | |
| .path-connector { | |
| width: 40px; | |
| height: 2px; | |
| border-top: 2px dashed rgba(99, 102, 241, 0.25); | |
| flex-shrink: 0; | |
| background: linear-gradient(90deg, rgba(99, 102, 241, 0.15), rgba(139, 92, 246, 0.25), rgba(99, 102, 241, 0.15)); | |
| background-size: 200% 100%; | |
| animation: pathDash 3s linear infinite; | |
| } | |
| @media (max-width: 640px) { | |
| .path-connector { | |
| width: 2px; | |
| height: 24px; | |
| border-top: none; | |
| border-left: 2px dashed rgba(99, 102, 241, 0.25); | |
| background: linear-gradient(180deg, rgba(99, 102, 241, 0.15), rgba(139, 92, 246, 0.25)); | |
| } | |
| } | |
| @keyframes pathDash { | |
| 0% { background-position: 0% 0; } | |
| 100% { background-position: 200% 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .streak-fire β Animated fire/streak indicator | |
| ---------------------------------------------------------- */ | |
| .streak-fire { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| padding: 0.25rem 0.625rem; | |
| border-radius: 9999px; | |
| background: linear-gradient(135deg, rgba(245, 158, 11, 0.12), rgba(249, 115, 22, 0.08)); | |
| border: 1px solid rgba(245, 158, 11, 0.25); | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| color: #fbbf24; | |
| animation: streakFlicker 2s ease-in-out infinite; | |
| } | |
| @keyframes streakFlicker { | |
| 0%, 100% { box-shadow: 0 0 8px rgba(245, 158, 11, 0.2); } | |
| 33% { box-shadow: 0 0 14px rgba(245, 158, 11, 0.35), 0 0 24px rgba(249, 115, 22, 0.15); } | |
| 66% { box-shadow: 0 0 10px rgba(245, 158, 11, 0.25); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .glass-chip β Small glass chip/tag component | |
| ---------------------------------------------------------- */ | |
| .glass-chip { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| padding: 0.375rem 0.875rem; | |
| border-radius: 9999px; | |
| font-size: 0.8125rem; | |
| font-weight: 500; | |
| background: rgba(15, 15, 35, 0.5); | |
| backdrop-filter: blur(8px); | |
| border: 1px solid rgba(99, 102, 241, 0.15); | |
| color: #94a3b8; | |
| transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| cursor: pointer; | |
| white-space: nowrap; | |
| } | |
| .glass-chip:hover { | |
| background: rgba(20, 20, 50, 0.7); | |
| border-color: rgba(99, 102, 241, 0.3); | |
| transform: translateY(-1px); | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
| color: #cbd5e1; | |
| } | |
| .glass-chip.active { | |
| background: rgba(99, 102, 241, 0.12); | |
| border-color: rgba(99, 102, 241, 0.35); | |
| color: #a5b4fc; | |
| box-shadow: 0 0 12px rgba(99, 102, 241, 0.1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .card-glow-emerald β Emerald glow on hover | |
| ---------------------------------------------------------- */ | |
| .card-glow-emerald { | |
| transition: | |
| box-shadow 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.45s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .card-glow-emerald:hover { | |
| border-color: rgba(16, 185, 129, 0.3); | |
| box-shadow: | |
| 0 8px 24px rgba(16, 185, 129, 0.1), | |
| 0 0 30px rgba(16, 185, 129, 0.06), | |
| 0 0 60px rgba(16, 185, 129, 0.03); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .card-glow-rose β Rose glow on hover | |
| ---------------------------------------------------------- */ | |
| .card-glow-rose { | |
| transition: | |
| box-shadow 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.45s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .card-glow-rose:hover { | |
| border-color: rgba(244, 63, 94, 0.3); | |
| box-shadow: | |
| 0 8px 24px rgba(244, 63, 94, 0.1), | |
| 0 0 30px rgba(244, 63, 94, 0.06), | |
| 0 0 60px rgba(236, 72, 153, 0.03); | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .sidebar-section-title β Sidebar section heading | |
| ---------------------------------------------------------- */ | |
| .sidebar-section-title { | |
| font-size: 0.6875rem; | |
| font-weight: 700; | |
| letter-spacing: 0.1em; | |
| text-transform: uppercase; | |
| color: #64748b; | |
| padding-left: 0.75rem; | |
| border-left: 3px solid transparent; | |
| border-image: linear-gradient(180deg, #6366f1, #8b5cf6) 1; | |
| margin-bottom: 0.5rem; | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .scroll-indicator-dots β Mobile scroll dots | |
| ---------------------------------------------------------- */ | |
| .scroll-indicator-dots { | |
| display: flex; | |
| justify-content: center; | |
| gap: 0.5rem; | |
| padding: 0.75rem 0; | |
| } | |
| .scroll-indicator-dots .dot { | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 50%; | |
| background: rgba(99, 102, 241, 0.2); | |
| transition: all 0.3s ease; | |
| } | |
| .scroll-indicator-dots .dot.active { | |
| background: #6366f1; | |
| box-shadow: 0 0 8px rgba(99, 102, 241, 0.4); | |
| width: 24px; | |
| border-radius: 9999px; | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .toast-celebration β Enhanced celebration toast | |
| ---------------------------------------------------------- */ | |
| .toast-celebration { | |
| position: relative; | |
| border: 1px solid rgba(245, 158, 11, 0.3); | |
| background: rgba(245, 158, 11, 0.06); | |
| overflow: hidden; | |
| } | |
| .toast-celebration::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background: linear-gradient(90deg, transparent, rgba(245, 158, 11, 0.04), transparent); | |
| background-size: 200% 100%; | |
| animation: toastSparkle 2s ease-in-out infinite; | |
| } | |
| @keyframes toastSparkle { | |
| 0% { background-position: -200% 0; } | |
| 100% { background-position: 200% 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 13. .onboarding-highlight β Pulsing onboarding overlay | |
| ---------------------------------------------------------- */ | |
| .onboarding-highlight { | |
| position: relative; | |
| pointer-events: auto; | |
| } | |
| .onboarding-highlight::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -4px; | |
| border-radius: inherit; | |
| border: 2px solid rgba(99, 102, 241, 0.5); | |
| animation: onboardingPulse 2s ease-in-out infinite; | |
| pointer-events: none; | |
| z-index: 10; | |
| } | |
| @keyframes onboardingPulse { | |
| 0%, 100% { opacity: 0.6; inset: -4px; } | |
| 50% { opacity: 1; inset: -6px; } | |
| } | |
| /* ============================================================ | |
| IA Academy β Phase 9 Enhancement Classes | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .mobile-nav β Fixed bottom mobile navigation bar | |
| ---------------------------------------------------------- | |
| Fixed-position navigation bar for mobile viewports, pinned | |
| to the bottom of the screen. Uses glassmorphism background | |
| with safe-area padding for notched devices. | |
| Usage: | |
| <nav class="mobile-nav"> | |
| <a class="mobile-nav-item active">...</a> | |
| <a class="mobile-nav-item">...</a> | |
| </nav> | |
| Note: | |
| - Place outside of scrollable content for true fixed behavior | |
| - Uses env(safe-area-inset-bottom) for iOS notch support | |
| - z-index: 60 ensures it stays above other overlays | |
| ---------------------------------------------------------- */ | |
| .mobile-nav { | |
| position: fixed; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| z-index: 60; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-around; | |
| padding: 0.5rem 0.75rem calc(0.5rem + env(safe-area-inset-bottom, 0px)); | |
| background: rgba(10, 10, 26, 0.85); | |
| backdrop-filter: blur(20px) saturate(1.4); | |
| -webkit-backdrop-filter: blur(20px) saturate(1.4); | |
| border-top: 1px solid rgba(99, 102, 241, 0.15); | |
| box-shadow: | |
| 0 -4px 20px rgba(0, 0, 0, 0.3), | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.04); | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .mobile-nav-item β Individual mobile nav item | |
| ---------------------------------------------------------- | |
| A single navigation item inside .mobile-nav. Displays as a | |
| centered column with icon + small label text. | |
| Usage: | |
| <a href="#accueil" class="mobile-nav-item active"> | |
| <Home size={20} /> | |
| <span>Accueil</span> | |
| </a> | |
| Note: | |
| - The .active modifier changes color and adds a subtle glow | |
| - Minimum 44px touch target via padding for accessibility | |
| ---------------------------------------------------------- */ | |
| .mobile-nav-item { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.25rem; | |
| padding: 0.375rem 0.75rem; | |
| min-height: 44px; | |
| min-width: 56px; | |
| font-size: 0.625rem; | |
| font-weight: 500; | |
| color: var(--muted-foreground, #94a3b8); | |
| text-decoration: none; | |
| border-radius: 12px; | |
| transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| cursor: pointer; | |
| -webkit-tap-highlight-color: transparent; | |
| position: relative; | |
| } | |
| .mobile-nav-item:hover { | |
| color: var(--foreground, #f8fafc); | |
| background: rgba(99, 102, 241, 0.06); | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .mobile-nav-item.active β Active nav item state | |
| ---------------------------------------------------------- | |
| Active state for the currently selected tab in the mobile | |
| navigation bar. Uses primary color with a subtle glow bg. | |
| Usage: | |
| <a href="#cours" class="mobile-nav-item active"> | |
| <BookOpen size={20} /> | |
| <span>Cours</span> | |
| </a> | |
| ---------------------------------------------------------- */ | |
| .mobile-nav-item.active { | |
| color: var(--primary, #6366f1); | |
| background: rgba(99, 102, 241, 0.1); | |
| box-shadow: 0 0 12px rgba(99, 102, 241, 0.08); | |
| } | |
| .mobile-nav-item.active::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| width: 20px; | |
| height: 2px; | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6); | |
| border-radius: 9999px; | |
| box-shadow: 0 0 6px rgba(99, 102, 241, 0.4); | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .quiz-timer β Quiz countdown timer display | |
| ---------------------------------------------------------- | |
| An inline-flex countdown timer for quiz questions. Uses | |
| tabular-nums and monospace font for stable digit width so | |
| the layout doesn't jump as numbers change. | |
| Usage: | |
| <div class="quiz-timer">02:30</div> | |
| <div class="quiz-timer warning">00:08</div> | |
| <div class="quiz-timer danger">00:03</div> | |
| Note: | |
| - .warning state activates below 10 seconds | |
| - .danger state activates below 5 seconds | |
| ---------------------------------------------------------- */ | |
| .quiz-timer { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| padding: 0.5rem 1rem; | |
| border-radius: 9999px; | |
| font-family: var(--font-mono, 'JetBrains Mono', monospace); | |
| font-size: 1.125rem; | |
| font-weight: 700; | |
| font-variant-numeric: tabular-nums; | |
| color: var(--foreground, #f8fafc); | |
| background: rgba(15, 15, 35, 0.6); | |
| backdrop-filter: blur(10px); | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| box-shadow: 0 0 12px rgba(99, 102, 241, 0.08); | |
| letter-spacing: 0.05em; | |
| transition: all 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: color, border-color, box-shadow; | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .quiz-timer.warning β Timer warning state (< 10s) | |
| ---------------------------------------------------------- | |
| Amber warning state when remaining time drops below 10 | |
| seconds. Uses a subtle pulse to draw attention. | |
| Usage: | |
| <div class="quiz-timer warning">00:09</div> | |
| ---------------------------------------------------------- */ | |
| .quiz-timer.warning { | |
| color: #fbbf24; | |
| border-color: rgba(245, 158, 11, 0.3); | |
| box-shadow: 0 0 12px rgba(245, 158, 11, 0.12); | |
| animation: quizTimerPulse 2s ease-in-out infinite; | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .quiz-timer.danger β Timer danger state (< 5s) | |
| ---------------------------------------------------------- | |
| Red danger state when remaining time drops below 5 seconds. | |
| Uses a faster pulse for urgency. | |
| Usage: | |
| <div class="quiz-timer danger">00:03</div> | |
| ---------------------------------------------------------- */ | |
| .quiz-timer.danger { | |
| color: #f87171; | |
| border-color: rgba(239, 68, 68, 0.4); | |
| box-shadow: 0 0 16px rgba(239, 68, 68, 0.18); | |
| animation: quizTimerPulse 0.8s ease-in-out infinite; | |
| } | |
| @keyframes quizTimerPulse { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.65; } | |
| } | |
| /* Reduced motion: disable timer pulse */ | |
| @media (prefers-reduced-motion: reduce) { | |
| .quiz-timer.warning, | |
| .quiz-timer.danger { | |
| animation: none; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .star-rating β Star rating container | |
| ---------------------------------------------------------- | |
| Horizontal row of interactive star icons for rating feedback. | |
| Stars are clickable with hover scale transition. | |
| Usage: | |
| <div class="star-rating"> | |
| <span class="star filled">(filled)</span> | |
| <span class="star filled">(filled)</span> | |
| <span class="star filled">(filled)</span> | |
| <span class="star empty">(empty)</span> | |
| <span class="star empty">(empty)</span> | |
| </div> | |
| Note: | |
| - .filled stars use amber-400 color | |
| - .empty stars use muted-foreground at 40% opacity | |
| - Stars scale up on hover for interactivity | |
| ---------------------------------------------------------- */ | |
| .star-rating { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| cursor: pointer; | |
| user-select: none; | |
| } | |
| .star-rating .star { | |
| font-size: 1.25rem; | |
| line-height: 1; | |
| transition: transform 0.2s cubic-bezier(0.23, 1, 0.32, 1), | |
| color 0.2s ease; | |
| cursor: pointer; | |
| } | |
| .star-rating .star:hover { | |
| transform: scale(1.25); | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .star-rating .star.filled β Filled star | |
| ---------------------------------------------------------- | |
| A filled (selected) star in the rating, colored amber. | |
| Usage: | |
| <span class="star filled">(filled)</span> | |
| ---------------------------------------------------------- */ | |
| .star-rating .star.filled { | |
| color: #fbbf24; | |
| text-shadow: 0 0 8px rgba(245, 158, 11, 0.4); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .star-rating .star.empty β Empty star | |
| ---------------------------------------------------------- | |
| An empty (unselected) star in the rating, dimmed. | |
| Usage: | |
| <span class="star empty">(empty)</span> | |
| ---------------------------------------------------------- */ | |
| .star-rating .star.empty { | |
| color: rgba(148, 163, 184, 0.4); | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .glass-card-elevated β Elevated glass card with stronger shadow | |
| ---------------------------------------------------------- | |
| A more prominent version of .glass-card with stronger | |
| drop shadow, deeper backdrop blur, and a hover lift effect. | |
| Suitable for hero cards or featured content. | |
| Usage: | |
| <div class="glass-card-elevated">Featured content</div> | |
| Note: | |
| - Inherits the glassmorphism aesthetic but with stronger | |
| shadow depth and a subtle border glow on hover | |
| - Hover lifts the card 6px with enhanced shadow spread | |
| ---------------------------------------------------------- */ | |
| .glass-card-elevated { | |
| background: rgba(15, 15, 35, 0.7); | |
| backdrop-filter: blur(24px) saturate(1.3); | |
| -webkit-backdrop-filter: blur(24px) saturate(1.3); | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| border-radius: 16px; | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.06), | |
| inset 0 -1px 0 0 rgba(0, 0, 0, 0.2), | |
| 0 12px 40px rgba(0, 0, 0, 0.4), | |
| 0 4px 12px rgba(0, 0, 0, 0.2), | |
| 0 0 0 1px rgba(99, 102, 241, 0.08); | |
| transition: | |
| transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .glass-card-elevated:hover { | |
| transform: translateY(-6px); | |
| border-color: rgba(99, 102, 241, 0.4); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.1), | |
| inset 0 0 40px rgba(99, 102, 241, 0.05), | |
| inset 0 -1px 0 0 rgba(0, 0, 0, 0.25), | |
| 0 20px 56px rgba(0, 0, 0, 0.5), | |
| 0 8px 20px rgba(0, 0, 0, 0.3), | |
| 0 0 0 1px rgba(99, 102, 241, 0.2), | |
| 0 0 50px rgba(99, 102, 241, 0.1), | |
| 0 0 100px rgba(139, 92, 246, 0.04); | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .text-3d β 3D text effect with layered text-shadow | |
| ---------------------------------------------------------- | |
| Creates depth in text using multiple text-shadow layers that | |
| simulate a 3D extrusion effect. Works best on larger text. | |
| Usage: | |
| <h1 class="text-3d">Heading with depth</h1> | |
| Note: | |
| - Works on any text color; shadows use a darker version | |
| - Best results on font-weight: 700 or higher | |
| - Combine with .gradient-text for a striking effect | |
| ---------------------------------------------------------- */ | |
| .text-3d { | |
| text-shadow: | |
| 0 1px 0 rgba(0, 0, 0, 0.4), | |
| 0 2px 0 rgba(0, 0, 0, 0.35), | |
| 0 3px 0 rgba(0, 0, 0, 0.3), | |
| 0 4px 0 rgba(0, 0, 0, 0.25), | |
| 0 5px 0 rgba(0, 0, 0, 0.2), | |
| 0 6px 1px rgba(0, 0, 0, 0.18), | |
| 0 0 20px rgba(99, 102, 241, 0.15), | |
| 0 0 40px rgba(99, 102, 241, 0.08); | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .skeleton-pulse β Pulse animation for loading skeletons | |
| ---------------------------------------------------------- | |
| A subtle pulse animation for skeleton placeholder elements | |
| during data loading. Provides visual feedback that content | |
| is being fetched. | |
| Usage: | |
| <div class="skeleton-pulse bg-muted rounded-lg h-48 w-full"></div> | |
| <div class="skeleton-pulse bg-muted rounded h-4 w-3/4"></div> | |
| Note: | |
| - Apply bg-muted (or similar gray background) alongside this class | |
| - The pulse uses a soft opacity change, not position/transform | |
| ---------------------------------------------------------- */ | |
| .skeleton-pulse { | |
| animation: skeletonPulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; | |
| background: linear-gradient( | |
| 90deg, | |
| rgba(30, 30, 60, 0.6) 0%, | |
| rgba(50, 50, 80, 0.8) 40%, | |
| rgba(70, 70, 100, 0.9) 50%, | |
| rgba(50, 50, 80, 0.8) 60%, | |
| rgba(30, 30, 60, 0.6) 100% | |
| ); | |
| background-size: 200% 100%; | |
| animation: skeletonPulse 2s ease-in-out infinite, skeletonShimmer 2s linear infinite; | |
| } | |
| @keyframes skeletonPulse { | |
| 0%, 100% { opacity: 0.6; } | |
| 50% { opacity: 1; } | |
| } | |
| @keyframes skeletonShimmer { | |
| 0% { background-position: 200% 0; } | |
| 100% { background-position: -200% 0; } | |
| } | |
| /* Reduced motion: disable skeleton pulse */ | |
| @media (prefers-reduced-motion: reduce) { | |
| .skeleton-pulse { | |
| animation: none; | |
| opacity: 0.6; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 13. .tooltip-hover β Tooltip on hover with CSS pseudo-element | |
| ---------------------------------------------------------- | |
| Pure CSS tooltip that appears on hover using ::after. No JS | |
| required. The tooltip text is set via the data-tooltip attribute. | |
| Usage: | |
| <span class="tooltip-hover" data-tooltip="Helpful info">Hover me</span> | |
| Note: | |
| - Tooltip appears centered above the element | |
| - Includes a small downward arrow via ::before | |
| - Dark glass background with small white text | |
| - Supports position variants via .top, .bottom, .left, .right | |
| ---------------------------------------------------------- */ | |
| .tooltip-hover { | |
| position: relative; | |
| cursor: help; | |
| } | |
| .tooltip-hover::after { | |
| content: attr(data-tooltip); | |
| position: absolute; | |
| bottom: calc(100% + 8px); | |
| left: 50%; | |
| transform: translateX(-50%) scale(0.9); | |
| padding: 0.375rem 0.75rem; | |
| border-radius: 8px; | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| line-height: 1.4; | |
| white-space: nowrap; | |
| color: #ffffff; | |
| background: rgba(15, 15, 35, 0.92); | |
| backdrop-filter: blur(12px); | |
| border: 1px solid rgba(99, 102, 241, 0.25); | |
| box-shadow: | |
| 0 4px 16px rgba(0, 0, 0, 0.35), | |
| 0 0 0 1px rgba(99, 102, 241, 0.1); | |
| opacity: 0; | |
| pointer-events: none; | |
| transition: | |
| opacity 0.2s cubic-bezier(0.23, 1, 0.32, 1), | |
| transform 0.2s cubic-bezier(0.23, 1, 0.32, 1); | |
| z-index: 50; | |
| } | |
| .tooltip-hover::before { | |
| content: ''; | |
| position: absolute; | |
| bottom: calc(100% + 2px); | |
| left: 50%; | |
| transform: translateX(-50%) rotate(45deg); | |
| width: 8px; | |
| height: 8px; | |
| background: rgba(15, 15, 35, 0.92); | |
| border-right: 1px solid rgba(99, 102, 241, 0.25); | |
| border-bottom: 1px solid rgba(99, 102, 241, 0.25); | |
| opacity: 0; | |
| pointer-events: none; | |
| transition: | |
| opacity 0.2s cubic-bezier(0.23, 1, 0.32, 1), | |
| transform 0.2s cubic-bezier(0.23, 1, 0.32, 1); | |
| z-index: 49; | |
| } | |
| .tooltip-hover:hover::after { | |
| opacity: 1; | |
| transform: translateX(-50%) scale(1); | |
| } | |
| .tooltip-hover:hover::before { | |
| opacity: 1; | |
| transform: translateX(-50%) rotate(45deg); | |
| } | |
| /* ---------------------------------------------------------- | |
| 14. .card-border-gradient β Card with animated gradient border | |
| ---------------------------------------------------------- | |
| A card whose border is an animated multi-color gradient, | |
| created using a rotating conic-gradient pseudo-element masked | |
| to the border area. | |
| Usage: | |
| <div class="card-border-gradient p-6">Content here</div> | |
| Note: | |
| - Uses isolation + z-index to contain the gradient layers | |
| - The gradient rotates continuously (6s cycle) | |
| - Content sits above the gradient via z-index layering | |
| ---------------------------------------------------------- */ | |
| .card-border-gradient { | |
| position: relative; | |
| border-radius: 16px; | |
| isolation: isolate; | |
| overflow: hidden; | |
| } | |
| .card-border-gradient::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| border-radius: inherit; | |
| padding: 2px; | |
| background: conic-gradient( | |
| from 0deg, | |
| #6366f1, | |
| #8b5cf6, | |
| #ec4899, | |
| #f59e0b, | |
| #10b981, | |
| #06b6d4, | |
| #6366f1 | |
| ); | |
| -webkit-mask: | |
| linear-gradient(#fff 0 0) content-box, | |
| linear-gradient(#fff 0 0); | |
| -webkit-mask-composite: xor; | |
| mask: | |
| linear-gradient(#fff 0 0) content-box, | |
| linear-gradient(#fff 0 0); | |
| mask-composite: exclude; | |
| animation: cardBorderRotate 6s linear infinite; | |
| z-index: -2; | |
| } | |
| .card-border-gradient::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 2px; | |
| border-radius: calc(16px - 2px); | |
| background: var(--card, #151530); | |
| z-index: -1; | |
| } | |
| @keyframes cardBorderRotate { | |
| 0% { | |
| background: conic-gradient(from 0deg, #6366f1, #8b5cf6, #ec4899, #f59e0b, #10b981, #06b6d4, #6366f1); | |
| } | |
| 25% { | |
| background: conic-gradient(from 90deg, #6366f1, #8b5cf6, #ec4899, #f59e0b, #10b981, #06b6d4, #6366f1); | |
| } | |
| 50% { | |
| background: conic-gradient(from 180deg, #6366f1, #8b5cf6, #ec4899, #f59e0b, #10b981, #06b6d4, #6366f1); | |
| } | |
| 75% { | |
| background: conic-gradient(from 270deg, #6366f1, #8b5cf6, #ec4899, #f59e0b, #10b981, #06b6d4, #6366f1); | |
| } | |
| 100% { | |
| background: conic-gradient(from 360deg, #6366f1, #8b5cf6, #ec4899, #f59e0b, #10b981, #06b6d4, #6366f1); | |
| } | |
| } | |
| /* Reduced motion: freeze gradient border rotation */ | |
| @media (prefers-reduced-motion: reduce) { | |
| .card-border-gradient::before { | |
| animation: none; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 15. .btn-social β Social media button (circular, glass) | |
| ---------------------------------------------------------- | |
| Circular button for social media links with glass background, | |
| centered icon, and a colored glow on hover matching the brand. | |
| Usage: | |
| <button class="btn-social" data-color="github"> | |
| <Github size={20} /> | |
| </button> | |
| Color variants (data-color attribute): | |
| - "github": neutral/white | |
| - "twitter": cyan | |
| - "linkedin": blue | |
| - "youtube": red | |
| - "default": indigo (fallback) | |
| Note: | |
| - 44px diameter for accessibility touch target | |
| - Icon should be centered via flexbox | |
| ---------------------------------------------------------- */ | |
| .btn-social { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 44px; | |
| height: 44px; | |
| border-radius: 50%; | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| background: rgba(15, 15, 35, 0.5); | |
| backdrop-filter: blur(12px); | |
| color: var(--foreground, #f8fafc); | |
| cursor: pointer; | |
| transition: all 0.35s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
| } | |
| .btn-social:hover { | |
| transform: translateY(-3px) scale(1.08); | |
| background: rgba(30, 30, 60, 0.7); | |
| border-color: rgba(99, 102, 241, 0.35); | |
| box-shadow: | |
| 0 8px 24px rgba(0, 0, 0, 0.3), | |
| 0 0 20px rgba(99, 102, 241, 0.15); | |
| color: #a5b4fc; | |
| } | |
| .btn-social:active { | |
| transform: translateY(0) scale(0.95); | |
| } | |
| .btn-social[data-color="twitter"]:hover { | |
| border-color: rgba(6, 182, 212, 0.4); | |
| box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3), 0 0 20px rgba(6, 182, 212, 0.15); | |
| color: #22d3ee; | |
| } | |
| .btn-social[data-color="linkedin"]:hover { | |
| border-color: rgba(99, 102, 241, 0.4); | |
| box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3), 0 0 20px rgba(99, 102, 241, 0.15); | |
| color: #818cf8; | |
| } | |
| .btn-social[data-color="youtube"]:hover { | |
| border-color: rgba(239, 68, 68, 0.4); | |
| box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3), 0 0 20px rgba(239, 68, 68, 0.15); | |
| color: #f87171; | |
| } | |
| .btn-social[data-color="email"]:hover { | |
| border-color: rgba(245, 158, 11, 0.4); | |
| box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3), 0 0 20px rgba(245, 158, 11, 0.15); | |
| color: #fbbf24; | |
| } | |
| /* ---------------------------------------------------------- | |
| 16. .section-reveal β Scroll-triggered reveal animation | |
| ---------------------------------------------------------- | |
| Elements fade in and slide up when they enter the viewport. | |
| Intended to be triggered via JS IntersectionObserver by | |
| adding an .in-view class. | |
| Usage: | |
| <div class="section-reveal">Hidden initially</div> | |
| // JS: observer adds .in-view when element intersects | |
| <div class="section-reveal in-view">Now visible</div> | |
| Stagger: | |
| - Use :nth-child(1) through :nth-child(6) for cascading delay | |
| Note: | |
| - Elements are invisible (opacity: 0, translateY: 24px) by default | |
| - .in-view triggers the reveal transition | |
| ---------------------------------------------------------- */ | |
| .section-reveal { | |
| opacity: 0; | |
| transform: translateY(24px); | |
| transition: | |
| opacity 0.7s cubic-bezier(0.23, 1, 0.32, 1), | |
| transform 0.7s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: opacity, transform; | |
| } | |
| .section-reveal.in-view { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| /* Stagger delay variants β apply to sibling children */ | |
| .section-reveal.in-view:nth-child(1) { transition-delay: 0ms; } | |
| .section-reveal.in-view:nth-child(2) { transition-delay: 100ms; } | |
| .section-reveal.in-view:nth-child(3) { transition-delay: 200ms; } | |
| .section-reveal.in-view:nth-child(4) { transition-delay: 300ms; } | |
| .section-reveal.in-view:nth-child(5) { transition-delay: 400ms; } | |
| .section-reveal.in-view:nth-child(6) { transition-delay: 500ms; } | |
| /* Reduced motion: skip reveal animation, show immediately */ | |
| @media (prefers-reduced-motion: reduce) { | |
| .section-reveal { | |
| opacity: 1; | |
| transform: none; | |
| transition: none; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 17. .glow-dot β Small glowing dot indicator | |
| ---------------------------------------------------------- | |
| A small 8px circular dot with a radial gradient glow, | |
| used for status indicators, live badges, or decorative | |
| highlights. | |
| Usage: | |
| <span class="glow-dot"></span> | |
| <span class="glow-dot" style="--glow-color: #10b981"></span> | |
| Color variants: | |
| - Default: indigo (#6366f1) | |
| - .emerald: green (#10b981) | |
| - .amber: amber (#f59e0b) | |
| - .red: red (#ef4444) | |
| - .rose: rose (#ec4899) | |
| - Custom: set --glow-color CSS variable | |
| Note: | |
| - The glow uses a radial-gradient box-shadow for soft light | |
| - A subtle pulse animation draws attention | |
| ---------------------------------------------------------- */ | |
| .glow-dot { | |
| display: inline-block; | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 50%; | |
| background: var(--glow-color, #6366f1); | |
| box-shadow: | |
| 0 0 4px var(--glow-color, #6366f1), | |
| 0 0 12px var(--glow-color, rgba(99, 102, 241, 0.4)), | |
| 0 0 24px var(--glow-color, rgba(99, 102, 241, 0.15)); | |
| animation: glowDotPulse 2.5s ease-in-out infinite; | |
| flex-shrink: 0; | |
| } | |
| .glow-dot.emerald { | |
| --glow-color: #10b981; | |
| box-shadow: | |
| 0 0 4px #10b981, | |
| 0 0 12px rgba(16, 185, 129, 0.4), | |
| 0 0 24px rgba(16, 185, 129, 0.15); | |
| } | |
| .glow-dot.amber { | |
| --glow-color: #f59e0b; | |
| box-shadow: | |
| 0 0 4px #f59e0b, | |
| 0 0 12px rgba(245, 158, 11, 0.4), | |
| 0 0 24px rgba(245, 158, 11, 0.15); | |
| } | |
| .glow-dot.red { | |
| --glow-color: #ef4444; | |
| box-shadow: | |
| 0 0 4px #ef4444, | |
| 0 0 12px rgba(239, 68, 68, 0.4), | |
| 0 0 24px rgba(239, 68, 68, 0.15); | |
| } | |
| .glow-dot.rose { | |
| --glow-color: #ec4899; | |
| box-shadow: | |
| 0 0 4px #ec4899, | |
| 0 0 12px rgba(236, 72, 153, 0.4), | |
| 0 0 24px rgba(236, 72, 153, 0.15); | |
| } | |
| .glow-dot.cyan { | |
| --glow-color: #06b6d4; | |
| box-shadow: | |
| 0 0 4px #06b6d4, | |
| 0 0 12px rgba(6, 182, 212, 0.4), | |
| 0 0 24px rgba(6, 182, 212, 0.15); | |
| } | |
| @keyframes glowDotPulse { | |
| 0%, 100% { | |
| opacity: 1; | |
| box-shadow: | |
| 0 0 4px var(--glow-color, #6366f1), | |
| 0 0 12px var(--glow-color, rgba(99, 102, 241, 0.4)), | |
| 0 0 24px var(--glow-color, rgba(99, 102, 241, 0.15)); | |
| } | |
| 50% { | |
| opacity: 0.7; | |
| box-shadow: | |
| 0 0 6px var(--glow-color, #6366f1), | |
| 0 0 18px var(--glow-color, rgba(99, 102, 241, 0.5)), | |
| 0 0 36px var(--glow-color, rgba(99, 102, 241, 0.2)); | |
| } | |
| } | |
| /* Reduced motion: disable glow dot pulse */ | |
| @media (prefers-reduced-motion: reduce) { | |
| .glow-dot { | |
| animation: none; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 18. .glass-chip-hover β Enhanced chip/tag with glass effect on hover | |
| ---------------------------------------------------------- | |
| An enhanced version of the standard chip/tag that gains a | |
| glassmorphism backdrop blur and subtle lift on hover. Ideal | |
| for filter tags, category pills, or metadata labels. | |
| Usage: | |
| <span class="glass-chip-hover">Machine Learning</span> | |
| <span class="glass-chip-hover">Python</span> | |
| Note: | |
| - Similar to .glass-chip but with more pronounced hover effects | |
| - Adds backdrop-filter on hover for a frosted glass look | |
| - Slight scale increase on hover for tactile feedback | |
| ---------------------------------------------------------- */ | |
| .glass-chip-hover { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| padding: 0.5rem 1rem; | |
| border-radius: 9999px; | |
| font-size: 0.8125rem; | |
| font-weight: 500; | |
| background: rgba(15, 15, 35, 0.4); | |
| border: 1px solid rgba(99, 102, 241, 0.12); | |
| color: #94a3b8; | |
| cursor: pointer; | |
| white-space: nowrap; | |
| transition: | |
| all 0.35s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow, backdrop-filter; | |
| } | |
| .glass-chip-hover:hover { | |
| background: rgba(20, 20, 50, 0.65); | |
| backdrop-filter: blur(16px) saturate(1.3); | |
| -webkit-backdrop-filter: blur(16px) saturate(1.3); | |
| border-color: rgba(99, 102, 241, 0.35); | |
| color: #cbd5e1; | |
| transform: translateY(-2px) scale(1.04); | |
| box-shadow: | |
| 0 6px 20px rgba(0, 0, 0, 0.25), | |
| 0 0 16px rgba(99, 102, 241, 0.08), | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.06); | |
| } | |
| .glass-chip-hover:active { | |
| transform: translateY(0) scale(0.98); | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); | |
| } | |
| /* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| PHASE 10: Additional CSS Enhancements | |
| βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ | |
| /* 1. .scroll-progress-bar β Enhanced scroll progress indicator | |
| Usage: Add to the fixed progress bar container */ | |
| .scroll-progress-bar { | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| z-index: 200; | |
| height: 3px; | |
| background: transparent; | |
| } | |
| .scroll-progress-bar::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| height: 100%; | |
| width: var(--scroll-progress, 0%); | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6, #f59e0b, #10b981); | |
| background-size: 200% 100%; | |
| animation: scroll-gradient-shift 3s linear infinite; | |
| border-radius: 0 2px 2px 0; | |
| box-shadow: 0 0 10px rgba(99, 102, 241, 0.5), 0 0 20px rgba(139, 92, 246, 0.3); | |
| transition: width 0.1s ease-out; | |
| } | |
| @keyframes scroll-gradient-shift { | |
| 0% { background-position: 0% 50%; } | |
| 100% { background-position: 200% 50%; } | |
| } | |
| /* 2. .footer-link β Footer navigation link with hover effect */ | |
| .footer-link { | |
| position: relative; | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| font-size: 0.875rem; | |
| color: oklch(var(--muted-foreground)); | |
| transition: color 0.2s ease; | |
| text-decoration: none; | |
| } | |
| .footer-link::after { | |
| content: ''; | |
| position: absolute; | |
| bottom: -2px; | |
| left: 0; | |
| width: 0; | |
| height: 1px; | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6); | |
| transition: width 0.3s ease; | |
| border-radius: 1px; | |
| } | |
| .footer-link:hover { | |
| color: oklch(var(--foreground)); | |
| } | |
| .footer-link:hover::after { | |
| width: 100%; | |
| } | |
| /* 3. .notebook-card β Enhanced notebook card for the public browser */ | |
| .notebook-card { | |
| position: relative; | |
| border-radius: 0.75rem; | |
| border: 1px solid oklch(var(--border)); | |
| background: oklch(var(--secondary) / 0.15); | |
| padding: 1rem; | |
| transition: all 0.25s ease; | |
| overflow: hidden; | |
| } | |
| .notebook-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 2px; | |
| background: linear-gradient(90deg, #10b981, #06b6d4); | |
| opacity: 0; | |
| transition: opacity 0.25s ease; | |
| } | |
| .notebook-card:hover { | |
| background: oklch(var(--secondary) / 0.3); | |
| border-color: oklch(var(--primary) / 0.2); | |
| transform: translateY(-1px); | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); | |
| } | |
| .notebook-card:hover::before { | |
| opacity: 1; | |
| } | |
| /* 4. .footer-social-btn β Social media button in footer */ | |
| .footer-social-btn { | |
| width: 2.25rem; | |
| height: 2.25rem; | |
| border-radius: 0.5rem; | |
| background: oklch(var(--secondary) / 0.5); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: oklch(var(--muted-foreground)); | |
| transition: all 0.2s ease; | |
| } | |
| .footer-social-btn:hover { | |
| color: oklch(var(--foreground)); | |
| background: oklch(var(--secondary)); | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); | |
| } | |
| /* 5. .info-list-item β Info list item in footer with icon */ | |
| .info-list-item { | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| font-size: 0.875rem; | |
| color: oklch(var(--muted-foreground)); | |
| transition: color 0.2s ease; | |
| } | |
| .info-list-item:hover { | |
| color: oklch(var(--foreground)); | |
| } | |
| .info-list-item svg { | |
| color: oklch(var(--primary) / 0.6); | |
| flex-shrink: 0; | |
| } | |
| /* 6. .shimmer-badge β Shimmer effect for badge elements */ | |
| .shimmer-badge { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .shimmer-badge::after { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: -100%; | |
| width: 50%; | |
| height: 100%; | |
| background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.15), transparent); | |
| animation: shimmer-badge-sweep 2s ease-in-out infinite; | |
| } | |
| @keyframes shimmer-badge-sweep { | |
| 0% { left: -100%; } | |
| 100% { left: 200%; } | |
| } | |
| /* 7. .hover-underline-fade β Text with fade-in underline on hover */ | |
| .hover-underline-fade { | |
| position: relative; | |
| display: inline; | |
| } | |
| .hover-underline-fade::after { | |
| content: ''; | |
| position: absolute; | |
| bottom: -1px; | |
| left: 50%; | |
| width: 0; | |
| height: 1px; | |
| background: currentColor; | |
| transition: all 0.3s ease; | |
| transform: translateX(-50%); | |
| } | |
| .hover-underline-fade:hover::after { | |
| width: 100%; | |
| } | |
| /* 8. .download-btn β Download button for notebooks */ | |
| .download-btn { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 0.375rem; | |
| width: 100%; | |
| padding: 0.5rem; | |
| border-radius: 0.375rem; | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| background: oklch(0.9 0.05 160 / 0.1); | |
| color: #10b981; | |
| transition: all 0.2s ease; | |
| } | |
| .download-btn:hover { | |
| background: oklch(0.9 0.05 160 / 0.2); | |
| transform: translateY(-1px); | |
| } | |
| .download-btn:active { | |
| transform: translateY(0); | |
| } | |
| /* 9. .glass-tag-pill β Small tag/pill for notebook metadata */ | |
| .glass-tag-pill { | |
| font-size: 0.625rem; | |
| color: oklch(var(--muted-foreground)); | |
| background: oklch(var(--secondary) / 0.5); | |
| padding: 0.125rem 0.5rem; | |
| border-radius: 9999px; | |
| white-space: nowrap; | |
| line-height: 1.4; | |
| } | |
| /* 10. .footer-divider β Gradient divider for footer sections */ | |
| .footer-divider { | |
| border-top: 1px solid oklch(var(--border) / 0.5); | |
| padding-top: 1.5rem; | |
| } | |
| /* ============================================================ | |
| IA Academy β Component Utility Classes (Batch 2) | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .hover-scale-sm β Subtle scale on hover (1.02) | |
| ---------------------------------------------------------- | |
| Adds a gentle scale-up effect on hover with a smooth | |
| cubic-bezier transition. For cards and interactive elements | |
| where a full lift effect is too aggressive. | |
| Usage: | |
| <div class="hover-scale-sm">Card or interactive element</div> | |
| ---------------------------------------------------------- */ | |
| .hover-scale-sm { | |
| transition: transform 0.35s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform; | |
| } | |
| .hover-scale-sm:hover { | |
| transform: scale(1.02); | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .text-balance β Balanced text wrapping for headings | |
| ---------------------------------------------------------- | |
| Uses text-wrap: balance to distribute text more evenly | |
| across lines, producing better-looking headings. | |
| Usage: | |
| <h2 class="text-balance">A long heading that benefits from balanced wrapping</h2> | |
| ---------------------------------------------------------- */ | |
| .text-balance { | |
| text-wrap: balance; | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .glass-tag β Small glass pill/tag with color variants | |
| ---------------------------------------------------------- | |
| A small rounded-full tag with glassmorphic background, | |
| thin border, and 3 color variants: .indigo, .emerald, .amber. | |
| Usage: | |
| <span class="glass-tag indigo">Classification</span> | |
| <span class="glass-tag emerald">Success</span> | |
| <span class="glass-tag amber">Warning</span> | |
| ---------------------------------------------------------- */ | |
| .glass-tag { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| padding: 0.2rem 0.6rem; | |
| border-radius: 9999px; | |
| font-size: 0.7rem; | |
| font-weight: 500; | |
| border: 1px solid rgba(255, 255, 255, 0.08); | |
| background: rgba(255, 255, 255, 0.05); | |
| backdrop-filter: blur(8px); | |
| -webkit-backdrop-filter: blur(8px); | |
| color: var(--muted-foreground); | |
| transition: all 0.25s ease; | |
| } | |
| .glass-tag.indigo { | |
| border-color: rgba(99, 102, 241, 0.25); | |
| background: rgba(99, 102, 241, 0.1); | |
| color: #a5b4fc; | |
| } | |
| .glass-tag.emerald { | |
| border-color: rgba(16, 185, 129, 0.25); | |
| background: rgba(16, 185, 129, 0.1); | |
| color: #34d399; | |
| } | |
| .glass-tag.amber { | |
| border-color: rgba(245, 158, 11, 0.25); | |
| background: rgba(245, 158, 11, 0.1); | |
| color: #fbbf24; | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .card-gradient-top β Card with gradient top border | |
| ---------------------------------------------------------- | |
| Card featuring a 3px gradient top border (indigo to purple), | |
| glassmorphic background, and a subtle glow on hover. | |
| Usage: | |
| <div class="card-gradient-top glass-card">Card content</div> | |
| ---------------------------------------------------------- */ | |
| .card-gradient-top { | |
| position: relative; | |
| border-top: 3px solid transparent; | |
| border-image: linear-gradient(90deg, #6366f1, #8b5cf6) 1; | |
| background: rgba(15, 15, 35, 0.65); | |
| backdrop-filter: blur(16px); | |
| -webkit-backdrop-filter: blur(16px); | |
| transition: box-shadow 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .card-gradient-top:hover { | |
| box-shadow: | |
| 0 0 20px rgba(99, 102, 241, 0.1), | |
| 0 0 40px rgba(139, 92, 246, 0.05); | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .section-fade-in β Opacity + translateY entrance | |
| ---------------------------------------------------------- | |
| Provides an opacity 0β1 and translateY 20pxβ0 transition. | |
| Designed to pair with framer-motion whileInView for | |
| scroll-triggered reveal animations. | |
| Usage: | |
| <motion.div | |
| className="section-fade-in" | |
| initial={{ opacity: 0, y: 20 }} | |
| whileInView={{ opacity: 1, y: 0 }} | |
| viewport={{ once: true }} | |
| > | |
| ---------------------------------------------------------- */ | |
| .section-fade-in { | |
| transition: | |
| opacity 0.7s cubic-bezier(0.23, 1, 0.32, 1), | |
| transform 0.7s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: opacity, transform; | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .hero-subtitle β Large subtitle with text glow | |
| ---------------------------------------------------------- | |
| Large subtitle text for hero sections featuring a subtle | |
| text-shadow glow. Responsive font-size (lg: 1.25rem). | |
| Usage: | |
| <p class="hero-subtitle">Formation complète en ML</p> | |
| ---------------------------------------------------------- */ | |
| .hero-subtitle { | |
| font-size: 1.0625rem; | |
| line-height: 1.75; | |
| color: var(--muted-foreground); | |
| text-shadow: 0 0 30px rgba(99, 102, 241, 0.08); | |
| } | |
| @media (min-width: 1024px) { | |
| .hero-subtitle { | |
| font-size: 1.25rem; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .formula-display β Dark code block for formulas | |
| ---------------------------------------------------------- | |
| Styled container for mathematical formulas with a dark bg, | |
| monospace font, rounded-lg, and a gradient left border | |
| (3px, indigoβpurple). | |
| Usage: | |
| <div class="formula-display">y = wx + b</div> | |
| ---------------------------------------------------------- */ | |
| .formula-display { | |
| background: rgba(99, 102, 241, 0.05); | |
| font-family: 'JetBrains Mono', monospace; | |
| border-radius: 0.5rem; | |
| padding: 0.5rem 1rem; | |
| border-left: 3px solid transparent; | |
| border-image: linear-gradient(180deg, #6366f1, #8b5cf6) 1; | |
| color: var(--foreground); | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .streak-badge β Small badge for streak counter | |
| ---------------------------------------------------------- | |
| A compact inline-flex badge with glass background and | |
| text-xs sizing. Includes fire emoji spacing and amber text. | |
| Usage: | |
| <span class="streak-badge">5 jours d'affilΓ©e</span> | |
| ---------------------------------------------------------- */ | |
| .streak-badge { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| padding: 0.15rem 0.5rem; | |
| border-radius: 9999px; | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| background: rgba(245, 158, 11, 0.08); | |
| border: 1px solid rgba(245, 158, 11, 0.2); | |
| color: #fbbf24; | |
| backdrop-filter: blur(8px); | |
| -webkit-backdrop-filter: blur(8px); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .tab-indicator β Active tab indicator line | |
| ---------------------------------------------------------- | |
| A 2px gradient line (indigoβpurple) positioned at the | |
| bottom of an active tab. Uses transition-all for smooth | |
| position/width changes. | |
| Usage: | |
| <div class="tab-indicator" /> | |
| ---------------------------------------------------------- */ | |
| .tab-indicator { | |
| height: 2px; | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6); | |
| border-radius: 9999px; | |
| transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| position: absolute; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .card-hover-border β Gradient border on hover | |
| ---------------------------------------------------------- | |
| Card with gradient border that only appears on hover. | |
| Uses a ::before pseudo-element with transform: scaleY(0) | |
| that transitions to scaleY(1) on hover. | |
| Usage: | |
| <div class="card-hover-border">Card content</div> | |
| Note: | |
| - Parent must have position: relative and overflow: hidden | |
| ---------------------------------------------------------- */ | |
| .card-hover-border { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .card-hover-border::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| border-radius: inherit; | |
| padding: 2px; | |
| background: linear-gradient(135deg, #6366f1, #8b5cf6, #ec4899, #6366f1); | |
| background-size: 300% 300%; | |
| -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); | |
| -webkit-mask-composite: xor; | |
| mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); | |
| mask-composite: exclude; | |
| transform: scaleY(0); | |
| transform-origin: top; | |
| transition: transform 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| pointer-events: none; | |
| z-index: 1; | |
| } | |
| .card-hover-border:hover::before { | |
| transform: scaleY(1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .shimmer-hover β Shimmer effect only on hover | |
| ---------------------------------------------------------- | |
| A shimmer/shine animation that is paused by default and | |
| only plays when the element is hovered. Uses | |
| animation-play-state: paused / running. | |
| Usage: | |
| <div class="shimmer-hover">Hover me to see shimmer</div> | |
| ---------------------------------------------------------- */ | |
| .shimmer-hover { | |
| position: relative; | |
| overflow: hidden; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(255, 255, 255, 0.04) 25%, | |
| rgba(255, 255, 255, 0.1) 50%, | |
| rgba(255, 255, 255, 0.04) 75%, | |
| transparent 100% | |
| ); | |
| background-size: 200% 100%; | |
| animation: shimmer-hover 2s ease-in-out infinite; | |
| animation-play-state: paused; | |
| } | |
| .shimmer-hover:hover { | |
| animation-play-state: running; | |
| } | |
| @keyframes shimmer-hover { | |
| 0% { background-position: 200% 0; } | |
| 100% { background-position: -200% 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .glow-dot β Small glowing dot indicator | |
| ---------------------------------------------------------- | |
| A compact 8Γ8px glowing dot with box-shadow color glow. | |
| 4 color variants: .indigo, .emerald, .amber, .rose. | |
| Usage: | |
| <span class="glow-dot indigo"></span> | |
| <span class="glow-dot emerald"></span> | |
| <span class="glow-dot amber"></span> | |
| <span class="glow-dot rose"></span> | |
| ---------------------------------------------------------- */ | |
| .glow-dot { | |
| display: inline-block; | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 9999px; | |
| background: #6366f1; | |
| box-shadow: 0 0 6px rgba(99, 102, 241, 0.6), 0 0 12px rgba(99, 102, 241, 0.3); | |
| flex-shrink: 0; | |
| } | |
| .glow-dot.indigo { | |
| background: #6366f1; | |
| box-shadow: 0 0 6px rgba(99, 102, 241, 0.6), 0 0 12px rgba(99, 102, 241, 0.3); | |
| } | |
| .glow-dot.emerald { | |
| background: #10b981; | |
| box-shadow: 0 0 6px rgba(16, 185, 129, 0.6), 0 0 12px rgba(16, 185, 129, 0.3); | |
| } | |
| .glow-dot.amber { | |
| background: #f59e0b; | |
| box-shadow: 0 0 6px rgba(245, 158, 11, 0.6), 0 0 12px rgba(245, 158, 11, 0.3); | |
| } | |
| .glow-dot.rose { | |
| background: #f43f5e; | |
| box-shadow: 0 0 6px rgba(244, 63, 94, 0.6), 0 0 12px rgba(244, 63, 94, 0.3); | |
| } | |
| /* ============================================================ | |
| IA Academy β Phase 4 Enhancement Classes | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .hover-glow-border β Card with colored glow border on hover | |
| ---------------------------------------------------------- | |
| Applies a colored box-shadow glow around the card edges on | |
| hover. Default uses indigo glow. Three color variants available. | |
| Usage: | |
| <div class="hover-glow-border">Card content</div> | |
| <div class="hover-glow-border amber">Amber glow</div> | |
| <div class="hover-glow-border emerald">Emerald glow</div> | |
| <div class="hover-glow-border rose">Pink glow</div> | |
| Variants: | |
| (default) β indigo glow | |
| .amber β amber/gold glow | |
| .emerald β emerald/green glow | |
| .rose β pink/rose glow | |
| ---------------------------------------------------------- */ | |
| .hover-glow-border { | |
| transition: | |
| box-shadow 0.4s cubic-bezier(0.4, 0, 0.2, 1), | |
| border-color 0.4s cubic-bezier(0.4, 0, 0.2, 1); | |
| will-change: box-shadow; | |
| } | |
| .hover-glow-border:hover { | |
| box-shadow: | |
| 0 0 8px rgba(99, 102, 241, 0.3), | |
| 0 0 20px rgba(99, 102, 241, 0.15), | |
| 0 0 40px rgba(99, 102, 241, 0.08); | |
| border-color: rgba(99, 102, 241, 0.4); | |
| } | |
| .hover-glow-border.amber:hover { | |
| box-shadow: | |
| 0 0 8px rgba(245, 158, 11, 0.3), | |
| 0 0 20px rgba(245, 158, 11, 0.15), | |
| 0 0 40px rgba(245, 158, 11, 0.08); | |
| border-color: rgba(245, 158, 11, 0.4); | |
| } | |
| .hover-glow-border.emerald:hover { | |
| box-shadow: | |
| 0 0 8px rgba(16, 185, 129, 0.3), | |
| 0 0 20px rgba(16, 185, 129, 0.15), | |
| 0 0 40px rgba(16, 185, 129, 0.08); | |
| border-color: rgba(16, 185, 129, 0.4); | |
| } | |
| .hover-glow-border.rose:hover { | |
| box-shadow: | |
| 0 0 8px rgba(236, 72, 153, 0.3), | |
| 0 0 20px rgba(236, 72, 153, 0.15), | |
| 0 0 40px rgba(236, 72, 153, 0.08); | |
| border-color: rgba(236, 72, 153, 0.4); | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .text-gradient-animated β Gradient text with color sweep | |
| ---------------------------------------------------------- | |
| A 6-color gradient background that sweeps across the text | |
| in 8s, creating a smooth animated rainbow effect. Uses | |
| background-clip to color the text itself. Different from | |
| .gradient-text (which has glow + different animation curve). | |
| Usage: | |
| <h2 class="text-gradient-animated">Animated heading</h2> | |
| Note: | |
| - Requires display: inline-block or inline-flex for proper | |
| background sizing | |
| ---------------------------------------------------------- */ | |
| .text-gradient-animated { | |
| background: linear-gradient( | |
| 90deg, | |
| #6366f1, | |
| #ec4899, | |
| #f59e0b, | |
| #10b981, | |
| #06b6d4, | |
| #8b5cf6, | |
| #6366f1 | |
| ); | |
| background-size: 200% auto; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| animation: gradientTextSweep 8s linear infinite; | |
| } | |
| @keyframes gradientTextSweep { | |
| 0% { background-position: 0% center; } | |
| 100% { background-position: 200% center; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .card-shine-effect β Holographic shine sweep on hover | |
| ---------------------------------------------------------- | |
| A diagonal light/glare sweep that moves across the card on | |
| hover using a ::after pseudo-element. Simulates a holographic | |
| card catch-light effect. | |
| Usage: | |
| <div class="card-shine-effect">Card content</div> | |
| Note: | |
| - Parent must have overflow: hidden and position: relative | |
| ---------------------------------------------------------- */ | |
| .card-shine-effect { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .card-shine-effect::after { | |
| content: ''; | |
| position: absolute; | |
| top: -50%; | |
| left: -50%; | |
| width: 30%; | |
| height: 200%; | |
| background: linear-gradient( | |
| 120deg, | |
| transparent 0%, | |
| rgba(255, 255, 255, 0.03) 30%, | |
| rgba(255, 255, 255, 0.12) 45%, | |
| rgba(255, 255, 255, 0.15) 50%, | |
| rgba(255, 255, 255, 0.12) 55%, | |
| rgba(255, 255, 255, 0.03) 70%, | |
| transparent 100% | |
| ); | |
| transform: translateX(-100%); | |
| transition: transform 0.6s ease; | |
| pointer-events: none; | |
| z-index: 3; | |
| } | |
| .card-shine-effect:hover::after { | |
| transform: translateX(350%); | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .tooltip-float β Floating tooltip on hover | |
| ---------------------------------------------------------- | |
| A tooltip that appears above an element on hover using the | |
| ::after pseudo-element. Content is pulled from the data-tooltip | |
| attribute. Small glass background with rounded corners. | |
| Usage: | |
| <button class="tooltip-float" data-tooltip="Save item"> | |
| <Icon /> | |
| </button> | |
| Note: | |
| - Tooltip text set via data-tooltip attribute | |
| - pointer-events: none prevents tooltip from blocking clicks | |
| ---------------------------------------------------------- */ | |
| .tooltip-float { | |
| position: relative; | |
| } | |
| .tooltip-float::after { | |
| content: attr(data-tooltip); | |
| position: absolute; | |
| bottom: calc(100% + 8px); | |
| left: 50%; | |
| transform: translateX(-50%); | |
| padding: 0.25rem 0.5rem; | |
| border-radius: 6px; | |
| font-size: 0.75rem; | |
| white-space: nowrap; | |
| color: #f8fafc; | |
| background: rgba(21, 21, 48, 0.9); | |
| backdrop-filter: blur(8px); | |
| -webkit-backdrop-filter: blur(8px); | |
| border: 1px solid rgba(99, 102, 241, 0.25); | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); | |
| opacity: 0; | |
| transition: opacity 0.25s ease; | |
| pointer-events: none; | |
| z-index: 10; | |
| } | |
| .tooltip-float:hover::after { | |
| opacity: 1; | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .badge-pulse β Badge with pulsing glow animation | |
| ---------------------------------------------------------- | |
| A badge with a subtle box-shadow that pulses between | |
| transparent and a colored glow. Default uses indigo. | |
| Usage: | |
| <span class="badge-pulse">Badge text</span> | |
| <span class="badge-pulse amber">Amber badge</span> | |
| <span class="badge-pulse emerald">Emerald badge</span> | |
| Variants: | |
| (default) β indigo pulse | |
| .amber β amber pulse | |
| .emerald β emerald pulse | |
| ---------------------------------------------------------- */ | |
| .badge-pulse { | |
| animation: badgePulse 3s ease-in-out infinite; | |
| box-shadow: 0 0 0px transparent; | |
| } | |
| .badge-pulse.amber { | |
| animation-name: badgePulseAmber; | |
| } | |
| .badge-pulse.emerald { | |
| animation-name: badgePulseEmerald; | |
| } | |
| @keyframes badgePulse { | |
| 0%, 100% { | |
| box-shadow: 0 0 0px transparent; | |
| } | |
| 50% { | |
| box-shadow: | |
| 0 0 8px rgba(99, 102, 241, 0.3), | |
| 0 0 16px rgba(99, 102, 241, 0.15); | |
| } | |
| } | |
| @keyframes badgePulseAmber { | |
| 0%, 100% { | |
| box-shadow: 0 0 0px transparent; | |
| } | |
| 50% { | |
| box-shadow: | |
| 0 0 8px rgba(245, 158, 11, 0.3), | |
| 0 0 16px rgba(245, 158, 11, 0.15); | |
| } | |
| } | |
| @keyframes badgePulseEmerald { | |
| 0%, 100% { | |
| box-shadow: 0 0 0px transparent; | |
| } | |
| 50% { | |
| box-shadow: | |
| 0 0 8px rgba(16, 185, 129, 0.3), | |
| 0 0 16px rgba(16, 185, 129, 0.15); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .scroll-shadow-top β Top shadow on scrollable elements | |
| ---------------------------------------------------------- | |
| Displays a shadow at the top edge of a scrollable container | |
| using a ::before pseudo-element with a 20px gradient fade. | |
| Indicates to the user that there is content above. | |
| Usage: | |
| <div class="scroll-shadow-top" style="position:relative;overflow-y:auto;max-height:300px"> | |
| <p>Content</p> | |
| </div> | |
| Note: | |
| - Parent must have position: relative and overflow: auto/scroll | |
| ---------------------------------------------------------- */ | |
| .scroll-shadow-top { | |
| position: relative; | |
| } | |
| .scroll-shadow-top::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 20px; | |
| background: linear-gradient( | |
| 180deg, | |
| rgba(0, 0, 0, 0.3) 0%, | |
| transparent 100% | |
| ); | |
| pointer-events: none; | |
| z-index: 5; | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .input-glow-focus β Enhanced input glow on focus | |
| ---------------------------------------------------------- | |
| Adds a 2px indigo ring with a soft glow shadow when the | |
| input receives focus. Smooth transition for box-shadow and | |
| border-color changes. | |
| Usage: | |
| <input class="input-glow-focus" placeholder="Type here..." /> | |
| Behavior: | |
| - Focus: indigo ring + outer soft glow shadow | |
| ---------------------------------------------------------- */ | |
| .input-glow-focus { | |
| transition: | |
| box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1), | |
| border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .input-glow-focus:focus { | |
| border-color: rgba(99, 102, 241, 0.5); | |
| box-shadow: | |
| 0 0 0 2px rgba(99, 102, 241, 0.3), | |
| 0 0 15px rgba(99, 102, 241, 0.1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .card-stack-shadow β Layered shadow for stacked cards | |
| ---------------------------------------------------------- | |
| Multiple layered box-shadows that create a visual illusion | |
| of stacked cards underneath. Produces a subtle depth effect | |
| with gradually fading shadows. | |
| Usage: | |
| <div class="card-stack-shadow glass-card">Card content</div> | |
| ---------------------------------------------------------- */ | |
| .card-stack-shadow { | |
| box-shadow: | |
| 0 1px 0 0 rgba(99, 102, 241, 0.1), | |
| 0 2px 4px rgba(0, 0, 0, 0.1), | |
| 0 4px 8px rgba(0, 0, 0, 0.05), | |
| 0 8px 16px rgba(0, 0, 0, 0.03); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .icon-bounce-hover β Icon bounce animation on hover | |
| ---------------------------------------------------------- | |
| Applies a subtle vertical bounce to an icon when hovered. | |
| The icon moves up 3px and back down on hover. | |
| Usage: | |
| <Database class="w-6 h-6 icon-bounce-hover" /> | |
| Tip: | |
| - Works on any element (icons, spans, small buttons) | |
| - 0.5s ease transition for snappy feel | |
| ---------------------------------------------------------- */ | |
| .icon-bounce-hover { | |
| display: inline-block; | |
| transition: transform 0.5s ease; | |
| } | |
| .icon-bounce-hover:hover { | |
| animation: iconBounce 0.5s ease; | |
| } | |
| @keyframes iconBounce { | |
| 0%, 100% { | |
| transform: translateY(0); | |
| } | |
| 50% { | |
| transform: translateY(-3px); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .glass-divider-gradient β Gradient fade horizontal divider | |
| ---------------------------------------------------------- | |
| A 1px tall horizontal divider with gradient fade from | |
| transparent β indigo β transparent. Centered with max-width. | |
| Ideal as a subtle separator after section headings. | |
| Usage: | |
| <hr class="glass-divider-gradient" /> | |
| Tip: | |
| - Use after section headings for subtle visual separation | |
| - Already max-w-xs and mx-auto for centered narrow width | |
| ---------------------------------------------------------- */ | |
| .glass-divider-gradient { | |
| border: none; | |
| height: 1px; | |
| max-width: 320px; | |
| margin: 1rem auto 1.5rem auto; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(99, 102, 241, 0.3) 30%, | |
| rgba(99, 102, 241, 0.3) 70%, | |
| transparent 100% | |
| ); | |
| } | |
| /* ============================================================ | |
| IA Academy β Premium Utility Classes (Task 13-a) | |
| ============================================================ | |
| 15 new high-quality CSS utility classes for enhanced UI effects. | |
| All classes use CSS custom properties, dark-theme palette, and | |
| follow existing naming conventions. Appended at end of file. | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .neon-text β Glowing neon text effect with text-shadow layers | |
| ---------------------------------------------------------- | |
| Multi-layered text-shadow creates a vibrant neon glow around | |
| text. Default is indigo. Color variants via child classes. | |
| Usage: | |
| <h1 class="neon-text">Indigo neon heading</h1> | |
| <h1 class="neon-text emerald">Emerald neon heading</h1> | |
| <h1 class="neon-text amber">Amber neon heading</h1> | |
| <h1 class="neon-text rose">Rose neon heading</h1> | |
| Tip: | |
| - Works best on larger text (headings, hero text) | |
| - Combine with dark backgrounds for maximum contrast | |
| ---------------------------------------------------------- */ | |
| .neon-text { | |
| color: #c7d2fe; | |
| text-shadow: | |
| 0 0 4px rgba(99, 102, 241, 0.8), | |
| 0 0 11px rgba(99, 102, 241, 0.6), | |
| 0 0 22px rgba(99, 102, 241, 0.4), | |
| 0 0 44px rgba(99, 102, 241, 0.2), | |
| 0 0 80px rgba(99, 102, 241, 0.1); | |
| } | |
| .neon-text.emerald { | |
| color: #a7f3d0; | |
| text-shadow: | |
| 0 0 4px rgba(16, 185, 129, 0.8), | |
| 0 0 11px rgba(16, 185, 129, 0.6), | |
| 0 0 22px rgba(16, 185, 129, 0.4), | |
| 0 0 44px rgba(16, 185, 129, 0.2), | |
| 0 0 80px rgba(16, 185, 129, 0.1); | |
| } | |
| .neon-text.amber { | |
| color: #fde68a; | |
| text-shadow: | |
| 0 0 4px rgba(245, 158, 11, 0.8), | |
| 0 0 11px rgba(245, 158, 11, 0.6), | |
| 0 0 22px rgba(245, 158, 11, 0.4), | |
| 0 0 44px rgba(245, 158, 11, 0.2), | |
| 0 0 80px rgba(245, 158, 11, 0.1); | |
| } | |
| .neon-text.rose { | |
| color: #fecdd3; | |
| text-shadow: | |
| 0 0 4px rgba(236, 72, 153, 0.8), | |
| 0 0 11px rgba(236, 72, 153, 0.6), | |
| 0 0 22px rgba(236, 72, 153, 0.4), | |
| 0 0 44px rgba(236, 72, 153, 0.2), | |
| 0 0 80px rgba(236, 72, 153, 0.1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .glass-morphism-card β Premium glassmorphism card | |
| ---------------------------------------------------------- | |
| Enhanced glass card with animated border gradient (via | |
| conic-gradient rotation), strong backdrop blur, and a subtle | |
| inner glow on hover. More premium than the base .glass-card. | |
| Usage: | |
| <div class="glass-morphism-card p-6"> | |
| <h3>Premium Card Title</h3> | |
| <p>Card content with glassmorphism effect.</p> | |
| </div> | |
| Tip: | |
| - Use on elevated cards for a premium, modern feel | |
| - Works best over gradient or colorful backgrounds | |
| ---------------------------------------------------------- */ | |
| .glass-morphism-card { | |
| position: relative; | |
| background: rgba(15, 15, 40, 0.55); | |
| backdrop-filter: blur(24px) saturate(1.4); | |
| -webkit-backdrop-filter: blur(24px) saturate(1.4); | |
| border: 1px solid rgba(99, 102, 241, 0.15); | |
| border-radius: 16px; | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.06), | |
| inset 0 -1px 0 0 rgba(0, 0, 0, 0.2), | |
| 0 8px 32px rgba(0, 0, 0, 0.35), | |
| 0 0 0 1px rgba(99, 102, 241, 0.06); | |
| transition: | |
| transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| isolation: isolate; | |
| overflow: hidden; | |
| } | |
| .glass-morphism-card::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -2px; | |
| border-radius: inherit; | |
| background: conic-gradient( | |
| from 0deg, | |
| transparent 0%, | |
| rgba(99, 102, 241, 0.3) 8%, | |
| rgba(139, 92, 246, 0.4) 16%, | |
| rgba(168, 85, 247, 0.3) 24%, | |
| transparent 32%, | |
| transparent 100% | |
| ); | |
| animation: glassMorphismSpin 6s linear infinite; | |
| z-index: -2; | |
| } | |
| .glass-morphism-card::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 1px; | |
| border-radius: inherit; | |
| background: rgba(15, 15, 40, 0.9); | |
| z-index: -1; | |
| } | |
| .glass-morphism-card:hover { | |
| border-color: rgba(99, 102, 241, 0.35); | |
| transform: translateY(-4px) scale(1.005); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.1), | |
| inset 0 0 40px rgba(99, 102, 241, 0.05), | |
| inset 0 -1px 0 0 rgba(0, 0, 0, 0.25), | |
| 0 20px 48px rgba(0, 0, 0, 0.4), | |
| 0 0 0 1px rgba(99, 102, 241, 0.15), | |
| 0 0 50px rgba(99, 102, 241, 0.08); | |
| } | |
| @keyframes glassMorphismSpin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .animated-border β Animated gradient border with @property | |
| ---------------------------------------------------------- | |
| Uses CSS @property to animate a conic-gradient angle for a | |
| smooth rotating gradient border effect. The angle CSS custom | |
| property is interpolated by the browser for 60fps animation. | |
| Usage: | |
| <div class="animated-border p-4">Content with spinning border</div> | |
| Note: | |
| - @property is supported in Chrome 85+, Edge 85+, Safari 15.4+ | |
| - Fallback: static gradient border in unsupported browsers | |
| ---------------------------------------------------------- */ | |
| @property --animated-border-angle { | |
| syntax: '<angle>'; | |
| initial-value: 0deg; | |
| inherits: false; | |
| } | |
| .animated-border { | |
| --animated-border-angle: 0deg; | |
| position: relative; | |
| border-radius: 12px; | |
| isolation: isolate; | |
| animation: animatedBorderRotate 4s linear infinite; | |
| } | |
| .animated-border::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -2px; | |
| border-radius: inherit; | |
| background: conic-gradient( | |
| from var(--animated-border-angle), | |
| #6366f1 0%, | |
| #8b5cf6 15%, | |
| #ec4899 30%, | |
| #f59e0b 45%, | |
| #10b981 60%, | |
| #06b6d4 75%, | |
| #6366f1 90%, | |
| #6366f1 100% | |
| ); | |
| z-index: -2; | |
| } | |
| .animated-border::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 2px; | |
| border-radius: inherit; | |
| background: var(--card, #151530); | |
| z-index: -1; | |
| } | |
| @keyframes animatedBorderRotate { | |
| 0% { --animated-border-angle: 0deg; } | |
| 100% { --animated-border-angle: 360deg; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .hover-scale β Clean scale-on-hover with intensity variants | |
| ---------------------------------------------------------- | |
| Simple scale transform on hover with smooth cubic-bezier easing. | |
| Three intensity variants: .sm (subtle), .md (medium, default), | |
| .lg (dramatic). | |
| Usage: | |
| <div class="hover-scale">Medium scale (default 1.05)</div> | |
| <div class="hover-scale sm">Subtle scale (1.02)</div> | |
| <div class="hover-scale lg">Dramatic scale (1.08)</div> | |
| Tip: | |
| - Combine with .glass-card for cards that "pop" on hover | |
| - .sm for buttons, .md for cards, .lg for feature icons | |
| ---------------------------------------------------------- */ | |
| .hover-scale { | |
| transition: transform 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform; | |
| } | |
| .hover-scale:hover { | |
| transform: scale(1.05); | |
| } | |
| .hover-scale.sm:hover { | |
| transform: scale(1.02); | |
| } | |
| .hover-scale.lg:hover { | |
| transform: scale(1.08); | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .text-stroke β Outlined/stroke text with color variants | |
| ---------------------------------------------------------- | |
| Uses -webkit-text-stroke to create outlined text where only | |
| the stroke is visible and the fill is transparent. Four color | |
| variants match the IA Academy palette. | |
| Usage: | |
| <h2 class="text-stroke">Outlined heading</h2> | |
| <h2 class="text-stroke indigo">Indigo outlined</h2> | |
| <h2 class="text-stroke emerald">Emerald outlined</h2> | |
| <h2 class="text-stroke amber">Amber outlined</h2> | |
| <h2 class="text-stroke rose">Rose outlined</h2> | |
| Note: | |
| - Requires -webkit prefix for all current browsers | |
| - Best on large display text (2xl+) | |
| ---------------------------------------------------------- */ | |
| .text-stroke { | |
| -webkit-text-stroke: 1.5px rgba(99, 102, 241, 0.6); | |
| color: transparent; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| .text-stroke.indigo { | |
| -webkit-text-stroke: 1.5px rgba(99, 102, 241, 0.7); | |
| color: transparent; | |
| -webkit-text-fill-color: transparent; | |
| filter: drop-shadow(0 0 6px rgba(99, 102, 241, 0.2)); | |
| } | |
| .text-stroke.emerald { | |
| -webkit-text-stroke: 1.5px rgba(16, 185, 129, 0.7); | |
| color: transparent; | |
| -webkit-text-fill-color: transparent; | |
| filter: drop-shadow(0 0 6px rgba(16, 185, 129, 0.2)); | |
| } | |
| .text-stroke.amber { | |
| -webkit-text-stroke: 1.5px rgba(245, 158, 11, 0.7); | |
| color: transparent; | |
| -webkit-text-fill-color: transparent; | |
| filter: drop-shadow(0 0 6px rgba(245, 158, 11, 0.2)); | |
| } | |
| .text-stroke.rose { | |
| -webkit-text-stroke: 1.5px rgba(236, 72, 153, 0.7); | |
| color: transparent; | |
| -webkit-text-fill-color: transparent; | |
| filter: drop-shadow(0 0 6px rgba(236, 72, 153, 0.2)); | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .morphing-blob β Animated blob shape with morphing keyframes | |
| ---------------------------------------------------------- | |
| Creates an organic, amorphous blob shape using border-radius | |
| keyframe animation. The shape continuously morphs between | |
| different organic forms with smooth easing. | |
| Usage: | |
| <div class="morphing-blob"></div> | |
| <div class="morphing-blob" style="--blob-color: #10b981; --blob-size: 200px;"></div> | |
| CSS Variables: | |
| --blob-size: width/height of the blob (default: 150px) | |
| --blob-color: background color (default: rgba(99, 102, 241, 0.15)) | |
| Tip: | |
| - Use as decorative background elements behind content | |
| - Apply blur filter for softer appearance: style="filter: blur(40px)" | |
| ---------------------------------------------------------- */ | |
| .morphing-blob { | |
| --blob-size: 150px; | |
| --blob-color: rgba(99, 102, 241, 0.15); | |
| width: var(--blob-size); | |
| height: var(--blob-size); | |
| background: var(--blob-color); | |
| animation: morphBlob 10s ease-in-out infinite; | |
| will-change: border-radius, transform; | |
| } | |
| @keyframes morphBlob { | |
| 0%, 100% { | |
| border-radius: 40% 60% 70% 30% / 40% 50% 60% 50%; | |
| transform: rotate(0deg) scale(1); | |
| } | |
| 20% { | |
| border-radius: 50% 30% 50% 70% / 60% 40% 60% 40%; | |
| transform: rotate(72deg) scale(1.05); | |
| } | |
| 40% { | |
| border-radius: 30% 60% 40% 70% / 50% 70% 30% 60%; | |
| transform: rotate(144deg) scale(0.95); | |
| } | |
| 60% { | |
| border-radius: 60% 40% 70% 30% / 40% 60% 50% 70%; | |
| transform: rotate(216deg) scale(1.03); | |
| } | |
| 80% { | |
| border-radius: 40% 70% 30% 60% / 70% 30% 60% 40%; | |
| transform: rotate(288deg) scale(0.97); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .noise-overlay β Standalone subtle noise texture overlay | |
| ---------------------------------------------------------- | |
| Full-coverage noise texture using an inline SVG data URI with | |
| feTurbulence. Creates a subtle film-grain aesthetic over any | |
| container. Differs from the scoped .particle-bg > .noise-overlay. | |
| Usage: | |
| <div class="relative"> | |
| <div class="noise-overlay"></div> | |
| <div class="relative z-10">Content on top</div> | |
| </div> | |
| Note: | |
| - Must be positioned absolutely inside a relative parent | |
| - Adjust opacity with style="opacity: 0.04" for more/less grain | |
| ---------------------------------------------------------- */ | |
| .noise-overlay { | |
| position: absolute; | |
| inset: -50%; | |
| width: 200%; | |
| height: 200%; | |
| pointer-events: none; | |
| z-index: 1; | |
| opacity: 0.04; | |
| background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); | |
| background-repeat: repeat; | |
| background-size: 256px 256px; | |
| animation: noiseOverlayShift 0.8s steps(6) infinite; | |
| will-change: transform; | |
| } | |
| @keyframes noiseOverlayShift { | |
| 0% { transform: translate(0, 0); } | |
| 20% { transform: translate(-5%, -5%); } | |
| 40% { transform: translate(3%, 2%); } | |
| 60% { transform: translate(-2%, 4%); } | |
| 80% { transform: translate(4%, -3%); } | |
| 100% { transform: translate(0, 0); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .skeleton-shimmer β Shimmer loading placeholder animation | |
| ---------------------------------------------------------- | |
| Replaces generic loading states with a shimmer sweep effect | |
| that moves across the placeholder from left to right. Multiple | |
| size/shape variants for different content types. | |
| Usage: | |
| <div class="skeleton-shimmer h-4 w-3/4 rounded"></div> | |
| <div class="skeleton-shimmer h-32 w-full rounded-lg"></div> | |
| <div class="skeleton-shimmer h-6 w-1/2 rounded-full"></div> | |
| Tip: | |
| - Add rounded-lg for card skeletons, rounded-full for avatar | |
| - The base background is set here; override with width/height | |
| ---------------------------------------------------------- */ | |
| .skeleton-shimmer { | |
| background: linear-gradient( | |
| 90deg, | |
| rgba(30, 30, 60, 0.6) 0%, | |
| rgba(50, 50, 80, 0.8) 20%, | |
| rgba(70, 70, 100, 0.9) 40%, | |
| rgba(50, 50, 80, 0.8) 60%, | |
| rgba(30, 30, 60, 0.6) 80%, | |
| rgba(30, 30, 60, 0.6) 100% | |
| ); | |
| background-size: 200% 100%; | |
| animation: skeletonShimmer 2s ease-in-out infinite; | |
| border-radius: 8px; | |
| will-change: background-position; | |
| } | |
| @keyframes skeletonShimmer { | |
| 0% { background-position: 200% 0; } | |
| 100% { background-position: -200% 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .glow-dot β Small glowing dot indicator with pulse animation | |
| ---------------------------------------------------------- | |
| Compact 8px dot with a soft glow and pulsing ring animation. | |
| Five color variants for status indicators, online dots, or | |
| decorative accents. | |
| Usage: | |
| <span class="glow-dot"></span> | |
| <span class="glow-dot indigo"></span> | |
| <span class="glow-dot emerald"></span> | |
| <span class="glow-dot amber"></span> | |
| <span class="glow-dot rose"></span> | |
| <span class="glow-dot cyan"></span> | |
| Tip: | |
| - Use inside flex containers with gap for status lists | |
| - Combine with a label: <span class="glow-dot emerald mr-2"></span>En ligne | |
| ---------------------------------------------------------- */ | |
| .glow-dot { | |
| position: relative; | |
| display: inline-block; | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 50%; | |
| background: #6366f1; | |
| flex-shrink: 0; | |
| box-shadow: 0 0 6px rgba(99, 102, 241, 0.5), 0 0 12px rgba(99, 102, 241, 0.2); | |
| will-change: box-shadow; | |
| } | |
| .glow-dot::after { | |
| content: ''; | |
| position: absolute; | |
| inset: -4px; | |
| border-radius: 50%; | |
| border: 1.5px solid rgba(99, 102, 241, 0.3); | |
| animation: glowDotPulse 2s ease-in-out infinite; | |
| } | |
| .glow-dot.indigo { | |
| background: #818cf8; | |
| box-shadow: 0 0 6px rgba(99, 102, 241, 0.5), 0 0 12px rgba(99, 102, 241, 0.2); | |
| } | |
| .glow-dot.indigo::after { | |
| border-color: rgba(99, 102, 241, 0.3); | |
| } | |
| .glow-dot.emerald { | |
| background: #34d399; | |
| box-shadow: 0 0 6px rgba(16, 185, 129, 0.5), 0 0 12px rgba(16, 185, 129, 0.2); | |
| } | |
| .glow-dot.emerald::after { | |
| border-color: rgba(16, 185, 129, 0.3); | |
| } | |
| .glow-dot.amber { | |
| background: #fbbf24; | |
| box-shadow: 0 0 6px rgba(245, 158, 11, 0.5), 0 0 12px rgba(245, 158, 11, 0.2); | |
| } | |
| .glow-dot.amber::after { | |
| border-color: rgba(245, 158, 11, 0.3); | |
| } | |
| .glow-dot.rose { | |
| background: #fb7185; | |
| box-shadow: 0 0 6px rgba(236, 72, 153, 0.5), 0 0 12px rgba(236, 72, 153, 0.2); | |
| } | |
| .glow-dot.rose::after { | |
| border-color: rgba(236, 72, 153, 0.3); | |
| } | |
| .glow-dot.cyan { | |
| background: #22d3ee; | |
| box-shadow: 0 0 6px rgba(6, 182, 212, 0.5), 0 0 12px rgba(6, 182, 212, 0.2); | |
| } | |
| .glow-dot.cyan::after { | |
| border-color: rgba(6, 182, 212, 0.3); | |
| } | |
| @keyframes glowDotPulse { | |
| 0%, 100% { | |
| transform: scale(1); | |
| opacity: 0.7; | |
| } | |
| 50% { | |
| transform: scale(1.8); | |
| opacity: 0; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .backdrop-blur-card β Card with configurable blur intensity | |
| ---------------------------------------------------------- | |
| Glass-effect card with backdrop-filter blur at three intensity | |
| levels. Light, medium, and heavy variants for different use | |
| cases depending on background complexity. | |
| Usage: | |
| <div class="backdrop-blur-card light">Light blur (8px)</div> | |
| <div class="backdrop-blur-card medium">Medium blur (16px)</div> | |
| <div class="backdrop-blur-card heavy">Heavy blur (28px)</div> | |
| Tip: | |
| - .light: simple backgrounds, minimal content behind card | |
| - .medium: moderate backgrounds, general purpose (default) | |
| - .heavy: complex/busy backgrounds that need more obscuring | |
| ---------------------------------------------------------- */ | |
| .backdrop-blur-card { | |
| background: rgba(15, 15, 40, 0.5); | |
| border: 1px solid rgba(255, 255, 255, 0.06); | |
| border-radius: 12px; | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.04), | |
| 0 4px 16px rgba(0, 0, 0, 0.3); | |
| transition: | |
| border-color 0.4s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .backdrop-blur-card:hover { | |
| border-color: rgba(99, 102, 241, 0.25); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.06), | |
| 0 8px 24px rgba(0, 0, 0, 0.35), | |
| 0 0 20px rgba(99, 102, 241, 0.06); | |
| } | |
| .backdrop-blur-card.light { | |
| backdrop-filter: blur(8px) saturate(1.2); | |
| -webkit-backdrop-filter: blur(8px) saturate(1.2); | |
| } | |
| .backdrop-blur-card.medium { | |
| backdrop-filter: blur(16px) saturate(1.3); | |
| -webkit-backdrop-filter: blur(16px) saturate(1.3); | |
| } | |
| .backdrop-blur-card.heavy { | |
| backdrop-filter: blur(28px) saturate(1.5); | |
| -webkit-backdrop-filter: blur(28px) saturate(1.5); | |
| background: rgba(15, 15, 40, 0.4); | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .text-glow-animated β Animated pulsing text glow effect | |
| ---------------------------------------------------------- | |
| Text with a glow that pulses between soft and intense using | |
| CSS animation. Creates an attention-grabbing effect for | |
| important headings or status text. | |
| Usage: | |
| <h2 class="text-glow-animated">Pulsing glow heading</h2> | |
| Tip: | |
| - Use sparingly on key call-to-action text only | |
| - Works well with the neon-text variants for double effect | |
| ---------------------------------------------------------- */ | |
| .text-glow-animated { | |
| color: #c7d2fe; | |
| animation: textGlowPulse 3s ease-in-out infinite; | |
| will-change: text-shadow; | |
| } | |
| @keyframes textGlowPulse { | |
| 0%, 100% { | |
| text-shadow: | |
| 0 0 5px rgba(99, 102, 241, 0.3), | |
| 0 0 15px rgba(99, 102, 241, 0.15); | |
| } | |
| 50% { | |
| text-shadow: | |
| 0 0 8px rgba(99, 102, 241, 0.7), | |
| 0 0 25px rgba(99, 102, 241, 0.4), | |
| 0 0 50px rgba(139, 92, 246, 0.2), | |
| 0 0 80px rgba(99, 102, 241, 0.1); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .floating-badge β Badge with gentle float animation + shadow | |
| ---------------------------------------------------------- | |
| A small badge/pill that gently floats up and down with a soft | |
| shadow. Ideal for notification counts, feature labels, or | |
| status indicators that need visual emphasis. | |
| Usage: | |
| <span class="floating-badge">3 nouveau(x)</span> | |
| <span class="floating-badge amber">En attente</span> | |
| Tip: | |
| - Combine with .badge-glow for extra visual emphasis | |
| - Use sparingly to avoid visual clutter | |
| ---------------------------------------------------------- */ | |
| .floating-badge { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| padding: 0.25rem 0.75rem; | |
| border-radius: 9999px; | |
| font-size: 0.75rem; | |
| font-weight: 600; | |
| letter-spacing: 0.02em; | |
| background: rgba(99, 102, 241, 0.15); | |
| color: #a5b4fc; | |
| border: 1px solid rgba(99, 102, 241, 0.25); | |
| box-shadow: | |
| 0 4px 12px rgba(0, 0, 0, 0.2), | |
| 0 0 8px rgba(99, 102, 241, 0.08); | |
| animation: floatingBadgeBob 3s ease-in-out infinite; | |
| will-change: transform; | |
| } | |
| .floating-badge.amber { | |
| background: rgba(245, 158, 11, 0.15); | |
| color: #fcd34d; | |
| border-color: rgba(245, 158, 11, 0.25); | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2), 0 0 8px rgba(245, 158, 11, 0.08); | |
| } | |
| .floating-badge.emerald { | |
| background: rgba(16, 185, 129, 0.15); | |
| color: #6ee7b7; | |
| border-color: rgba(16, 185, 129, 0.25); | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2), 0 0 8px rgba(16, 185, 129, 0.08); | |
| } | |
| @keyframes floatingBadgeBob { | |
| 0%, 100% { | |
| transform: translateY(0); | |
| } | |
| 50% { | |
| transform: translateY(-4px); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 13. .gradient-border-card β Card with rotating conic-gradient border | |
| ---------------------------------------------------------- | |
| Card wrapped with a continuously rotating conic-gradient border | |
| using isolation/z-index layering. The gradient border spins | |
| smoothly around the card perimeter. | |
| Usage: | |
| <div class="gradient-border-card p-6">Premium card content</div> | |
| Tip: | |
| - The inner background inherits from --card CSS variable | |
| - For custom inner bg, override ::after background | |
| ---------------------------------------------------------- */ | |
| .gradient-border-card { | |
| position: relative; | |
| border-radius: 16px; | |
| isolation: isolate; | |
| overflow: hidden; | |
| } | |
| .gradient-border-card::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -3px; | |
| border-radius: inherit; | |
| background: conic-gradient( | |
| from 0deg, | |
| #6366f1 0%, | |
| #8b5cf6 25%, | |
| #ec4899 50%, | |
| #f59e0b 75%, | |
| #10b981 90%, | |
| #6366f1 100% | |
| ); | |
| animation: gradientBorderCardSpin 5s linear infinite; | |
| z-index: -2; | |
| } | |
| .gradient-border-card::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 2px; | |
| border-radius: inherit; | |
| background: var(--card, #151530); | |
| z-index: -1; | |
| } | |
| @keyframes gradientBorderCardSpin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 14. .hover-underline-animated β Underline animates left-to-right | |
| ---------------------------------------------------------- | |
| A subtle underline that slides in from left to right on hover. | |
| Uses a pseudo-element with scaleX transform for smooth animation. | |
| Default color is indigo; matches the IA Academy palette. | |
| Usage: | |
| <a href="#" class="hover-underline-animated">Hover me</a> | |
| <span class="hover-underline-animated">Interactive text</span> | |
| Note: | |
| - Works on any inline or inline-block element | |
| - The underline sits 2px below the text baseline | |
| ---------------------------------------------------------- */ | |
| .hover-underline-animated { | |
| position: relative; | |
| display: inline-block; | |
| text-decoration: none; | |
| cursor: pointer; | |
| } | |
| .hover-underline-animated::after { | |
| content: ''; | |
| position: absolute; | |
| bottom: -2px; | |
| left: 0; | |
| width: 100%; | |
| height: 2px; | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6); | |
| border-radius: 1px; | |
| transform: scaleX(0); | |
| transform-origin: left; | |
| transition: transform 0.35s cubic-bezier(0.23, 1, 0.32, 1); | |
| } | |
| .hover-underline-animated:hover::after { | |
| transform: scaleX(1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 15. .card-hover-lift β Card lifts and gains shadow on hover | |
| ---------------------------------------------------------- | |
| Card that smoothly lifts upward and gains a deeper shadow | |
| on hover, with a subtle perspective tilt for a 3D feel. | |
| Uses perspective transform for premium depth effect. | |
| Usage: | |
| <div class="card-hover-lift glass-card p-6"> | |
| <h3>Card that lifts on hover</h3> | |
| <p>Content here</p> | |
| </div> | |
| Tip: | |
| - Combine with .glass-card or .glass-morphism-card | |
| - The perspective is set on the container (800px) | |
| - lift height: 8px, shadow depth: 40px on hover | |
| ---------------------------------------------------------- */ | |
| .card-hover-lift { | |
| transition: | |
| transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| perspective: 800px; | |
| } | |
| .card-hover-lift:hover { | |
| transform: translateY(-8px) rotateX(1deg); | |
| box-shadow: | |
| 0 20px 40px rgba(0, 0, 0, 0.3), | |
| 0 8px 16px rgba(0, 0, 0, 0.2), | |
| 0 0 20px rgba(99, 102, 241, 0.06); | |
| } | |
| .card-hover-lift:active { | |
| transform: translateY(-2px) rotateX(0.5deg); | |
| box-shadow: | |
| 0 8px 16px rgba(0, 0, 0, 0.2), | |
| 0 4px 8px rgba(0, 0, 0, 0.1); | |
| transition-duration: 0.15s; | |
| } | |
| /* ============================================================ | |
| IA Academy β Task 13-a Styling Enhancements | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .glass-card-hover-3d β 3D perspective tilt card on hover | |
| ---------------------------------------------------------- | |
| A glass card that tilts in 3D perspective on hover using | |
| rotateX and rotateY transforms. Provides a subtle border | |
| glow effect and preserves the glassmorphism appearance. | |
| Usage: | |
| <div class="glass-card glass-card-hover-3d p-6">Content</div> | |
| Note: | |
| - Combine with .glass-card for the base glassmorphism style | |
| - Uses perspective: 1000px for realistic depth | |
| - Tilt angle: Β±5deg on each axis on hover | |
| ---------------------------------------------------------- */ | |
| .glass-card-hover-3d { | |
| perspective: 1000px; | |
| transform-style: preserve-3d; | |
| transition: | |
| transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .glass-card-hover-3d:hover { | |
| transform: rotateX(3deg) rotateY(-3deg) translateY(-4px) scale(1.02); | |
| border-color: rgba(99, 102, 241, 0.45); | |
| box-shadow: | |
| 0 20px 50px rgba(0, 0, 0, 0.4), | |
| 0 0 30px rgba(99, 102, 241, 0.12), | |
| 0 0 60px rgba(139, 92, 246, 0.06), | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .text-shadow-neon β Neon text shadow effect | |
| ---------------------------------------------------------- | |
| Adds a vibrant neon glow text-shadow effect. Four color | |
| variants available using modifier classes: .indigo, .purple, | |
| .emerald, .rose. | |
| Usage: | |
| <span class="text-shadow-neon indigo">Glowing text</span> | |
| <h1 class="text-shadow-neon purple">Neon heading</h1> | |
| Color variants: | |
| - .indigo β #6366f1 indigo glow | |
| - .purple β #8b5cf6 purple glow | |
| - .emerald β #10b981 emerald glow | |
| - .rose β #ec4899 rose glow | |
| ---------------------------------------------------------- */ | |
| .text-shadow-neon { | |
| color: #f8fafc; | |
| font-weight: 700; | |
| } | |
| .text-shadow-neon.indigo { | |
| text-shadow: | |
| 0 0 7px rgba(99, 102, 241, 0.8), | |
| 0 0 15px rgba(99, 102, 241, 0.5), | |
| 0 0 30px rgba(99, 102, 241, 0.3), | |
| 0 0 50px rgba(99, 102, 241, 0.15); | |
| } | |
| .text-shadow-neon.purple { | |
| text-shadow: | |
| 0 0 7px rgba(139, 92, 246, 0.8), | |
| 0 0 15px rgba(139, 92, 246, 0.5), | |
| 0 0 30px rgba(139, 92, 246, 0.3), | |
| 0 0 50px rgba(139, 92, 246, 0.15); | |
| } | |
| .text-shadow-neon.emerald { | |
| text-shadow: | |
| 0 0 7px rgba(16, 185, 129, 0.8), | |
| 0 0 15px rgba(16, 185, 129, 0.5), | |
| 0 0 30px rgba(16, 185, 129, 0.3), | |
| 0 0 50px rgba(16, 185, 129, 0.15); | |
| } | |
| .text-shadow-neon.rose { | |
| text-shadow: | |
| 0 0 7px rgba(236, 72, 153, 0.8), | |
| 0 0 15px rgba(236, 72, 153, 0.5), | |
| 0 0 30px rgba(236, 72, 153, 0.3), | |
| 0 0 50px rgba(236, 72, 153, 0.15); | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .animated-border β Animated rotating border gradient | |
| ---------------------------------------------------------- | |
| Uses @property to animate a custom --angle CSS property | |
| that drives a conic-gradient border rotation. Creates a | |
| continuously spinning colorful border effect. | |
| Usage: | |
| <div class="animated-border p-6">Content with spinning border</div> | |
| Note: | |
| - Uses @property for smooth angle animation (Chrome/Edge/Safari) | |
| - Falls back gracefully in Firefox (static gradient) | |
| - Border width: 2px, rotation period: 4s | |
| ---------------------------------------------------------- */ | |
| @property --animated-border-angle { | |
| syntax: '<angle>'; | |
| initial-value: 0deg; | |
| inherits: false; | |
| } | |
| .animated-border { | |
| position: relative; | |
| border: 2px solid transparent; | |
| border-radius: 12px; | |
| background: | |
| linear-gradient(var(--background, #151530), var(--background, #151530)) padding-box, | |
| conic-gradient( | |
| from var(--animated-border-angle), | |
| #6366f1, | |
| #8b5cf6, | |
| #ec4899, | |
| #f59e0b, | |
| #10b981, | |
| #06b6d4, | |
| #6366f1 | |
| ) border-box; | |
| animation: animatedBorderSpin 4s linear infinite; | |
| will-change: --animated-border-angle; | |
| } | |
| @keyframes animatedBorderSpin { | |
| to { --animated-border-angle: 360deg; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .card-gradient-bg β Glass card with gradient bg overlay | |
| ---------------------------------------------------------- | |
| A glass card variant that adds a subtle gradient background | |
| overlay behind the glass effect. Four color variants provide | |
| different mood options. | |
| Usage: | |
| <div class="card-gradient-bg indigo p-6">Colored card</div> | |
| <div class="card-gradient-bg amber glass-card p-6">Amber tint</div> | |
| Color variants: | |
| - .indigo β indigo-to-purple gradient overlay | |
| - .purple β purple-to-rose gradient overlay | |
| - .emerald β emerald-to-cyan gradient overlay | |
| - .amber β amber-to-orange gradient overlay | |
| ---------------------------------------------------------- */ | |
| .card-gradient-bg { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .card-gradient-bg::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| opacity: 0.08; | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| .card-gradient-bg.indigo::before { | |
| background: linear-gradient(135deg, rgba(99, 102, 241, 0.6), rgba(139, 92, 246, 0.4)); | |
| } | |
| .card-gradient-bg.purple::before { | |
| background: linear-gradient(135deg, rgba(139, 92, 246, 0.6), rgba(236, 72, 153, 0.4)); | |
| } | |
| .card-gradient-bg.emerald::before { | |
| background: linear-gradient(135deg, rgba(16, 185, 129, 0.6), rgba(6, 182, 212, 0.4)); | |
| } | |
| .card-gradient-bg.amber::before { | |
| background: linear-gradient(135deg, rgba(245, 158, 11, 0.6), rgba(249, 115, 22, 0.4)); | |
| } | |
| .card-gradient-bg > * { | |
| position: relative; | |
| z-index: 1; | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .hover-scale-glow β Combined scale + glow on hover | |
| ---------------------------------------------------------- | |
| Combines a subtle scale-up with a colored glow effect on | |
| hover for interactive cards. Uses the indigo/purple palette | |
| for a cohesive IA Academy look. | |
| Usage: | |
| <div class="hover-scale-glow glass-card p-6">Interactive card</div> | |
| Note: | |
| - Scale: 1.03 on hover | |
| - Glow: 20px indigo outer + 40px purple ambient | |
| - Works well with .glass-card | |
| ---------------------------------------------------------- */ | |
| .hover-scale-glow { | |
| transition: | |
| transform 0.4s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.4s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .hover-scale-glow:hover { | |
| transform: scale(1.03); | |
| box-shadow: | |
| 0 0 20px rgba(99, 102, 241, 0.2), | |
| 0 0 40px rgba(139, 92, 246, 0.1), | |
| 0 12px 30px rgba(0, 0, 0, 0.3); | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .shimmer-loading β Skeleton loading shimmer animation | |
| ---------------------------------------------------------- | |
| A shimmer sweep animation for loading placeholder states. | |
| The gradient sweeps left-to-right repeatedly, simulating | |
| content loading. Can be used for skeleton screens or applied | |
| to initial loading states. | |
| Usage: | |
| <div class="shimmer-loading h-4 w-32 rounded bg-secondary/50"></div> | |
| <div class="shimmer-loading h-20 w-full rounded-lg bg-secondary/30"></div> | |
| Note: | |
| - Apply a base background color via Tailwind (bg-secondary/50) | |
| - Animation duration: 2s, infinite loop | |
| - Gradient uses white at 10% opacity for subtle effect | |
| ---------------------------------------------------------- */ | |
| .shimmer-loading { | |
| background: linear-gradient( | |
| 90deg, | |
| transparent 0%, | |
| rgba(255, 255, 255, 0.06) 20%, | |
| rgba(255, 255, 255, 0.1) 50%, | |
| rgba(255, 255, 255, 0.06) 80%, | |
| transparent 100% | |
| ); | |
| background-size: 200% 100%; | |
| animation: shimmerLoading 2s ease-in-out infinite; | |
| will-change: background-position; | |
| } | |
| @keyframes shimmerLoading { | |
| 0% { background-position: 200% 0; } | |
| 100% { background-position: -200% 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .scrollbar-track-hidden β Hide scrollbar track, keep thumb | |
| ---------------------------------------------------------- | |
| Hides the scrollbar track background while keeping the thumb | |
| visible for a cleaner sidebar appearance. Works for both | |
| Webkit (Chrome/Safari/Edge) and Firefox. | |
| Usage: | |
| <div class="scrollbar-track-hidden overflow-y-auto h-64"> | |
| Long scrollable content... | |
| </div> | |
| Note: | |
| - Track: transparent background | |
| - Thumb: indigo gradient, 6px wide, rounded | |
| - Apply to any scrollable container | |
| ---------------------------------------------------------- */ | |
| .scrollbar-track-hidden { | |
| scrollbar-width: thin; | |
| scrollbar-color: rgba(99, 102, 241, 0.3) transparent; | |
| } | |
| .scrollbar-track-hidden::-webkit-scrollbar { | |
| width: 6px; | |
| } | |
| .scrollbar-track-hidden::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| .scrollbar-track-hidden::-webkit-scrollbar-thumb { | |
| background: rgba(99, 102, 241, 0.3); | |
| border-radius: 10px; | |
| border: none; | |
| } | |
| .scrollbar-track-hidden::-webkit-scrollbar-thumb:hover { | |
| background: rgba(99, 102, 241, 0.5); | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .text-outline β Gradient outline text | |
| ---------------------------------------------------------- | |
| Renders text with a gradient outline using -webkit-text-stroke, | |
| making the text appear as outlined/stroked rather than filled. | |
| Two color variants: .primary and .amber. | |
| Usage: | |
| <span class="text-outline primary">Outlined text</span> | |
| <h2 class="text-outline amber text-4xl">Big outline</h2> | |
| Color variants: | |
| - .primary β indigo-to-purple gradient stroke | |
| - .amber β amber-to-orange gradient stroke | |
| Note: | |
| - Uses background-clip trick for gradient stroke effect | |
| - Text fill is transparent to show only the outline | |
| - Best on large text (headings) | |
| ---------------------------------------------------------- */ | |
| .text-outline { | |
| -webkit-text-stroke: 2px transparent; | |
| background-clip: text; | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| font-weight: 900; | |
| } | |
| .text-outline.primary { | |
| -webkit-text-stroke: 2px #6366f1; | |
| background-image: linear-gradient(135deg, #6366f1, #8b5cf6); | |
| } | |
| .text-outline.amber { | |
| -webkit-text-stroke: 2px #f59e0b; | |
| background-image: linear-gradient(135deg, #f59e0b, #f97316); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .dot-indicator β Small dot with pulse animation | |
| ---------------------------------------------------------- | |
| A small circular dot indicator with a subtle pulse animation. | |
| Three size variants and emerald color modifier for status use. | |
| Usage: | |
| <span class="dot-indicator sm emerald"></span> | |
| <span class="dot-indicator md"></span> | |
| <span class="dot-indicator lg amber"></span> | |
| Size variants: | |
| - .sm β 6px dot | |
| - .md β 8px dot (default) | |
| - .lg β 12px dot | |
| Color variants: | |
| - Default: indigo (#6366f1) | |
| - .emerald β green (#10b981) | |
| - .amber β amber (#f59e0b) | |
| ---------------------------------------------------------- */ | |
| .dot-indicator { | |
| display: inline-block; | |
| width: 8px; | |
| height: 8px; | |
| border-radius: 50%; | |
| background: #6366f1; | |
| position: relative; | |
| flex-shrink: 0; | |
| } | |
| .dot-indicator.sm { | |
| width: 6px; | |
| height: 6px; | |
| } | |
| .dot-indicator.lg { | |
| width: 12px; | |
| height: 12px; | |
| } | |
| .dot-indicator::after { | |
| content: ''; | |
| position: absolute; | |
| inset: -3px; | |
| border-radius: 50%; | |
| border: 1px solid rgba(99, 102, 241, 0.3); | |
| animation: dotIndicatorPulse 2s ease-in-out infinite; | |
| } | |
| .dot-indicator.lg::after { | |
| inset: -4px; | |
| } | |
| .dot-indicator.emerald { | |
| background: #10b981; | |
| } | |
| .dot-indicator.emerald::after { | |
| border-color: rgba(16, 185, 129, 0.3); | |
| } | |
| .dot-indicator.amber { | |
| background: #f59e0b; | |
| } | |
| .dot-indicator.amber::after { | |
| border-color: rgba(245, 158, 11, 0.3); | |
| } | |
| @keyframes dotIndicatorPulse { | |
| 0%, 100% { | |
| transform: scale(1); | |
| opacity: 0.5; | |
| } | |
| 50% { | |
| transform: scale(1.6); | |
| opacity: 0; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .glass-badge-3d β 3D glass badge with depth | |
| ---------------------------------------------------------- | |
| A badge/tag with a glass background, depth shadow, hover lift | |
| effect, and subtle border. Designed for quiz difficulty badges, | |
| tags, and status indicators. | |
| Usage: | |
| <span class="glass-badge-3d">Facile</span> | |
| <span class="glass-badge-3d amber">IntermΓ©diaire</span> | |
| Note: | |
| - Combines backdrop-blur, shadow depth, and hover scale | |
| - Lifts 2px on hover with enhanced shadow | |
| - Works alongside existing Tailwind utility classes | |
| ---------------------------------------------------------- */ | |
| .glass-badge-3d { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.3rem; | |
| padding: 0.2rem 0.65rem; | |
| border-radius: 8px; | |
| font-size: 0.7rem; | |
| font-weight: 600; | |
| letter-spacing: 0.02em; | |
| background: rgba(15, 15, 35, 0.7); | |
| backdrop-filter: blur(12px); | |
| -webkit-backdrop-filter: blur(12px); | |
| border: 1px solid rgba(99, 102, 241, 0.25); | |
| color: #c7d2fe; | |
| box-shadow: | |
| 0 2px 8px rgba(0, 0, 0, 0.3), | |
| 0 1px 2px rgba(0, 0, 0, 0.2), | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.06); | |
| transition: | |
| transform 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .glass-badge-3d:hover { | |
| transform: translateY(-2px) scale(1.05); | |
| box-shadow: | |
| 0 6px 16px rgba(0, 0, 0, 0.35), | |
| 0 2px 4px rgba(0, 0, 0, 0.2), | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.08); | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .gradient-line-v β Vertical gradient line separator | |
| ---------------------------------------------------------- | |
| A vertical line with a gradient fade. Three color variants | |
| provide different gradient directions for visual variety. | |
| Usage: | |
| <div className="gradient-line-v indigo h-16 w-px"></div> | |
| Color variants: | |
| - .indigo β indigo top to transparent bottom | |
| - .purple β purple center, fading to transparent ends | |
| - .amber β amber top to transparent bottom | |
| ---------------------------------------------------------- */ | |
| .gradient-line-v { | |
| width: 1px; | |
| background: linear-gradient(180deg, transparent 0%, rgba(99, 102, 241, 0.4) 50%, transparent 100%); | |
| } | |
| .gradient-line-v.indigo { | |
| background: linear-gradient(180deg, rgba(99, 102, 241, 0.05) 0%, rgba(99, 102, 241, 0.4) 30%, rgba(139, 92, 246, 0.3) 70%, rgba(139, 92, 246, 0.05) 100%); | |
| } | |
| .gradient-line-v.purple { | |
| background: linear-gradient(180deg, rgba(139, 92, 246, 0.05) 0%, rgba(139, 92, 246, 0.4) 30%, rgba(168, 85, 247, 0.3) 70%, rgba(168, 85, 247, 0.05) 100%); | |
| } | |
| .gradient-line-v.amber { | |
| background: linear-gradient(180deg, rgba(245, 158, 11, 0.05) 0%, rgba(245, 158, 11, 0.4) 30%, rgba(249, 115, 22, 0.3) 70%, rgba(249, 115, 22, 0.05) 100%); | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .hover-underline-animated β Underline from left on hover | |
| ---------------------------------------------------------- | |
| NOTE: This class already exists above (section 14 of a | |
| previous block). This is an enhanced variant with additional | |
| gradient color support and a more visible underline. | |
| Usage: | |
| <a href="#" class="hover-underline-animated-v2">Link text</a> | |
| <button class="hover-underline-animated-v2">Button</button> | |
| Note: | |
| - Underline sits 3px below baseline for better visibility | |
| - Width: 2px, gradient from indigo to purple | |
| - Uses scaleX transform for smooth animation | |
| ---------------------------------------------------------- */ | |
| /* (Original .hover-underline-animated already defined above; keeping for reference) */ | |
| /* ---------------------------------------------------------- | |
| 13. .card-spotlight-hover β Spotlight follows cursor on hover | |
| ---------------------------------------------------------- | |
| A radial gradient "spotlight" that appears to follow the | |
| mouse cursor when hovering over a card. Uses a pseudo-element | |
| positioned at the top-right by default, shifting on hover. | |
| Usage: | |
| <div class="card-spotlight-hover glass-card p-6">Content</div> | |
| Note: | |
| - Uses ::before pseudo-element for the spotlight gradient | |
| - Default position: top-right corner | |
| - On hover: shifts to center, enlarges | |
| - Works best with .glass-card and overflow: hidden | |
| ---------------------------------------------------------- */ | |
| .card-spotlight-hover { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .card-spotlight-hover::before { | |
| content: ''; | |
| position: absolute; | |
| top: -40%; | |
| right: -20%; | |
| width: 50%; | |
| height: 60%; | |
| background: radial-gradient( | |
| circle at center, | |
| rgba(99, 102, 241, 0.12) 0%, | |
| rgba(139, 92, 246, 0.06) 40%, | |
| transparent 70% | |
| ); | |
| border-radius: 50%; | |
| pointer-events: none; | |
| z-index: 1; | |
| transition: | |
| top 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| right 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| width 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| height 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| opacity 0.5s ease; | |
| opacity: 0; | |
| } | |
| .card-spotlight-hover:hover::before { | |
| top: 20%; | |
| right: 20%; | |
| width: 70%; | |
| height: 80%; | |
| opacity: 1; | |
| } | |
| /* ---------------------------------------------------------- | |
| 14. .stagger-grid β Grid with staggered child animations | |
| ---------------------------------------------------------- | |
| A grid container that applies staggered animation delays to | |
| its direct children using nth-child selectors. Children should | |
| have a transition or animation defined for the delay to be | |
| visible (e.g., framer-motion or opacity transitions). | |
| Usage: | |
| <div class="stagger-grid grid sm:grid-cols-2 lg:grid-cols-3 gap-6"> | |
| <div>Card 1</div> <!-- 0ms delay --> | |
| <div>Card 2</div> <!-- 80ms delay --> | |
| <div>Card 3</div> <!-- 160ms delay --> | |
| ... | |
| </div> | |
| Note: | |
| - Applies to up to 12 children (nth-child(1) through nth-child(12)) | |
| - Each child gets an additional 80ms delay | |
| - Children need their own opacity/transform transition | |
| ---------------------------------------------------------- */ | |
| .stagger-grid > :nth-child(1) { animation-delay: 0ms; transition-delay: 0ms; } | |
| .stagger-grid > :nth-child(2) { animation-delay: 80ms; transition-delay: 80ms; } | |
| .stagger-grid > :nth-child(3) { animation-delay: 160ms; transition-delay: 160ms; } | |
| .stagger-grid > :nth-child(4) { animation-delay: 240ms; transition-delay: 240ms; } | |
| .stagger-grid > :nth-child(5) { animation-delay: 320ms; transition-delay: 320ms; } | |
| .stagger-grid > :nth-child(6) { animation-delay: 400ms; transition-delay: 400ms; } | |
| .stagger-grid > :nth-child(7) { animation-delay: 480ms; transition-delay: 480ms; } | |
| .stagger-grid > :nth-child(8) { animation-delay: 560ms; transition-delay: 560ms; } | |
| .stagger-grid > :nth-child(9) { animation-delay: 640ms; transition-delay: 640ms; } | |
| .stagger-grid > :nth-child(10) { animation-delay: 720ms; transition-delay: 720ms; } | |
| .stagger-grid > :nth-child(11) { animation-delay: 800ms; transition-delay: 800ms; } | |
| .stagger-grid > :nth-child(12) { animation-delay: 880ms; transition-delay: 880ms; } | |
| /* ---------------------------------------------------------- | |
| 15. .text-gradient-scroll β Text gradient shifts over time | |
| ---------------------------------------------------------- | |
| Text with a gradient fill that continuously scrolls/shifts | |
| through colors over time. Creates an eye-catching animated | |
| rainbow gradient text effect. | |
| Usage: | |
| <h1 class="text-gradient-scroll text-4xl font-bold">Animated text</h1> | |
| <span class="text-gradient-scroll">Colorful label</span> | |
| Note: | |
| - Animation cycle: 8s, infinite loop | |
| - Uses 6 colors from the IA Academy palette | |
| - background-size: 300% for smooth gradient travel | |
| - Works best on bold text for maximum visual impact | |
| ---------------------------------------------------------- */ | |
| .text-gradient-scroll { | |
| background: linear-gradient( | |
| 90deg, | |
| #6366f1 0%, | |
| #8b5cf6 17%, | |
| #ec4899 33%, | |
| #f59e0b 50%, | |
| #10b981 67%, | |
| #06b6d4 83%, | |
| #6366f1 100% | |
| ); | |
| background-size: 300% 100%; | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| animation: textGradientScroll 8s linear infinite; | |
| will-change: background-position; | |
| } | |
| @keyframes textGradientScroll { | |
| 0% { background-position: 0% 50%; } | |
| 100% { background-position: 300% 50%; } | |
| } | |
| /* ============================================================ | |
| CSS CYCLE 8 β 12 New Utility Classes | |
| ============================================================ | |
| 1. .glass-card-amber β Warm amber glass card variant | |
| 2. .text-glow-soft β Soft ambient text glow (4 color variants) | |
| 3. .hover-border-glow β Animated border glow on hover (3 variants) | |
| 4. .card-hover-bounce β Card with spring bounce on hover | |
| 5. .shimmer-border β Shimmer animation on border | |
| 6. .text-count-up β Styled for counting number displays | |
| 7. .glass-chip β Small inline glass chip/tag (5 variants) | |
| 8. .hover-lift-sm β Small lift effect on hover | |
| 9. .gradient-text-warm β Warm gradient text (amber β orange β rose) | |
| 10. .card-inner-glow β Card with soft inner glow inset shadow | |
| 11. .animate-fade-in-up β Fade-in-up animation (3 duration variants) | |
| 12. .dot-grid-bg β Subtle dot grid background pattern | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .glass-card-amber β Glass card with warm amber tint | |
| ---------------------------------------------------------- | |
| Glassmorphism card variant with a subtle warm amber/gold | |
| overlay and an amber border glow on hover. | |
| Usage: | |
| <div className="glass-card-amber p-6 rounded-xl">Content</div> | |
| Note: | |
| - Uses rgba(245, 158, 11, 0.06) overlay for warm tint | |
| - Border glow: amber-400 with 20% opacity on hover | |
| - Inherits glassmorphism backdrop-blur from glass-card pattern | |
| ---------------------------------------------------------- */ | |
| .glass-card-amber { | |
| background: rgba(245, 158, 11, 0.06); | |
| backdrop-filter: blur(16px); | |
| -webkit-backdrop-filter: blur(16px); | |
| border: 1px solid rgba(245, 158, 11, 0.12); | |
| border-radius: 1rem; | |
| transition: border-color 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .glass-card-amber:hover { | |
| border-color: rgba(251, 191, 36, 0.3); | |
| box-shadow: 0 0 20px rgba(245, 158, 11, 0.08), 0 8px 32px rgba(245, 158, 11, 0.04); | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .text-glow-soft β Soft ambient text glow | |
| ---------------------------------------------------------- | |
| Subtle text glow effect using text-shadow with small blur | |
| values for a softer, more refined look than text-shadow-neon. | |
| Usage: | |
| <h2 className="text-glow-soft indigo">Glowing heading</h2> | |
| <span className="text-glow-soft emerald">Status</span> | |
| Variants: | |
| .indigo β #6366f1 glow | |
| .purple β #8b5cf6 glow | |
| .emerald β #10b981 glow | |
| .amber β #f59e0b glow | |
| Note: | |
| - Uses 6px and 12px blur values for subtlety | |
| - Text color matches the glow color for cohesion | |
| - 0.3-0.5 opacity to keep it soft | |
| ---------------------------------------------------------- */ | |
| .text-glow-soft.indigo { | |
| color: #818cf8; | |
| text-shadow: 0 0 6px rgba(99, 102, 241, 0.4), 0 0 12px rgba(99, 102, 241, 0.2); | |
| } | |
| .text-glow-soft.purple { | |
| color: #a78bfa; | |
| text-shadow: 0 0 6px rgba(139, 92, 246, 0.4), 0 0 12px rgba(139, 92, 246, 0.2); | |
| } | |
| .text-glow-soft.emerald { | |
| color: #34d399; | |
| text-shadow: 0 0 6px rgba(16, 185, 129, 0.4), 0 0 12px rgba(16, 185, 129, 0.2); | |
| } | |
| .text-glow-soft.amber { | |
| color: #fbbf24; | |
| text-shadow: 0 0 6px rgba(245, 158, 11, 0.4), 0 0 12px rgba(245, 158, 11, 0.2); | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .hover-border-glow β Animated border glow on hover | |
| ---------------------------------------------------------- | |
| Interactive element where the border transitions from | |
| transparent/ subtle to a colored glow on hover. | |
| Usage: | |
| <div className="hover-border-glow indigo p-4 rounded-xl">Item</div> | |
| Variants: | |
| .indigo β #6366f1 border glow | |
| .emerald β #10b981 border glow | |
| .rose β #f43f5e border glow | |
| Note: | |
| - Border transitions smoothly over 0.3s | |
| - Box-shadow spreads 12px on hover for glow effect | |
| - Requires explicit border-radius for proper visual | |
| ---------------------------------------------------------- */ | |
| .hover-border-glow { | |
| border: 1px solid transparent; | |
| transition: border-color 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .hover-border-glow.indigo:hover { | |
| border-color: rgba(99, 102, 241, 0.4); | |
| box-shadow: 0 0 12px rgba(99, 102, 241, 0.15), inset 0 0 12px rgba(99, 102, 241, 0.05); | |
| } | |
| .hover-border-glow.emerald:hover { | |
| border-color: rgba(16, 185, 129, 0.4); | |
| box-shadow: 0 0 12px rgba(16, 185, 129, 0.15), inset 0 0 12px rgba(16, 185, 129, 0.05); | |
| } | |
| .hover-border-glow.rose:hover { | |
| border-color: rgba(244, 63, 94, 0.4); | |
| box-shadow: 0 0 12px rgba(244, 63, 94, 0.15), inset 0 0 12px rgba(244, 63, 94, 0.05); | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .card-hover-bounce β Card with spring bounce on hover | |
| ---------------------------------------------------------- | |
| Card that bounces slightly on hover with a spring-like | |
| animation using cubic-bezier easing for a playful feel. | |
| Usage: | |
| <div className="card-hover-bounce p-6 rounded-xl">Content</div> | |
| Note: | |
| - translateY: -6px on hover | |
| - cubic-bezier(0.34, 1.56, 0.64, 1) for spring overshoot | |
| - Subtle shadow increase for depth | |
| - transition: 0.35s for smooth spring motion | |
| ---------------------------------------------------------- */ | |
| .card-hover-bounce { | |
| transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.35s ease; | |
| } | |
| .card-hover-bounce:hover { | |
| transform: translateY(-6px); | |
| box-shadow: 0 12px 28px rgba(0, 0, 0, 0.25), 0 4px 10px rgba(0, 0, 0, 0.1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .shimmer-border β Shimmer animation on border | |
| ---------------------------------------------------------- | |
| Card or container with a shimmering animated gradient | |
| border that sweeps around the perimeter. | |
| Usage: | |
| <div className="shimmer-border p-6 rounded-xl">Content</div> | |
| Note: | |
| - Uses a pseudo-element for the animated gradient border | |
| - Background-size: 300% 300% for the sweep animation | |
| - Animation: shimmerBorder 3s linear infinite | |
| - Requires position: relative on the parent | |
| ---------------------------------------------------------- */ | |
| .shimmer-border { | |
| position: relative; | |
| border: 1px solid rgba(99, 102, 241, 0.2); | |
| border-radius: 1rem; | |
| overflow: hidden; | |
| } | |
| .shimmer-border::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -1px; | |
| border-radius: inherit; | |
| padding: 1px; | |
| background: linear-gradient( | |
| 60deg, | |
| transparent 20%, | |
| rgba(99, 102, 241, 0.5) 40%, | |
| rgba(139, 92, 246, 0.5) 50%, | |
| rgba(236, 72, 153, 0.3) 60%, | |
| transparent 80% | |
| ); | |
| background-size: 300% 300%; | |
| animation: shimmerBorder 3s linear infinite; | |
| -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); | |
| mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); | |
| -webkit-mask-composite: xor; | |
| mask-composite: exclude; | |
| pointer-events: none; | |
| } | |
| @keyframes shimmerBorder { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .text-count-up β Styled for counting number displays | |
| ---------------------------------------------------------- | |
| Text element styled for displaying numbers that change | |
| (count-up animations, stats, timers, etc.). | |
| Usage: | |
| <span className="text-count-up text-2xl font-bold">1,247</span> | |
| Note: | |
| - font-variant-numeric: tabular-nums for fixed-width digits | |
| - letter-spacing: 0.05em for readability | |
| - Prevents layout shift when digits change | |
| ---------------------------------------------------------- */ | |
| .text-count-up { | |
| font-variant-numeric: tabular-nums; | |
| letter-spacing: 0.05em; | |
| font-feature-settings: 'tnum' on, 'lnum' on; | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .glass-chip β Small inline chip/tag with glass bg | |
| ---------------------------------------------------------- | |
| Small inline chip/tag with glass background, rounded-full, | |
| and subtle border. Ideal for categories, tags, and filters. | |
| Usage: | |
| <span className="glass-chip indigo">Category</span> | |
| <span className="glass-chip emerald">Active</span> | |
| Variants: | |
| .default β Neutral gray glass chip | |
| .indigo β #6366f1 tinted glass chip | |
| .emerald β #10b981 tinted glass chip | |
| .amber β #f59e0b tinted glass chip | |
| .rose β #f43f5e tinted glass chip | |
| Note: | |
| - backdrop-filter: blur(8px) for glass effect | |
| - border: 1px solid with low opacity color match | |
| - font-size: 0.75rem (text-xs), padding: 0.25rem 0.75rem | |
| ---------------------------------------------------------- */ | |
| .glass-chip { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.375rem; | |
| padding: 0.25rem 0.75rem; | |
| border-radius: 9999px; | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| backdrop-filter: blur(8px); | |
| -webkit-backdrop-filter: blur(8px); | |
| transition: all 0.2s ease; | |
| } | |
| .glass-chip.default { | |
| background: rgba(148, 163, 184, 0.1); | |
| border: 1px solid rgba(148, 163, 184, 0.2); | |
| color: #94a3b8; | |
| } | |
| .glass-chip.indigo { | |
| background: rgba(99, 102, 241, 0.12); | |
| border: 1px solid rgba(99, 102, 241, 0.25); | |
| color: #818cf8; | |
| } | |
| .glass-chip.emerald { | |
| background: rgba(16, 185, 129, 0.12); | |
| border: 1px solid rgba(16, 185, 129, 0.25); | |
| color: #34d399; | |
| } | |
| .glass-chip.amber { | |
| background: rgba(245, 158, 11, 0.12); | |
| border: 1px solid rgba(245, 158, 11, 0.25); | |
| color: #fbbf24; | |
| } | |
| .glass-chip.rose { | |
| background: rgba(244, 63, 94, 0.12); | |
| border: 1px solid rgba(244, 63, 94, 0.25); | |
| color: #fb7185; | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .hover-lift-sm β Small lift effect on hover | |
| ---------------------------------------------------------- | |
| Smaller lift effect for smaller interactive elements like | |
| buttons and chips. Less dramatic than card lift effects. | |
| Usage: | |
| <button className="hover-lift-sm px-4 py-2 rounded-lg">Click me</button> | |
| Note: | |
| - translateY: -2px (subtle) | |
| - box-shadow: 0 4px 12px for depth | |
| - transition: 0.2s for snappy response | |
| ---------------------------------------------------------- */ | |
| .hover-lift-sm { | |
| transition: transform 0.2s ease, box-shadow 0.2s ease; | |
| } | |
| .hover-lift-sm:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .gradient-text-warm β Warm gradient text | |
| ---------------------------------------------------------- | |
| Warm gradient text variant using amber β orange β rose | |
| colors for emphasis and warning elements. | |
| Usage: | |
| <h2 className="gradient-text-warm text-2xl font-bold">Important</h2> | |
| Note: | |
| - Colors: #f59e0b β #f97316 β #f43f5e | |
| - Uses background-clip: text for gradient fill | |
| - Works with any text size | |
| ---------------------------------------------------------- */ | |
| .gradient-text-warm { | |
| background: linear-gradient(135deg, #f59e0b 0%, #f97316 50%, #f43f5e 100%); | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .card-inner-glow β Card with soft inner glow | |
| ---------------------------------------------------------- | |
| Card with a soft inner glow effect using box-shadow inset. | |
| Creates a subtle luminous feel from within the card. | |
| Usage: | |
| <div className="card-inner-glow p-6 rounded-xl">Content</div> | |
| Note: | |
| - Uses inset box-shadow with low opacity | |
| - Color: rgba(99, 102, 241, 0.06) for indigo tint | |
| - Combines with outer shadow for depth | |
| ---------------------------------------------------------- */ | |
| .card-inner-glow { | |
| box-shadow: inset 0 1px 20px rgba(99, 102, 241, 0.06), 0 4px 16px rgba(0, 0, 0, 0.08); | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .animate-fade-in-up β Fade-in-up animation | |
| ---------------------------------------------------------- | |
| Fade-in-up animation with opacity 0β1 and | |
| translateY 20pxβ0. Includes 3 duration variants. | |
| Usage: | |
| <div className="animate-fade-in-up normal">Content</div> | |
| <div className="animate-fade-in-up fast">Quick entry</div> | |
| Variants: | |
| .fast β 0.3s duration (snappy) | |
| .normal β 0.5s duration (default, smooth) | |
| .slow β 0.8s duration (dramatic) | |
| Note: | |
| - ease-out timing for natural deceleration | |
| - fill-mode: both to hold end state | |
| ---------------------------------------------------------- */ | |
| .animate-fade-in-up.fast { | |
| animation: fadeInUp 0.3s ease-out both; | |
| } | |
| .animate-fade-in-up.normal { | |
| animation: fadeInUp 0.5s ease-out both; | |
| } | |
| .animate-fade-in-up.slow { | |
| animation: fadeInUp 0.8s ease-out both; | |
| } | |
| @keyframes fadeInUp { | |
| 0% { | |
| opacity: 0; | |
| transform: translateY(20px); | |
| } | |
| 100% { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .dot-grid-bg β Subtle dot grid background pattern | |
| ---------------------------------------------------------- | |
| Very subtle dot grid background using radial-gradient. | |
| Ideal for section backgrounds to add visual texture. | |
| Usage: | |
| <section className="dot-grid-bg py-16">Content</section> | |
| Note: | |
| - Dot size: 1px, gap: 24px | |
| - Color: rgba(148, 163, 184, 0.1) for subtlety | |
| - Does not interfere with content readability | |
| ---------------------------------------------------------- */ | |
| .dot-grid-bg { | |
| background-image: radial-gradient(circle, rgba(148, 163, 184, 0.1) 1px, transparent 1px); | |
| background-size: 24px 24px; | |
| } | |
| /* ========================================================== | |
| NEW UTILITY CLASSES β Appended batch | |
| ========================================================== */ | |
| /* ---------------------------------------------------------- | |
| 1. .text-shadow-soft β Soft, diffused text shadow | |
| ---------------------------------------------------------- | |
| Improves text readability when placed over gradient | |
| backgrounds, hero images, or any visually busy surface. | |
| Usage: | |
| <h1 className="text-shadow-soft">Title over gradient</h1> | |
| Note: | |
| - shadow: rgba(0,0,0,0.5) with 8px blur | |
| - Fully compatible with light / white text on dark bg | |
| ---------------------------------------------------------- */ | |
| .text-shadow-soft { | |
| text-shadow: | |
| 0 2px 4px rgba(0, 0, 0, 0.3), | |
| 0 0 8px rgba(0, 0, 0, 0.5); | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .card-gradient-top β Card with a gradient top border | |
| ---------------------------------------------------------- | |
| Adds a thin (3px) gradient accent strip at the top of a | |
| card, giving it a coloured "header stripe" appearance. | |
| Variants: | |
| .indigo β primary (#6366f1) β purple (#8b5cf6) | |
| .emerald β emerald (#10b981) β cyan (#06b6d4) | |
| .amber β amber (#f59e0b) β pink (#ec4899) | |
| .rose β pink (#ec4899) β red (#ef4444) | |
| Usage: | |
| <div className="card-gradient-top indigo rounded-xl p-6"> | |
| Card content | |
| </div> | |
| Note: | |
| - Uses ::before pseudo-element so it layers above | |
| background but below card content (z-index: 1). | |
| - Cards should have position: relative. | |
| ---------------------------------------------------------- */ | |
| .card-gradient-top { | |
| position: relative; | |
| border-radius: var(--radius, 0.75rem); | |
| overflow: hidden; | |
| } | |
| .card-gradient-top::before { | |
| content: ""; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| height: 3px; | |
| z-index: 1; | |
| } | |
| .card-gradient-top.indigo::before { | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6); | |
| } | |
| .card-gradient-top.emerald::before { | |
| background: linear-gradient(90deg, #10b981, #06b6d4); | |
| } | |
| .card-gradient-top.amber::before { | |
| background: linear-gradient(90deg, #f59e0b, #ec4899); | |
| } | |
| .card-gradient-top.rose::before { | |
| background: linear-gradient(90deg, #ec4899, #ef4444); | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .hover-scale-sm β Subtle scale on hover | |
| ---------------------------------------------------------- | |
| Gentle lift effect for interactive cards, buttons, or any | |
| element that needs a tactile hover response. | |
| Usage: | |
| <div className="hover-scale-sm cursor-pointer"> | |
| Hover me | |
| </div> | |
| Note: | |
| - Scale: 1 β 1.02 | |
| - Transition: 0.3s ease | |
| - Works best with will-change for GPU compositing | |
| ---------------------------------------------------------- */ | |
| .hover-scale-sm { | |
| transition: transform 0.3s ease; | |
| will-change: transform; | |
| } | |
| .hover-scale-sm:hover { | |
| transform: scale(1.02); | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .scroll-shadow-top β Inner shadow at top of scroll area | |
| ---------------------------------------------------------- | |
| Indicates there is more content scrolled out of view | |
| above. Apply to the scrollable container itself. | |
| Usage: | |
| <div className="scroll-shadow-top overflow-y-auto max-h-64"> | |
| <p>Long contentβ¦</p> | |
| </div> | |
| Note: | |
| - Inset box-shadow: 0 8px 6px -6px rgba(0,0,0,0.3) | |
| - Only affects the top edge | |
| ---------------------------------------------------------- */ | |
| .scroll-shadow-top { | |
| box-shadow: inset 0 8px 6px -6px rgba(0, 0, 0, 0.3); | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .skeleton-pulse β Skeleton loading animation | |
| ---------------------------------------------------------- | |
| Pulsing placeholder for content that is still loading. | |
| Usage: | |
| <div className="skeleton-pulse h-4 w-48 rounded" /> | |
| Note: | |
| - Animates between bg-muted at 30% β 60% opacity | |
| - Duration: 1.5s, ease-in-out, infinite loop | |
| - Rounded corners inherited from applied classes | |
| ---------------------------------------------------------- */ | |
| .skeleton-pulse { | |
| background: rgba(var(--muted), 0.3); | |
| animation: skeletonPulse 1.5s ease-in-out infinite; | |
| } | |
| @keyframes skeletonPulse { | |
| 0%, | |
| 100% { | |
| background: rgba(128, 128, 128, 0.3); | |
| } | |
| 50% { | |
| background: rgba(128, 128, 128, 0.6); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .glass-divider-h β Horizontal glass divider | |
| ---------------------------------------------------------- | |
| A 1px horizontal line that fades to transparent at both | |
| edges, fitting naturally inside glassmorphism layouts. | |
| Usage: | |
| <hr className="glass-divider-h my-6" /> | |
| Note: | |
| - Height: 1px | |
| - Gradient: transparent β var(--border) β transparent | |
| - border: none to reset browser defaults | |
| ---------------------------------------------------------- */ | |
| .glass-divider-h { | |
| border: none; | |
| height: 1px; | |
| background: linear-gradient( | |
| 90deg, | |
| transparent, | |
| var(--border, #2a2a4a), | |
| transparent | |
| ); | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .tooltip-float β Small floating tooltip element | |
| ---------------------------------------------------------- | |
| Absolute-positioned dark tooltip with a bottom-pointing | |
| arrow. Designed to sit above trigger elements. | |
| Usage: | |
| <div className="tooltip-float">Tooltip text</div> | |
| Note: | |
| - Font size: 12px | |
| - Background: var(--background, #0a0a1a) | |
| - Border: 1px solid var(--border, #2a2a4a) | |
| - Arrow via ::after pseudo-element (bottom center) | |
| - Box shadow for depth separation | |
| ---------------------------------------------------------- */ | |
| .tooltip-float { | |
| position: absolute; | |
| top: calc(100% + 8px); | |
| left: 50%; | |
| transform: translateX(-50%); | |
| padding: 6px 12px; | |
| font-size: 12px; | |
| line-height: 1.4; | |
| color: var(--foreground, #ffffff); | |
| background: var(--background, #0a0a1a); | |
| border: 1px solid var(--border, #2a2a4a); | |
| border-radius: 6px; | |
| white-space: nowrap; | |
| box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); | |
| z-index: 50; | |
| pointer-events: none; | |
| } | |
| .tooltip-float::after { | |
| content: ""; | |
| position: absolute; | |
| bottom: 100%; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| border-width: 5px; | |
| border-style: solid; | |
| border-color: transparent transparent var(--border, #2a2a4a) transparent; | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .tag-outline β Outlined tag / badge | |
| ---------------------------------------------------------- | |
| Transparent tag with a 1px border that fills on hover | |
| with the primary colour at 10 % opacity. | |
| Usage: | |
| <span className="tag-outline">Machine Learning</span> | |
| Note: | |
| - border-radius: 9999px (rounded-full) | |
| - border: 1px solid var(--border) | |
| - Hover bg: rgba(99, 102, 241, 0.1) | |
| - Smooth 0.2s transition | |
| ---------------------------------------------------------- */ | |
| .tag-outline { | |
| display: inline-flex; | |
| align-items: center; | |
| padding: 4px 12px; | |
| font-size: 0.75rem; | |
| line-height: 1; | |
| color: var(--foreground, #ffffff); | |
| background: transparent; | |
| border: 1px solid var(--border, #2a2a4a); | |
| border-radius: 9999px; | |
| transition: background 0.2s ease, border-color 0.2s ease; | |
| cursor: default; | |
| } | |
| .tag-outline:hover { | |
| background: rgba(99, 102, 241, 0.1); | |
| border-color: rgba(99, 102, 241, 0.4); | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .icon-badge β Small circular icon badge (24Γ24) | |
| ---------------------------------------------------------- | |
| A compact circle meant to hold a small icon, typically | |
| placed on cards or list items. | |
| Usage: | |
| <div className="icon-badge"> | |
| <Icon name="star" size={14} /> | |
| </div> | |
| Note: | |
| - Size: 24px Γ 24px | |
| - Flexbox centred | |
| - Background: rgba(99, 102, 241, 0.2) (primary/20) | |
| - Border-radius: 9999px | |
| ---------------------------------------------------------- */ | |
| .icon-badge { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 24px; | |
| height: 24px; | |
| background: rgba(99, 102, 241, 0.2); | |
| border-radius: 9999px; | |
| flex-shrink: 0; | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .progress-bar-glass β Glassmorphism progress bar | |
| ---------------------------------------------------------- | |
| A 6px rounded track with a gradient inner fill. The fill | |
| width is controlled via an inline style (--value). | |
| Usage: | |
| <div className="progress-bar-glass" style="--value: 65%"> | |
| <div className="progress-bar-glass__fill" /> | |
| </div> | |
| Note: | |
| - Track: bg var(--secondary, #1e1e3a), rounded-full | |
| - Fill: gradient indigo β purple, transition 0.4s | |
| - Backdrop blur on track for glass effect | |
| ---------------------------------------------------------- */ | |
| .progress-bar-glass { | |
| position: relative; | |
| height: 6px; | |
| background: rgba(255, 255, 255, 0.06); | |
| border-radius: 9999px; | |
| overflow: hidden; | |
| backdrop-filter: blur(4px); | |
| } | |
| .progress-bar-glass__fill { | |
| height: 100%; | |
| width: var(--value, 0%); | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6); | |
| border-radius: 9999px; | |
| transition: width 0.4s ease; | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .card-hover-border β Card border colour change on hover | |
| ---------------------------------------------------------- | |
| A card whose border subtly highlights when hovered, | |
| accompanied by a soft box-shadow glow. | |
| Usage: | |
| <div className="card-hover-border rounded-xl p-4"> | |
| Card content | |
| </div> | |
| Note: | |
| - Default border: var(--border, #2a2a4a) | |
| - Hover border: rgba(99, 102, 241, 0.4) | |
| - Hover shadow: 0 0 12px rgba(99, 102, 241, 0.15) | |
| - Transition: 0.3s ease | |
| ---------------------------------------------------------- */ | |
| .card-hover-border { | |
| border: 1px solid var(--border, #2a2a4a); | |
| transition: border-color 0.3s ease, box-shadow 0.3s ease; | |
| } | |
| .card-hover-border:hover { | |
| border-color: rgba(99, 102, 241, 0.4); | |
| box-shadow: 0 0 12px rgba(99, 102, 241, 0.15); | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .text-truncate-2 β Truncate text to 2 lines | |
| ---------------------------------------------------------- | |
| Clips overflowing text after two lines and appends an | |
| ellipsis ("β¦"). | |
| Usage: | |
| <p className="text-truncate-2"> | |
| Very long description that should be clamped⦠| |
| </p> | |
| Note: | |
| - -webkit-line-clamp: 2 | |
| - display: -webkit-box | |
| - -webkit-box-orient: vertical | |
| - overflow: hidden | |
| ---------------------------------------------------------- */ | |
| .text-truncate-2 { | |
| display: -webkit-box; | |
| -webkit-line-clamp: 2; | |
| -webkit-box-orient: vertical; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| /* ---------------------------------------------------------- | |
| 13. .glass-tag β Small glassmorphism tag / pill | |
| ---------------------------------------------------------- | |
| A tiny inline pill with frosted-glass aesthetics. | |
| Usage: | |
| <span className="glass-tag">NLP</span> | |
| Note: | |
| - bg: rgba(255, 255, 255, 0.05) | |
| - backdrop-filter: blur(8px) | |
| - border: 1px solid rgba(255, 255, 255, 0.1) | |
| - rounded-full, text-xs, px-3 py-1 | |
| ---------------------------------------------------------- */ | |
| .glass-tag { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 4px; | |
| padding: 4px 12px; | |
| font-size: 0.75rem; | |
| line-height: 1; | |
| color: var(--foreground, #ffffff); | |
| background: rgba(255, 255, 255, 0.05); | |
| backdrop-filter: blur(8px); | |
| -webkit-backdrop-filter: blur(8px); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| border-radius: 9999px; | |
| } | |
| /* ---------------------------------------------------------- | |
| 14. .notification-dot β Small red notification indicator | |
| ---------------------------------------------------------- | |
| An 8px pulsing dot for unread-count indicators. Designed | |
| to be positioned at the top-right of its parent. | |
| Usage: | |
| <div className="relative"> | |
| <BellIcon /> | |
| <span className="notification-dot" /> | |
| </div> | |
| Note: | |
| - Size: 8px Γ 8px | |
| - Background: #ef4444 (red-500) | |
| - Absolute: top-0 right-0 (with -2px offset) | |
| - Pulse animation: 2s ease-in-out infinite | |
| ---------------------------------------------------------- */ | |
| .notification-dot { | |
| position: absolute; | |
| top: -2px; | |
| right: -2px; | |
| width: 8px; | |
| height: 8px; | |
| background: #ef4444; | |
| border-radius: 9999px; | |
| animation: notificationPulse 2s ease-in-out infinite; | |
| } | |
| @keyframes notificationPulse { | |
| 0%, | |
| 100% { | |
| box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.5); | |
| } | |
| 50% { | |
| box-shadow: 0 0 0 5px rgba(239, 68, 68, 0); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 15. .hover-underline-animated β Animated underline on hover | |
| ---------------------------------------------------------- | |
| An underline that slides in from the left when the element | |
| is hovered, using ::after with scaleX transform. | |
| Usage: | |
| <a className="hover-underline-animated">Link text</a> | |
| Note: | |
| - ::after positioned below the text baseline | |
| - scaleX(0) β scaleX(1) on hover | |
| - transform-origin: left | |
| - Gradient underline: indigo β purple | |
| - Transition: 0.3s ease | |
| ---------------------------------------------------------- */ | |
| .hover-underline-animated { | |
| position: relative; | |
| display: inline-block; | |
| cursor: pointer; | |
| } | |
| .hover-underline-animated::after { | |
| content: ""; | |
| position: absolute; | |
| bottom: -2px; | |
| left: 0; | |
| width: 100%; | |
| height: 2px; | |
| background: linear-gradient(90deg, #6366f1, #8b5cf6); | |
| border-radius: 1px; | |
| transform: scaleX(0); | |
| transform-origin: left; | |
| transition: transform 0.3s ease; | |
| } | |
| .hover-underline-animated:hover::after { | |
| transform: scaleX(1); | |
| } | |
| /* ============================================================ | |
| IA Academy β Additional Utility Classes (Batch 3) | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .card-tilt β 3D perspective card tilt on hover | |
| ---------------------------------------------------------- */ | |
| .card-tilt { | |
| perspective: 1000px; | |
| transition: | |
| transform 0.45s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.45s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .card-tilt:hover { | |
| transform: rotateX(2deg) rotateY(-2deg); | |
| box-shadow: | |
| 0 16px 40px rgba(0, 0, 0, 0.35), | |
| 0 0 20px rgba(99, 102, 241, 0.06); | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .shimmer-border β Animated border shimmer effect | |
| ---------------------------------------------------------- */ | |
| .shimmer-border { | |
| position: relative; | |
| border-radius: 12px; | |
| overflow: hidden; | |
| isolation: isolate; | |
| } | |
| .shimmer-border::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -2px; | |
| border-radius: inherit; | |
| background: conic-gradient( | |
| from 0deg, | |
| transparent 0%, | |
| rgba(99, 102, 241, 0.4) 10%, | |
| rgba(139, 92, 246, 0.6) 15%, | |
| rgba(6, 182, 212, 0.4) 20%, | |
| transparent 25%, | |
| transparent 100% | |
| ); | |
| animation: shimmerBorderRotate 3s linear infinite; | |
| z-index: -2; | |
| } | |
| .shimmer-border::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 2px; | |
| border-radius: inherit; | |
| background: var(--card, #151530); | |
| z-index: -1; | |
| } | |
| @keyframes shimmerBorderRotate { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .text-glow-animated β Pulsing glow text effect | |
| ---------------------------------------------------------- */ | |
| .text-glow-animated { | |
| animation: textGlowPulse 2s ease-in-out infinite; | |
| will-change: text-shadow; | |
| } | |
| @keyframes textGlowPulse { | |
| 0%, 100% { | |
| text-shadow: | |
| 0 0 4px rgba(99, 102, 241, 0.2), | |
| 0 0 8px rgba(99, 102, 241, 0.1); | |
| } | |
| 50% { | |
| text-shadow: | |
| 0 0 8px rgba(99, 102, 241, 0.5), | |
| 0 0 20px rgba(99, 102, 241, 0.3), | |
| 0 0 40px rgba(99, 102, 241, 0.15); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .glass-chip β Small inline glass chip / pill | |
| ---------------------------------------------------------- */ | |
| .glass-chip { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.3rem; | |
| padding: 0.25rem 0.65rem; | |
| border-radius: 9999px; | |
| font-size: 0.7rem; | |
| font-weight: 600; | |
| letter-spacing: 0.02em; | |
| background: rgba(21, 21, 48, 0.7); | |
| backdrop-filter: blur(12px); | |
| -webkit-backdrop-filter: blur(12px); | |
| border: 1px solid rgba(99, 102, 241, 0.15); | |
| border-top: 2px solid; | |
| border-image: linear-gradient(90deg, #6366f1, #8b5cf6) 1; | |
| border-radius: 9999px; | |
| color: #a5b4fc; | |
| white-space: nowrap; | |
| } | |
| .glass-chip.emerald { | |
| border-top: 2px solid; | |
| border-image: linear-gradient(90deg, #10b981, #34d399) 1; | |
| border-radius: 9999px; | |
| color: #6ee7b7; | |
| border-color: rgba(16, 185, 129, 0.15); | |
| } | |
| .glass-chip.amber { | |
| border-top: 2px solid; | |
| border-image: linear-gradient(90deg, #f59e0b, #fbbf24) 1; | |
| border-radius: 9999px; | |
| color: #fcd34d; | |
| border-color: rgba(245, 158, 11, 0.15); | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .scrollbar-hidden β Hide scrollbar, keep scroll | |
| ---------------------------------------------------------- */ | |
| .scrollbar-hidden { | |
| -ms-overflow-style: none; | |
| scrollbar-width: none; | |
| } | |
| .scrollbar-hidden::-webkit-scrollbar { | |
| display: none; | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .hover-brightness β Hover brightness boost | |
| ---------------------------------------------------------- */ | |
| .hover-brightness { | |
| transition: filter 0.35s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: filter; | |
| } | |
| .hover-brightness:hover { | |
| filter: brightness(1.1); | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .inset-shadow β Inner shadow effect | |
| ---------------------------------------------------------- */ | |
| .inset-shadow { | |
| box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3); | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .line-clamp-3 β Truncate text to 3 lines | |
| ---------------------------------------------------------- */ | |
| .line-clamp-3 { | |
| display: -webkit-box; | |
| -webkit-box-orient: vertical; | |
| -webkit-line-clamp: 3; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .floating-action-btn β FAB with hover expansion | |
| ---------------------------------------------------------- */ | |
| .floating-action-btn { | |
| position: relative; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 48px; | |
| height: 48px; | |
| border-radius: 9999px; | |
| background: linear-gradient(135deg, #6366f1, #8b5cf6); | |
| color: #ffffff; | |
| border: none; | |
| cursor: pointer; | |
| overflow: hidden; | |
| white-space: nowrap; | |
| transition: width 0.3s cubic-bezier(0.23, 1, 0.32, 1); | |
| box-shadow: 0 4px 14px rgba(99, 102, 241, 0.3); | |
| will-change: width; | |
| } | |
| .floating-action-btn .fab-label { | |
| display: inline-block; | |
| max-width: 0; | |
| opacity: 0; | |
| padding: 0; | |
| font-size: 0.8125rem; | |
| font-weight: 600; | |
| transition: | |
| max-width 0.3s cubic-bezier(0.23, 1, 0.32, 1), | |
| opacity 0.3s ease, | |
| padding 0.3s ease; | |
| } | |
| .floating-action-btn:hover { | |
| width: auto; | |
| padding-left: 1.25rem; | |
| padding-right: 1.25rem; | |
| } | |
| .floating-action-btn:hover .fab-label { | |
| max-width: 200px; | |
| opacity: 1; | |
| padding-left: 0.5rem; | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .glass-card-emerald β Emerald-accent glass card | |
| ---------------------------------------------------------- */ | |
| .glass-card-emerald { | |
| background: rgba(15, 15, 35, 0.65); | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| border: 1px solid rgba(16, 185, 129, 0.2); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.05), | |
| inset 0 -1px 0 0 rgba(0, 0, 0, 0.2), | |
| 0 8px 32px rgba(0, 0, 0, 0.3), | |
| 0 0 0 1px rgba(16, 185, 129, 0.08); | |
| transition: | |
| transform 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| box-shadow 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| background 0.5s cubic-bezier(0.23, 1, 0.32, 1), | |
| border-color 0.5s cubic-bezier(0.23, 1, 0.32, 1); | |
| will-change: transform, box-shadow; | |
| } | |
| .glass-card-emerald:hover { | |
| background: rgba(20, 20, 50, 0.8); | |
| border-color: rgba(16, 185, 129, 0.4); | |
| box-shadow: | |
| inset 0 1px 0 0 rgba(255, 255, 255, 0.1), | |
| inset 0 0 30px rgba(16, 185, 129, 0.06), | |
| inset 0 -1px 0 0 rgba(0, 0, 0, 0.25), | |
| 0 16px 48px rgba(0, 0, 0, 0.45), | |
| 0 0 0 1px rgba(16, 185, 129, 0.18), | |
| 0 0 40px rgba(16, 185, 129, 0.1), | |
| 0 0 80px rgba(16, 185, 129, 0.04); | |
| transform: translateY(-3px) scale(1.005); | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .gradient-text-vertical β Vertical gradient text | |
| ---------------------------------------------------------- */ | |
| .gradient-text-vertical { | |
| background: linear-gradient(to bottom, #a5b4fc, #6366f1, #8b5cf6, #c084fc); | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| .gradient-text-vertical.emerald { | |
| background: linear-gradient(to bottom, #6ee7b7, #10b981, #059669, #047857); | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| /* ---------------------------------------------------------- | |
| 12. .dot-indicator β Small dot with pulse animation | |
| ---------------------------------------------------------- */ | |
| .dot-indicator { | |
| position: relative; | |
| display: inline-block; | |
| width: 6px; | |
| height: 6px; | |
| border-radius: 50%; | |
| background: #10b981; | |
| box-shadow: 0 0 6px rgba(16, 185, 129, 0.5); | |
| will-change: opacity; | |
| } | |
| .dot-indicator::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -3px; | |
| border-radius: 50%; | |
| background: rgba(16, 185, 129, 0.3); | |
| animation: dotPulse 2s ease-in-out infinite; | |
| } | |
| .dot-indicator.red { | |
| background: #ef4444; | |
| box-shadow: 0 0 6px rgba(239, 68, 68, 0.5); | |
| } | |
| .dot-indicator.red::before { | |
| background: rgba(239, 68, 68, 0.3); | |
| } | |
| .dot-indicator.amber { | |
| background: #f59e0b; | |
| box-shadow: 0 0 6px rgba(245, 158, 11, 0.5); | |
| } | |
| .dot-indicator.amber::before { | |
| background: rgba(245, 158, 11, 0.3); | |
| } | |
| @keyframes dotPulse { | |
| 0%, 100% { | |
| transform: scale(1); | |
| opacity: 0.8; | |
| } | |
| 50% { | |
| transform: scale(1.8); | |
| opacity: 0; | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 13. .card-stagger β Stagger child card animations | |
| ---------------------------------------------------------- */ | |
| .card-stagger > *:nth-child(1) { transition-delay: 0ms; } | |
| .card-stagger > *:nth-child(2) { transition-delay: 80ms; } | |
| .card-stagger > *:nth-child(3) { transition-delay: 160ms; } | |
| .card-stagger > *:nth-child(4) { transition-delay: 240ms; } | |
| .card-stagger > *:nth-child(5) { transition-delay: 320ms; } | |
| .card-stagger > *:nth-child(6) { transition-delay: 400ms; } | |
| .card-stagger > *:nth-child(7) { transition-delay: 480ms; } | |
| .card-stagger > *:nth-child(8) { transition-delay: 560ms; } | |
| /* ---------------------------------------------------------- | |
| 14. .noise-bg β Subtle noise texture overlay | |
| ---------------------------------------------------------- */ | |
| .noise-bg { | |
| position: relative; | |
| } | |
| .noise-bg::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| opacity: 0.03; | |
| pointer-events: none; | |
| z-index: 1; | |
| background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); | |
| background-repeat: repeat; | |
| background-size: 180px 180px; | |
| } | |
| /* ---------------------------------------------------------- | |
| 15. .badge-soft β Soft low-contrast badge | |
| ---------------------------------------------------------- */ | |
| .badge-soft { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| padding: 0.2rem 0.6rem; | |
| border-radius: 9999px; | |
| font-size: 0.7rem; | |
| font-weight: 500; | |
| border: none; | |
| background: rgba(99, 102, 241, 0.08); | |
| color: rgba(165, 180, 252, 0.8); | |
| transition: background 0.25s ease, color 0.25s ease; | |
| } | |
| .badge-soft:hover { | |
| background: rgba(99, 102, 241, 0.15); | |
| color: #a5b4fc; | |
| } | |
| .badge-soft.emerald { | |
| background: rgba(16, 185, 129, 0.08); | |
| color: rgba(110, 231, 183, 0.8); | |
| } | |
| .badge-soft.emerald:hover { | |
| background: rgba(16, 185, 129, 0.15); | |
| color: #6ee7b7; | |
| } | |
| .badge-soft.amber { | |
| background: rgba(245, 158, 11, 0.08); | |
| color: rgba(252, 211, 77, 0.8); | |
| } | |
| .badge-soft.amber:hover { | |
| background: rgba(245, 158, 11, 0.15); | |
| color: #fcd34d; | |
| } | |
| .badge-soft.rose { | |
| background: rgba(244, 63, 94, 0.08); | |
| color: rgba(253, 164, 175, 0.8); | |
| } | |
| .badge-soft.rose:hover { | |
| background: rgba(244, 63, 94, 0.15); | |
| color: #fda4af; | |
| } | |
| .badge-soft.cyan { | |
| background: rgba(6, 182, 212, 0.08); | |
| color: rgba(103, 232, 249, 0.8); | |
| } | |
| .badge-soft.cyan:hover { | |
| background: rgba(6, 182, 212, 0.15); | |
| color: #67e8f9; | |
| } | |
| /* ============================================================ | |
| IA Academy β Task 14: New Utility Classes | |
| ============================================================ */ | |
| /* ββ Gradient Text Utilities ββββββββββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 1. .text-gradient-warm β Warm gradient text (amber β orange β red) | |
| ---------------------------------------------------------- */ | |
| .text-gradient-warm { | |
| background: linear-gradient(135deg, #f59e0b, #f97316, #ef4444); | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .text-gradient-cool β Cool gradient text (cyan β indigo β purple) | |
| ---------------------------------------------------------- */ | |
| .text-gradient-cool { | |
| background: linear-gradient(135deg, #06b6d4, #6366f1, #8b5cf6); | |
| -webkit-background-clip: text; | |
| background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| /* ββ Card Interaction Effects ββββββββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 3. .card-hover-shine β Diagonal shine sweep on hover | |
| ---------------------------------------------------------- */ | |
| .card-hover-shine { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .card-hover-shine::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background: linear-gradient( | |
| 105deg, | |
| transparent 40%, | |
| rgba(255, 255, 255, 0.08) 45%, | |
| rgba(255, 255, 255, 0.12) 50%, | |
| rgba(255, 255, 255, 0.08) 55%, | |
| transparent 60% | |
| ); | |
| transform: translateX(-100%); | |
| transition: transform 0.6s ease; | |
| pointer-events: none; | |
| z-index: 2; | |
| } | |
| .card-hover-shine:hover::after { | |
| transform: translateX(100%); | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .border-gradient-animated β Animated gradient border (rotating conic) | |
| ---------------------------------------------------------- */ | |
| @property --angle { | |
| syntax: '<angle>'; | |
| initial-value: 0deg; | |
| inherits: false; | |
| } | |
| .border-gradient-animated { | |
| border: 2px solid; | |
| border-image: conic-gradient( | |
| from var(--angle, 0deg), | |
| #6366f1, #8b5cf6, #ec4899, #f59e0b, #6366f1 | |
| ) 1; | |
| animation: rotate-border-angle 4s linear infinite; | |
| } | |
| @keyframes rotate-border-angle { | |
| to { --angle: 360deg; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .backdrop-blur-heavy β Heavy backdrop blur utility | |
| ---------------------------------------------------------- */ | |
| .backdrop-blur-heavy { | |
| backdrop-filter: blur(24px) saturate(1.5); | |
| -webkit-backdrop-filter: blur(24px) saturate(1.5); | |
| } | |
| /* ββ Text Effects βββββββββββββββββββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 6. .text-shadow-soft β Subtle text shadow for readability | |
| ---------------------------------------------------------- */ | |
| .text-shadow-soft { | |
| text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3); | |
| } | |
| /* ββ Hover & Interaction Utilities ββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 7. .hover-scale-smooth β Smooth scale on hover with bounce easing | |
| ---------------------------------------------------------- */ | |
| .hover-scale-smooth { | |
| transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| } | |
| .hover-scale-smooth:hover { | |
| transform: scale(1.03); | |
| } | |
| /* ββ Badge & Chip Utilities βββββββββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 8. .glass-badge-3d β 3D-looking glass badge | |
| ---------------------------------------------------------- */ | |
| .glass-badge-3d { | |
| background: rgba(255, 255, 255, 0.06); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| border-radius: 9999px; | |
| padding: 2px 10px; | |
| font-size: 0.75rem; | |
| box-shadow: | |
| 0 2px 8px rgba(0, 0, 0, 0.2), | |
| inset 0 1px 0 rgba(255, 255, 255, 0.1); | |
| } | |
| /* ββ Divider Effects βββββββββββββββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 9. .glow-line-animated β Animated glowing horizontal line | |
| ---------------------------------------------------------- */ | |
| .glow-line-animated { | |
| height: 1px; | |
| background: linear-gradient(90deg, transparent, #6366f1, #8b5cf6, transparent); | |
| background-size: 200% 100%; | |
| animation: glow-line-sweep 3s ease-in-out infinite; | |
| } | |
| @keyframes glow-line-sweep { | |
| 0% { background-position: -200% 0; } | |
| 100% { background-position: 200% 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .chip-hover β Interactive chip/pill with hover lift | |
| ---------------------------------------------------------- */ | |
| .chip-hover { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| padding: 0.25rem 0.75rem; | |
| border-radius: 9999px; | |
| font-size: 0.8125rem; | |
| transition: all 0.3s; | |
| } | |
| .chip-hover:hover { | |
| transform: translateY(-1px); | |
| box-shadow: 0 4px 12px rgba(99, 102, 241, 0.2); | |
| } | |
| /* ββ Animation Utilities ββββββββββββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 11. .section-fade-in β Section-level fade-in animation | |
| ---------------------------------------------------------- */ | |
| .section-fade-in { | |
| opacity: 0; | |
| transform: translateY(20px); | |
| animation: section-appear 0.6s ease-out forwards; | |
| } | |
| @keyframes section-appear { | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| /* ββ Stat Highlight βββββββββββββββββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 12. .stat-highlight β Highlight effect for stat numbers | |
| ---------------------------------------------------------- */ | |
| .stat-highlight { | |
| font-variant-numeric: tabular-nums; | |
| text-shadow: | |
| 0 0 20px rgba(99, 102, 241, 0.5), | |
| 0 0 40px rgba(99, 102, 241, 0.2); | |
| } | |
| /* ββ Glass Chip βββββββββββββββββββββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 13. .glass-chip β Small glass chip for tags and labels | |
| ---------------------------------------------------------- */ | |
| .glass-chip { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| padding: 0.125rem 0.5rem; | |
| border-radius: 0.375rem; | |
| font-size: 0.6875rem; | |
| background: rgba(255, 255, 255, 0.05); | |
| border: 1px solid rgba(255, 255, 255, 0.08); | |
| } | |
| .glass-chip.emerald { | |
| border-color: rgba(16, 185, 129, 0.2); | |
| color: #34d399; | |
| } | |
| .glass-chip.amber { | |
| border-color: rgba(245, 158, 11, 0.2); | |
| color: #fbbf24; | |
| } | |
| .glass-chip.primary { | |
| border-color: rgba(99, 102, 241, 0.2); | |
| color: #a5b4fc; | |
| } | |
| /* ββ Scroll Indicator βββββββββββββββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 14. .scroll-indicator β Animated scroll-down dots for hero | |
| ---------------------------------------------------------- */ | |
| .scroll-indicator { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 4px; | |
| } | |
| .scroll-indicator .dot { | |
| width: 4px; | |
| height: 4px; | |
| border-radius: 50%; | |
| background: rgba(255, 255, 255, 0.4); | |
| animation: scroll-bounce 1.5s ease-in-out infinite; | |
| } | |
| .scroll-indicator .dot:nth-child(2) { | |
| animation-delay: 0.15s; | |
| } | |
| .scroll-indicator .dot:nth-child(3) { | |
| animation-delay: 0.3s; | |
| } | |
| @keyframes scroll-bounce { | |
| 0%, 100% { opacity: 0.3; transform: translateY(0); } | |
| 50% { opacity: 1; transform: translateY(-4px); } | |
| } | |
| /* ββ Card Inner Glow ββββββββββββββββββββββββββββββββββββββββ */ | |
| /* ---------------------------------------------------------- | |
| 15. .card-inner-glow β Subtle inner glow on hover | |
| ---------------------------------------------------------- */ | |
| .card-inner-glow { | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .card-inner-glow::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background: radial-gradient(circle at 30% 30%, rgba(99, 102, 241, 0.06), transparent 60%); | |
| opacity: 0; | |
| transition: opacity 0.4s; | |
| pointer-events: none; | |
| } | |
| .card-inner-glow:hover::before { | |
| opacity: 1; | |
| } | |
| /* ---------------------------------------------------------- | |
| Testimonials Carousel β hide scrollbar | |
| ---------------------------------------------------------- */ | |
| #testimonials-carousel::-webkit-scrollbar { | |
| display: none; | |
| } | |
| /* ---------------------------------------------------------- | |
| Testimonials Dot β active state indicator | |
| ---------------------------------------------------------- */ | |
| .testimonial-dot { | |
| cursor: pointer; | |
| border: none; | |
| outline: none; | |
| } | |
| .testimonial-dot:focus-visible { | |
| outline: 2px solid rgba(99, 102, 241, 0.5); | |
| outline-offset: 2px; | |
| } | |
| /* ============================================================ | |
| Task 16 β 12 New Animation-Focused CSS Classes | |
| ============================================================ */ | |
| /* ---------------------------------------------------------- | |
| 1. .animate-float β Gentle continuous floating animation | |
| ---------------------------------------------------------- */ | |
| .animate-float { | |
| animation: float 6s ease-in-out infinite; | |
| } | |
| @keyframes float { | |
| 0%, 100% { transform: translateY(0); } | |
| 50% { transform: translateY(-8px); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 2. .animate-pulse-soft β Soft pulsing opacity | |
| ---------------------------------------------------------- */ | |
| .animate-pulse-soft { | |
| animation: pulse-soft 3s ease-in-out infinite; | |
| } | |
| @keyframes pulse-soft { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.6; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 3. .animate-gradient-x β Horizontal gradient background | |
| ---------------------------------------------------------- */ | |
| .animate-gradient-x { | |
| background-size: 200% 100%; | |
| animation: gradient-x 3s ease infinite; | |
| } | |
| @keyframes gradient-x { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 4. .animate-shimmer β Shimmer sweep effect | |
| ---------------------------------------------------------- */ | |
| .animate-shimmer { | |
| background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.06), transparent); | |
| background-size: 200% 100%; | |
| animation: shimmer-sweep 2s infinite; | |
| } | |
| @keyframes shimmer-sweep { | |
| 0% { background-position: -200% 0; } | |
| 100% { background-position: 200% 0; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 5. .animate-border-glow β Animated border glow | |
| ---------------------------------------------------------- */ | |
| .animate-border-glow { | |
| animation: border-glow 2s ease-in-out infinite alternate; | |
| } | |
| @keyframes border-glow { | |
| from { | |
| box-shadow: 0 0 5px rgba(99, 102, 241, 0.3); | |
| } | |
| to { | |
| box-shadow: 0 0 20px rgba(99, 102, 241, 0.6), 0 0 40px rgba(99, 102, 241, 0.2); | |
| } | |
| } | |
| /* ---------------------------------------------------------- | |
| 6. .animate-spin-slow β Very slow spin for decorative use | |
| ---------------------------------------------------------- */ | |
| .animate-spin-slow { | |
| animation: spin 8s linear infinite; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 7. .animate-bounce-in β Bounce-in entrance animation | |
| ---------------------------------------------------------- */ | |
| .animate-bounce-in { | |
| animation: bounce-in 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55); | |
| } | |
| @keyframes bounce-in { | |
| 0% { transform: scale(0); opacity: 0; } | |
| 100% { transform: scale(1); opacity: 1; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 8. .animate-slide-up-fade β Slide up with fade in | |
| ---------------------------------------------------------- */ | |
| .animate-slide-up-fade { | |
| animation: slide-up-fade 0.5s ease-out; | |
| } | |
| @keyframes slide-up-fade { | |
| from { opacity: 0; transform: translateY(20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 9. .animate-slide-in-left β Slide in from left | |
| ---------------------------------------------------------- */ | |
| .animate-slide-in-left { | |
| animation: slide-in-left 0.5s ease-out; | |
| } | |
| @keyframes slide-in-left { | |
| from { opacity: 0; transform: translateX(-30px); } | |
| to { opacity: 1; transform: translateX(0); } | |
| } | |
| /* ---------------------------------------------------------- | |
| 10. .animate-scale-in β Scale in from small | |
| ---------------------------------------------------------- */ | |
| .animate-scale-in { | |
| animation: scale-in 0.4s cubic-bezier(0.34, 1.56, 0.64, 1); | |
| } | |
| @keyframes scale-in { | |
| from { transform: scale(0.8); opacity: 0; } | |
| to { transform: scale(1); opacity: 1; } | |
| } | |
| /* ---------------------------------------------------------- | |
| 11. .stagger-children β Staggered children animation delay | |
| ---------------------------------------------------------- */ | |
| .stagger-children > * { | |
| animation: slide-up-fade 0.5s ease-out both; | |
| } | |
| .stagger-children > *:nth-child(1) { animation-delay: 0ms; } | |
| .stagger-children > *:nth-child(2) { animation-delay: 100ms; } | |
| .stagger-children > *:nth-child(3) { animation-delay: 200ms; } | |
| .stagger-children > *:nth-child(4) { animation-delay: 300ms; } | |
| .stagger-children > *:nth-child(5) { animation-delay: 400ms; } | |
| .stagger-children > *:nth-child(6) { animation-delay: 500ms; } | |
| .stagger-children > *:nth-child(7) { animation-delay: 600ms; } | |
| .stagger-children > *:nth-child(8) { animation-delay: 700ms; } | |
| /* ---------------------------------------------------------- | |
| 12. .glass-card-animated β Glass card with animated border | |
| ---------------------------------------------------------- | |
| Same glassmorphism as .glass-card but with an animated | |
| conic-gradient border using @property --angle (already | |
| defined earlier in this file). | |
| ---------------------------------------------------------- */ | |
| .glass-card-animated { | |
| position: relative; | |
| background: rgba(15, 15, 35, 0.65); | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| border-radius: 1rem; | |
| padding: 1.5rem; | |
| isolation: isolate; | |
| } | |
| @property --angle { | |
| syntax: '<angle>'; | |
| initial-value: 0deg; | |
| inherits: false; | |
| } | |
| .glass-card-animated::before { | |
| content: ''; | |
| position: absolute; | |
| inset: -2px; | |
| border-radius: inherit; | |
| background: conic-gradient( | |
| from var(--angle), | |
| rgba(99, 102, 241, 0.4), | |
| rgba(168, 85, 247, 0.6), | |
| rgba(236, 72, 153, 0.4), | |
| rgba(245, 158, 11, 0.3), | |
| rgba(16, 185, 129, 0.4), | |
| rgba(99, 102, 241, 0.4) | |
| ); | |
| animation: rotate-angle 4s linear infinite; | |
| z-index: -2; | |
| } | |
| .glass-card-animated::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| border-radius: inherit; | |
| background: rgba(15, 15, 35, 0.92); | |
| z-index: -1; | |
| } | |
| @keyframes rotate-angle { | |
| to { --angle: 360deg; } | |
| } | |