mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-08-20 13:47:46 +02:00
RAINBOW MODE!!!!
This commit is contained in:
parent
342345cbb9
commit
41efd80dd5
@ -1 +0,0 @@
|
|||||||
{}
|
|
@ -1,6 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { MantineProvider } from '@mantine/core';
|
import { RainbowThemeProvider } from './components/RainbowThemeProvider';
|
||||||
import { mantineTheme } from './theme/mantineTheme';
|
|
||||||
import HomePage from './pages/HomePage';
|
import HomePage from './pages/HomePage';
|
||||||
|
|
||||||
// Import global styles
|
// Import global styles
|
||||||
@ -9,8 +8,8 @@ import './index.css';
|
|||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return (
|
||||||
<MantineProvider theme={mantineTheme}>
|
<RainbowThemeProvider>
|
||||||
<HomePage />
|
<HomePage />
|
||||||
</MantineProvider>
|
</RainbowThemeProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
55
frontend/src/components/RainbowThemeProvider.tsx
Normal file
55
frontend/src/components/RainbowThemeProvider.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import React, { createContext, useContext, ReactNode } from 'react';
|
||||||
|
import { MantineProvider, ColorSchemeScript } from '@mantine/core';
|
||||||
|
import { useRainbowTheme } from '../hooks/useRainbowTheme';
|
||||||
|
import { mantineTheme } from '../theme/mantineTheme';
|
||||||
|
import rainbowStyles from '../styles/rainbow.module.css';
|
||||||
|
|
||||||
|
interface RainbowThemeContextType {
|
||||||
|
themeMode: 'light' | 'dark' | 'rainbow';
|
||||||
|
isRainbowMode: boolean;
|
||||||
|
isToggleDisabled: boolean;
|
||||||
|
toggleTheme: () => void;
|
||||||
|
activateRainbow: () => void;
|
||||||
|
deactivateRainbow: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RainbowThemeContext = createContext<RainbowThemeContextType | null>(null);
|
||||||
|
|
||||||
|
export function useRainbowThemeContext() {
|
||||||
|
const context = useContext(RainbowThemeContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useRainbowThemeContext must be used within RainbowThemeProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RainbowThemeProviderProps {
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RainbowThemeProvider({ children }: RainbowThemeProviderProps) {
|
||||||
|
const rainbowTheme = useRainbowTheme();
|
||||||
|
|
||||||
|
// Determine the Mantine color scheme
|
||||||
|
const mantineColorScheme = rainbowTheme.themeMode === 'rainbow' ? 'dark' : rainbowTheme.themeMode;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ColorSchemeScript defaultColorScheme={mantineColorScheme} />
|
||||||
|
<RainbowThemeContext.Provider value={rainbowTheme}>
|
||||||
|
<MantineProvider
|
||||||
|
theme={mantineTheme}
|
||||||
|
defaultColorScheme={mantineColorScheme}
|
||||||
|
forceColorScheme={mantineColorScheme}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={rainbowTheme.isRainbowMode ? rainbowStyles.rainbowMode : ''}
|
||||||
|
style={{ minHeight: '100vh' }}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</MantineProvider>
|
||||||
|
</RainbowThemeContext.Provider>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Button, SegmentedControl } from "@mantine/core";
|
import { Button, SegmentedControl } from "@mantine/core";
|
||||||
import { useMantineColorScheme } from "@mantine/core";
|
import { useRainbowThemeContext } from "./RainbowThemeProvider";
|
||||||
import LanguageSelector from "./LanguageSelector";
|
import LanguageSelector from "./LanguageSelector";
|
||||||
|
import rainbowStyles from '../styles/rainbow.module.css';
|
||||||
import DarkModeIcon from '@mui/icons-material/DarkMode';
|
import DarkModeIcon from '@mui/icons-material/DarkMode';
|
||||||
import LightModeIcon from '@mui/icons-material/LightMode';
|
import LightModeIcon from '@mui/icons-material/LightMode';
|
||||||
|
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
|
||||||
import VisibilityIcon from "@mui/icons-material/Visibility";
|
import VisibilityIcon from "@mui/icons-material/Visibility";
|
||||||
import EditNoteIcon from "@mui/icons-material/EditNote";
|
import EditNoteIcon from "@mui/icons-material/EditNote";
|
||||||
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
|
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
|
||||||
@ -45,18 +47,34 @@ const TopControls: React.FC<TopControlsProps> = ({
|
|||||||
currentView,
|
currentView,
|
||||||
setCurrentView,
|
setCurrentView,
|
||||||
}) => {
|
}) => {
|
||||||
const { colorScheme, toggleColorScheme } = useMantineColorScheme();
|
const { themeMode, isRainbowMode, isToggleDisabled, toggleTheme } = useRainbowThemeContext();
|
||||||
|
|
||||||
|
const getThemeIcon = () => {
|
||||||
|
if (isRainbowMode) return <AutoAwesomeIcon className={rainbowStyles.rainbowText} />;
|
||||||
|
if (themeMode === "dark") return <LightModeIcon />;
|
||||||
|
return <DarkModeIcon />;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="absolute left-0 w-full top-0 z-[9999] pointer-events-none">
|
<div className="absolute left-0 w-full top-0 z-[100] pointer-events-none">
|
||||||
<div className="absolute left-4 top-1/2 -translate-y-1/2 pointer-events-auto flex gap-2 items-center">
|
<div className="absolute left-4 top-1/2 -translate-y-1/2 pointer-events-auto flex gap-2 items-center">
|
||||||
<Button
|
<Button
|
||||||
onClick={toggleColorScheme}
|
onClick={toggleTheme}
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
size="md"
|
size="md"
|
||||||
aria-label="Toggle theme"
|
aria-label="Toggle theme"
|
||||||
|
disabled={isToggleDisabled}
|
||||||
|
className={isRainbowMode ? rainbowStyles.rainbowButton : ''}
|
||||||
|
title={
|
||||||
|
isToggleDisabled
|
||||||
|
? "Button disabled for 3 seconds..."
|
||||||
|
: isRainbowMode
|
||||||
|
? "Rainbow Mode Active! Click to exit"
|
||||||
|
: "Toggle theme (click rapidly 6 times for a surprise!)"
|
||||||
|
}
|
||||||
|
style={isToggleDisabled ? { opacity: 0.5, cursor: 'not-allowed' } : {}}
|
||||||
>
|
>
|
||||||
{colorScheme === "dark" ? <LightModeIcon /> : <DarkModeIcon />}
|
{getThemeIcon()}
|
||||||
</Button>
|
</Button>
|
||||||
<LanguageSelector />
|
<LanguageSelector />
|
||||||
</div>
|
</div>
|
||||||
@ -69,6 +87,7 @@ const TopControls: React.FC<TopControlsProps> = ({
|
|||||||
radius="xl"
|
radius="xl"
|
||||||
size="md"
|
size="md"
|
||||||
fullWidth
|
fullWidth
|
||||||
|
className={isRainbowMode ? rainbowStyles.rainbowSegmentedControl : ''}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
200
frontend/src/hooks/useRainbowTheme.ts
Normal file
200
frontend/src/hooks/useRainbowTheme.ts
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import { useState, useCallback, useRef, useEffect } from 'react';
|
||||||
|
|
||||||
|
type ThemeMode = 'light' | 'dark' | 'rainbow';
|
||||||
|
|
||||||
|
interface RainbowThemeHook {
|
||||||
|
themeMode: ThemeMode;
|
||||||
|
isRainbowMode: boolean;
|
||||||
|
isToggleDisabled: boolean;
|
||||||
|
toggleTheme: () => void;
|
||||||
|
activateRainbow: () => void;
|
||||||
|
deactivateRainbow: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useRainbowTheme(initialTheme: 'light' | 'dark' = 'light'): RainbowThemeHook {
|
||||||
|
// Get theme from localStorage or use initial
|
||||||
|
const [themeMode, setThemeMode] = useState<ThemeMode>(() => {
|
||||||
|
const stored = localStorage.getItem('stirling-theme');
|
||||||
|
if (stored && ['light', 'dark', 'rainbow'].includes(stored)) {
|
||||||
|
return stored as ThemeMode;
|
||||||
|
}
|
||||||
|
return initialTheme;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Track rapid toggles for easter egg
|
||||||
|
const toggleCount = useRef(0);
|
||||||
|
const lastToggleTime = useRef(Date.now());
|
||||||
|
const [isToggleDisabled, setIsToggleDisabled] = useState(false);
|
||||||
|
|
||||||
|
// Save theme to localStorage whenever it changes
|
||||||
|
useEffect(() => {
|
||||||
|
localStorage.setItem('stirling-theme', themeMode);
|
||||||
|
|
||||||
|
// Apply rainbow class to body if in rainbow mode
|
||||||
|
if (themeMode === 'rainbow') {
|
||||||
|
document.body.classList.add('rainbow-mode-active');
|
||||||
|
|
||||||
|
// Show easter egg notification
|
||||||
|
showRainbowNotification();
|
||||||
|
} else {
|
||||||
|
document.body.classList.remove('rainbow-mode-active');
|
||||||
|
}
|
||||||
|
}, [themeMode]);
|
||||||
|
|
||||||
|
const showRainbowNotification = () => {
|
||||||
|
// Remove any existing notification
|
||||||
|
const existingNotification = document.getElementById('rainbow-notification');
|
||||||
|
if (existingNotification) {
|
||||||
|
existingNotification.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and show rainbow notification
|
||||||
|
const notification = document.createElement('div');
|
||||||
|
notification.id = 'rainbow-notification';
|
||||||
|
notification.innerHTML = '🌈 RAINBOW MODE ACTIVATED! 🌈<br><small>Button disabled for 3 seconds, then click to exit</small>';
|
||||||
|
notification.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
background: linear-gradient(45deg, #ff0000, #ff8800, #ffff00, #88ff00, #00ff88, #00ffff, #0088ff, #8800ff);
|
||||||
|
background-size: 300% 300%;
|
||||||
|
animation: rainbowBackground 1s ease infinite;
|
||||||
|
color: white;
|
||||||
|
padding: 15px 20px;
|
||||||
|
border-radius: 25px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
z-index: 1000;
|
||||||
|
border: 2px solid white;
|
||||||
|
box-shadow: 0 0 20px rgba(255, 255, 255, 0.8);
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(notification);
|
||||||
|
|
||||||
|
// Auto-remove notification after 3 seconds
|
||||||
|
setTimeout(() => {
|
||||||
|
if (notification) {
|
||||||
|
notification.style.opacity = '0';
|
||||||
|
setTimeout(() => {
|
||||||
|
if (notification.parentNode) {
|
||||||
|
notification.parentNode.removeChild(notification);
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showExitNotification = () => {
|
||||||
|
// Remove any existing notification
|
||||||
|
const existingNotification = document.getElementById('rainbow-exit-notification');
|
||||||
|
if (existingNotification) {
|
||||||
|
existingNotification.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and show exit notification
|
||||||
|
const notification = document.createElement('div');
|
||||||
|
notification.id = 'rainbow-exit-notification';
|
||||||
|
notification.innerHTML = '🌙 Rainbow mode deactivated';
|
||||||
|
notification.style.cssText = `
|
||||||
|
position: fixed;
|
||||||
|
top: 20px;
|
||||||
|
right: 20px;
|
||||||
|
background: linear-gradient(45deg, #333, #666);
|
||||||
|
color: white;
|
||||||
|
padding: 15px 20px;
|
||||||
|
border-radius: 25px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
z-index: 1000;
|
||||||
|
border: 2px solid #999;
|
||||||
|
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.appendChild(notification);
|
||||||
|
|
||||||
|
// Auto-remove notification after 2 seconds
|
||||||
|
setTimeout(() => {
|
||||||
|
if (notification) {
|
||||||
|
notification.style.opacity = '0';
|
||||||
|
setTimeout(() => {
|
||||||
|
if (notification.parentNode) {
|
||||||
|
notification.parentNode.removeChild(notification);
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleTheme = useCallback(() => {
|
||||||
|
// Don't allow toggle if disabled
|
||||||
|
if (isToggleDisabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentTime = Date.now();
|
||||||
|
|
||||||
|
// Simple exit from rainbow mode with single click (after cooldown period)
|
||||||
|
if (themeMode === 'rainbow') {
|
||||||
|
setThemeMode('light');
|
||||||
|
console.log('🌈 Rainbow mode deactivated. Thanks for trying it!');
|
||||||
|
showExitNotification();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset counter if too much time has passed (2.5 seconds)
|
||||||
|
if (currentTime - lastToggleTime.current > 2500) {
|
||||||
|
toggleCount.current = 1;
|
||||||
|
} else {
|
||||||
|
toggleCount.current++;
|
||||||
|
}
|
||||||
|
lastToggleTime.current = currentTime;
|
||||||
|
|
||||||
|
// Easter egg: Activate rainbow mode after 6 rapid toggles
|
||||||
|
if (toggleCount.current >= 6) {
|
||||||
|
setThemeMode('rainbow');
|
||||||
|
console.log('🌈 RAINBOW MODE ACTIVATED! 🌈 You found the secret easter egg!');
|
||||||
|
console.log('🌈 Button will be disabled for 3 seconds, then click once to exit!');
|
||||||
|
|
||||||
|
// Disable toggle for 3 seconds
|
||||||
|
setIsToggleDisabled(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
setIsToggleDisabled(false);
|
||||||
|
console.log('🌈 Theme toggle re-enabled! Click once to exit rainbow mode.');
|
||||||
|
}, 3000);
|
||||||
|
|
||||||
|
// Reset counter
|
||||||
|
toggleCount.current = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal theme switching
|
||||||
|
setThemeMode(prevMode => prevMode === 'light' ? 'dark' : 'light');
|
||||||
|
}, [themeMode, isToggleDisabled]);
|
||||||
|
|
||||||
|
const activateRainbow = useCallback(() => {
|
||||||
|
setThemeMode('rainbow');
|
||||||
|
console.log('🌈 Rainbow mode manually activated!');
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const deactivateRainbow = useCallback(() => {
|
||||||
|
if (themeMode === 'rainbow') {
|
||||||
|
setThemeMode('light');
|
||||||
|
console.log('🌈 Rainbow mode manually deactivated.');
|
||||||
|
}
|
||||||
|
}, [themeMode]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
themeMode,
|
||||||
|
isRainbowMode: themeMode === 'rainbow',
|
||||||
|
isToggleDisabled,
|
||||||
|
toggleTheme,
|
||||||
|
activateRainbow,
|
||||||
|
deactivateRainbow,
|
||||||
|
};
|
||||||
|
}
|
@ -2,6 +2,7 @@
|
|||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
@ -11,6 +12,7 @@ body {
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
monospace;
|
monospace;
|
||||||
|
@ -5,7 +5,9 @@ import { useToolParams } from "../hooks/useToolParams";
|
|||||||
import AddToPhotosIcon from "@mui/icons-material/AddToPhotos";
|
import AddToPhotosIcon from "@mui/icons-material/AddToPhotos";
|
||||||
import ContentCutIcon from "@mui/icons-material/ContentCut";
|
import ContentCutIcon from "@mui/icons-material/ContentCut";
|
||||||
import ZoomInMapIcon from "@mui/icons-material/ZoomInMap";
|
import ZoomInMapIcon from "@mui/icons-material/ZoomInMap";
|
||||||
import { Group, Paper, Box, Button, useMantineTheme, useMantineColorScheme } from "@mantine/core";
|
import { Group, Paper, Box, Button, useMantineTheme } from "@mantine/core";
|
||||||
|
import { useRainbowThemeContext } from "../components/RainbowThemeProvider";
|
||||||
|
import rainbowStyles from '../styles/rainbow.module.css';
|
||||||
|
|
||||||
import ToolPicker from "../components/ToolPicker";
|
import ToolPicker from "../components/ToolPicker";
|
||||||
import FileManager from "../components/FileManager";
|
import FileManager from "../components/FileManager";
|
||||||
@ -41,7 +43,7 @@ export default function HomePage() {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const theme = useMantineTheme();
|
const theme = useMantineTheme();
|
||||||
const { colorScheme, toggleColorScheme } = useMantineColorScheme();
|
const { isRainbowMode } = useRainbowThemeContext();
|
||||||
|
|
||||||
// Core app state
|
// Core app state
|
||||||
const [selectedToolKey, setSelectedToolKey] = useState<string>(searchParams.get("t") || "split");
|
const [selectedToolKey, setSelectedToolKey] = useState<string>(searchParams.get("t") || "split");
|
||||||
@ -81,7 +83,7 @@ export default function HomePage() {
|
|||||||
{/* Left: Tool Picker */}
|
{/* Left: Tool Picker */}
|
||||||
{sidebarsVisible && (
|
{sidebarsVisible && (
|
||||||
<div
|
<div
|
||||||
className="h-screen z-sticky flex flex-col bg-surface border-r border-border min-w-[180px] max-w-[240px] w-[16vw]"
|
className={`h-screen z-sticky flex flex-col bg-surface border-r border-border min-w-[180px] max-w-[240px] w-[16vw] ${isRainbowMode ? rainbowStyles.rainbowPaper : ''}`}
|
||||||
style={{ padding: '1rem' }}
|
style={{ padding: '1rem' }}
|
||||||
>
|
>
|
||||||
<ToolPicker
|
<ToolPicker
|
||||||
@ -136,7 +138,7 @@ export default function HomePage() {
|
|||||||
{/* Right: Tool Interaction */}
|
{/* Right: Tool Interaction */}
|
||||||
{sidebarsVisible && (
|
{sidebarsVisible && (
|
||||||
<div
|
<div
|
||||||
className="h-screen bg-surface border-l border-border gap-6 z-sticky flex flex-col min-w-[260px] max-w-[400px] w-[22vw]"
|
className={`h-screen bg-surface border-l border-border gap-6 z-sticky flex flex-col min-w-[260px] max-w-[400px] w-[22vw] ${isRainbowMode ? rainbowStyles.rainbowPaper : ''}`}
|
||||||
style={{ padding: '1.5rem' }}
|
style={{ padding: '1.5rem' }}
|
||||||
>
|
>
|
||||||
<ToolRenderer
|
<ToolRenderer
|
||||||
|
202
frontend/src/styles/rainbow.module.css
Normal file
202
frontend/src/styles/rainbow.module.css
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/* Rainbow Mode Styles - Easter Egg! */
|
||||||
|
@keyframes rainbowBackground {
|
||||||
|
0% { background-position: 0% 50%; }
|
||||||
|
50% { background-position: 100% 50%; }
|
||||||
|
100% { background-position: 0% 50%; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rainbowBorder {
|
||||||
|
0% { border-color: #ff0000; box-shadow: 0 0 15px #ff0000; }
|
||||||
|
14% { border-color: #ff8800; box-shadow: 0 0 15px #ff8800; }
|
||||||
|
28% { border-color: #ffff00; box-shadow: 0 0 15px #ffff00; }
|
||||||
|
42% { border-color: #88ff00; box-shadow: 0 0 15px #88ff00; }
|
||||||
|
57% { border-color: #00ff88; box-shadow: 0 0 15px #00ff88; }
|
||||||
|
71% { border-color: #0088ff; box-shadow: 0 0 15px #0088ff; }
|
||||||
|
85% { border-color: #8800ff; box-shadow: 0 0 15px #8800ff; }
|
||||||
|
100% { border-color: #ff0000; box-shadow: 0 0 15px #ff0000; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rainbowText {
|
||||||
|
0% { color: #ff0000; text-shadow: 0 0 10px #ff0000; }
|
||||||
|
14% { color: #ff8800; text-shadow: 0 0 10px #ff8800; }
|
||||||
|
28% { color: #ffff00; text-shadow: 0 0 10px #ffff00; }
|
||||||
|
42% { color: #88ff00; text-shadow: 0 0 10px #88ff00; }
|
||||||
|
57% { color: #00ff88; text-shadow: 0 0 10px #00ff88; }
|
||||||
|
71% { color: #0088ff; text-shadow: 0 0 10px #0088ff; }
|
||||||
|
85% { color: #8800ff; text-shadow: 0 0 10px #8800ff; }
|
||||||
|
100% { color: #ff0000; text-shadow: 0 0 10px #ff0000; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rainbowPulse {
|
||||||
|
0%, 100% { transform: scale(1); }
|
||||||
|
50% { transform: scale(1.05); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main rainbow theme class */
|
||||||
|
.rainbowMode {
|
||||||
|
background: linear-gradient(
|
||||||
|
-45deg,
|
||||||
|
#ff0000, #ff8800, #ffff00, #88ff00, #00ff88, #00ffff, #0088ff, #8800ff, #ff0088, #ff0000
|
||||||
|
) !important;
|
||||||
|
background-size: 400% 400% !important;
|
||||||
|
animation: rainbowBackground 3s ease infinite !important;
|
||||||
|
color: white !important;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rainbow components */
|
||||||
|
.rainbowCard {
|
||||||
|
background: linear-gradient(
|
||||||
|
45deg,
|
||||||
|
#ff0000, #ff8800, #ffff00, #88ff00, #00ff88, #00ffff, #0088ff, #8800ff, #ff0088
|
||||||
|
) !important;
|
||||||
|
background-size: 400% 400% !important;
|
||||||
|
animation: rainbowBackground 4s ease infinite, rainbowBorder 2s linear infinite !important;
|
||||||
|
color: white !important;
|
||||||
|
border: 2px solid !important;
|
||||||
|
border-radius: 15px !important;
|
||||||
|
box-shadow: 0 0 20px rgba(255, 255, 255, 0.3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rainbowButton {
|
||||||
|
background: linear-gradient(
|
||||||
|
45deg,
|
||||||
|
#ff0000, #ff8800, #ffff00, #88ff00, #00ff88, #00ffff, #0088ff, #8800ff, #ff0088
|
||||||
|
) !important;
|
||||||
|
background-size: 300% 300% !important;
|
||||||
|
animation: rainbowBackground 2s ease infinite, rainbowBorder 1s linear infinite !important;
|
||||||
|
border: 2px solid !important;
|
||||||
|
color: white !important;
|
||||||
|
border-radius: 8px !important;
|
||||||
|
transition: all 0.3s ease !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rainbowButton:hover {
|
||||||
|
transform: scale(1.05) !important;
|
||||||
|
animation: rainbowBackground 1s ease infinite, rainbowBorder 0.5s linear infinite, rainbowPulse 0.5s ease infinite !important;
|
||||||
|
box-shadow: 0 0 25px rgba(255, 255, 255, 0.6) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rainbowInput {
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
#ff0000, #ff8800, #ffff00, #88ff00, #00ff88, #00ffff, #0088ff, #8800ff, #ff0088
|
||||||
|
) !important;
|
||||||
|
background-size: 300% 300% !important;
|
||||||
|
animation: rainbowBackground 2.5s ease infinite, rainbowBorder 1.5s linear infinite !important;
|
||||||
|
border: 2px solid !important;
|
||||||
|
color: white !important;
|
||||||
|
border-radius: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rainbowInput::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.8) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rainbowText {
|
||||||
|
animation: rainbowText 3s linear infinite !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
text-shadow: 0 0 10px currentColor !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rainbowSegmentedControl {
|
||||||
|
background: linear-gradient(
|
||||||
|
45deg,
|
||||||
|
#ff0000, #ff8800, #ffff00, #88ff00, #00ff88, #00ffff, #0088ff, #8800ff, #ff0088
|
||||||
|
) !important;
|
||||||
|
background-size: 400% 400% !important;
|
||||||
|
animation: rainbowBackground 3s ease infinite, rainbowBorder 2s linear infinite !important;
|
||||||
|
border: 2px solid !important;
|
||||||
|
border-radius: 12px !important;
|
||||||
|
padding: 4px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rainbowPaper {
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
#00ffff, #0088ff, #8800ff, #ff0088
|
||||||
|
) !important;
|
||||||
|
background-size: 100% 100% !important;
|
||||||
|
animation: rainbowBackground 3.5s ease infinite, rainbowBorder 2s linear infinite !important;
|
||||||
|
border: 2px solid !important;
|
||||||
|
color: white !important;
|
||||||
|
border-radius: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Easter egg notification */
|
||||||
|
.rainbowNotification {
|
||||||
|
position: fixed !important;
|
||||||
|
top: 20px !important;
|
||||||
|
right: 20px !important;
|
||||||
|
background: linear-gradient(45deg,#ffff00, #88ff00, #00ff88, #00ffff) !important;
|
||||||
|
background-size: 300% 300% !important;
|
||||||
|
animation: rainbowBackground 1s ease infinite, rainbowBorder 0.5s linear infinite !important;
|
||||||
|
color: white !important;
|
||||||
|
padding: 15px 20px !important;
|
||||||
|
border-radius: 25px !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
font-size: 16px !important;
|
||||||
|
z-index: 10000 !important;
|
||||||
|
border: 2px solid white !important;
|
||||||
|
box-shadow: 0 0 20px rgba(255, 255, 255, 0.8) !important;
|
||||||
|
user-select: none !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Specific component overrides */
|
||||||
|
.rainbowMode [data-mantine-color-scheme] {
|
||||||
|
background: linear-gradient(
|
||||||
|
-45deg,
|
||||||
|
#ff0000, #ff8800, #ffff00, #88ff00, #00ff88, #00ffff, #0088ff, #8800ff, #ff0088, #ff0000
|
||||||
|
) !important;
|
||||||
|
background-size: 400% 400% !important;
|
||||||
|
animation: rainbowBackground 3s ease infinite !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make all buttons rainbow in rainbow mode */
|
||||||
|
.rainbowMode button {
|
||||||
|
background: linear-gradient(
|
||||||
|
45deg,
|
||||||
|
#ffff00, #88ff00, #00ff88, #00ffff
|
||||||
|
) !important;
|
||||||
|
background-size: 100% 100% !important;
|
||||||
|
animation: rainbowBackground 2s ease infinite !important;
|
||||||
|
border: 2px solid !important;
|
||||||
|
animation: rainbowBackground 2s ease infinite, rainbowBorder 1.5s linear infinite !important;
|
||||||
|
color: white !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make all inputs rainbow in rainbow mode */
|
||||||
|
.rainbowMode input,
|
||||||
|
.rainbowMode select,
|
||||||
|
.rainbowMode textarea {
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
#ffff00, #88ff00, #00ff88, #00ffff
|
||||||
|
) !important;
|
||||||
|
background-size: 100% 100% !important;
|
||||||
|
animation: rainbowBackground 2.5s ease infinite !important;
|
||||||
|
border: 2px solid !important;
|
||||||
|
animation: rainbowBackground 2.5s ease infinite, rainbowBorder 1.5s linear infinite !important;
|
||||||
|
color: white !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rainbow text class */
|
||||||
|
.rainbowText {
|
||||||
|
animation: rainbowText 3s linear infinite !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
text-shadow: 0 0 10px currentColor !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make all text rainbow */
|
||||||
|
.rainbowMode h1,
|
||||||
|
.rainbowMode h2,
|
||||||
|
.rainbowMode h3,
|
||||||
|
.rainbowMode h4,
|
||||||
|
.rainbowMode h5,
|
||||||
|
.rainbowMode h6 {
|
||||||
|
animation: rainbowText 3s linear infinite !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user