IAacademyTraining / src /app /globals.css
MAALOUFimad02's picture
Upload 72 files
ddd2690 verified
Raw
History Blame Contribute Delete
317 kB
@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) !important;
}
/* 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 !important;
}
/* ----------------------------------------------------------
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 !important;
background-clip: text !important;
-webkit-text-fill-color: transparent !important;
font-weight: 700;
background-size: 100% 100% !important;
animation: none !important;
position: static !important;
filter: none !important;
}
.text-gradient-static::after {
display: none !important;
}
.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; }
}