@import url("https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap"); @import "tailwindcss"; /* * Design direction: Swiss Industrial * Dark neutral base, sharp teal accent, geometric precision. * Outfit for headings (geometric, characterful), system for body. * No purple gradients, no Inter, no AI slop. */ @theme { --color-surface-0: #0a0c10; --color-surface-1: #12151c; --color-surface-2: #1a1e28; --color-surface-3: #242a36; --color-text-primary: #e8ecf4; --color-text-secondary: #8892a4; --color-text-muted: #565e6e; --color-accent: #00d4aa; --color-accent-dim: #00b892; --color-accent-glow: #00d4aa26; --color-border: #1e2330; --color-border-active: #2c3344; --color-success: #34d399; --color-warning: #fbbf24; --color-error: #f87171; --font-display: "Outfit", system-ui, sans-serif; --font-body: "Outfit", system-ui, sans-serif; --font-mono: "IBM Plex Mono", monospace; } html { background: var(--color-surface-0); color: var(--color-text-primary); font-family: var(--font-body); -webkit-font-smoothing: antialiased; } /* Utility: subtle noise texture overlay */ .bg-noise::after { content: ""; position: absolute; inset: 0; opacity: 0.03; 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.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); pointer-events: none; } /* Accent underline for headings */ .accent-rule { position: relative; display: inline-block; } .accent-rule::after { content: ""; position: absolute; bottom: -4px; left: 0; width: 32px; height: 2px; background: var(--color-accent); } /* Card hover lift */ .card-interactive { transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease; } .card-interactive:hover { transform: translateY(-1px); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); border-color: var(--color-border-active); } /* Status dot pulse */ @keyframes pulse-dot { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } } .status-pulse { animation: pulse-dot 2s ease-in-out infinite; } /* Staggered fade-in for page content */ @keyframes fade-up { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } } .animate-in { animation: fade-up 0.4s ease-out both; } .animate-in-delay-1 { animation-delay: 0.05s; } .animate-in-delay-2 { animation-delay: 0.1s; } .animate-in-delay-3 { animation-delay: 0.15s; }