Files
OCR/frontend/src/index.css
beabigegg 57cf91271c feat: modernize frontend UI with Tailwind v4 and professional design system
BREAKING CHANGE: Migrated to Tailwind CSS v4 configuration system

Key Changes:
- Migrated from Tailwind v3 to v4 configuration system
  - Removed tailwind.config.js (incompatible with v4)
  - Updated index.css with @theme directive and oklch color space
  - Defined all custom animations directly in CSS using @keyframes

- Redesigned LoginPage with modern, enterprise-grade UI:
  - Full-screen gradient background (blue → purple → pink)
  - Floating animated orbs with blur effects
  - Glass morphism white card with backdrop-blur
  - Gradient buttons with shadow effects
  - 7 custom animations: fade-in, slide-in-right, slide-in-left, scale-in, shimmer, pulse, float

- Added shadcn/ui components:
  - alert.tsx, dialog.tsx, input.tsx, label.tsx, select.tsx, tabs.tsx

- Updated dependencies:
  - Added class-variance-authority ^0.7.0
  - Added react-markdown ^9.0.1

- Updated frontend documentation:
  - Comprehensive README.md with feature list, tech stack, project structure
  - Quick start guide and deployment instructions

Technical Details:
- Tailwind v4 uses @import "tailwindcss" instead of @tailwind directives
- All theme customization now in @theme block with CSS variables
- Color system migrated to oklch for better perceptual uniformity
- Animation definitions moved from config to CSS @layer utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 08:55:01 +08:00

266 lines
5.6 KiB
CSS

@import "tailwindcss";
@theme {
/* Clean, modern color palette */
--color-background: oklch(95% 0.02 220);
--color-foreground: oklch(20% 0.02 220);
--color-card: oklch(100% 0 0);
--color-card-foreground: oklch(20% 0.02 220);
--color-popover: oklch(100% 0 0);
--color-popover-foreground: oklch(20% 0.02 220);
/* Primary: Professional blue */
--color-primary: oklch(65% 0.25 250);
--color-primary-foreground: oklch(100% 0 0);
--color-primary-hover: oklch(60% 0.25 250);
/* Secondary: Subtle gray-blue */
--color-secondary: oklch(95% 0.02 220);
--color-secondary-foreground: oklch(30% 0.02 220);
/* Accent: Vibrant teal */
--color-accent: oklch(65% 0.20 180);
--color-accent-foreground: oklch(100% 0 0);
/* Muted */
--color-muted: oklch(93% 0.02 220);
--color-muted-foreground: oklch(50% 0.02 220);
/* Destructive */
--color-destructive: oklch(60% 0.22 25);
--color-destructive-foreground: oklch(100% 0 0);
/* Success */
--color-success: oklch(55% 0.20 150);
--color-success-foreground: oklch(100% 0 0);
/* Warning */
--color-warning: oklch(65% 0.22 60);
--color-warning-foreground: oklch(100% 0 0);
/* Borders and inputs */
--color-border: oklch(88% 0.02 220);
--color-input: oklch(88% 0.02 220);
--color-ring: oklch(65% 0.25 250);
/* Border radius */
--radius-lg: 0.5rem;
--radius-md: calc(0.5rem - 2px);
--radius-sm: calc(0.5rem - 4px);
/* Animations */
--animate-fade-in: fade-in 0.5s ease-out;
--animate-slide-in-right: slide-in-right 0.5s ease-out;
--animate-slide-in-left: slide-in-left 0.5s ease-out;
--animate-scale-in: scale-in 0.3s ease-out;
--animate-shimmer: shimmer 2s linear infinite;
--animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
--animate-float: float 3s ease-in-out infinite;
}
@layer base {
body {
background-color: var(--color-background);
color: var(--color-foreground);
font-feature-settings: "rlig" 1, "calt" 1;
}
}
@layer utilities {
/* Animations */
@keyframes fade-in {
0% {
opacity: 0;
transform: translateY(10px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slide-in-right {
0% {
opacity: 0;
transform: translateX(20px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
@keyframes slide-in-left {
0% {
opacity: 0;
transform: translateX(-20px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
@keyframes scale-in {
0% {
opacity: 0;
transform: scale(0.95);
}
100% {
opacity: 1;
transform: scale(1);
}
}
@keyframes shimmer {
0% {
background-position: -1000px 0;
}
100% {
background-position: 1000px 0;
}
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.8;
}
}
@keyframes float {
0%, 100% {
transform: translateY(0px);
}
50% {
transform: translateY(-10px);
}
}
.animate-fade-in {
animation: fade-in 0.5s ease-out;
}
.animate-slide-in-right {
animation: slide-in-right 0.5s ease-out;
}
.animate-slide-in-left {
animation: slide-in-left 0.5s ease-out;
}
.animate-scale-in {
animation: scale-in 0.3s ease-out;
}
.animate-shimmer {
animation: shimmer 2s linear infinite;
}
.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
.animate-float {
animation: float 3s ease-in-out infinite;
}
/* Custom scrollbar */
.scrollbar-thin::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.scrollbar-thin::-webkit-scrollbar-track {
background: var(--color-muted);
border-radius: 3px;
}
.scrollbar-thin::-webkit-scrollbar-thumb {
background: color-mix(in oklch, var(--color-muted-foreground) 30%, transparent);
border-radius: 3px;
}
.scrollbar-thin::-webkit-scrollbar-thumb:hover {
background: color-mix(in oklch, var(--color-muted-foreground) 50%, transparent);
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
}
@layer components {
/* Page header */
.page-header {
margin-bottom: 2rem;
}
.page-title {
font-size: 1.875rem;
font-weight: 700;
color: var(--color-foreground);
margin-bottom: 0.5rem;
}
.page-description {
color: var(--color-muted-foreground);
font-size: 0.875rem;
}
/* Section */
.section {
background: var(--color-card);
border: 1px solid var(--color-border);
border-radius: var(--radius-lg);
padding: 1.5rem;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
.section-header {
font-size: 1.125rem;
font-weight: 600;
color: var(--color-foreground);
margin-bottom: 1rem;
padding-bottom: 0.75rem;
border-bottom: 1px solid var(--color-border);
}
/* Status badge */
.status-badge {
display: inline-flex;
align-items: center;
padding: 0.25rem 0.75rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
}
.status-badge-success {
background: color-mix(in oklch, var(--color-success) 10%, transparent);
color: var(--color-success);
}
.status-badge-warning {
background: color-mix(in oklch, var(--color-warning) 10%, transparent);
color: var(--color-warning);
}
.status-badge-error {
background: color-mix(in oklch, var(--color-destructive) 10%, transparent);
color: var(--color-destructive);
}
.status-badge-info {
background: color-mix(in oklch, var(--color-primary) 10%, transparent);
color: var(--color-primary);
}
}