Files
Pac-Man/web/layouts/tailwind.css
Xevion 3bb3908853 feat(web): add smooth page transitions and WASM loading states
- Implement navigation state tracking with optimistic UI updates
- Add loading spinner and error handling for WASM initialization
- Insert browser yield points during game initialization to prevent freezing
- Redesign leaderboard with tabbed navigation and mock data structure
- Add utility CSS classes for consistent page layouts
2025-12-29 03:33:43 -06:00

173 lines
3.2 KiB
CSS

@import "tailwindcss";
@layer base {
/* Page transitions */
body {
--transition-duration: 200ms;
}
body main {
opacity: 1;
transform: translateY(0);
transition:
opacity var(--transition-duration) ease-out,
transform var(--transition-duration) ease-out;
}
body.page-is-transitioning main {
opacity: 0;
transform: translateY(8px);
}
:root {
font-family:
"Outfit",
ui-sans-serif,
system-ui,
-apple-system,
"Segoe UI",
Roboto,
"Helvetica Neue",
Arial,
"Noto Sans",
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol",
sans-serif;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 500;
}
.os-scrollbar-handle {
background: rgb(250 204 21 / 0.25) !important;
}
.os-scrollbar-handle:hover {
background: rgb(250 204 21 / 0.4) !important;
}
.os-scrollbar-track {
background: transparent !important;
}
}
@keyframes glimmer {
0% {
background-position: -200% center;
}
100% {
background-position: 200% center;
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Loading spinner - CSS animation runs on compositor thread,
continues even during main thread blocking */
.loading-spinner {
width: 48px;
height: 48px;
border: 4px solid rgb(250 204 21 / 0.3);
border-top-color: rgb(250 204 21);
border-radius: 50%;
animation: spin 1s linear infinite;
}
/* Error indicator - X mark with shake animation */
@keyframes shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-4px); }
40%, 80% { transform: translateX(4px); }
}
.error-indicator {
width: 48px;
height: 48px;
position: relative;
animation: shake 0.5s ease-out;
}
.error-indicator::before,
.error-indicator::after {
content: '';
position: absolute;
width: 4px;
height: 32px;
background: rgb(239 68 68);
border-radius: 2px;
top: 50%;
left: 50%;
}
.error-indicator::before {
transform: translate(-50%, -50%) rotate(45deg);
}
.error-indicator::after {
transform: translate(-50%, -50%) rotate(-45deg);
}
@layer utilities {
.page-container {
@apply mx-auto max-w-3xl py-8 px-4;
}
.card {
@apply border border-yellow-400/20 rounded-md bg-transparent p-6 shadow-[0_4px_20px_rgba(250,204,21,0.08)];
}
.title-hover {
transition: transform 0.2s ease-out, filter 0.2s ease-out;
}
.title-hover:hover {
transform: scale(1.03);
filter: brightness(1.15);
}
.title-base {
position: relative;
}
.title-base::before {
content: attr(data-text);
position: absolute;
inset: 0;
background: linear-gradient(
90deg,
rgb(156 163 175) 0%,
rgb(156 163 175) 35%,
rgb(250 204 21) 45%,
rgb(250 204 21) 55%,
rgb(156 163 175) 65%,
rgb(156 163 175) 100%
);
background-size: 200% 100%;
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: glimmer 3s ease-in-out infinite;
opacity: 0;
transition: opacity 0.2s ease-out;
}
.title-base.title-glimmer::before {
opacity: 1;
}
}