From 9dcdcff712bf97b6b75a77f81df50d4a8ffaf2d8 Mon Sep 17 00:00:00 2001 From: Michael Reber Date: Mon, 1 Dec 2025 23:42:11 +0100 Subject: [PATCH] Fix lotr loading implementation --- pkg/web/static/lotr-theme.css | 439 ------------------- pkg/web/static/lotr.css | 764 ++++++++++++++++++++++++++++++++++ pkg/web/templates/index.html | 45 +- 3 files changed, 804 insertions(+), 444 deletions(-) delete mode 100644 pkg/web/static/lotr-theme.css create mode 100644 pkg/web/static/lotr.css diff --git a/pkg/web/static/lotr-theme.css b/pkg/web/static/lotr-theme.css deleted file mode 100644 index 9601893..0000000 --- a/pkg/web/static/lotr-theme.css +++ /dev/null @@ -1,439 +0,0 @@ -/* ============================================ - LOTR Easter Egg Theme - Middle-earth Styling - ============================================ */ - -/* Only apply when body has lotr-mode class */ -body.lotr-mode { - /* Color Variables */ - --lotr-forest-green: #1a4d2e; - --lotr-dark-green: #0d2818; - --lotr-gold: #d4af37; - --lotr-dark-gold: #b8941f; - --lotr-brown: #3d2817; - --lotr-stone-gray: #8b7355; - --lotr-parchment: #f4e8d0; - --lotr-dark-parchment: #e8d5b7; - --lotr-purple: #4a148c; - --lotr-dark-purple: #2d0a4f; - --lotr-fire-orange: #ff6b35; - --lotr-fire-red: #c1121f; -} - -/* Base Theme Overrides */ -body.lotr-mode { - background: linear-gradient(135deg, var(--lotr-dark-green) 0%, var(--lotr-forest-green) 50%, var(--lotr-brown) 100%); - background-attachment: fixed; - color: var(--lotr-parchment); - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; -} - -/* Typography */ -body.lotr-mode h1, -body.lotr-mode h2, -body.lotr-mode h3, -body.lotr-mode .text-2xl, -body.lotr-mode .text-xl { - font-family: 'Cinzel', serif; - color: var(--lotr-gold); - text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); - letter-spacing: 0.05em; -} - -body.lotr-mode h1 { - font-weight: 700; -} - -body.lotr-mode h2, -body.lotr-mode h3 { - font-weight: 600; -} - -/* Cards - Parchment Style */ -body.lotr-mode .bg-white { - background: var(--lotr-parchment) !important; - border: 3px solid var(--lotr-gold); - border-radius: 8px; - box-shadow: - 0 4px 6px rgba(0, 0, 0, 0.3), - inset 0 1px 0 rgba(255, 255, 255, 0.2), - inset 0 -1px 0 rgba(0, 0, 0, 0.1); - position: relative; -} - -body.lotr-mode .bg-white::before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - background: - repeating-linear-gradient( - 0deg, - transparent, - transparent 2px, - rgba(139, 115, 85, 0.03) 2px, - rgba(139, 115, 85, 0.03) 4px - ); - pointer-events: none; - border-radius: 8px; -} - -body.lotr-mode .bg-white .text-gray-800, -body.lotr-mode .bg-white .text-gray-900 { - color: var(--lotr-brown) !important; -} - -body.lotr-mode .bg-white .text-gray-700 { - color: var(--lotr-brown) !important; -} - -/* Buttons - Medieval Shield Style */ -body.lotr-mode button, -body.lotr-mode .bg-blue-500, -body.lotr-mode .bg-blue-600 { - background: linear-gradient(135deg, var(--lotr-gold) 0%, var(--lotr-dark-gold) 100%) !important; - border: 2px solid var(--lotr-brown) !important; - color: var(--lotr-brown) !important; - font-weight: 600; - text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.3); - box-shadow: - 0 2px 4px rgba(0, 0, 0, 0.3), - inset 0 1px 0 rgba(255, 255, 255, 0.2); - transition: all 0.2s ease; -} - -body.lotr-mode button:hover, -body.lotr-mode .bg-blue-500:hover, -body.lotr-mode .bg-blue-600:hover { - background: linear-gradient(135deg, var(--lotr-dark-gold) 0%, var(--lotr-gold) 100%) !important; - box-shadow: - 0 4px 8px rgba(0, 0, 0, 0.4), - inset 0 1px 0 rgba(255, 255, 255, 0.3); - transform: translateY(-1px); -} - -body.lotr-mode button:active { - transform: translateY(0); -} - -/* Input Fields - Scroll Style */ -body.lotr-mode input, -body.lotr-mode select, -body.lotr-mode textarea { - background: var(--lotr-dark-parchment) !important; - border: 2px solid var(--lotr-stone-gray) !important; - color: var(--lotr-brown) !important; - border-radius: 4px; -} - -body.lotr-mode input:focus, -body.lotr-mode select:focus, -body.lotr-mode textarea:focus { - border-color: var(--lotr-gold) !important; - box-shadow: 0 0 0 3px rgba(212, 175, 55, 0.2) !important; - outline: none; -} - -/* Navigation */ -body.lotr-mode nav { - background: linear-gradient(135deg, var(--lotr-brown) 0%, var(--lotr-dark-green) 100%) !important; - border-bottom: 3px solid var(--lotr-gold); - box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4); -} - -body.lotr-mode nav .text-gray-700, -body.lotr-mode nav .text-gray-800 { - color: var(--lotr-gold) !important; -} - -/* Loading Spinner - One Ring Animation */ -body.lotr-mode #loading-overlay .animate-spin { - border-color: var(--lotr-gold); - border-top-color: transparent; - width: 60px; - height: 60px; - position: relative; -} - -body.lotr-mode #loading-overlay .animate-spin::before { - content: ''; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - width: 40px; - height: 40px; - border: 3px solid var(--lotr-gold); - border-radius: 50%; - box-shadow: - 0 0 20px var(--lotr-gold), - inset 0 0 20px var(--lotr-gold); - animation: ringGlow 2s ease-in-out infinite; -} - -@keyframes ringGlow { - 0%, 100% { - opacity: 0.6; - box-shadow: - 0 0 20px var(--lotr-gold), - inset 0 0 20px var(--lotr-gold); - } - 50% { - opacity: 1; - box-shadow: - 0 0 40px var(--lotr-gold), - 0 0 60px var(--lotr-gold), - inset 0 0 30px var(--lotr-gold); - } -} - -/* Toast Notifications - Scroll Style */ -body.lotr-mode .toast { - background: var(--lotr-parchment) !important; - border: 2px solid var(--lotr-gold); - color: var(--lotr-brown) !important; - box-shadow: - 0 4px 12px rgba(0, 0, 0, 0.4), - inset 0 0 20px rgba(212, 175, 55, 0.1); - position: relative; - padding-left: 50px; -} - -body.lotr-mode .toast::before { - content: '⚔'; - position: absolute; - left: 15px; - font-size: 20px; -} - -body.lotr-mode .toast-success { - border-color: var(--lotr-forest-green); -} - -body.lotr-mode .toast-error { - border-color: var(--lotr-fire-red); -} - -body.lotr-mode .toast-info { - border-color: var(--lotr-gold); -} - -/* Dashboard Cards - Medieval Banners */ -body.lotr-mode .bg-blue-50, -body.lotr-mode .bg-gray-50 { - background: var(--lotr-dark-parchment) !important; -} - -body.lotr-mode .text-blue-600 { - color: var(--lotr-gold) !important; -} - -/* Tables */ -body.lotr-mode table { - border-collapse: separate; - border-spacing: 0; -} - -body.lotr-mode table th { - background: linear-gradient(135deg, var(--lotr-brown) 0%, var(--lotr-stone-gray) 100%); - color: var(--lotr-gold); - border: 2px solid var(--lotr-gold); - font-family: 'Cinzel', serif; - font-weight: 600; -} - -body.lotr-mode table td { - background: var(--lotr-parchment); - border: 1px solid var(--lotr-stone-gray); - color: var(--lotr-brown); -} - -body.lotr-mode table tr:hover td { - background: var(--lotr-dark-parchment); -} - -/* Modal - Parchment Scroll */ -body.lotr-mode .modal-content { - background: var(--lotr-parchment) !important; - border: 4px solid var(--lotr-gold); - border-radius: 12px; - box-shadow: - 0 8px 32px rgba(0, 0, 0, 0.5), - inset 0 0 40px rgba(212, 175, 55, 0.1); -} - -body.lotr-mode .modal-content h2, -body.lotr-mode .modal-content h3 { - border-bottom: 2px solid var(--lotr-gold); - padding-bottom: 10px; - margin-bottom: 20px; -} - -/* Badges and Labels */ -body.lotr-mode .bg-green-100, -body.lotr-mode .bg-green-500 { - background: var(--lotr-forest-green) !important; - color: var(--lotr-gold) !important; -} - -body.lotr-mode .bg-red-100, -body.lotr-mode .bg-red-500 { - background: var(--lotr-fire-red) !important; - color: var(--lotr-parchment) !important; -} - -body.lotr-mode .bg-yellow-400 { - background: var(--lotr-gold) !important; - color: var(--lotr-brown) !important; -} - -/* Restart Banner */ -body.lotr-mode #restartBanner { - background: linear-gradient(135deg, var(--lotr-gold) 0%, var(--lotr-dark-gold) 100%) !important; - border-top: 3px solid var(--lotr-brown); - border-bottom: 3px solid var(--lotr-brown); - color: var(--lotr-brown) !important; - font-weight: 600; -} - -/* Select2 Styling */ -body.lotr-mode .select2-container--default .select2-selection { - background: var(--lotr-dark-parchment) !important; - border: 2px solid var(--lotr-stone-gray) !important; - color: var(--lotr-brown) !important; -} - -body.lotr-mode .select2-container--default .select2-selection--multiple .select2-selection__choice { - background: var(--lotr-gold) !important; - border: 1px solid var(--lotr-brown) !important; - color: var(--lotr-brown) !important; -} - -/* Scrollbar Styling */ -body.lotr-mode ::-webkit-scrollbar { - width: 12px; - height: 12px; -} - -body.lotr-mode ::-webkit-scrollbar-track { - background: var(--lotr-dark-green); - border: 1px solid var(--lotr-stone-gray); -} - -body.lotr-mode ::-webkit-scrollbar-thumb { - background: linear-gradient(135deg, var(--lotr-gold) 0%, var(--lotr-dark-gold) 100%); - border: 2px solid var(--lotr-brown); - border-radius: 6px; -} - -body.lotr-mode ::-webkit-scrollbar-thumb:hover { - background: linear-gradient(135deg, var(--lotr-dark-gold) 0%, var(--lotr-gold) 100%); -} - -/* Decorative Elements */ -body.lotr-mode .lotr-divider { - height: 2px; - background: linear-gradient(90deg, - transparent 0%, - var(--lotr-gold) 20%, - var(--lotr-gold) 80%, - transparent 100%); - margin: 20px 0; - position: relative; -} - -body.lotr-mode .lotr-divider::before, -body.lotr-mode .lotr-divider::after { - content: '⚔'; - position: absolute; - top: 50%; - transform: translateY(-50%); - color: var(--lotr-gold); - font-size: 20px; - background: var(--lotr-parchment); - padding: 0 10px; -} - -body.lotr-mode .lotr-divider::before { - left: 20%; -} - -body.lotr-mode .lotr-divider::after { - right: 20%; -} - -/* Glow Effects */ -body.lotr-mode .lotr-glow { - text-shadow: - 0 0 10px var(--lotr-gold), - 0 0 20px var(--lotr-gold), - 0 0 30px var(--lotr-gold); - animation: gentleGlow 3s ease-in-out infinite; -} - -@keyframes gentleGlow { - 0%, 100% { - text-shadow: - 0 0 10px var(--lotr-gold), - 0 0 20px var(--lotr-gold), - 0 0 30px var(--lotr-gold); - } - 50% { - text-shadow: - 0 0 15px var(--lotr-gold), - 0 0 30px var(--lotr-gold), - 0 0 45px var(--lotr-gold); - } -} - -/* Fire Effect (for email headers) */ -body.lotr-mode .lotr-fire { - background: linear-gradient(180deg, - var(--lotr-fire-red) 0%, - var(--lotr-fire-orange) 50%, - var(--lotr-gold) 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - font-weight: 700; - text-shadow: 0 0 20px var(--lotr-fire-orange); - animation: fireFlicker 2s ease-in-out infinite; -} - -@keyframes fireFlicker { - 0%, 100% { - filter: brightness(1); - } - 25% { - filter: brightness(1.2); - } - 50% { - filter: brightness(0.9); - } - 75% { - filter: brightness(1.1); - } -} - -/* Smooth Theme Transition */ -body.lotr-mode, -body.lotr-mode * { - transition: background-color 0.5s ease, - color 0.5s ease, - border-color 0.5s ease; -} - -/* Mobile Responsive */ -@media (max-width: 768px) { - body.lotr-mode .bg-white { - border-width: 2px; - } - - body.lotr-mode h1, - body.lotr-mode h2, - body.lotr-mode h3 { - font-size: 1.5em; - } -} - diff --git a/pkg/web/static/lotr.css b/pkg/web/static/lotr.css new file mode 100644 index 0000000..15998e2 --- /dev/null +++ b/pkg/web/static/lotr.css @@ -0,0 +1,764 @@ +/* ============================================ + LOTR Easter Egg Theme - Middle-earth Styling + ============================================ */ + +/* Only apply when body has lotr-mode class */ +body.lotr-mode { + /* Enhanced Color Variables - Better Contrast */ + --lotr-forest-green: #1a4d2e; + --lotr-dark-green: #0d2818; + --lotr-deep-green: #051a0f; + --lotr-gold: #d4af37; + --lotr-bright-gold: #f4d03f; + --lotr-dark-gold: #b8941f; + --lotr-brown: #3d2817; + --lotr-dark-brown: #2a1a0f; + --lotr-stone-gray: #8b7355; + --lotr-light-stone: #a68b6b; + --lotr-parchment: #faf8f3; + --lotr-warm-parchment: #f5f0e8; + --lotr-dark-parchment: #e8d5b7; + --lotr-purple: #4a148c; + --lotr-dark-purple: #2d0a4f; + --lotr-fire-orange: #ff6b35; + --lotr-fire-red: #c1121f; + --lotr-text-dark: #2c1810; + --lotr-text-light: #faf8f3; +} + +/* Base Theme Overrides - Beautiful Background */ +body.lotr-mode { + background: + radial-gradient(ellipse at top, rgba(26, 77, 46, 0.3) 0%, transparent 50%), + radial-gradient(ellipse at bottom, rgba(45, 10, 79, 0.2) 0%, transparent 50%), + linear-gradient(135deg, #0d2818 0%, #1a4d2e 30%, #2d0a4f 70%, #0d2818 100%); + background-attachment: fixed; + background-size: 100% 100%; + color: var(--lotr-text-light); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + min-height: 100vh; +} + +/* Enhanced Typography with Better Contrast */ +body.lotr-mode h1, +body.lotr-mode h2, +body.lotr-mode h3, +body.lotr-mode .text-2xl, +body.lotr-mode .text-xl { + font-family: 'Cinzel', serif; + color: var(--lotr-bright-gold); + text-shadow: + 2px 2px 4px rgba(0, 0, 0, 0.8), + 0 0 10px rgba(212, 175, 55, 0.3); + letter-spacing: 0.05em; + font-weight: 700; +} + +body.lotr-mode h1 { + font-size: 2.5rem; + text-shadow: + 3px 3px 6px rgba(0, 0, 0, 0.9), + 0 0 15px rgba(212, 175, 55, 0.4); +} + +body.lotr-mode h2, +body.lotr-mode h3 { + font-weight: 600; +} + +/* Enhanced Cards - Beautiful Parchment Style */ +body.lotr-mode .bg-white { + background: linear-gradient(135deg, var(--lotr-parchment) 0%, var(--lotr-warm-parchment) 100%) !important; + border: 4px solid var(--lotr-gold); + border-radius: 12px; + box-shadow: + 0 8px 16px rgba(0, 0, 0, 0.4), + 0 2px 4px rgba(0, 0, 0, 0.3), + inset 0 1px 0 rgba(255, 255, 255, 0.3), + inset 0 -1px 0 rgba(0, 0, 0, 0.1); + position: relative; + overflow: hidden; +} + +body.lotr-mode .bg-white::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: + repeating-linear-gradient( + 0deg, + transparent, + transparent 3px, + rgba(139, 115, 85, 0.05) 3px, + rgba(139, 115, 85, 0.05) 6px + ), + radial-gradient(circle at 20% 30%, rgba(212, 175, 55, 0.05) 0%, transparent 50%), + radial-gradient(circle at 80% 70%, rgba(139, 115, 85, 0.03) 0%, transparent 50%); + pointer-events: none; + border-radius: 12px; +} + +body.lotr-mode .bg-white::after { + content: ''; + position: absolute; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + background: linear-gradient(45deg, + var(--lotr-gold) 0%, + transparent 25%, + transparent 75%, + var(--lotr-gold) 100%); + border-radius: 12px; + z-index: -1; + opacity: 0.3; +} + +/* Text Colors with High Contrast */ +body.lotr-mode .bg-white .text-gray-800, +body.lotr-mode .bg-white .text-gray-900 { + color: var(--lotr-text-dark) !important; + font-weight: 500; +} + +body.lotr-mode .bg-white .text-gray-700 { + color: var(--lotr-dark-brown) !important; +} + +body.lotr-mode .bg-white .text-gray-500, +body.lotr-mode .bg-white .text-gray-600 { + color: var(--lotr-brown) !important; +} + +/* Beautiful Buttons - Medieval Shield Style */ +body.lotr-mode button:not(.toast), +body.lotr-mode .bg-blue-500:not(.toast), +body.lotr-mode .bg-blue-600:not(.toast) { + background: linear-gradient(135deg, var(--lotr-bright-gold) 0%, var(--lotr-gold) 50%, var(--lotr-dark-gold) 100%) !important; + border: 3px solid var(--lotr-brown) !important; + border-radius: 8px; + color: var(--lotr-text-dark) !important; + font-weight: 700; + text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5); + box-shadow: + 0 4px 8px rgba(0, 0, 0, 0.4), + inset 0 2px 4px rgba(255, 255, 255, 0.3), + inset 0 -2px 4px rgba(0, 0, 0, 0.2); + transition: all 0.3s ease; + position: relative; + overflow: hidden; +} + +body.lotr-mode button::before, +body.lotr-mode .bg-blue-500::before, +body.lotr-mode .bg-blue-600::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, + transparent, + rgba(255, 255, 255, 0.3), + transparent); + transition: left 0.5s ease; +} + +body.lotr-mode button:hover::before, +body.lotr-mode .bg-blue-500:hover::before, +body.lotr-mode .bg-blue-600:hover::before { + left: 100%; +} + +body.lotr-mode button:hover, +body.lotr-mode .bg-blue-500:hover, +body.lotr-mode .bg-blue-600:hover { + background: linear-gradient(135deg, var(--lotr-gold) 0%, var(--lotr-bright-gold) 50%, var(--lotr-gold) 100%) !important; + box-shadow: + 0 6px 12px rgba(0, 0, 0, 0.5), + inset 0 2px 6px rgba(255, 255, 255, 0.4), + inset 0 -2px 6px rgba(0, 0, 0, 0.3); + transform: translateY(-2px); + border-color: var(--lotr-bright-gold); +} + +body.lotr-mode button:active { + transform: translateY(0); + box-shadow: + 0 2px 4px rgba(0, 0, 0, 0.4), + inset 0 2px 4px rgba(0, 0, 0, 0.2); +} + +/* Enhanced Input Fields - Scroll Style */ +body.lotr-mode input:not([type="checkbox"]):not([type="radio"]), +body.lotr-mode select, +body.lotr-mode textarea { + background: var(--lotr-warm-parchment) !important; + border: 3px solid var(--lotr-stone-gray) !important; + color: var(--lotr-text-dark) !important; + border-radius: 6px; + font-weight: 500; + box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1); +} + +body.lotr-mode input::placeholder, +body.lotr-mode textarea::placeholder { + color: var(--lotr-stone-gray) !important; + opacity: 0.7; +} + +body.lotr-mode input:focus, +body.lotr-mode select:focus, +body.lotr-mode textarea:focus { + background: var(--lotr-parchment) !important; + border-color: var(--lotr-bright-gold) !important; + box-shadow: + 0 0 0 4px rgba(212, 175, 55, 0.3), + inset 0 2px 4px rgba(0, 0, 0, 0.1) !important; + outline: none; +} + +/* Beautiful Navigation */ +body.lotr-mode nav { + background: linear-gradient(135deg, + var(--lotr-dark-brown) 0%, + var(--lotr-brown) 30%, + var(--lotr-dark-green) 70%, + var(--lotr-deep-green) 100%) !important; + border-bottom: 4px solid var(--lotr-gold); + box-shadow: + 0 4px 12px rgba(0, 0, 0, 0.5), + inset 0 1px 0 rgba(212, 175, 55, 0.2); + position: relative; +} + +body.lotr-mode nav::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, + transparent, + var(--lotr-bright-gold) 20%, + var(--lotr-bright-gold) 80%, + transparent); +} + +body.lotr-mode nav .text-gray-700, +body.lotr-mode nav .text-gray-800, +body.lotr-mode nav .text-white { + color: var(--lotr-bright-gold) !important; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7); +} + +body.lotr-mode nav a { + color: var(--lotr-bright-gold) !important; + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7); + transition: all 0.3s ease; +} + +body.lotr-mode nav a:hover { + background: rgba(212, 175, 55, 0.2) !important; + text-shadow: + 1px 1px 2px rgba(0, 0, 0, 0.7), + 0 0 10px rgba(212, 175, 55, 0.5); +} + +/* Enhanced Loading Spinner - One Ring Animation */ +body.lotr-mode #loading-overlay { + background: rgba(13, 40, 24, 0.9) !important; + backdrop-filter: blur(8px); +} + +body.lotr-mode #loading-overlay .animate-spin { + border-color: var(--lotr-gold); + border-top-color: transparent; + width: 80px; + height: 80px; + position: relative; + border-width: 6px; +} + +body.lotr-mode #loading-overlay .animate-spin::before { + content: ''; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 50px; + height: 50px; + border: 4px solid var(--lotr-bright-gold); + border-radius: 50%; + box-shadow: + 0 0 30px var(--lotr-gold), + 0 0 60px var(--lotr-gold), + inset 0 0 30px var(--lotr-gold); + animation: ringGlow 2s ease-in-out infinite; +} + +body.lotr-mode #loading-overlay .animate-spin::after { + content: '⚔'; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 24px; + color: var(--lotr-bright-gold); + text-shadow: 0 0 20px var(--lotr-gold); + animation: swordPulse 1.5s ease-in-out infinite; +} + +@keyframes ringGlow { + 0%, 100% { + opacity: 0.7; + box-shadow: + 0 0 30px var(--lotr-gold), + 0 0 60px var(--lotr-gold), + inset 0 0 30px var(--lotr-gold); + transform: translate(-50%, -50%) scale(1); + } + 50% { + opacity: 1; + box-shadow: + 0 0 50px var(--lotr-gold), + 0 0 100px var(--lotr-gold), + 0 0 150px var(--lotr-gold), + inset 0 0 50px var(--lotr-gold); + transform: translate(-50%, -50%) scale(1.1); + } +} + +@keyframes swordPulse { + 0%, 100% { + opacity: 0.8; + transform: translate(-50%, -50%) rotate(0deg); + } + 50% { + opacity: 1; + transform: translate(-50%, -50%) rotate(15deg); + } +} + +/* Enhanced Toast Notifications - Scroll Style */ +body.lotr-mode .toast { + background: linear-gradient(135deg, var(--lotr-parchment) 0%, var(--lotr-warm-parchment) 100%) !important; + border: 3px solid var(--lotr-gold); + color: var(--lotr-text-dark) !important; + box-shadow: + 0 8px 16px rgba(0, 0, 0, 0.5), + inset 0 0 30px rgba(212, 175, 55, 0.15); + position: relative; + padding: 16px 20px 16px 60px; + font-weight: 600; + border-radius: 8px; +} + +body.lotr-mode .toast::before { + content: '⚔'; + position: absolute; + left: 20px; + top: 50%; + transform: translateY(-50%); + font-size: 24px; + color: var(--lotr-gold); + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3); +} + +body.lotr-mode .toast-success { + border-color: var(--lotr-forest-green); + background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%) !important; +} + +body.lotr-mode .toast-success::before { + content: '✓'; + color: var(--lotr-forest-green); +} + +body.lotr-mode .toast-error { + border-color: var(--lotr-fire-red); + background: linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%) !important; +} + +body.lotr-mode .toast-error::before { + content: '✕'; + color: var(--lotr-fire-red); +} + +body.lotr-mode .toast-info { + border-color: var(--lotr-gold); +} + +/* Dashboard Cards - Medieval Banners */ +body.lotr-mode .bg-blue-50, +body.lotr-mode .bg-gray-50 { + background: linear-gradient(135deg, var(--lotr-warm-parchment) 0%, var(--lotr-dark-parchment) 100%) !important; + border: 2px solid var(--lotr-stone-gray); + border-radius: 8px; +} + +body.lotr-mode .text-blue-600 { + color: var(--lotr-gold) !important; + font-weight: 600; +} + +/* Enhanced Tables */ +body.lotr-mode table { + border-collapse: separate; + border-spacing: 0; + border-radius: 8px; + overflow: hidden; +} + +body.lotr-mode table th { + background: linear-gradient(135deg, var(--lotr-dark-brown) 0%, var(--lotr-brown) 50%, var(--lotr-stone-gray) 100%); + color: var(--lotr-bright-gold); + border: 2px solid var(--lotr-gold); + font-family: 'Cinzel', serif; + font-weight: 700; + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7); + padding: 12px; +} + +body.lotr-mode table td { + background: var(--lotr-parchment); + border: 1px solid var(--lotr-stone-gray); + color: var(--lotr-text-dark); + padding: 10px 12px; +} + +body.lotr-mode table tr:hover td { + background: var(--lotr-warm-parchment); + box-shadow: inset 0 0 10px rgba(212, 175, 55, 0.1); +} + +body.lotr-mode table tr:nth-child(even) td { + background: var(--lotr-dark-parchment); +} + +body.lotr-mode table tr:nth-child(even):hover td { + background: var(--lotr-warm-parchment); +} + +/* Enhanced Modal - Parchment Scroll */ +body.lotr-mode .modal-content { + background: linear-gradient(135deg, var(--lotr-parchment) 0%, var(--lotr-warm-parchment) 100%) !important; + border: 5px solid var(--lotr-gold); + border-radius: 16px; + box-shadow: + 0 12px 48px rgba(0, 0, 0, 0.6), + inset 0 0 60px rgba(212, 175, 55, 0.15); + position: relative; + overflow: hidden; +} + +body.lotr-mode .modal-content::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: + repeating-linear-gradient( + 0deg, + transparent, + transparent 4px, + rgba(139, 115, 85, 0.04) 4px, + rgba(139, 115, 85, 0.04) 8px + ); + pointer-events: none; +} + +body.lotr-mode .modal-content h2, +body.lotr-mode .modal-content h3 { + border-bottom: 3px solid var(--lotr-gold); + padding-bottom: 12px; + margin-bottom: 24px; + color: var(--lotr-text-dark); + position: relative; +} + +body.lotr-mode .modal-content h2::after, +body.lotr-mode .modal-content h3::after { + content: '⚔'; + position: absolute; + right: 0; + color: var(--lotr-gold); + opacity: 0.5; +} + +/* Enhanced Badges and Labels */ +body.lotr-mode .bg-green-100, +body.lotr-mode .bg-green-500 { + background: linear-gradient(135deg, var(--lotr-forest-green) 0%, var(--lotr-dark-green) 100%) !important; + color: var(--lotr-bright-gold) !important; + border: 2px solid var(--lotr-gold); + font-weight: 600; + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7); +} + +body.lotr-mode .bg-red-100, +body.lotr-mode .bg-red-500 { + background: linear-gradient(135deg, var(--lotr-fire-red) 0%, #a00d1a 100%) !important; + color: var(--lotr-text-light) !important; + border: 2px solid var(--lotr-fire-orange); + font-weight: 600; + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7); +} + +body.lotr-mode .bg-yellow-400 { + background: linear-gradient(135deg, var(--lotr-bright-gold) 0%, var(--lotr-gold) 100%) !important; + color: var(--lotr-text-dark) !important; + border: 3px solid var(--lotr-brown); + font-weight: 700; + text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5); +} + +/* Enhanced Restart Banner */ +body.lotr-mode #restartBanner { + background: linear-gradient(135deg, + var(--lotr-bright-gold) 0%, + var(--lotr-gold) 30%, + var(--lotr-dark-gold) 70%, + var(--lotr-gold) 100%) !important; + border-top: 4px solid var(--lotr-brown); + border-bottom: 4px solid var(--lotr-brown); + color: var(--lotr-text-dark) !important; + font-weight: 700; + text-shadow: 1px 1px 2px rgba(255, 255, 255, 0.5); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4); +} + +/* Enhanced Select2 Styling */ +body.lotr-mode .select2-container--default .select2-selection { + background: var(--lotr-warm-parchment) !important; + border: 3px solid var(--lotr-stone-gray) !important; + color: var(--lotr-text-dark) !important; + border-radius: 6px; + min-height: 42px; +} + +body.lotr-mode .select2-container--default .select2-selection--multiple .select2-selection__choice { + background: linear-gradient(135deg, var(--lotr-gold) 0%, var(--lotr-dark-gold) 100%) !important; + border: 2px solid var(--lotr-brown) !important; + color: var(--lotr-text-dark) !important; + font-weight: 600; + border-radius: 6px; + padding: 4px 8px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +body.lotr-mode .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { + color: var(--lotr-text-dark) !important; + font-weight: 700; + margin-right: 6px; +} + +/* Enhanced Scrollbar Styling */ +body.lotr-mode ::-webkit-scrollbar { + width: 14px; + height: 14px; +} + +body.lotr-mode ::-webkit-scrollbar-track { + background: var(--lotr-dark-green); + border: 2px solid var(--lotr-stone-gray); + border-radius: 8px; +} + +body.lotr-mode ::-webkit-scrollbar-thumb { + background: linear-gradient(135deg, var(--lotr-bright-gold) 0%, var(--lotr-gold) 50%, var(--lotr-dark-gold) 100%); + border: 3px solid var(--lotr-brown); + border-radius: 8px; + box-shadow: + inset 0 2px 4px rgba(255, 255, 255, 0.2), + inset 0 -2px 4px rgba(0, 0, 0, 0.2); +} + +body.lotr-mode ::-webkit-scrollbar-thumb:hover { + background: linear-gradient(135deg, var(--lotr-gold) 0%, var(--lotr-bright-gold) 50%, var(--lotr-gold) 100%); + box-shadow: + inset 0 2px 4px rgba(255, 255, 255, 0.3), + inset 0 -2px 4px rgba(0, 0, 0, 0.3), + 0 0 10px rgba(212, 175, 55, 0.5); +} + +/* Beautiful Decorative Elements */ +body.lotr-mode .lotr-divider { + height: 4px; + background: linear-gradient(90deg, + transparent 0%, + var(--lotr-gold) 15%, + var(--lotr-bright-gold) 50%, + var(--lotr-gold) 85%, + transparent 100%); + margin: 30px 0; + position: relative; + box-shadow: 0 2px 8px rgba(212, 175, 55, 0.5); +} + +body.lotr-mode .lotr-divider::before, +body.lotr-mode .lotr-divider::after { + content: '⚔'; + position: absolute; + top: 50%; + transform: translateY(-50%); + font-size: 28px; + color: var(--lotr-bright-gold); + background: var(--lotr-parchment); + padding: 0 15px; + text-shadow: + 2px 2px 4px rgba(0, 0, 0, 0.5), + 0 0 10px rgba(212, 175, 55, 0.8); + animation: swordGlow 2s ease-in-out infinite; +} + +@keyframes swordGlow { + 0%, 100% { + text-shadow: + 2px 2px 4px rgba(0, 0, 0, 0.5), + 0 0 10px rgba(212, 175, 55, 0.8); + } + 50% { + text-shadow: + 2px 2px 4px rgba(0, 0, 0, 0.5), + 0 0 20px rgba(212, 175, 55, 1), + 0 0 30px rgba(212, 175, 55, 0.8); + } +} + +body.lotr-mode .lotr-divider::before { + left: 20%; +} + +body.lotr-mode .lotr-divider::after { + right: 20%; +} + +/* Enhanced Glow Effects */ +body.lotr-mode .lotr-glow { + text-shadow: + 0 0 15px var(--lotr-gold), + 0 0 30px var(--lotr-gold), + 0 0 45px var(--lotr-gold); + animation: gentleGlow 3s ease-in-out infinite; +} + +@keyframes gentleGlow { + 0%, 100% { + text-shadow: + 0 0 15px var(--lotr-gold), + 0 0 30px var(--lotr-gold), + 0 0 45px var(--lotr-gold); + } + 50% { + text-shadow: + 0 0 25px var(--lotr-bright-gold), + 0 0 50px var(--lotr-gold), + 0 0 75px var(--lotr-gold); + } +} + +/* Fire Effect (for email headers) */ +body.lotr-mode .lotr-fire { + background: linear-gradient(180deg, + var(--lotr-fire-red) 0%, + var(--lotr-fire-orange) 30%, + var(--lotr-bright-gold) 70%, + var(--lotr-gold) 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + font-weight: 700; + text-shadow: 0 0 30px var(--lotr-fire-orange); + animation: fireFlicker 2s ease-in-out infinite; + filter: drop-shadow(0 0 10px var(--lotr-fire-orange)); +} + +@keyframes fireFlicker { + 0%, 100% { + filter: brightness(1) drop-shadow(0 0 10px var(--lotr-fire-orange)); + } + 25% { + filter: brightness(1.3) drop-shadow(0 0 15px var(--lotr-fire-orange)); + } + 50% { + filter: brightness(0.9) drop-shadow(0 0 8px var(--lotr-fire-orange)); + } + 75% { + filter: brightness(1.2) drop-shadow(0 0 12px var(--lotr-fire-orange)); + } +} + +/* Smooth Theme Transition */ +body.lotr-mode, +body.lotr-mode * { + transition: background-color 0.6s ease, + color 0.6s ease, + border-color 0.6s ease, + box-shadow 0.6s ease; +} + +/* Links */ +body.lotr-mode a { + color: var(--lotr-bright-gold); + text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7); + transition: all 0.3s ease; +} + +body.lotr-mode a:hover { + color: var(--lotr-gold); + text-shadow: + 1px 1px 2px rgba(0, 0, 0, 0.7), + 0 0 10px rgba(212, 175, 55, 0.6); +} + +/* Checkboxes and Radio Buttons */ +body.lotr-mode input[type="checkbox"], +body.lotr-mode input[type="radio"] { + width: 20px; + height: 20px; + accent-color: var(--lotr-gold); + cursor: pointer; +} + +/* Labels */ +body.lotr-mode label { + color: var(--lotr-text-dark); + font-weight: 600; +} + +body.lotr-mode .bg-white label { + color: var(--lotr-text-dark) !important; +} + +/* Main Content Area */ +body.lotr-mode main { + background: transparent; +} + +/* Mobile Responsive */ +@media (max-width: 768px) { + body.lotr-mode .bg-white { + border-width: 3px; + } + + body.lotr-mode h1, + body.lotr-mode h2, + body.lotr-mode h3 { + font-size: 1.8em; + } + + body.lotr-mode .lotr-divider::before, + body.lotr-mode .lotr-divider::after { + font-size: 20px; + padding: 0 10px; + } +} diff --git a/pkg/web/templates/index.html b/pkg/web/templates/index.html index a2f237f..3391eba 100644 --- a/pkg/web/templates/index.html +++ b/pkg/web/templates/index.html @@ -37,7 +37,7 @@ - + @@ -1001,6 +1001,23 @@ window.addEventListener('DOMContentLoaded', function() { showLoading(true); displayExternalIP(); + + // Check LOTR mode on page load to apply immediately + fetch('/api/settings') + .then(res => res.json()) + .then(data => { + const alertCountries = data.alertCountries || []; + checkAndApplyLOTRTheme(alertCountries); + // Store in global for later use + if (typeof currentSettings === 'undefined') { + window.currentSettings = {}; + } + window.currentSettings.alertCountries = alertCountries; + }) + .catch(err => { + console.warn('Could not check LOTR on load:', err); + }); + Promise.all([ loadServers(), getTranslationsSettingsOnPageload() @@ -3023,23 +3040,30 @@ // Apply or remove LOTR theme function applyLOTRTheme(active) { const body = document.body; - const lotrCSS = document.getElementById('lotr-theme-css'); + const lotrCSS = document.getElementById('lotr-css'); if (active) { - body.classList.add('lotr-mode'); + // Enable CSS first if (lotrCSS) { lotrCSS.disabled = false; } + // Then add class to body + body.classList.add('lotr-mode'); isLOTRModeActive = true; console.log('🎭 LOTR Mode Activated - Welcome to Middle-earth!'); } else { + // Remove class first body.classList.remove('lotr-mode'); + // Then disable CSS if (lotrCSS) { lotrCSS.disabled = true; } isLOTRModeActive = false; console.log('🎭 LOTR Mode Deactivated'); } + + // Force a reflow to ensure styles are applied + void body.offsetHeight; } // Check and apply LOTR theme based on current settings @@ -3139,9 +3163,20 @@ divider.className = 'lotr-divider'; divider.style.marginTop = '20px'; divider.style.marginBottom = '20px'; - const firstChild = settingsSection.querySelector('.bg-white'); - if (firstChild) { + + // Find the first child element (not text node) to insert before + const firstChild = Array.from(settingsSection.childNodes).find( + node => node.nodeType === Node.ELEMENT_NODE + ); + + if (firstChild && firstChild.parentNode === settingsSection) { settingsSection.insertBefore(divider, firstChild); + } else if (settingsSection.firstChild) { + // Fallback: append if insertBefore fails + settingsSection.insertBefore(divider, settingsSection.firstChild); + } else { + // Last resort: append to end + settingsSection.appendChild(divider); } } }