gridloc / src /styles.css
lassanmonster's picture
GridLoc: Bengaluru parking congestion digital twin
db3dbe1
Raw
History Blame Contribute Delete
12 kB
@import 'tailwindcss';
/* ── Design tokens (Deep Space Glacier) ──────────────────────────────────── */
@theme {
/* Backgrounds - neutral greyscale, no hue. */
--color-bg: #0a0a0b;
--color-bg-2: #0f0f10;
--color-panel: #141415;
--color-panel-2: #1a1a1c;
--color-line: #2a2a2c;
--color-line-2: #38383b;
/* Text */
--color-text: #ededed;
--color-muted: #8a8a8e;
--color-muted-2: #a6a6aa;
/* "Accents" are now just lighter/darker greys - monochrome aesthetic.
Names kept so existing class references (text-cyan, etc.) still resolve. */
--color-cyan: #d4d4d8;
--color-cyan-bright: #ffffff;
--color-indigo: #9a9a9e;
--color-amber: #b0b0b4;
--color-red: #e6e6e8;
--color-critical: #e6e6e8;
--color-green: #6a6a6e;
/* Zone-category severity - encoded by brightness, not hue. */
--color-hotspot: #efefef;
--color-blindspot: #9a9a9e;
--color-calm: #5a5a5e;
/* Fonts */
--font-display: 'Clash Display', 'Space Grotesk', system-ui, sans-serif;
--font-sans: 'Inter', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', 'Cascadia Code', monospace;
/* shadcn-compatible aliases - let dropped-in shadcn components (e.g. the
mapcn map) resolve bg-background/text-foreground/border-border/etc.
against our Deep Space Glacier palette. */
--color-background: #141415;
--color-foreground: #ededed;
--color-popover: #141415;
--color-popover-foreground: #ededed;
--color-muted-foreground: #8a8a8e;
--color-accent: #1f1f21;
--color-border: #2a2a2c;
--color-ring: #d4d4d8;
/* Tokens for shadcn-style components (limelight nav, etc.). */
--color-card: #141415;
--color-primary: #ededed;
--color-secondary: #1a1a1c;
--color-primary-foreground: #0a0a0b;
--color-card-foreground: #ededed;
}
/* Plain token BGPattern's fade masks expect (var(--background)). Matches the
page background so the masked edges blend into it. */
:root {
--background: #0a0a0b;
/* LimelightNav's glow shadow reads var(--primary) directly. */
--primary: #ededed;
}
html,
body {
margin: 0;
padding: 0;
height: 100%;
background: #0a0a0b;
color: #ededed;
font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
#app,
#root {
height: 100%;
}
/* Lenis smooth-scroll baseline */
html.lenis,
html.lenis body {
height: auto;
}
.lenis.lenis-smooth {
scroll-behavior: auto !important;
}
.lenis.lenis-stopped {
overflow: hidden;
}
/* Hex-grid backdrop */
.tron-grid {
background-image:
linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px);
background-size: 44px 44px;
}
/* Slow pulse for preview hexagons */
@keyframes hexpulse {
0%, 100% { opacity: 0.85; }
50% { opacity: 0.30; }
}
.hex-pulse { animation: hexpulse 3.2s ease-in-out infinite; }
/* Soft glow text utility */
.text-glow-cyan { text-shadow: 0 0 24px rgba(255, 255, 255, 0.35); }
/* Bobbing scroll cue */
@keyframes scrollcue {
0%, 100% { transform: translateY(0); opacity: 0.5; }
50% { transform: translateY(6px); opacity: 1; }
}
.scroll-cue { animation: scrollcue 1.8s ease-in-out infinite; }
/* Display-face helpers */
.font-display { font-family: var(--font-display); }
.font-mono { font-family: var(--font-mono); }
/* Section reveal - used by IntersectionObserver-driven sections */
.reveal {
opacity: 0;
transform: translateY(28px);
transition: opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1),
transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}
.reveal.is-visible {
opacity: 1;
transform: translateY(0);
}
/* ── Landing page theming ────────────────────────────────────────────────
The landing root carries data-theme="dark|light"; everything reads these
vars so the night/day toggle restyles the whole page. */
.landing-root {
--lp-bg: #07070a;
--lp-text: #ededed;
--lp-muted: #9a9a9e;
--lp-eyebrow: #b8b8bc;
--lp-line: #2a2a2c;
--lp-section: rgba(10, 10, 11, 0.5);
--lp-glow: rgba(214, 84, 44, 0.16);
--lp-grid: rgba(255, 255, 255, 0.09);
--lp-nav: rgba(10, 10, 11, 0.72);
--lp-chip: rgba(255, 255, 255, 0.04);
--lp-scrim: linear-gradient(90deg, #0a0a0b 0%, rgba(10, 10, 11, 0.8) 30%, rgba(10, 10, 11, 0) 56%);
}
.landing-root[data-theme='light'] {
--lp-bg: #eceef2;
--lp-text: #15171d;
--lp-muted: #565a63;
--lp-eyebrow: #6a6e77;
--lp-line: rgba(0, 0, 0, 0.12);
--lp-section: rgba(255, 255, 255, 0.45);
--lp-glow: rgba(214, 84, 44, 0.12);
--lp-grid: rgba(0, 0, 0, 0.06);
--lp-nav: rgba(255, 255, 255, 0.72);
--lp-chip: rgba(0, 0, 0, 0.04);
--lp-scrim: linear-gradient(90deg, #eceef2 0%, rgba(236, 238, 242, 0.8) 30%, rgba(236, 238, 242, 0) 56%);
}
/* Premium film-grain texture - fixed, very subtle, blended over everything. */
.grain-overlay {
position: fixed;
inset: 0;
z-index: 60;
pointer-events: none;
opacity: 0.03; /* Slightly lower opacity since normal blending is more visible than overlay */
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
background-size: 160px 160px;
}
/* Top scroll-progress meter. */
.scroll-progress {
position: fixed;
top: 0;
left: 0;
height: 2px;
z-index: 60;
transform-origin: left center;
background: linear-gradient(90deg, rgba(214,84,44,0.0), #d6542c 55%, #ff8a5c);
box-shadow: 0 0 12px rgba(214,84,44,0.55);
will-change: transform;
}
/* Glass "live" chip used for hero eyebrow. */
.live-dot {
position: relative;
display: inline-block;
width: 6px;
height: 6px;
border-radius: 999px;
background: #ff8a5c;
box-shadow: 0 0 8px rgba(255,138,92,0.9);
}
.live-dot::after {
content: '';
position: absolute;
inset: -4px;
border-radius: 999px;
border: 1px solid rgba(255,138,92,0.6);
animation: livePulse 2.2s ease-out infinite;
}
@keyframes livePulse {
0% { transform: scale(0.6); opacity: 0.9; }
100% { transform: scale(2.2); opacity: 0; }
}
/* Shine sweep - diagonal light pass on hover for premium buttons/cards. */
.shine {
position: relative;
overflow: hidden;
}
.shine::before {
content: '';
position: absolute;
top: 0;
left: -120%;
width: 80%;
height: 100%;
background: linear-gradient(100deg, transparent, rgba(255,255,255,0.18), transparent);
transform: skewX(-18deg);
transition: left 0.6s cubic-bezier(0.22, 1, 0.36, 1);
pointer-events: none;
}
.shine:hover::before { left: 130%; }
/* Animated gradient text sweep - for the hero headline accent. */
@keyframes textPan {
to { background-position: 200% center; }
}
.text-shimmer {
background-size: 200% auto;
animation: textPan 7s linear infinite;
}
/* Gentle floating bob - for accent elements that should feel alive. */
@keyframes floaty {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-7px); }
}
.floaty { animation: floaty 6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
.reveal { transition: none; opacity: 1; transform: none; }
.hex-pulse { animation: none; }
.text-shimmer { animation: none; }
.floaty { animation: none; }
.live-dot::after { animation: none; }
.shine::before { transition: none; }
}
/* ── Dashboard panel theming ─────────────────────────────────────────────
The dashboard root carries data-theme="dark|light"; panels read these vars
so a single attribute flip restyles every panel to match the basemap tone. */
.twin-root {
--tw-panel: rgba(17, 17, 17, 0.88);
--tw-border: rgba(255, 255, 255, 0.10);
--tw-text: #eaf0f7;
--tw-text-strong: #ffffff;
--tw-muted: #9a9a9e;
--tw-hover: rgba(255, 255, 255, 0.05);
--tw-scrollbar: rgba(255, 255, 255, 0.25);
--tw-scrollbar-hover: rgba(255, 255, 255, 0.45);
}
.twin-root[data-theme='light'] {
--tw-panel: rgba(249, 249, 251, 0.92);
--tw-border: rgba(0, 0, 0, 0.10);
--tw-text: #16181d;
--tw-text-strong: #000000;
--tw-muted: #5a5a5e;
--tw-hover: rgba(0, 0, 0, 0.05);
--tw-scrollbar: rgba(0, 0, 0, 0.3);
--tw-scrollbar-hover: rgba(0, 0, 0, 0.5);
}
/* Thin, rounded, track-less scrollbar for the dashboard panels. */
.twin-scroll {
scrollbar-width: thin; /* Firefox */
scrollbar-color: var(--tw-scrollbar) transparent;
}
.twin-scroll::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.twin-scroll::-webkit-scrollbar-track {
background: transparent;
}
.twin-scroll::-webkit-scrollbar-thumb {
background: var(--tw-scrollbar);
border-radius: 999px;
}
.twin-scroll::-webkit-scrollbar-thumb:hover {
background: var(--tw-scrollbar-hover);
}
.twin-scroll::-webkit-scrollbar-button {
display: none;
height: 0;
}
/* Extra-thin (4px) scrollbar for the detail panel's inner scroll area. */
.twin-scroll-thin {
scrollbar-width: thin; /* Firefox */
scrollbar-color: var(--tw-scrollbar) transparent;
}
.twin-scroll-thin::-webkit-scrollbar {
width: 4px;
}
.twin-scroll-thin::-webkit-scrollbar-track {
background: transparent;
}
.twin-scroll-thin::-webkit-scrollbar-thumb {
background: var(--tw-scrollbar);
border-radius: 2px;
}
.twin-scroll-thin::-webkit-scrollbar-button {
display: none;
height: 0;
}
/* Always-visible, grabbable scrollbar for the zone list (left panel, right
side). Wider track + solid thumb so the user can drag back to the top. */
.twin-scroll-visible {
scrollbar-width: auto; /* Firefox */
scrollbar-color: var(--tw-scrollbar) var(--tw-hover);
overscroll-behavior: contain;
}
.twin-scroll-visible::-webkit-scrollbar {
width: 11px;
}
.twin-scroll-visible::-webkit-scrollbar-track {
background: var(--tw-hover);
border-radius: 999px;
}
.twin-scroll-visible::-webkit-scrollbar-thumb {
background: var(--tw-scrollbar);
border-radius: 999px;
border: 2px solid transparent;
background-clip: padding-box;
min-height: 44px;
}
.twin-scroll-visible::-webkit-scrollbar-thumb:hover {
background: var(--tw-scrollbar-hover);
background-clip: padding-box;
}
.twin-scroll-visible::-webkit-scrollbar-button {
display: none;
height: 0;
}
/* Hide scrollbar completely for the main page to create an immersive experience. */
html {
scrollbar-width: none; /* Firefox */
}
html::-webkit-scrollbar {
display: none;
}
/* Bengaluru hub marker - soft expanding pulse halo behind the pin. */
@keyframes globehubpulse {
0% { transform: scale(0.6); opacity: 0.6; }
70% { transform: scale(1.8); opacity: 0; }
100% { transform: scale(1.8); opacity: 0; }
}
.globe-hub-pulse {
width: 26px;
height: 26px;
background: radial-gradient(circle, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 70%);
animation: globehubpulse 2.6s ease-out infinite;
}
@media (prefers-reduced-motion: reduce) {
.globe-hub-pulse { animation: none; opacity: 0.3; }
}
/* Police-light dot - gentle red↔blue crossfade (subtle, not a harsh strobe). */
@keyframes police-light {
0% { background: #e0544e; box-shadow: 0 0 8px 1px rgba(224,84,78,0.45); }
50% { background: #5a86e0; box-shadow: 0 0 8px 1px rgba(90,134,224,0.45); }
100% { background: #e0544e; box-shadow: 0 0 8px 1px rgba(224,84,78,0.45); }
}
.police-light {
animation: police-light 3.4s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
.police-light { animation: none; background: #d4d4d8; box-shadow: 0 0 12px rgba(255,255,255,0.5); }
}