/* Linear-Inspired Design System v2.0 */ /* Fonts: Space Grotesk for headlines, Inter for body */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Space+Grotesk:wght@500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap'); @tailwind base; @tailwind components; @tailwind utilities; @layer base { /* ============================================ CSS Custom Properties (Design Tokens) ============================================ */ :root { /* Font families */ --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; --font-display: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; --font-mono: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace; /* Transition timing */ --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); --ease-in-out-expo: cubic-bezier(0.87, 0, 0.13, 1); --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* Duration */ --duration-instant: 50ms; --duration-fast: 100ms; --duration-normal: 150ms; --duration-slow: 250ms; --duration-slower: 400ms; /* ===== NEW DESIGN SYSTEM: Climate Monitoring Palette ===== */ /* Light mode backgrounds */ --color-bg-primary: #F9FAFB; --color-bg-secondary: #F1F5F9; --color-bg-tertiary: #E2E8F0; --color-bg-elevated: #FFFFFF; /* Light mode text */ --color-text-primary: #0F172A; --color-text-secondary: #475569; --color-text-tertiary: #94A3B8; --color-text-quaternary: #CBD5E1; --color-text-inverse: #F9FAFB; /* Light mode borders */ --color-border-default: #E2E8F0; --color-border-subtle: #F1F5F9; --color-border-strong: #94A3B8; /* Primary accent (Cultivation Green) */ --color-primary: #4ADE80; --color-primary-hover: #22C55E; --color-primary-soft: rgba(74, 222, 128, 0.15); /* Secondary accent (Cyan/Blue) */ --color-accent: #38BDF8; --color-accent-hover: #0EA5E9; --color-accent-soft: rgba(56, 189, 248, 0.15); /* Status colors */ --color-success: #4ADE80; --color-warning: #FACC15; --color-error: #F97373; --color-info: #38BDF8; /* Chart colors */ --color-chart-green: #4ADE80; --color-chart-blue: #38BDF8; --color-chart-orange: #FDBA74; --color-chart-purple: #A855F7; --color-chart-gridline: #E2E8F0; /* Layout constants */ --sidebar-width: 260px; --topbar-height: 64px; --card-radius: 16px; --card-padding: 20px; --radius-xs: 4px; --radius-sm: 8px; --radius-md: 12px; --radius-lg: 16px; --radius-xl: 24px; --radius-full: 999px; /* shadcn/ui compatibility */ --background: 210 20% 98%; --foreground: 222 47% 11%; --card: 0 0% 100%; --card-foreground: 222 47% 11%; --popover: 0 0% 100%; --popover-foreground: 222 47% 11%; --primary: 142 71% 45%; --primary-foreground: 0 0% 100%; --secondary: 210 40% 96%; --secondary-foreground: 222 47% 11%; --muted: 210 40% 96%; --muted-foreground: 215 16% 47%; --accent: 199 89% 48%; --accent-foreground: 0 0% 100%; --destructive: 0 72% 51%; --destructive-foreground: 0 0% 100%; --border: 214 32% 91%; --input: 214 32% 91%; --ring: 142 71% 45%; --radius: 16px; } /* ===== DARK MODE (Primary Theme) ===== */ .dark { /* Backgrounds - Deep blue-charcoal */ --color-bg-primary: #0B1020; --color-bg-secondary: #11182A; --color-bg-tertiary: #151C30; --color-bg-elevated: #11182A; /* Text */ --color-text-primary: #F9FAFB; --color-text-secondary: #9CA3AF; --color-text-tertiary: #6B7280; --color-text-quaternary: #374151; --color-text-inverse: #020617; /* Borders */ --color-border-default: #1E293B; --color-border-subtle: #151C30; --color-border-strong: #334155; /* Primary (Emerald Green) */ --color-primary: #4ADE80; --color-primary-hover: #22C55E; --color-primary-soft: #1C3B2B; /* Accent (Cyan) */ --color-accent: #38BDF8; --color-accent-hover: #0EA5E9; --color-accent-soft: #102538; /* Status Colors */ --color-success: #4ADE80; --color-warning: #FACC15; --color-error: #F97373; --color-info: #38BDF8; /* Chart colors */ --color-chart-gridline: #1E293B; /* shadcn/ui compatibility */ --background: 222 47% 5%; --foreground: 210 40% 98%; --card: 222 47% 8%; --card-foreground: 210 40% 98%; --popover: 222 47% 8%; --popover-foreground: 210 40% 98%; --primary: 142 71% 45%; --primary-foreground: 222 47% 5%; --secondary: 222 47% 12%; --secondary-foreground: 210 40% 98%; --muted: 222 47% 12%; --muted-foreground: 215 20% 65%; --accent: 199 89% 48%; --accent-foreground: 210 40% 98%; --destructive: 0 63% 45%; --destructive-foreground: 210 40% 98%; --border: 217 33% 17%; --input: 217 33% 17%; --ring: 142 71% 45%; } /* ============================================ Base Styles ============================================ */ html { font-size: 100%; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; scroll-behavior: smooth; overflow-x: hidden; } body { background-color: var(--color-bg-primary); color: var(--color-text-primary); font-family: var(--font-sans); font-feature-settings: 'ss01' 1, 'cv01' 1; letter-spacing: -0.011em; transition: background-color var(--duration-slow) var(--ease-out-expo), color var(--duration-slow) var(--ease-out-expo); } /* Code */ code, pre, kbd, samp { font-family: var(--font-mono); } /* Headings - Space Grotesk */ h1, h2, h3, h4, h5, h6, .font-display { font-family: var(--font-display); font-weight: 600; letter-spacing: -0.02em; } h1 { font-size: 2rem; line-height: 1.2; } h2 { font-size: 1.5rem; line-height: 1.25; } h3 { font-size: 1.25rem; line-height: 1.3; } h4 { font-size: 1.125rem; line-height: 1.35; } h5 { font-size: 1rem; line-height: 1.4; } h6 { font-size: 0.875rem; line-height: 1.45; } /* ============================================ Interactive Elements ============================================ */ button, input, select, textarea, a { min-height: 44px; min-width: 44px; -webkit-tap-highlight-color: transparent; touch-action: manipulation; } /* Global interactive transition */ button, a, input, select, textarea, [role="button"], [tabindex="0"] { transition: background-color var(--duration-fast) var(--ease-out-expo), border-color var(--duration-fast) var(--ease-out-expo), color var(--duration-fast) var(--ease-out-expo), box-shadow var(--duration-normal) var(--ease-out-expo), transform var(--duration-fast) var(--ease-spring); } /* Focus ring (Linear-style) */ *:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--color-bg-primary), 0 0 0 4px var(--color-accent); transition: box-shadow var(--duration-normal) var(--ease-out-expo); } /* Subtle press effect */ button:active:not(:disabled), [role="button"]:active:not(:disabled) { transform: scale(0.98); } /* ============================================ Typography ============================================ */ h1, h2, h3, h4, h5, h6 { font-weight: 600; letter-spacing: -0.02em; color: var(--color-text-primary); } h1 { font-size: 30px; line-height: 1.2; } h2 { font-size: 24px; line-height: 1.3; } h3 { font-size: 18px; line-height: 1.4; } h4 { font-size: 16px; line-height: 1.5; } /* Links (subtle, no color, underline on hover) */ a:not(.btn):not([class*="bg-"]) { color: var(--color-text-primary); text-decoration: none; transition: color var(--duration-fast) var(--ease-out-expo); } a:not(.btn):not([class*="bg-"]):hover { color: var(--color-accent); } /* Selection */ ::selection { background-color: var(--color-accent-muted); color: var(--color-text-primary); } /* ============================================ Reduced Motion ============================================ */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } } /* ============================================ High Contrast Mode ============================================ */ @media (prefers-contrast: high) { :root { --color-border-default: #171717; --color-border-subtle: #525252; } .dark { --color-border-default: #FAFAFA; --color-border-subtle: #A3A3A3; } } } @layer components { /* ============================================ Custom Scrollbar (Linear-style) ============================================ */ .custom-scrollbar::-webkit-scrollbar { width: 8px; height: 8px; } .custom-scrollbar::-webkit-scrollbar-track { background: transparent; } .custom-scrollbar::-webkit-scrollbar-thumb { background-color: var(--color-border-default); border-radius: 4px; border: 2px solid transparent; background-clip: content-box; } .custom-scrollbar::-webkit-scrollbar-thumb:hover { background-color: var(--color-border-strong); } /* Hide scrollbar */ .no-scrollbar::-webkit-scrollbar { display: none; } .no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; } /* ============================================ Button Styles ============================================ */ .btn { @apply inline-flex items-center justify-center gap-2; height: 36px; padding: 0 14px; font-size: 13px; font-weight: 500; border-radius: var(--radius-sm); cursor: pointer; user-select: none; white-space: nowrap; } .btn-primary { background-color: var(--color-primary); color: var(--color-text-inverse); } .btn-primary:hover:not(:disabled) { background-color: var(--color-primary-hover); } .btn-secondary { background-color: transparent; color: var(--color-text-secondary); border: 1px solid var(--color-border-default); } .btn-secondary:hover:not(:disabled) { background-color: var(--color-bg-tertiary); color: var(--color-text-primary); border-color: var(--color-border-strong); } .btn-ghost { background-color: transparent; color: var(--color-text-secondary); } .btn-ghost:hover:not(:disabled) { background-color: var(--color-bg-tertiary); color: var(--color-text-primary); } .btn-destructive { background-color: #EF4444; color: white; } .btn-destructive:hover:not(:disabled) { background-color: #DC2626; } .btn:disabled { opacity: 0.5; cursor: not-allowed; } /* ============================================ Card Styles (Climate Monitoring Design) ============================================ */ .card { background-color: var(--color-bg-elevated); border: 1px solid var(--color-border-subtle); border-radius: var(--card-radius); padding: var(--card-padding); transition: border-color var(--duration-fast) var(--ease-out-expo), box-shadow var(--duration-normal) var(--ease-out-expo); } .card:hover { border-color: var(--color-border-default); } .card-interactive { cursor: pointer; } .card-interactive:hover { border-color: var(--color-border-strong); box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08); } .dark .card { box-shadow: 0 18px 45px rgba(15, 23, 42, 0.55); } .dark .card-interactive:hover { box-shadow: 0 18px 45px rgba(15, 23, 42, 0.65); } /* Stat/KPI Card */ .stat-card { background-color: var(--color-bg-elevated); border: 1px solid var(--color-border-subtle); border-radius: var(--card-radius); padding: var(--card-padding); } .dark .stat-card { box-shadow: 0 18px 45px rgba(15, 23, 42, 0.55); } /* ============================================ Input Styles ============================================ */ .input { height: 36px; padding: 0 12px; font-size: 14px; background-color: var(--color-bg-primary); border: 1px solid var(--color-border-default); border-radius: 6px; color: var(--color-text-primary); transition: border-color var(--duration-fast) var(--ease-out-expo), box-shadow var(--duration-normal) var(--ease-out-expo); } .input::placeholder { color: var(--color-text-tertiary); } .input:focus { border-color: var(--color-accent); box-shadow: 0 0 0 3px var(--color-accent-muted); outline: none; } /* ============================================ Badge Styles (Pill design) ============================================ */ .badge { @apply inline-flex items-center justify-center; height: 22px; padding: 0 10px; font-size: 11px; font-weight: 600; letter-spacing: 0.06em; border-radius: var(--radius-full); background-color: var(--color-bg-tertiary); color: var(--color-text-secondary); } .badge-accent { background-color: var(--color-accent-soft); color: var(--color-accent); } .badge-primary { background-color: var(--color-primary-soft); color: var(--color-primary); } .badge-success { background-color: var(--color-success); color: var(--color-text-inverse); } .badge-warning { background-color: var(--color-warning); color: var(--color-text-inverse); } .badge-destructive { background-color: var(--color-error); color: var(--color-text-inverse); } /* Chip (smaller, for filters) */ .chip { @apply inline-flex items-center justify-center; height: 26px; padding: 0 12px; font-size: 11px; font-weight: 600; letter-spacing: 0.04em; border-radius: var(--radius-full); background-color: var(--color-bg-tertiary); color: var(--color-text-secondary); cursor: pointer; transition: all var(--duration-fast) var(--ease-out-expo); } .chip:hover { background-color: var(--color-border-default); color: var(--color-text-primary); } .chip.active { background-color: var(--color-primary); color: var(--color-text-inverse); } /* ============================================ Skeleton Loading (Shimmer) ============================================ */ .skeleton { background: linear-gradient(90deg, var(--color-bg-tertiary) 0%, var(--color-bg-secondary) 50%, var(--color-bg-tertiary) 100%); background-size: 200% 100%; animation: shimmer 1.5s ease-in-out infinite; border-radius: 4px; } @keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } /* ============================================ Tooltip ============================================ */ .tooltip { position: absolute; z-index: 50; padding: 6px 10px; font-size: 12px; font-weight: 500; background-color: var(--color-text-primary); color: var(--color-bg-primary); border-radius: 6px; pointer-events: none; opacity: 0; transform: translateY(4px); transition: opacity var(--duration-fast) var(--ease-out-expo), transform var(--duration-normal) var(--ease-out-expo); } .tooltip.show { opacity: 1; transform: translateY(0); } /* ============================================ Divider ============================================ */ .divider { height: 1px; background-color: var(--color-border-subtle); } } @layer utilities { /* Screen reader only */ .sr-only { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; } /* Touch target */ .touch-target { min-height: 44px; min-width: 44px; @apply flex items-center justify-center; } /* Text colors using CSS vars */ .text-primary { color: var(--color-text-primary); } .text-secondary { color: var(--color-text-secondary); } .text-tertiary { color: var(--color-text-tertiary); } .text-quaternary { color: var(--color-text-quaternary); } .text-accent { color: var(--color-accent); } /* Background colors using CSS vars */ .bg-primary { background-color: var(--color-bg-primary); } .bg-secondary { background-color: var(--color-bg-secondary); } .bg-tertiary { background-color: var(--color-bg-tertiary); } .bg-elevated { background-color: var(--color-bg-elevated); } /* Border colors using CSS vars */ .border-default { border-color: var(--color-border-default); } .border-subtle { border-color: var(--color-border-subtle); } .border-strong { border-color: var(--color-border-strong); } /* Animation utilities */ .animate-in { animation: fade-in var(--duration-normal) var(--ease-out-expo); } .animate-slide-up { animation: slide-up var(--duration-slow) var(--ease-out-expo); } .animate-scale-in { animation: scale-in var(--duration-normal) var(--ease-out-expo); } @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes slide-up { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } @keyframes scale-in { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } } }