/** * Design System Utilities * * Semantic component primitives using the consolidated color system. * Layout, spacing, typography utilities come from Tailwind. */ /* ===== KEYFRAMES ===== */ @keyframes cp-fade-up { from { opacity: 0; transform: translateY(var(--cp-translate-lg)); } to { opacity: 1; transform: translateY(0); } } @keyframes cp-fade-scale { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } } @keyframes cp-slide-in-left { from { opacity: 0; transform: translateX(calc(var(--cp-translate-xl) * -1)); } to { opacity: 1; transform: translateX(0); } } @keyframes cp-shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } @keyframes cp-toast-enter { from { opacity: 0; transform: translateX(100%) scale(0.9); } to { opacity: 1; transform: translateX(0) scale(1); } } @keyframes cp-toast-exit { from { opacity: 1; transform: translateX(0) scale(1); } to { opacity: 0; transform: translateX(100%) scale(0.9); } } @keyframes cp-shake { 0%, 100% { transform: translateX(0); } 20%, 60% { transform: translateX(-4px); } 40%, 80% { transform: translateX(4px); } } @keyframes cp-activity-enter { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: translateX(0); } } @keyframes cp-float { 0%, 100% { transform: translateY(0px) rotate(0deg); } 50% { transform: translateY(-20px) rotate(2deg); } } @keyframes cp-float-slow { 0%, 100% { transform: translateY(0px) rotate(0deg); } 50% { transform: translateY(-12px) rotate(-1deg); } } @keyframes cp-pulse-glow { 0%, 100% { box-shadow: 0 0 0 0 var(--primary); } 50% { box-shadow: 0 0 20px 4px color-mix(in oklch, var(--primary) 40%, transparent); } } /* Legacy shimmer animation for compatibility */ @keyframes cp-skeleton-shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } /* ===== DISPLAY TYPOGRAPHY (Tailwind v4 @utility) ===== */ /* Only set font-size + letter-spacing. Font weight, line-height, and font-family are explicit Tailwind classes at the call site so they can be overridden without cascade conflicts. */ @utility text-display-xl { font-size: var(--cp-text-display-xl); letter-spacing: var(--cp-tracking-tight); } @utility text-display-lg { font-size: var(--cp-text-display-lg); letter-spacing: var(--cp-tracking-tight); } @utility text-display-md { font-size: var(--cp-text-display-md); letter-spacing: var(--cp-tracking-tight); } @utility text-display-sm { font-size: var(--cp-text-display-sm); letter-spacing: var(--cp-tracking-tight); } @layer utilities { /* ===== PAGE ENTRANCE ANIMATIONS ===== */ .cp-animate-in { animation: cp-fade-up var(--cp-duration-slow) var(--cp-ease-out) forwards; } .cp-animate-scale-in { animation: cp-fade-scale var(--cp-duration-normal) var(--cp-ease-out) forwards; } .cp-animate-slide-left { animation: cp-slide-in-left var(--cp-duration-slow) var(--cp-ease-out) forwards; } /* Staggered children animation */ .cp-stagger-children > * { opacity: 0; animation: cp-fade-up var(--cp-duration-slow) var(--cp-ease-out) forwards; } .cp-stagger-children > *:nth-child(1) { animation-delay: var(--cp-stagger-1); } .cp-stagger-children > *:nth-child(2) { animation-delay: var(--cp-stagger-2); } .cp-stagger-children > *:nth-child(3) { animation-delay: var(--cp-stagger-3); } .cp-stagger-children > *:nth-child(4) { animation-delay: var(--cp-stagger-4); } .cp-stagger-children > *:nth-child(5) { animation-delay: var(--cp-stagger-5); } .cp-stagger-children > *:nth-child(n + 6) { animation-delay: calc(var(--cp-stagger-5) + 50ms); } /* ===== CARD HOVER LIFT ===== */ .cp-card-hover-lift { transition: transform var(--cp-duration-normal) var(--cp-ease-out), box-shadow var(--cp-duration-normal) var(--cp-ease-out); } .cp-card-hover-lift:hover { transform: translateY(-2px); box-shadow: 0 10px 40px -10px rgb(0 0 0 / 0.15), 0 4px 6px -2px rgb(0 0 0 / 0.05); } .cp-card-hover-lift:active { transform: translateY(0); transition-duration: var(--cp-duration-fast); } /* ===== SKELETON SHIMMER ===== */ .cp-skeleton-shimmer { position: relative; overflow: hidden; background: var(--cp-skeleton-base); } .cp-skeleton-shimmer::after { content: ""; position: absolute; inset: 0; background: linear-gradient( 90deg, transparent 0%, var(--cp-skeleton-shimmer) 50%, transparent 100% ); animation: cp-shimmer 1.5s ease-in-out infinite; } /* ===== INPUT FOCUS ANIMATIONS ===== */ .cp-input-focus { transition: border-color var(--cp-duration-fast) var(--cp-ease-out), box-shadow var(--cp-duration-fast) var(--cp-ease-out), background-color var(--cp-duration-fast) var(--cp-ease-out); } .cp-input-focus:focus { border-color: var(--primary); box-shadow: 0 0 0 3px color-mix(in oklch, var(--primary) 15%, transparent); } .cp-input-error-shake { animation: cp-shake var(--cp-duration-slow) var(--cp-ease-out); } /* ===== TOAST ANIMATIONS ===== */ .cp-toast-enter { animation: cp-toast-enter var(--cp-duration-slow) var(--cp-ease-spring) forwards; } .cp-toast-exit { animation: cp-toast-exit var(--cp-duration-normal) var(--cp-ease-in) forwards; } /* ===== ACTIVITY FEED ===== */ .cp-activity-item { opacity: 0; animation: cp-activity-enter var(--cp-duration-normal) var(--cp-ease-out) forwards; } .cp-activity-item:nth-child(1) { animation-delay: 0ms; } .cp-activity-item:nth-child(2) { animation-delay: 50ms; } .cp-activity-item:nth-child(3) { animation-delay: 100ms; } .cp-activity-item:nth-child(4) { animation-delay: 150ms; } .cp-activity-item:nth-child(5) { animation-delay: 200ms; } /* ===== FLOAT ANIMATIONS ===== */ .cp-float { animation: cp-float 6s ease-in-out infinite; } .cp-float-slow { animation: cp-float-slow 8s ease-in-out infinite; } .cp-float-delayed { animation: cp-float 6s ease-in-out infinite 2s; } /* ===== GLASS MORPHISM ===== */ .cp-glass { background: var(--glass-bg); backdrop-filter: blur(var(--glass-blur)); -webkit-backdrop-filter: blur(var(--glass-blur)); border: 1px solid var(--glass-border); } .cp-glass-strong { background: var(--glass-bg-strong); backdrop-filter: blur(var(--glass-blur-strong)); -webkit-backdrop-filter: blur(var(--glass-blur-strong)); border: 1px solid var(--glass-border); } .cp-glass-card { background: var(--glass-bg); backdrop-filter: blur(var(--glass-blur)); -webkit-backdrop-filter: blur(var(--glass-blur)); border: 1px solid var(--glass-border); border-radius: var(--cp-card-radius); box-shadow: 0 4px 24px -4px oklch(0 0 0 / 0.08), inset 0 1px 0 oklch(1 0 0 / 0.1); } /* ===== GRADIENTS ===== */ .cp-gradient-primary { background: var(--gradient-primary); } .cp-gradient-premium { background: var(--gradient-premium); } .cp-gradient-subtle { background: var(--gradient-subtle); } .cp-gradient-text { background: var(--gradient-primary); -webkit-background-clip: text; background-clip: text; color: transparent; } .cp-gradient-glow { position: relative; } .cp-gradient-glow::before { content: ""; position: absolute; inset: -1px; background: var(--gradient-primary); border-radius: inherit; z-index: -1; opacity: 0; filter: blur(12px); transition: opacity var(--cp-duration-slow) ease; } .cp-gradient-glow:hover::before { opacity: 0.4; } /* ===== PREMIUM BUTTONS ===== */ .cp-btn-premium { background: var(--gradient-primary); color: var(--primary-foreground); box-shadow: var(--shadow-primary-sm); transition: all var(--cp-duration-normal) ease; } .cp-btn-premium:hover { box-shadow: var(--shadow-primary-md); transform: translateY(-1px); } .cp-btn-premium:active { transform: translateY(0); box-shadow: var(--shadow-primary-sm); } /* ===== GLOW EFFECTS ===== */ .cp-glow { box-shadow: var(--shadow-primary-sm); transition: box-shadow var(--cp-duration-slow) ease; } .cp-glow:hover { box-shadow: var(--shadow-primary-lg); } .cp-glow-pulse { animation: cp-pulse-glow 2s ease-in-out infinite; } /* ===== PREMIUM CARD VARIANTS ===== */ .cp-card-glass { background: var(--glass-bg); backdrop-filter: blur(var(--glass-blur)); -webkit-backdrop-filter: blur(var(--glass-blur)); border: 1px solid var(--glass-border); border-radius: var(--cp-card-radius); box-shadow: 0 4px 24px -4px oklch(0 0 0 / 0.06), inset 0 1px 0 oklch(1 0 0 / 0.08); } .cp-card-gradient { background: var(--gradient-subtle); border: 1px solid var(--border); border-radius: var(--cp-card-radius); } .cp-card-premium { background: var(--card); border: 1px solid color-mix(in oklch, var(--primary) 20%, transparent); border-radius: var(--cp-card-radius); box-shadow: 0 4px 24px -4px color-mix(in oklch, var(--primary) 8%, transparent), inset 0 1px 0 oklch(1 0 0 / 0.05); transition: all var(--cp-duration-normal) ease; } .cp-card-premium:hover { border-color: color-mix(in oklch, var(--primary) 40%, transparent); box-shadow: 0 8px 32px -8px color-mix(in oklch, var(--primary) 15%, transparent), inset 0 1px 0 oklch(1 0 0 / 0.05); transform: translateY(-2px); } /* ===== GRADIENT BORDER ===== */ .cp-gradient-border { position: relative; } .cp-gradient-border::before { content: ""; position: absolute; inset: 0; padding: 1px; border-radius: inherit; background: var(--gradient-primary); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor; mask-composite: exclude; opacity: 0; transition: opacity var(--cp-duration-slow) ease; } .cp-gradient-border:hover::before { opacity: 1; } /* ===== CARD (legacy) ===== */ .cp-card { background: var(--card); color: var(--card-foreground); border: 1px solid color-mix(in oklch, var(--border) 60%, transparent); border-radius: var(--cp-card-radius); box-shadow: var(--cp-card-shadow); padding: var(--cp-card-padding); transition: box-shadow var(--cp-duration-normal) ease, border-color var(--cp-duration-normal) ease; } .cp-card:hover { box-shadow: var(--cp-card-shadow-lg); border-color: var(--border); } .cp-card-sm { padding: var(--cp-card-padding-sm); } .cp-card-lg { border-radius: var(--cp-card-radius-lg); box-shadow: var(--cp-card-shadow-lg); } .cp-card-interactive { cursor: pointer; } .cp-card-interactive:hover { transform: translateY(-1px); } .cp-card-interactive:active { transform: translateY(0); } /* ===== BADGE ===== */ .cp-badge { display: inline-flex; align-items: center; gap: var(--cp-space-1); border-radius: var(--cp-badge-radius); padding: var(--cp-badge-padding-y) var(--cp-badge-padding-x); font-size: var(--cp-badge-font-size); font-weight: var(--cp-badge-font-weight); line-height: 1; white-space: nowrap; } /* Badge variants - using 5 semantic colors */ .cp-badge-primary { background: var(--primary); color: var(--primary-foreground); } .cp-badge-secondary { background: var(--secondary); color: var(--secondary-foreground); } .cp-badge-success { background: var(--success); color: var(--success-foreground); } .cp-badge-info { background: var(--info); color: var(--info-foreground); } .cp-badge-warning { background: var(--warning); color: var(--warning-foreground); } .cp-badge-danger { background: var(--danger); color: var(--danger-foreground); } .cp-badge-neutral { background: var(--neutral); color: var(--neutral-foreground); } /* Soft badge variants (light bg, dark text) */ .cp-badge-soft-success { background: var(--success-soft); color: var(--success); } .cp-badge-soft-info { background: var(--info-soft); color: var(--info); } .cp-badge-soft-warning { background: var(--warning-soft); color: var(--warning); } .cp-badge-soft-danger { background: var(--danger-soft); color: var(--danger); } .cp-badge-soft-neutral { background: var(--neutral-soft); color: var(--neutral); } .cp-badge-outline { background: transparent; border: 1px solid currentColor; } /* ===== SKELETON (Loading state) ===== */ .cp-skeleton { background: var(--cp-skeleton-base); border-radius: var(--cp-radius-md); position: relative; overflow: hidden; } .cp-skeleton::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, transparent, var(--cp-skeleton-shimmer), transparent); animation: cp-skeleton-shimmer 2s infinite; } /* ===== FOCUS RING ===== */ .cp-focus-ring { outline: var(--cp-focus-ring); outline-offset: var(--cp-focus-ring-offset); } .cp-focus-ring-visible:focus-visible { outline: var(--cp-focus-ring); outline-offset: var(--cp-focus-ring-offset); } /* ===== SCROLLBAR ===== */ .scrollbar-hide { -ms-overflow-style: none; /* IE and Edge */ scrollbar-width: none; /* Firefox */ } .scrollbar-hide::-webkit-scrollbar { display: none; /* Chrome, Safari, Opera */ } /* ===== ACCESSIBILITY: REDUCED MOTION ===== */ @media (prefers-reduced-motion: reduce) { .cp-animate-in, .cp-animate-scale-in, .cp-animate-slide-left, .cp-stagger-children > *, .cp-card-hover-lift, .cp-toast-enter, .cp-toast-exit, .cp-activity-item, .cp-float, .cp-float-slow, .cp-float-delayed, .cp-glow-pulse { animation: none !important; transition: none !important; opacity: 1 !important; } } }