Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>HireScope AI — Intelligent Resume Screening</title> | |
| <meta name="description" content="AI-powered resume screening system with semantic matching, skill extraction, and audio transcription."> | |
| <!-- Google Fonts --> | |
| <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=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet"> | |
| <!-- Tailwind CSS CDN --> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| fontFamily: { | |
| sans: ['Inter', 'system-ui', 'sans-serif'], | |
| }, | |
| colors: { | |
| brand: { | |
| 50: '#eef2ff', | |
| 100: '#e0e7ff', | |
| 200: '#c7d2fe', | |
| 300: '#a5b4fc', | |
| 400: '#818cf8', | |
| 500: '#6366f1', | |
| 600: '#4f46e5', | |
| 700: '#4338ca', | |
| 800: '#3730a3', | |
| 900: '#312e81', | |
| }, | |
| sky: { | |
| 50: '#f0f9ff', | |
| 400: '#38bdf8', | |
| 500: '#0ea5e9', | |
| 600: '#0284c7', | |
| } | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| * { font-family: 'Inter', system-ui, sans-serif; } | |
| body { | |
| background: linear-gradient(135deg, #f0f4f8 0%, #e8edf5 50%, #f0f0ff 100%); | |
| min-height: 100vh; | |
| } | |
| .glass-card { | |
| background: rgba(255, 255, 255, 0.85); | |
| backdrop-filter: blur(20px); | |
| -webkit-backdrop-filter: blur(20px); | |
| border: 1px solid rgba(255, 255, 255, 0.9); | |
| box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04); | |
| } | |
| .glass-card:hover { | |
| box-shadow: 0 8px 40px rgba(99, 102, 241, 0.08), 0 2px 8px rgba(0, 0, 0, 0.06); | |
| } | |
| .gradient-text { | |
| background: linear-gradient(135deg, #6366f1, #0ea5e9); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| } | |
| .nav-glass { | |
| background: rgba(255, 255, 255, 0.92); | |
| backdrop-filter: blur(24px); | |
| -webkit-backdrop-filter: blur(24px); | |
| border-bottom: 1px solid rgba(226, 232, 240, 0.8); | |
| } | |
| @keyframes fadeInUp { | |
| from { opacity: 0; transform: translateY(20px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| @keyframes slideInRight { | |
| from { opacity: 0; transform: translateX(20px); } | |
| to { opacity: 1; transform: translateX(0); } | |
| } | |
| @keyframes pulse-soft { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.6; } | |
| } | |
| .animate-fade-in-up { animation: fadeInUp 0.5s ease-out forwards; } | |
| .animate-fade-in-up-delay { animation: fadeInUp 0.5s ease-out 0.1s forwards; opacity: 0; } | |
| .animate-fade-in-up-delay-2 { animation: fadeInUp 0.5s ease-out 0.2s forwards; opacity: 0; } | |
| .animate-slide-in { animation: slideInRight 0.4s ease-out forwards; } | |
| .animate-pulse-soft { animation: pulse-soft 2s ease-in-out infinite; } | |
| /* Custom scrollbar */ | |
| ::-webkit-scrollbar { width: 6px; } | |
| ::-webkit-scrollbar-track { background: transparent; } | |
| ::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; } | |
| ::-webkit-scrollbar-thumb:hover { background: #94a3b8; } | |
| /* Smooth transitions for interactive elements */ | |
| .btn-primary { | |
| background: linear-gradient(135deg, #6366f1, #4f46e5); | |
| transition: all 0.3s ease; | |
| } | |
| .btn-primary:hover { | |
| background: linear-gradient(135deg, #818cf8, #6366f1); | |
| box-shadow: 0 8px 25px rgba(99, 102, 241, 0.3); | |
| transform: translateY(-1px); | |
| } | |
| .btn-secondary { | |
| background: linear-gradient(135deg, #0ea5e9, #0284c7); | |
| transition: all 0.3s ease; | |
| } | |
| .btn-secondary:hover { | |
| background: linear-gradient(135deg, #38bdf8, #0ea5e9); | |
| box-shadow: 0 8px 25px rgba(14, 165, 233, 0.3); | |
| transform: translateY(-1px); | |
| } | |
| /* Flash message styles */ | |
| .flash-success { background: linear-gradient(135deg, #ecfdf5, #d1fae5); border-left: 4px solid #10b981; } | |
| .flash-error { background: linear-gradient(135deg, #fef2f2, #fecaca); border-left: 4px solid #ef4444; } | |
| .flash-info { background: linear-gradient(135deg, #eff6ff, #dbeafe); border-left: 4px solid #3b82f6; } | |
| .flash-warning { background: linear-gradient(135deg, #fffbeb, #fef3c7); border-left: 4px solid #f59e0b; } | |
| /* Mobile menu */ | |
| .mobile-menu { display: none; } | |
| .mobile-menu.open { display: flex; } | |
| /* Modal backdrop */ | |
| .modal-backdrop { | |
| background: rgba(15, 23, 42, 0.5); | |
| backdrop-filter: blur(4px); | |
| } | |
| /* Skill tag animation */ | |
| .skill-tag { | |
| transition: all 0.2s ease; | |
| } | |
| .skill-tag:hover { | |
| transform: translateY(-1px); | |
| box-shadow: 0 2px 8px rgba(99, 102, 241, 0.2); | |
| } | |
| </style> | |
| </head> | |
| <body class="min-h-screen flex flex-col font-sans antialiased text-slate-800"> | |
| <!-- Navigation --> | |
| <nav class="nav-glass sticky top-0 z-50"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="flex items-center justify-between h-16"> | |
| <!-- Logo --> | |
| <div class="flex items-center gap-3"> | |
| <div class="bg-gradient-to-br from-brand-500 to-sky-500 p-2 rounded-xl shadow-lg shadow-brand-200"> | |
| <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path> | |
| </svg> | |
| </div> | |
| <a href="/" class="text-xl font-extrabold gradient-text tracking-tight">HireScope AI</a> | |
| </div> | |
| <!-- Desktop Navigation --> | |
| <div class="hidden md:flex items-center gap-2"> | |
| {% if session.get('user_id') %} | |
| <a href="/" class="px-4 py-2 text-slate-600 hover:text-brand-600 hover:bg-brand-50 rounded-lg transition font-medium text-sm"> | |
| <span class="flex items-center gap-2"> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"></path></svg> | |
| Upload | |
| </span> | |
| </a> | |
| <a href="/results" class="px-4 py-2 text-slate-600 hover:text-brand-600 hover:bg-brand-50 rounded-lg transition font-medium text-sm"> | |
| <span class="flex items-center gap-2"> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"></path></svg> | |
| Results | |
| </span> | |
| </a> | |
| <a href="/ranking" class="px-4 py-2 text-slate-600 hover:text-brand-600 hover:bg-brand-50 rounded-lg transition font-medium text-sm flex items-center gap-2"> | |
| <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0v8m0-8l-8 8-4-4-6 6"></path></svg> | |
| Leaderboard | |
| {% if candidate_count is defined and candidate_count > 0 %} | |
| <span class="bg-brand-500 text-white text-xs px-2 py-0.5 rounded-full font-semibold">{{ candidate_count }}</span> | |
| {% endif %} | |
| </a> | |
| <div class="pl-3 ml-2 border-l border-slate-200 flex items-center gap-3"> | |
| <div class="flex items-center gap-2 bg-slate-100 px-3 py-1.5 rounded-lg"> | |
| <div class="w-7 h-7 bg-gradient-to-br from-brand-500 to-sky-500 rounded-full flex items-center justify-center text-white text-xs font-bold"> | |
| {{ session.username[0]|upper }} | |
| </div> | |
| <span class="text-sm font-medium text-slate-700">{{ session.username }}</span> | |
| </div> | |
| <a href="/logout" class="text-sm text-red-500 hover:text-red-600 hover:bg-red-50 px-3 py-1.5 rounded-lg transition font-medium">Log out</a> | |
| </div> | |
| {% else %} | |
| <a href="/login" class="px-4 py-2 text-slate-600 hover:text-brand-600 font-medium text-sm rounded-lg hover:bg-brand-50 transition">Sign In</a> | |
| <a href="/register" class="btn-primary text-white px-5 py-2 rounded-lg text-sm font-semibold shadow-md">Sign Up Free</a> | |
| {% endif %} | |
| </div> | |
| <!-- Mobile Hamburger --> | |
| <button onclick="document.getElementById('mobile-nav').classList.toggle('open')" class="md:hidden p-2 rounded-lg hover:bg-slate-100 transition"> | |
| <svg class="w-6 h-6 text-slate-600" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path></svg> | |
| </button> | |
| </div> | |
| <!-- Mobile Menu --> | |
| <div id="mobile-nav" class="mobile-menu flex-col gap-2 pb-4 md:hidden"> | |
| {% if session.get('user_id') %} | |
| <a href="/" class="px-4 py-2 text-slate-600 hover:bg-brand-50 rounded-lg font-medium text-sm">Upload</a> | |
| <a href="/results" class="px-4 py-2 text-slate-600 hover:bg-brand-50 rounded-lg font-medium text-sm">Results</a> | |
| <a href="/ranking" class="px-4 py-2 text-slate-600 hover:bg-brand-50 rounded-lg font-medium text-sm">Leaderboard</a> | |
| <a href="/logout" class="px-4 py-2 text-red-500 hover:bg-red-50 rounded-lg font-medium text-sm">Log out</a> | |
| {% else %} | |
| <a href="/login" class="px-4 py-2 text-slate-600 hover:bg-brand-50 rounded-lg font-medium text-sm">Sign In</a> | |
| <a href="/register" class="px-4 py-2 text-brand-600 hover:bg-brand-50 rounded-lg font-medium text-sm">Sign Up</a> | |
| {% endif %} | |
| </div> | |
| </div> | |
| </nav> | |
| <!-- Flash Messages --> | |
| {% with messages = get_flashed_messages(with_categories=true) %} | |
| {% if messages %} | |
| <div class="max-w-5xl mx-auto mt-6 px-4 w-full space-y-3"> | |
| {% for category, message in messages %} | |
| <div class="flash-{{ category }} px-5 py-4 rounded-xl flex items-center gap-3 animate-slide-in shadow-sm"> | |
| {% if category == 'success' %} | |
| <svg class="w-5 h-5 text-emerald-600 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg> | |
| <span class="text-emerald-800 font-medium text-sm">{{ message }}</span> | |
| {% elif category == 'error' %} | |
| <svg class="w-5 h-5 text-red-600 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg> | |
| <span class="text-red-800 font-medium text-sm">{{ message }}</span> | |
| {% elif category == 'warning' %} | |
| <svg class="w-5 h-5 text-amber-600 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"></path></svg> | |
| <span class="text-amber-800 font-medium text-sm">{{ message }}</span> | |
| {% else %} | |
| <svg class="w-5 h-5 text-blue-600 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg> | |
| <span class="text-blue-800 font-medium text-sm">{{ message }}</span> | |
| {% endif %} | |
| </div> | |
| {% endfor %} | |
| </div> | |
| {% endif %} | |
| {% endwith %} | |
| <!-- Main Content --> | |
| <main class="flex-grow flex flex-col pt-6 pb-16"> | |
| {% block content %}{% endblock %} | |
| </main> | |
| <!-- Footer --> | |
| <footer class="border-t border-slate-200 bg-white/60 backdrop-blur py-6"> | |
| <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> | |
| <div class="flex flex-col md:flex-row items-center justify-between gap-4"> | |
| <div class="flex items-center gap-2"> | |
| <div class="bg-gradient-to-br from-brand-500 to-sky-500 p-1.5 rounded-lg"> | |
| <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path></svg> | |
| </div> | |
| <span class="text-sm font-semibold gradient-text">HireScope AI</span> | |
| </div> | |
| <p class="text-xs text-slate-400">Built with Semantic AI, Whisper & Sentence-Transformers</p> | |
| </div> | |
| </div> | |
| </footer> | |
| </body> | |
| </html> | |