/*
* =============================================================================
* 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; }