mirror of
				https://github.com/Frooodle/Stirling-PDF.git
				synced 2025-11-01 01:21:18 +01:00 
			
		
		
		
	RAINBOW MODE!!!!
This commit is contained in:
		
							parent
							
								
									342345cbb9
								
							
						
					
					
						commit
						41efd80dd5
					
				@ -1 +0,0 @@
 | 
			
		||||
{}
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { MantineProvider } from '@mantine/core';
 | 
			
		||||
import { mantineTheme } from './theme/mantineTheme';
 | 
			
		||||
import { RainbowThemeProvider } from './components/RainbowThemeProvider';
 | 
			
		||||
import HomePage from './pages/HomePage';
 | 
			
		||||
 | 
			
		||||
// Import global styles
 | 
			
		||||
@ -9,8 +8,8 @@ import './index.css';
 | 
			
		||||
 | 
			
		||||
export default function App() {
 | 
			
		||||
  return (
 | 
			
		||||
    <MantineProvider theme={mantineTheme}>
 | 
			
		||||
    <RainbowThemeProvider>
 | 
			
		||||
      <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 { Button, SegmentedControl } from "@mantine/core";
 | 
			
		||||
import { useMantineColorScheme } from "@mantine/core";
 | 
			
		||||
import { useRainbowThemeContext } from "./RainbowThemeProvider";
 | 
			
		||||
import LanguageSelector from "./LanguageSelector";
 | 
			
		||||
import rainbowStyles from '../styles/rainbow.module.css';
 | 
			
		||||
import DarkModeIcon from '@mui/icons-material/DarkMode';
 | 
			
		||||
import LightModeIcon from '@mui/icons-material/LightMode';
 | 
			
		||||
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome';
 | 
			
		||||
import VisibilityIcon from "@mui/icons-material/Visibility";
 | 
			
		||||
import EditNoteIcon from "@mui/icons-material/EditNote";
 | 
			
		||||
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
 | 
			
		||||
@ -45,18 +47,34 @@ const TopControls: React.FC<TopControlsProps> = ({
 | 
			
		||||
  currentView,
 | 
			
		||||
  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 (
 | 
			
		||||
    <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">
 | 
			
		||||
        <Button
 | 
			
		||||
          onClick={toggleColorScheme}
 | 
			
		||||
          onClick={toggleTheme}
 | 
			
		||||
          variant="subtle"
 | 
			
		||||
          size="md"
 | 
			
		||||
          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>
 | 
			
		||||
        <LanguageSelector />
 | 
			
		||||
      </div>
 | 
			
		||||
@ -69,6 +87,7 @@ const TopControls: React.FC<TopControlsProps> = ({
 | 
			
		||||
            radius="xl"
 | 
			
		||||
            size="md"
 | 
			
		||||
            fullWidth
 | 
			
		||||
            className={isRainbowMode ? rainbowStyles.rainbowSegmentedControl : ''}
 | 
			
		||||
          />
 | 
			
		||||
      </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 utilities;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
 | 
			
		||||
@ -11,6 +12,7 @@ body {
 | 
			
		||||
  -moz-osx-font-smoothing: grayscale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
code {
 | 
			
		||||
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
 | 
			
		||||
    monospace;
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,9 @@ import { useToolParams } from "../hooks/useToolParams";
 | 
			
		||||
import AddToPhotosIcon from "@mui/icons-material/AddToPhotos";
 | 
			
		||||
import ContentCutIcon from "@mui/icons-material/ContentCut";
 | 
			
		||||
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 FileManager from "../components/FileManager";
 | 
			
		||||
@ -41,7 +43,7 @@ export default function HomePage() {
 | 
			
		||||
  const { t } = useTranslation();
 | 
			
		||||
  const [searchParams] = useSearchParams();
 | 
			
		||||
  const theme = useMantineTheme();
 | 
			
		||||
  const { colorScheme, toggleColorScheme } = useMantineColorScheme();
 | 
			
		||||
  const { isRainbowMode } = useRainbowThemeContext();
 | 
			
		||||
 | 
			
		||||
  // Core app state
 | 
			
		||||
  const [selectedToolKey, setSelectedToolKey] = useState<string>(searchParams.get("t") || "split");
 | 
			
		||||
@ -81,7 +83,7 @@ export default function HomePage() {
 | 
			
		||||
      {/* Left: Tool Picker */}
 | 
			
		||||
      {sidebarsVisible && (
 | 
			
		||||
        <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' }}
 | 
			
		||||
        >
 | 
			
		||||
          <ToolPicker
 | 
			
		||||
@ -136,7 +138,7 @@ export default function HomePage() {
 | 
			
		||||
      {/* Right: Tool Interaction */}
 | 
			
		||||
      {sidebarsVisible && (
 | 
			
		||||
        <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' }}
 | 
			
		||||
        >
 | 
			
		||||
          <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