Files
Claude-Code-Workflow/ccw/frontend/src/index.css
catlog22 166211dcd4 feat: add Unsplash search hook and API proxy routes
- Implemented `useUnsplashSearch` hook for searching Unsplash photos with debounce.
- Created Unsplash API client functions for searching photos and triggering downloads.
- Added proxy routes for Unsplash API to handle search requests and background image uploads.
- Introduced accessibility utilities for WCAG compliance checks and motion preference management.
- Developed theme sharing module for encoding and decoding theme configurations as base64url strings.
2026-02-08 20:01:28 +08:00

747 lines
19 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap');
@import './styles/typography.css';
@tailwind base;
@tailwind components;
@tailwind utilities;
/* ===========================
Multi-Theme Color System
4 Colors × 2 Modes = 8 Themes
=========================== */
/* Classic Blue - Light Mode */
:root,
[data-theme="light-blue"] {
--bg: 0 0% 98%;
--surface: 220 60% 99%;
--border: 220 20% 88%;
--text: 220 30% 15%;
--text-secondary: 220 15% 45%;
--accent: 220 60% 65%;
/* Legacy variables for backward compatibility */
--background: var(--bg);
--foreground: var(--text);
--card: var(--surface);
--card-foreground: var(--text);
--primary: var(--accent);
--primary-foreground: 0 0% 100%;
--primary-light: 220 60% 92%;
--secondary: 220 60% 65%;
--secondary-foreground: 0 0% 100%;
--accent-foreground: 0 0% 100%;
--destructive: 8 75% 55%;
--destructive-foreground: 0 0% 100%;
--muted: 220 20% 96%;
--muted-foreground: var(--text-secondary);
--sidebar-background: 220 40% 97%;
--sidebar-foreground: var(--text);
--hover: 220 20% 93%;
--input: var(--border);
--ring: var(--accent);
--success: 142 71% 45%;
--success-light: 142 76% 90%;
--warning: 38 92% 50%;
--warning-light: 48 96% 89%;
--info: 220 60% 60%;
--info-light: 210 80% 92%;
--indigo: 239 65% 60%;
--indigo-light: 239 65% 92%;
--orange: 25 90% 55%;
--orange-light: 25 90% 92%;
}
/* Classic Blue - Dark Mode */
[data-theme="dark-blue"] {
--bg: 220 30% 10%;
--surface: 220 25% 14%;
--border: 220 20% 22%;
--text: 220 20% 90%;
--text-secondary: 220 15% 60%;
--accent: 220 60% 65%;
/* Legacy variables */
--background: var(--bg);
--foreground: var(--text);
--card: var(--surface);
--card-foreground: var(--text);
--primary: var(--accent);
--primary-foreground: 220 30% 10%;
--primary-light: 220 60% 30%;
--secondary: 220 60% 60%;
--secondary-foreground: 0 0% 100%;
--accent-foreground: 220 30% 10%;
--destructive: 8 70% 50%;
--destructive-foreground: 0 0% 100%;
--muted: 220 25% 18%;
--muted-foreground: var(--text-secondary);
--sidebar-background: 220 30% 12%;
--sidebar-foreground: var(--text);
--hover: 220 20% 24%;
--input: var(--border);
--ring: var(--accent);
--success: 142 71% 40%;
--success-light: 142 50% 20%;
--warning: 38 85% 45%;
--warning-light: 40 50% 20%;
--info: 220 60% 55%;
--info-light: 210 50% 20%;
--indigo: 239 60% 55%;
--indigo-light: 239 40% 20%;
--orange: 25 85% 50%;
--orange-light: 25 50% 20%;
}
/* Deep Green - Light Mode */
[data-theme="light-green"] {
--bg: 0 0% 98%;
--surface: 150 50% 99%;
--border: 150 20% 88%;
--text: 150 30% 15%;
--text-secondary: 150 15% 45%;
--accent: 150 75% 42%;
/* Legacy variables */
--background: var(--bg);
--foreground: var(--text);
--card: var(--surface);
--card-foreground: var(--text);
--primary: var(--accent);
--primary-foreground: 0 0% 100%;
--primary-light: 150 75% 95%;
--secondary: 150 60% 55%;
--secondary-foreground: 0 0% 100%;
--accent-foreground: 0 0% 100%;
--destructive: 8 75% 55%;
--destructive-foreground: 0 0% 100%;
--muted: 150 20% 96%;
--muted-foreground: var(--text-secondary);
--sidebar-background: 150 30% 97%;
--sidebar-foreground: var(--text);
--hover: 150 20% 93%;
--input: var(--border);
--ring: var(--accent);
--success: 142 71% 45%;
--success-light: 142 76% 90%;
--warning: 38 92% 50%;
--warning-light: 48 96% 89%;
--info: 210 80% 55%;
--info-light: 210 80% 92%;
--indigo: 239 65% 60%;
--indigo-light: 239 65% 92%;
--orange: 25 90% 55%;
--orange-light: 25 90% 92%;
}
/* Deep Green - Dark Mode */
[data-theme="dark-green"] {
--bg: 150 30% 10%;
--surface: 150 25% 14%;
--border: 150 20% 22%;
--text: 150 15% 90%;
--text-secondary: 150 12% 60%;
--accent: 150 75% 45%;
/* Legacy variables */
--background: var(--bg);
--foreground: var(--text);
--card: var(--surface);
--card-foreground: var(--text);
--primary: var(--accent);
--primary-foreground: 150 30% 10%;
--primary-light: 150 60% 25%;
--secondary: 150 55% 50%;
--secondary-foreground: 0 0% 100%;
--accent-foreground: 150 30% 10%;
--destructive: 8 70% 50%;
--destructive-foreground: 0 0% 100%;
--muted: 150 25% 18%;
--muted-foreground: var(--text-secondary);
--sidebar-background: 150 30% 12%;
--sidebar-foreground: var(--text);
--hover: 150 20% 24%;
--input: var(--border);
--ring: var(--accent);
--success: 142 71% 40%;
--success-light: 142 50% 20%;
--warning: 38 85% 45%;
--warning-light: 40 50% 20%;
--info: 210 75% 50%;
--info-light: 210 50% 20%;
--indigo: 239 60% 55%;
--indigo-light: 239 40% 20%;
--orange: 25 85% 50%;
--orange-light: 25 50% 20%;
}
/* Vibrant Orange - Light Mode */
[data-theme="light-orange"] {
--bg: 0 0% 98%;
--surface: 25 70% 99%;
--border: 25 30% 88%;
--text: 25 30% 15%;
--text-secondary: 25 15% 45%;
--accent: 25 95% 53%;
/* Legacy variables */
--background: var(--bg);
--foreground: var(--text);
--card: var(--surface);
--card-foreground: var(--text);
--primary: var(--accent);
--primary-foreground: 0 0% 100%;
--primary-light: 25 95% 95%;
--secondary: 25 80% 60%;
--secondary-foreground: 0 0% 100%;
--accent-foreground: 0 0% 100%;
--destructive: 8 75% 55%;
--destructive-foreground: 0 0% 100%;
--muted: 25 20% 96%;
--muted-foreground: var(--text-secondary);
--sidebar-background: 25 40% 97%;
--sidebar-foreground: var(--text);
--hover: 25 30% 93%;
--input: var(--border);
--ring: var(--accent);
--success: 142 71% 45%;
--success-light: 142 76% 90%;
--warning: 38 92% 50%;
--warning-light: 48 96% 89%;
--info: 210 80% 55%;
--info-light: 210 80% 92%;
--indigo: 239 65% 60%;
--indigo-light: 239 65% 92%;
--orange: 25 90% 55%;
--orange-light: 25 90% 92%;
}
/* Vibrant Orange - Dark Mode */
[data-theme="dark-orange"] {
--bg: 25 30% 10%;
--surface: 25 25% 14%;
--border: 25 20% 22%;
--text: 25 15% 90%;
--text-secondary: 25 12% 60%;
--accent: 25 95% 55%;
/* Legacy variables */
--background: var(--bg);
--foreground: var(--text);
--card: var(--surface);
--card-foreground: var(--text);
--primary: var(--accent);
--primary-foreground: 25 30% 10%;
--primary-light: 25 80% 30%;
--secondary: 25 75% 55%;
--secondary-foreground: 0 0% 100%;
--accent-foreground: 25 30% 10%;
--destructive: 8 70% 50%;
--destructive-foreground: 0 0% 100%;
--muted: 25 25% 18%;
--muted-foreground: var(--text-secondary);
--sidebar-background: 25 30% 12%;
--sidebar-foreground: var(--text);
--hover: 25 20% 24%;
--input: var(--border);
--ring: var(--accent);
--success: 142 71% 40%;
--success-light: 142 50% 20%;
--warning: 38 85% 45%;
--warning-light: 40 50% 20%;
--info: 210 75% 50%;
--info-light: 210 50% 20%;
--indigo: 239 60% 55%;
--indigo-light: 239 40% 20%;
--orange: 25 85% 50%;
--orange-light: 25 50% 20%;
}
/* Elegant Purple - Light Mode */
[data-theme="light-purple"] {
--bg: 0 0% 98%;
--surface: 270 60% 99%;
--border: 270 20% 88%;
--text: 270 30% 15%;
--text-secondary: 270 15% 45%;
--accent: 270 75% 60%;
/* Legacy variables */
--background: var(--bg);
--foreground: var(--text);
--card: var(--surface);
--card-foreground: var(--text);
--primary: var(--accent);
--primary-foreground: 0 0% 100%;
--primary-light: 270 75% 95%;
--secondary: 270 65% 65%;
--secondary-foreground: 0 0% 100%;
--accent-foreground: 0 0% 100%;
--destructive: 8 75% 55%;
--destructive-foreground: 0 0% 100%;
--muted: 270 20% 96%;
--muted-foreground: var(--text-secondary);
--sidebar-background: 270 35% 97%;
--sidebar-foreground: var(--text);
--hover: 270 20% 93%;
--input: var(--border);
--ring: var(--accent);
--success: 142 71% 45%;
--success-light: 142 76% 90%;
--warning: 38 92% 50%;
--warning-light: 48 96% 89%;
--info: 210 80% 55%;
--info-light: 210 80% 92%;
--indigo: 239 65% 60%;
--indigo-light: 239 65% 92%;
--orange: 25 90% 55%;
--orange-light: 25 90% 92%;
}
/* Elegant Purple - Dark Mode */
[data-theme="dark-purple"] {
--bg: 270 30% 10%;
--surface: 270 25% 14%;
--border: 270 20% 22%;
--text: 270 15% 90%;
--text-secondary: 270 12% 60%;
--accent: 270 75% 62%;
/* Legacy variables */
--background: var(--bg);
--foreground: var(--text);
--card: var(--surface);
--card-foreground: var(--text);
--primary: var(--accent);
--primary-foreground: 270 30% 10%;
--primary-light: 270 60% 30%;
--secondary: 270 60% 58%;
--secondary-foreground: 0 0% 100%;
--accent-foreground: 270 30% 10%;
--destructive: 8 70% 50%;
--destructive-foreground: 0 0% 100%;
--muted: 270 25% 18%;
--muted-foreground: var(--text-secondary);
--sidebar-background: 270 30% 12%;
--sidebar-foreground: var(--text);
--hover: 270 20% 24%;
--input: var(--border);
--ring: var(--accent);
--success: 142 71% 40%;
--success-light: 142 50% 20%;
--warning: 38 85% 45%;
--warning-light: 40 50% 20%;
--info: 210 75% 50%;
--info-light: 210 50% 20%;
--indigo: 239 60% 55%;
--indigo-light: 239 40% 20%;
--orange: 25 85% 50%;
--orange-light: 25 50% 20%;
}
/* Alias for legacy dark mode */
[data-theme="dark"] {
--bg: var(--bg, 220 30% 10%);
--surface: var(--surface, 220 25% 14%);
--border: var(--border, 220 20% 22%);
--text: var(--text, 220 20% 90%);
--text-secondary: var(--text-secondary, 220 15% 60%);
--accent: var(--accent, 220 60% 65%);
/* Apply dark-blue theme as fallback */
--background: 220 30% 10%;
--foreground: 220 20% 90%;
--card: 220 25% 14%;
--card-foreground: 220 20% 90%;
--border: 220 20% 22%;
--input: 220 20% 22%;
--ring: 220 60% 65%;
--primary: 220 60% 65%;
--primary-foreground: 220 30% 10%;
--primary-light: 220 60% 30%;
--secondary: 220 60% 60%;
--secondary-foreground: 0 0% 100%;
--accent: 220 60% 65%;
--accent-foreground: 220 30% 10%;
--destructive: 8 70% 50%;
--destructive-foreground: 0 0% 100%;
--muted: 220 25% 18%;
--muted-foreground: 220 15% 60%;
--sidebar-background: 220 30% 12%;
--sidebar-foreground: 220 20% 90%;
--hover: 220 20% 24%;
--success: 142 71% 40%;
--success-light: 142 50% 20%;
--warning: 38 85% 45%;
--warning-light: 40 50% 20%;
--info: 220 60% 55%;
--info-light: 210 50% 20%;
--indigo: 239 60% 55%;
--indigo-light: 239 40% 20%;
--orange: 25 85% 50%;
--orange-light: 25 50% 20%;
}
/* Base styles */
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-family: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Code and data display should use monospace */
code, kbd, pre {
@apply font-mono;
}
}
/* Scrollbar styling */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: hsl(var(--border));
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: hsl(var(--muted-foreground));
}
/* Animations */
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.animate-spin {
animation: spin 1s linear infinite;
}
/* ===========================
Gradient Effects System
Conditional styles based on data attributes
=========================== */
/* Disable gradients when off */
[data-gradient="off"] .bg-gradient-primary,
[data-gradient="off"] .bg-gradient-brand,
[data-gradient="off"] .bg-gradient-accent {
background-image: none !important;
background: inherit;
}
[data-gradient="off"] .gradient-text {
background-image: none !important;
-webkit-background-clip: unset;
background-clip: unset;
-webkit-text-fill-color: inherit;
}
[data-gradient="off"] .border-gradient-brand::before {
display: none;
}
/* Standard gradients (default) */
[data-gradient="standard"] .bg-gradient-primary {
background: linear-gradient(135deg, hsl(var(--primary)) 0%, hsl(var(--accent)) 100%);
}
[data-gradient="standard"] .bg-gradient-brand {
background: linear-gradient(135deg, hsl(var(--accent)) 0%, hsl(var(--primary)) 100%);
}
[data-gradient="standard"] .bg-gradient-accent {
background: linear-gradient(90deg, hsl(var(--accent)) 0%, hsl(var(--primary)) 100%);
}
[data-gradient="standard"] .gradient-text {
background: linear-gradient(135deg, hsl(var(--primary)) 0%, hsl(var(--accent)) 100%);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
/* Enhanced gradients - more vibrant with multiple color stops */
[data-gradient="enhanced"] .bg-gradient-primary {
background: linear-gradient(135deg,
hsl(var(--primary)) 0%,
hsl(var(--accent)) 50%,
hsl(var(--secondary)) 100%
);
}
[data-gradient="enhanced"] .bg-gradient-brand {
background: linear-gradient(135deg,
hsl(var(--accent)) 0%,
hsl(var(--primary)) 40%,
hsl(var(--secondary)) 100%
);
}
[data-gradient="enhanced"] .bg-gradient-accent {
background: linear-gradient(90deg,
hsl(var(--accent)) 0%,
hsl(var(--primary)) 50%,
hsl(var(--accent)) 100%
);
}
[data-gradient="enhanced"] .gradient-text {
background: linear-gradient(135deg,
hsl(var(--primary)) 0%,
hsl(var(--accent)) 50%,
hsl(var(--secondary)) 100%
);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
/* Hover glow effects - disabled when data-hover-glow="false" */
.hover-glow,
.hover-glow-primary {
transition: box-shadow 0.3s ease;
}
.hover-glow:hover {
box-shadow: 0 0 20px hsla(var(--accent), 0.4);
}
.hover-glow-primary:hover {
box-shadow: 0 0 20px hsla(var(--primary), 0.4);
}
[data-hover-glow="false"] .hover-glow:hover,
[data-hover-glow="false"] .hover-glow-primary:hover {
box-shadow: none;
}
/* Background animation keyframes */
@keyframes slow-gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
/* Animated background gradient class */
.animate-slow-gradient {
background-size: 200% 200%;
animation: slow-gradient 15s ease infinite;
}
/* Disable background animation when data-bg-animation="false" */
[data-bg-animation="false"] .animate-slow-gradient {
animation: none;
background-size: 100% 100%;
}
/* ===========================
Global Ambient Gradient Background
Always visible behind content
=========================== */
/* Standard ambient gradient - subtle */
[data-gradient="standard"] body::before {
content: '';
position: fixed;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle at 30% 30%, hsla(var(--accent), 0.03) 0%, transparent 50%),
radial-gradient(circle at 70% 70%, hsla(var(--primary), 0.03) 0%, transparent 50%);
pointer-events: none;
z-index: -1;
}
/* Enhanced ambient gradient - more vibrant with animation */
[data-gradient="enhanced"] body::before {
content: '';
position: fixed;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle at 20% 20%, hsla(var(--accent), 0.08) 0%, transparent 40%),
radial-gradient(circle at 80% 80%, hsla(var(--primary), 0.08) 0%, transparent 40%),
radial-gradient(circle at 50% 50%, hsla(var(--secondary), 0.05) 0%, transparent 50%);
pointer-events: none;
z-index: -1;
animation: ambient-shift 20s ease-in-out infinite;
}
/* Disable ambient gradient when off */
[data-gradient="off"] body::before {
display: none;
}
/* Ambient shift animation for enhanced gradient */
@keyframes ambient-shift {
0%, 100% { transform: translate(0, 0); }
50% { transform: translate(-2%, -2%); }
}
/* ===========================
Reduced Motion System
data-reduced-motion attribute + prefers-reduced-motion fallback
=========================== */
/* Disable View Transition animations when reduced motion is active */
[data-reduced-motion="true"]::view-transition-old(*),
[data-reduced-motion="true"]::view-transition-new(*),
[data-reduced-motion="true"]::view-transition-group(*) {
animation-duration: 0s !important;
}
/* Disable background gradient animation */
[data-reduced-motion="true"] .animate-slow-gradient {
animation: none;
background-size: 100% 100%;
}
/* Disable hover glow pulse */
[data-reduced-motion="true"] .hover-glow:hover,
[data-reduced-motion="true"] .hover-glow-primary:hover {
box-shadow: none;
}
/* Disable ambient gradient shift animation */
[data-reduced-motion="true"] body::before {
animation: none !important;
}
/* Reduce gradient opacity for enhanced mode */
[data-reduced-motion="true"][data-gradient="enhanced"] body::before {
opacity: 0.5;
}
/* OS-level prefers-reduced-motion fallback (applies when data attr not set) */
@media (prefers-reduced-motion: reduce) {
::view-transition-old(*),
::view-transition-new(*),
::view-transition-group(*) {
animation-duration: 0s !important;
}
.animate-slow-gradient {
animation: none;
background-size: 100% 100%;
}
.hover-glow:hover,
.hover-glow-primary:hover {
box-shadow: none;
}
body::before {
animation: none !important;
}
[data-gradient="enhanced"] body::before {
opacity: 0.5;
}
}
/* ===========================
Background Image System
Layered rendering with effects
=========================== */
/* Hide gradient layer when image-only mode */
[data-bg-mode="image-only"] body::before {
display: none;
}
/* Reduce gradient opacity when overlaying on image */
[data-bg-mode="image-gradient"] body::before {
opacity: 0.6;
}
/* Background image layer */
.bg-image-layer {
position: fixed;
inset: 0;
z-index: -3;
overflow: hidden;
transition: opacity 0.5s ease;
}
.bg-image-layer img {
width: 100%;
height: 100%;
object-fit: cover;
}
/* Darken overlay */
.bg-darken-overlay {
position: fixed;
inset: 0;
z-index: -2;
pointer-events: none;
}
/* Grain texture overlay */
.bg-grain-overlay {
position: fixed;
inset: 0;
z-index: -2;
pointer-events: none;
opacity: 0;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.7' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
background-repeat: repeat;
background-size: 256px 256px;
}
[data-bg-grain="true"] .bg-grain-overlay {
opacity: 0.08;
}
/* Vignette overlay */
.bg-vignette-overlay {
position: fixed;
inset: 0;
z-index: -2;
pointer-events: none;
opacity: 0;
background: radial-gradient(ellipse at center, transparent 50%, rgba(0, 0, 0, 0.5) 100%);
}
[data-bg-vignette="true"] .bg-vignette-overlay {
opacity: 1;
}
/* Frosted glass effect on content area */
[data-bg-frosted="true"] .app-shell-content {
backdrop-filter: blur(12px) saturate(1.2);
-webkit-backdrop-filter: blur(12px) saturate(1.2);
background-color: hsla(var(--bg), 0.75);
}
/* Disable image layer transitions when reduced motion is active */
[data-reduced-motion="true"] .bg-image-layer {
transition: none !important;
}