puzzle-trainer/app/globals.css
2026-05-23 01:05:21 +00:00

212 lines
7.9 KiB
CSS

@import "tailwindcss";
/* ── Design tokens ──────────────────────────────────────────────────────────── */
:root {
--radius-sm: 6px;
--radius-md: 12px;
--radius-lg: 20px;
--radius-full: 9999px;
--shadow-card: 0 1px 3px 0 rgb(0 0 0 / 0.06), 0 1px 2px -1px rgb(0 0 0 / 0.04);
--shadow-hover: 0 4px 12px 0 rgb(0 0 0 / 0.08), 0 2px 4px -1px rgb(0 0 0 / 0.05);
--shadow-win: 0 8px 24px 0 rgb(34 197 94 / 0.18);
--transition-base: 150ms ease;
--transition-smooth: 250ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* ── PWA / iOS native feel ──────────────────────────────────────────────────── */
html, body {
/* Full height accounting for iOS dynamic viewport */
height: 100%;
min-height: -webkit-fill-available;
}
body {
/* Prevent bounce scroll on iOS (native app feel) */
overscroll-behavior: none;
/* Prevent text selection on interactive elements */
-webkit-touch-callout: none;
}
/* Tap targets: no highlight flash on iOS */
* { -webkit-tap-highlight-color: transparent; }
/* Game grids: no text selection, instant touch response */
.game-grid, [data-game-grid] {
touch-action: manipulation;
user-select: none;
-webkit-user-select: none;
}
/* ── Reset & base ───────────────────────────────────────────────────────────── */
* { box-sizing: border-box; }
html {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
scroll-behavior: smooth;
color-scheme: light;
}
body {
background: #f8fafc;
color: #09090b;
font-family: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", "Helvetica Neue", Arial, sans-serif;
line-height: 1.5;
}
/* ── Focus visible ──────────────────────────────────────────────────────────── */
:focus-visible {
outline: 2px solid #3b82f6;
outline-offset: 2px;
border-radius: 4px;
}
/* ── Scrollbar ──────────────────────────────────────────────────────────────── */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: #9ca3af; }
/* ── Page fade-in ───────────────────────────────────────────────────────────── */
@keyframes fadeUp {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
main > div { animation: fadeUp 0.25s ease both; }
/* ── Win banner animation ───────────────────────────────────────────────────── */
@keyframes popIn {
0% { transform: scale(0.85); opacity: 0; }
60% { transform: scale(1.04); }
100% { transform: scale(1); opacity: 1; }
}
.win-banner {
animation: popIn 0.38s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
/* ── Cell flash (win feedback) ──────────────────────────────────────────────── */
@keyframes cellWin {
0% { background-color: inherit; }
40% { background-color: #bbf7d0; }
100% { background-color: inherit; }
}
.cell-win { animation: cellWin 0.6s ease both; }
/* ── Shake animation (error) ────────────────────────────────────────────────── */
@keyframes shake {
0%, 100% { transform: translateX(0); }
20% { transform: translateX(-4px); }
40% { transform: translateX(4px); }
60% { transform: translateX(-3px); }
80% { transform: translateX(3px); }
}
.shake { animation: shake 0.35s ease; }
/* ── Skeleton loading ───────────────────────────────────────────────────────── */
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
.skeleton {
background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%);
background-size: 200% 100%;
animation: shimmer 1.4s ease infinite;
border-radius: var(--radius-md);
}
/* ── Progress bar ───────────────────────────────────────────────────────────── */
.progress-track {
height: 5px;
border-radius: var(--radius-full);
background: #e2e8f0;
overflow: hidden;
}
.progress-fill {
height: 100%;
border-radius: var(--radius-full);
transition: width 0.7s cubic-bezier(0.4, 0, 0.2, 1);
}
/* ── Timer display ──────────────────────────────────────────────────────────── */
.timer-mono {
font-variant-numeric: tabular-nums;
letter-spacing: 0.05em;
}
/* ── Pulse ring (current level) ─────────────────────────────────────────────── */
@keyframes pulseRing {
0%, 100% { box-shadow: 0 0 0 0px currentColor; }
50% { box-shadow: 0 0 0 3px currentColor; }
}
.level-current { animation: pulseRing 1.8s ease-in-out infinite; }
/* ── Solved card overlay ────────────────────────────────────────────────────── */
.card-solved {
position: relative;
}
.card-solved::after {
content: "✓";
position: absolute;
top: 6px;
right: 8px;
font-size: 11px;
font-weight: 700;
color: #16a34a;
opacity: 0.8;
}
/* ── Dark mode ──────────────────────────────────────────────────────────────── */
@media (prefers-color-scheme: dark) {
html { color-scheme: dark; }
body {
background: #0f1117;
color: #f1f5f9;
}
/* Cards & panels */
.bg-white { background: #1e2130 !important; }
.border-gray-100 { border-color: #2a2f42 !important; }
.border-gray-200 { border-color: #363b52 !important; }
.bg-gray-50 { background: #181c27 !important; }
.bg-gray-100 { background: #252a3a !important; }
/* Text */
.text-gray-900 { color: #f1f5f9 !important; }
.text-gray-800 { color: #e2e8f0 !important; }
.text-gray-700 { color: #cbd5e1 !important; }
.text-gray-600 { color: #94a3b8 !important; }
.text-gray-500 { color: #64748b !important; }
.text-gray-400 { color: #475569 !important; }
.text-gray-300 { color: #374151 !important; }
/* Header */
header { background: rgba(15, 17, 23, 0.92) !important; border-color: #1e2130 !important; }
/* Footer */
footer { background: #0f1117 !important; border-color: #1e2130 !important; }
/* Skeleton */
.skeleton {
background: linear-gradient(90deg, #1e2130 25%, #252a3a 50%, #1e2130 75%) !important;
}
/* Progress track */
.progress-track { background: #252a3a !important; }
/* Scrollbar */
::-webkit-scrollbar-thumb { background: #363b52; }
::-webkit-scrollbar-thumb:hover { background: #475569; }
/* Bottom nav */
nav.fixed.bottom-0 { background: rgba(15, 17, 23, 0.95) !important; border-color: #1e2130 !important; }
}