Spaces:
Runtime error
Runtime error
| <html lang="en" class="dark"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <link rel="apple-touch-icon" sizes="180x180" href="{{ url_for('main.favicon_files', filename='apple-touch-icon.png') }}"> | |
| <link rel="icon" type="image/png" sizes="32x32" href="{{ url_for('main.favicon_files', filename='favicon-32x32.png') }}"> | |
| <link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('main.favicon_files', filename='favicon-16x16.png') }}"> | |
| <link rel="icon" href="{{ url_for('main.favicon') }}"> | |
| <link rel="manifest" href="{{ url_for('main.favicon_files', filename='site.webmanifest') }}"> | |
| <title>{% block title %}PoraHobeBot{% endblock %}</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link | |
| href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;700;800&family=JetBrains+Mono:wght@200;400;600&display=swap" | |
| rel="stylesheet"> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| fontFamily: { | |
| 'display': ['Space Grotesk', 'sans-serif'], | |
| 'mono': ['JetBrains Mono', 'monospace'] | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| body { | |
| background: #030305; | |
| font-family: 'JetBrains Mono', monospace; | |
| overflow-x: hidden; | |
| /* Prevent horizontal scroll */ | |
| } | |
| .glass { | |
| background: rgba(255, 255, 255, 0.03); | |
| backdrop-filter: blur(20px); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| } | |
| .glow { | |
| box-shadow: 0 0 40px rgba(59, 130, 246, 0.3); | |
| } | |
| .mesh-bg { | |
| background: radial-gradient(circle at 20% 50%, rgba(59, 130, 246, 0.15) 0%, transparent 50%), | |
| radial-gradient(circle at 80% 80%, rgba(139, 92, 246, 0.15) 0%, transparent 50%); | |
| } | |
| .animate-float { | |
| animation: float 6s ease-in-out infinite; | |
| } | |
| @keyframes float { | |
| 0%, | |
| 100% { | |
| transform: translateY(0px); | |
| } | |
| 50% { | |
| transform: translateY(-20px); | |
| } | |
| } | |
| .animate-glow { | |
| animation: glow 2s ease-in-out infinite alternate; | |
| } | |
| @keyframes glow { | |
| from { | |
| box-shadow: 0 0 20px rgba(59, 130, 246, 0.3); | |
| } | |
| to { | |
| box-shadow: 0 0 40px rgba(59, 130, 246, 0.6); | |
| } | |
| } | |
| .marquee { | |
| animation: marquee 20s linear infinite; | |
| } | |
| @keyframes marquee { | |
| 0% { | |
| transform: translateX(0); | |
| } | |
| 100% { | |
| transform: translateX(-50%); | |
| } | |
| } | |
| .card-hover { | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .card-hover:hover { | |
| transform: translateY(-8px) scale(1.02); | |
| } | |
| .btn-magnetic { | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .btn-magnetic:hover { | |
| transform: scale(1.05); | |
| } | |
| /* Mobile Menu Transitions */ | |
| .mobile-menu { | |
| max-height: 0; | |
| opacity: 0; | |
| overflow: hidden; | |
| transition: all 0.3s ease-in-out; | |
| } | |
| .mobile-menu.active { | |
| max-height: 500px; | |
| /* Arbitrary large height */ | |
| opacity: 1; | |
| margin-top: 1rem; | |
| padding-top: 1rem; | |
| border-top: 1px solid rgba(255, 255, 255, 0.1); | |
| } | |
| /* Force dark options for select inputs */ | |
| select option { | |
| background-color: #030305; | |
| color: #e5e7eb; | |
| } | |
| </style> | |
| </head> | |
| <body class="text-gray-100 min-h-screen flex flex-col"> | |
| <!-- Mesh Background --> | |
| <div class="fixed inset-0 mesh-bg pointer-events-none"></div> | |
| <!-- Floating Navbar --> | |
| <div class="fixed top-4 left-0 right-0 z-50 px-2 sm:px-4 flex justify-center pointer-events-none"> | |
| <nav | |
| class="w-full max-w-7xl glass rounded-xl px-4 py-2 sm:px-6 sm:py-2 pointer-events-auto shadow-2xl transition-all duration-300"> | |
| <div class="flex items-center justify-between"> | |
| <a href="{{ url_for('main.index') }}" class="font-display text-lg sm:text-xl font-bold tracking-tight"> | |
| <span class="bg-gradient-to-r from-blue-400 to-purple-500 bg-clip-text text-transparent">PoraHobe</span> | |
| </a> | |
| {% if current_user.is_authenticated %} | |
| <!-- Desktop Menu --> | |
| <div class="hidden md:flex items-center gap-4 font-mono text-xs sm:text-sm"> | |
| <a href="{{ url_for('notes.upload') }}" class="hover:text-blue-400 transition">Upload</a> | |
| <a href="{{ url_for('notes.list') }}" class="hover:text-blue-400 transition">Notes</a> | |
| <a href="{{ url_for('notes.activity') }}" class="hover:text-blue-400 transition">Activity</a> | |
| {% if current_user.is_admin %} | |
| <a href="{{ url_for('admin.dashboard') }}" class="hover:text-purple-400 transition">Admin</a> | |
| {% endif %} | |
| <!-- User Dropdown --> | |
| <div class="relative group"> | |
| <button class="flex items-center gap-2 glass px-2 py-1.5 rounded-lg hover:bg-white/5 transition"> | |
| <div | |
| class="w-7 h-7 rounded-full bg-gradient-to-br from-blue-500 to-purple-500 flex items-center justify-center font-display text-xs font-bold"> | |
| <img src="https://api.dicebear.com/9.x/thumbs/svg?seed={{ current_user.email }}" | |
| alt="{{ current_user.name }} Avatar" class="w-7 h-7 rounded-full"> | |
| </div> | |
| </button> | |
| <!-- Dropdown Menu --> | |
| <div | |
| class="absolute right-0 mt-4 w-48 glass rounded-xl overflow-hidden opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 transform origin-top-right z-40"> | |
| <a href="{{ url_for('main.profile') }}" | |
| class="block px-4 py-2.5 hover:bg-white/5 transition font-mono text-xs">Profile</a> | |
| <a href="{{ url_for('notes.my_notes') }}" | |
| class="block px-4 py-2.5 hover:bg-white/5 transition font-mono text-xs">My Notes</a> | |
| <a href="{{ url_for('main.logout') }}" | |
| class="block px-4 py-2.5 hover:bg-red-500/20 transition font-mono text-xs text-red-400">Logout</a> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Mobile Menu Button --> | |
| <button onclick="toggleMobileMenu()" class="md:hidden glass p-2 rounded-lg hover:bg-white/10 transition"> | |
| <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" /> | |
| </svg> | |
| </button> | |
| {% else %} | |
| <!-- Guest Actions --> | |
| <div class="flex items-center gap-4"> | |
| <a href="{{ url_for('main.login') }}" | |
| class="glass px-4 py-2 rounded-lg font-mono text-sm hover:bg-white/10 transition">Login</a> | |
| </div> | |
| {% endif %} | |
| </div> | |
| <!-- Mobile Menu --> | |
| {% if current_user.is_authenticated %} | |
| <div id="mobile-menu" class="mobile-menu md:hidden"> | |
| <div class="flex items-center gap-3 mb-4 pb-4 border-b border-white/10"> | |
| <div | |
| class="w-10 h-10 rounded-full bg-gradient-to-br from-blue-500 to-purple-500 flex items-center justify-center font-display font-bold"> | |
| <img src="https://api.dicebear.com/9.x/thumbs/svg?seed={{ current_user.email }}" | |
| alt="{{ current_user.name }} Avatar" class="w-10 h-10 rounded-full"> | |
| </div> | |
| <div class="overflow-hidden"> | |
| <p class="font-mono text-sm font-semibold truncate">{{ current_user.name }}</p> | |
| <p class="font-mono text-xs text-gray-400 truncate">{{ current_user.email }}</p> | |
| </div> | |
| </div> | |
| <div class="space-y-1"> | |
| <a href="{{ url_for('notes.upload') }}" | |
| class="block py-2 px-2 rounded hover:bg-white/5 font-mono text-sm hover:text-blue-400 transition">Upload</a> | |
| <a href="{{ url_for('notes.list') }}" | |
| class="block py-2 px-2 rounded hover:bg-white/5 font-mono text-sm hover:text-blue-400 transition">Notes</a> | |
| <a href="{{ url_for('notes.activity') }}" | |
| class="block py-2 px-2 rounded hover:bg-white/5 font-mono text-sm hover:text-blue-400 transition">Activity</a> | |
| <a href="{{ url_for('main.profile') }}" | |
| class="block py-2 px-2 rounded hover:bg-white/5 font-mono text-sm hover:text-blue-400 transition">Profile</a> | |
| <a href="{{ url_for('notes.my_notes') }}" | |
| class="block py-2 px-2 rounded hover:bg-white/5 font-mono text-sm hover:text-blue-400 transition">My | |
| Notes</a> | |
| {% if current_user.is_admin %} | |
| <a href="{{ url_for('admin.dashboard') }}" | |
| class="block py-2 px-2 rounded hover:bg-white/5 font-mono text-sm hover:text-purple-400 transition">Admin</a> | |
| {% endif %} | |
| <a href="{{ url_for('main.logout') }}" | |
| class="block py-2 px-2 rounded hover:bg-red-500/10 font-mono text-sm text-red-400 hover:text-red-300 transition">Logout</a> | |
| </div> | |
| </div> | |
| {% endif %} | |
| </nav> | |
| </div> | |
| <!-- Main Content --> | |
| <!-- Increased padding-top to account for floating navbar --> | |
| <main class="relative pt-32 pb-20 flex-grow"> | |
| {% with messages = get_flashed_messages(with_categories=true) %} | |
| {% if messages %} | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 mb-6"> | |
| {% for category, message in messages %} | |
| <div class="glass rounded-xl px-4 py-3 font-mono text-sm {% if category == 'error' %}text-red-300 border-red-400/30{% else %}text-blue-300 border-blue-400/30{% endif %}"> | |
| {{ message }} | |
| </div> | |
| {% endfor %} | |
| </div> | |
| {% endif %} | |
| {% endwith %} | |
| {% block content %}{% endblock %} | |
| </main> | |
| <!-- Footer --> | |
| <footer class="relative border-t border-white/10 overflow-hidden mt-auto"> | |
| <div class="py-8 sm:py-12"> | |
| <div class="whitespace-nowrap"> | |
| <div class="inline-block marquee"> | |
| <span class="font-display text-6xl sm:text-8xl font-bold text-white/5 mx-4 sm:mx-8">PORA HOBE</span> | |
| <span class="font-display text-6xl sm:text-8xl font-bold text-white/5 mx-4 sm:mx-8">PORA HOBE</span> | |
| <span class="font-display text-6xl sm:text-8xl font-bold text-white/5 mx-4 sm:mx-8">PORA HOBE</span> | |
| <span class="font-display text-6xl sm:text-8xl font-bold text-white/5 mx-4 sm:mx-8">PORA HOBE</span> | |
| </div> | |
| <div class="inline-block marquee"> | |
| <span class="font-display text-6xl sm:text-8xl font-bold text-white/5 mx-4 sm:mx-8">PORA HOBE</span> | |
| <span class="font-display text-6xl sm:text-8xl font-bold text-white/5 mx-4 sm:mx-8">PORA HOBE</span> | |
| <span class="font-display text-6xl sm:text-8xl font-bold text-white/5 mx-4 sm:mx-8">PORA HOBE</span> | |
| <span class="font-display text-6xl sm:text-8xl font-bold text-white/5 mx-4 sm:mx-8">PORA HOBE</span> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 py-6 sm:py-8 text-center"> | |
| <div class="flex justify-between items-center"> | |
| <p class="font-mono text-xs sm:text-sm text-gray-500">Pora Hobe // By SpreadSheets600</p> | |
| <div class="flex space-x-6"> | |
| <a href="https://spreadsheets600.is-a.dev" target="_blank" rel="noopener noreferrer" | |
| class="text-gray-400 hover:text-blue-400 transition-colors"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" | |
| stroke="currentColor" class="size-6"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" /> | |
| </svg> | |
| </a> | |
| <a href="https://github.com/spreadsheets600/porahobebot" target="_blank" rel="noopener noreferrer" | |
| class="text-gray-400 hover:text-purple-400 transition-colors"> | |
| <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" | |
| stroke="currentColor" class="size-6"> | |
| <path stroke-linecap="round" stroke-linejoin="round" | |
| d="M14.25 9.75 16.5 12l-2.25 2.25m-4.5 0L7.5 12l2.25-2.25M6 20.25h12A2.25 2.25 0 0 0 20.25 18V6A2.25 2.25 0 0 0 18 3.75H6A2.25 2.25 0 0 0 3.75 6v12A2.25 2.25 0 0 0 6 20.25Z" /> | |
| </svg> | |
| </a> | |
| </div> | |
| </div> | |
| </div> | |
| </footer> | |
| <script> | |
| function toggleMobileMenu() { | |
| const menu = document.getElementById('mobile-menu'); | |
| menu.classList.toggle('active'); | |
| } | |
| </script> | |
| {% block scripts %}{% endblock %} | |
| </body> | |
| </html> | |