/* * ============================================================================= * VibeQuant (vquant) — AI-Powered Financial Intelligence Platform * ----------------------------------------------------------------------------- * File: client/src/index.css * * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * Website: https://www.spboucher.ai * Demo: https://www.vquant.ai * License: MIT (see LICENSE) * * Copyright © 2026 Simon-Pierre Boucher. All rights reserved. * ============================================================================= */ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500&display=swap'); @tailwind base; @tailwind components; @tailwind utilities; /* LIGHT MODE */ :root { --button-outline: rgba(0,0,0, .10); --badge-outline: rgba(0,0,0, .05); /* Automatic computation of border around primary / danger buttons */ --opaque-button-border-intensity: -8; /* In terms of percentages */ /* Backgrounds applied on top of other backgrounds when hovered/active */ --elevate-1: rgba(0,0,0, .03); --elevate-2: rgba(0,0,0, .08); --background: 210 20% 98%; --foreground: 222 47% 11%; --border: 214 20% 88%; --card: 0 0% 100%; --card-foreground: 222 47% 11%; --card-border: 214 20% 92%; --sidebar: 210 25% 95%; --sidebar-foreground: 222 47% 11%; --sidebar-border: 214 20% 86%; --sidebar-primary: 250 84% 60%; --sidebar-primary-foreground: 210 20% 98%; --sidebar-accent: 210 25% 90%; --sidebar-accent-foreground: 222 47% 11%; --sidebar-ring: 250 84% 60%; --popover: 210 25% 93%; --popover-foreground: 222 47% 11%; --popover-border: 214 20% 84%; --primary: 250 84% 60%; --primary-foreground: 210 20% 98%; --secondary: 210 25% 88%; --secondary-foreground: 222 47% 11%; --muted: 215 16% 90%; --muted-foreground: 215 14% 45%; --accent: 210 20% 92%; --accent-foreground: 222 47% 11%; --destructive: 0 84% 50%; --destructive-foreground: 0 0% 98%; --success: 142 76% 36%; --success-foreground: 210 20% 98%; --warning: 38 92% 50%; --warning-foreground: 222 47% 11%; --info: 199 89% 48%; --info-foreground: 210 20% 98%; --input: 214 20% 75%; --ring: 250 84% 60%; --chart-1: 210 100% 45%; --chart-2: 142 76% 36%; --chart-3: 199 89% 48%; --chart-4: 38 92% 50%; --chart-5: 200 90% 50%; --font-sans: Inter, -apple-system, BlinkMacSystemFont, sans-serif; --font-display: Inter, -apple-system, BlinkMacSystemFont, sans-serif; --font-serif: Georgia, serif; --font-mono: JetBrains Mono, Menlo, monospace; --radius: 0.9rem; --shadow-2xs: 0px 1px 2px 0px hsl(222 15% 8% / 0.05); --shadow-xs: 0px 1px 3px 0px hsl(222 15% 8% / 0.08); --shadow-sm: 0px 2px 4px -1px hsl(222 15% 8% / 0.06), 0px 1px 2px -1px hsl(222 15% 8% / 0.08); --shadow: 0px 4px 6px -1px hsl(222 15% 8% / 0.08), 0px 2px 4px -2px hsl(222 15% 8% / 0.06); --shadow-md: 0px 6px 12px -2px hsl(222 15% 8% / 0.12), 0px 3px 7px -3px hsl(222 15% 8% / 0.08); --shadow-lg: 0px 12px 24px -4px hsl(222 15% 8% / 0.18), 0px 6px 12px -4px hsl(222 15% 8% / 0.12); --shadow-xl: 0px 24px 40px -8px hsl(222 15% 8% / 0.24), 0px 10px 20px -6px hsl(222 15% 8% / 0.16); --shadow-2xl: 0px 32px 64px -12px hsl(222 15% 8% / 0.30); --tracking-normal: 0em; --spacing: 0.25rem; /* Automatically computed borders - intensity can be controlled by the user by the --opaque-button-border-intensity setting */ /* Fallback for older browsers */ --sidebar-primary-border: hsl(var(--sidebar-primary)); --sidebar-primary-border: hsl(from hsl(var(--sidebar-primary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); /* Fallback for older browsers */ --sidebar-accent-border: hsl(var(--sidebar-accent)); --sidebar-accent-border: hsl(from hsl(var(--sidebar-accent)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); /* Fallback for older browsers */ --primary-border: hsl(var(--primary)); --primary-border: hsl(from hsl(var(--primary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); /* Fallback for older browsers */ --secondary-border: hsl(var(--secondary)); --secondary-border: hsl(from hsl(var(--secondary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); /* Fallback for older browsers */ --muted-border: hsl(var(--muted)); --muted-border: hsl(from hsl(var(--muted)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); /* Fallback for older browsers */ --accent-border: hsl(var(--accent)); --accent-border: hsl(from hsl(var(--accent)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); /* Fallback for older browsers */ --destructive-border: hsl(var(--destructive)); --destructive-border: hsl(from hsl(var(--destructive)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); } .dark { --button-outline: rgba(255,255,255, .10); --badge-outline: rgba(255,255,255, .05); --opaque-button-border-intensity: 9; /* In terms of percentages */ /* Backgrounds applied on top of other backgrounds when hovered/active */ --elevate-1: rgba(255,255,255, .04); --elevate-2: rgba(255,255,255, .09); --background: 222 15% 8%; --foreground: 210 20% 98%; --border: 217 19% 20%; --card: 222 15% 11%; --card-foreground: 210 20% 98%; --card-border: 217 19% 24%; --sidebar: 222 15% 15%; --sidebar-foreground: 210 20% 98%; --sidebar-border: 217 19% 28%; --sidebar-primary: 250 84% 66%; --sidebar-primary-foreground: 210 20% 98%; --sidebar-accent: 222 15% 18%; --sidebar-accent-foreground: 210 20% 98%; --sidebar-ring: 250 84% 66%; --popover: 222 15% 18%; --popover-foreground: 210 20% 98%; --popover-border: 217 19% 32%; --primary: 250 84% 60%; --primary-foreground: 210 20% 98%; --secondary: 222 15% 22%; --secondary-foreground: 210 20% 98%; --muted: 217 19% 20%; --muted-foreground: 215 16% 65%; --accent: 222 12% 20%; --accent-foreground: 210 20% 98%; --destructive: 0 84% 60%; --destructive-foreground: 210 20% 98%; --success: 142 76% 55%; --success-foreground: 210 20% 98%; --warning: 38 92% 65%; --warning-foreground: 222 15% 8%; --info: 199 89% 60%; --info-foreground: 210 20% 98%; --input: 217 19% 35%; --ring: 250 84% 66%; --chart-1: 210 100% 65%; --chart-2: 142 76% 55%; --chart-3: 199 89% 60%; --chart-4: 38 92% 65%; --chart-5: 200 90% 65%; --shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.25); --shadow-xs: 0px 1px 3px 0px hsl(0 0% 0% / 0.30); --shadow-sm: 0px 2px 4px -1px hsl(0 0% 0% / 0.28), 0px 1px 2px -1px hsl(0 0% 0% / 0.35); --shadow: 0px 4px 6px -1px hsl(0 0% 0% / 0.35), 0px 2px 4px -2px hsl(0 0% 0% / 0.30); --shadow-md: 0px 6px 12px -2px hsl(0 0% 0% / 0.40), 0px 3px 7px -3px hsl(0 0% 0% / 0.35); --shadow-lg: 0px 12px 28px -4px hsl(0 0% 0% / 0.48), 0px 6px 14px -4px hsl(0 0% 0% / 0.40); --shadow-xl: 0px 24px 48px -8px hsl(0 0% 0% / 0.56), 0px 12px 24px -6px hsl(0 0% 0% / 0.48); --shadow-2xl: 0px 36px 72px -12px hsl(0 0% 0% / 0.64); /* Automatically computed borders - intensity can be controlled by the user by the --opaque-button-border-intensity setting */ --sidebar-primary-border: hsl(from hsl(var(--sidebar-primary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); --sidebar-accent-border: hsl(from hsl(var(--sidebar-accent)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); --primary-border: hsl(from hsl(var(--primary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); --secondary-border: hsl(from hsl(var(--secondary)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); --muted-border: hsl(from hsl(var(--muted)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); --accent-border: hsl(from hsl(var(--accent)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); --destructive-border: hsl(from hsl(var(--destructive)) h s calc(l + var(--opaque-button-border-intensity)) / alpha); } @layer base { * { @apply border-border; } body { @apply font-sans antialiased bg-background text-foreground; background-image: radial-gradient(1100px 520px at 100% -8%, hsl(var(--primary) / 0.06), transparent 60%), radial-gradient(900px 480px at 0% 0%, hsl(var(--info) / 0.05), transparent 55%); background-attachment: fixed; } } /** * Using the elevate system. * Automatic contrast adjustment. * * * * * // Using the tailwind utility when a data attribute is "on" * * // Or manually controlling the toggle state * * * Elevation systems have to handle many states. * - not-hovered, vs. hovered vs. active (three mutually exclusive states) * - toggled or not * - focused or not (this is not handled with these utilities) * * Even without handling focused or not, this is six possible combinations that * need to be distinguished from eachother visually. */ @layer utilities { /* Hide ugly search cancel button in Chrome until we can style it properly */ input[type="search"]::-webkit-search-cancel-button { @apply hidden; } /* Placeholder styling for contentEditable div */ [contenteditable][data-placeholder]:empty::before { content: attr(data-placeholder); color: hsl(var(--muted-foreground)); pointer-events: none; } /* .no-default-hover-elevate/no-default-active-elevate is an escape hatch so consumers of * buttons/badges can remove the automatic brightness adjustment on interactions * and program their own. */ .no-default-hover-elevate {} .no-default-active-elevate {} /** * Toggleable backgrounds go behind the content. Hoverable/active goes on top. * This way they can stack/compound. Both will overlap the parent's borders! * So borders will be automatically adjusted both on toggle, and hover/active, * and they will be compounded. */ .toggle-elevate::before, .toggle-elevate-2::before { content: ""; pointer-events: none; position: absolute; inset: 0px; /*border-radius: inherit; match rounded corners */ border-radius: inherit; z-index: -1; /* sits behind content but above backdrop */ } .toggle-elevate.toggle-elevated::before { background-color: var(--elevate-2); } /* If there's a 1px border, adjust the inset so that it covers that parent's border */ .border.toggle-elevate::before { inset: -1px; } /* Does not work on elements with overflow:hidden! */ .hover-elevate:not(.no-default-hover-elevate), .active-elevate:not(.no-default-active-elevate), .hover-elevate-2:not(.no-default-hover-elevate), .active-elevate-2:not(.no-default-active-elevate) { position: relative; z-index: 0; } .hover-elevate:not(.no-default-hover-elevate)::after, .active-elevate:not(.no-default-active-elevate)::after, .hover-elevate-2:not(.no-default-hover-elevate)::after, .active-elevate-2:not(.no-default-active-elevate)::after { content: ""; pointer-events: none; position: absolute; inset: 0px; /*border-radius: inherit; match rounded corners */ border-radius: inherit; z-index: 999; /* sits in front of content */ } .hover-elevate:hover:not(.no-default-hover-elevate)::after, .active-elevate:active:not(.no-default-active-elevate)::after { background-color: var(--elevate-1); } .hover-elevate-2:hover:not(.no-default-hover-elevate)::after, .active-elevate-2:active:not(.no-default-active-elevate)::after { background-color: var(--elevate-2); } /* If there's a 1px border, adjust the inset so that it covers that parent's border */ .border.hover-elevate:not(.no-hover-interaction-elevate)::after, .border.active-elevate:not(.no-active-interaction-elevate)::after, .border.hover-elevate-2:not(.no-hover-interaction-elevate)::after, .border.active-elevate-2:not(.no-active-interaction-elevate)::after, .border.hover-elevate:not(.no-hover-interaction-elevate)::after { inset: -1px; } @keyframes fade-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .animate-fade-in { animation: fade-in 0.6s ease-out; } /* Glass effect */ .glass { background: hsl(var(--card) / 0.95); border: 1px solid hsl(var(--border)); } /* Premium card effect */ .card-premium { background: hsl(var(--card)); border: 1px solid hsl(var(--border)); transition: border-color 0.2s ease, box-shadow 0.2s ease; } .card-premium:hover { border-color: hsl(var(--primary) / 0.4); box-shadow: var(--shadow-md); } } /* ── Modern polish: thin rounded scrollbars + selection ── */ * { scrollbar-width: thin; scrollbar-color: hsl(var(--muted-foreground) / 0.3) transparent; } *::-webkit-scrollbar { width: 10px; height: 10px; } *::-webkit-scrollbar-track { background: transparent; } *::-webkit-scrollbar-thumb { background: hsl(var(--muted-foreground) / 0.28); border-radius: 9999px; border: 2px solid transparent; background-clip: content-box; } *::-webkit-scrollbar-thumb:hover { background: hsl(var(--muted-foreground) / 0.45); background-clip: content-box; } ::selection { background: hsl(var(--primary) / 0.22); } /* ════════════════ VQuant × hot-sunset reskin (vcrawl-inspired) ════════════════ */ /* Unlayered + appended last → overrides the earlier token blocks. */ :root { --background: 40 30% 97%; --foreground: 24 14% 10%; --border: 36 22% 86%; --input: 36 20% 80%; --card: 0 0% 100%; --card-foreground: 24 14% 10%; --card-border: 36 22% 89%; --popover: 0 0% 100%; --popover-foreground: 24 14% 10%; --popover-border: 36 22% 86%; --primary: 14 100% 52%; --primary-foreground: 0 0% 100%; --secondary: 38 26% 92%; --secondary-foreground: 24 14% 12%; --muted: 38 26% 93%; --muted-foreground: 28 8% 42%; --accent: 38 30% 91%; --accent-foreground: 24 14% 12%; --warning: 34 100% 50%; --warning-foreground: 24 14% 10%; --ring: 14 100% 52%; --sidebar: 40 28% 95%; --sidebar-foreground: 24 14% 12%; --sidebar-border: 36 22% 86%; --sidebar-primary: 14 100% 52%; --sidebar-primary-foreground: 0 0% 100%; --sidebar-accent: 38 26% 90%; --sidebar-accent-foreground: 24 14% 12%; --sidebar-ring: 14 100% 52%; --chart-1: 14 100% 55%; --chart-2: 34 100% 55%; --chart-3: 338 90% 58%; --chart-4: 158 64% 42%; --chart-5: 199 89% 48%; } .dark { --background: 240 22% 5%; --foreground: 240 20% 98%; --border: 240 14% 16%; --input: 240 14% 20%; --card: 240 21% 9%; --card-foreground: 240 20% 98%; --card-border: 240 14% 18%; --popover: 240 18% 12%; --popover-foreground: 240 20% 98%; --popover-border: 240 14% 20%; --primary: 14 100% 56%; --primary-foreground: 0 0% 100%; --secondary: 240 16% 13%; --secondary-foreground: 240 20% 98%; --muted: 240 14% 16%; --muted-foreground: 230 14% 62%; --accent: 240 16% 16%; --accent-foreground: 240 20% 98%; --warning: 34 100% 60%; --warning-foreground: 240 22% 6%; --ring: 14 100% 56%; --sidebar: 240 22% 7%; --sidebar-foreground: 240 20% 98%; --sidebar-border: 240 14% 16%; --sidebar-primary: 14 100% 56%; --sidebar-primary-foreground: 0 0% 100%; --sidebar-accent: 240 16% 14%; --sidebar-accent-foreground: 240 20% 98%; --sidebar-ring: 14 100% 56%; --chart-1: 14 100% 60%; --chart-2: 34 100% 60%; --chart-3: 338 100% 66%; --chart-4: 158 64% 50%; --chart-5: 199 89% 62%; } body { background-image: radial-gradient(72% 55% at 50% -8%, hsl(var(--primary) / 0.16), transparent 70%), radial-gradient(42% 42% at 100% 0%, hsl(338 100% 60% / 0.08), transparent 60%); background-attachment: fixed; } /* ── hot-sunset wow utilities ── */ .bg-hot { background-image: linear-gradient(120deg, #ff9f1c 0%, #ff4d1c 46%, #ff2d78 100%); } .gradient-text { background-image: linear-gradient(120deg, #ff9f1c 0%, #ff4d1c 46%, #ff2d78 100%); -webkit-background-clip: text; background-clip: text; color: transparent; } .shadow-hot { box-shadow: 0 8px 30px -6px rgba(255,77,28,0.55); } .glow-ring { box-shadow: 0 0 0 1px hsl(var(--primary) / 0.35), 0 14px 48px -12px hsl(var(--primary) / 0.5); } .bg-grid { background-image: linear-gradient(hsl(var(--primary) / 0.12) 1px, transparent 1px), linear-gradient(90deg, hsl(var(--primary) / 0.12) 1px, transparent 1px); background-size: 44px 44px; } .hero-mask { -webkit-mask-image: radial-gradient(60% 60% at 50% 30%, black, transparent 75%); mask-image: radial-gradient(60% 60% at 50% 30%, black, transparent 75%); } @keyframes vq-float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-5px); } } .animate-float { animation: vq-float 4s ease-in-out infinite; } @keyframes vq-pulse-ring { 0% { box-shadow: 0 0 0 0 rgba(255,77,28,0.45); } 70% { box-shadow: 0 0 0 10px rgba(255,77,28,0); } 100% { box-shadow: 0 0 0 0 rgba(255,77,28,0); } } .animate-pulse-ring { animation: vq-pulse-ring 2.2s infinite; }