qwfjgp2 commited on
Commit
7249792
·
verified ·
1 Parent(s): 293cffc

Upload 46 files

Browse files
README.md CHANGED
@@ -1,10 +1,10 @@
1
- ---
2
- title: My Flask App
3
- emoji: 🚀
4
- colorFrom: green
5
- colorTo: yellow
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- # Flask app running with Docker on Hugging Face Spaces
 
1
+ ---
2
+ title: My Flask App
3
+ emoji: 🚀
4
+ colorFrom: green
5
+ colorTo: yellow
6
+ sdk: docker
7
+ pinned: false
8
+ ---
9
+
10
+ # Flask app running with Docker on Hugging Face Spaces
__pycache__/image_routes.cpython-312.pyc CHANGED
Binary files a/__pycache__/image_routes.cpython-312.pyc and b/__pycache__/image_routes.cpython-312.pyc differ
 
__pycache__/models.cpython-312.pyc CHANGED
Binary files a/__pycache__/models.cpython-312.pyc and b/__pycache__/models.cpython-312.pyc differ
 
static/js/analysis.js CHANGED
@@ -1,7 +1,17 @@
1
  import { getCurrentLanguage, translate } from './i18n.js';
2
  import { getCurrentImageFile } from './upload.js';
 
 
3
 
4
  async function analyzeImage() {
 
 
 
 
 
 
 
 
5
  const currentImageFile = getCurrentImageFile();
6
  if (!currentImageFile) {
7
  alert(getCurrentLanguage() === 'az' ? 'Zəhmət olmasa əvvəlcə şəkil seçin' : 'Please select an image first');
 
1
  import { getCurrentLanguage, translate } from './i18n.js';
2
  import { getCurrentImageFile } from './upload.js';
3
+ import { apiCall } from './auth.js';
4
+ import { navigateTo } from './navigation.js';
5
 
6
  async function analyzeImage() {
7
+ // Check authentication first
8
+ const authResult = await apiCall('/api/check-auth');
9
+ if (!authResult.success || !authResult.data.authenticated) {
10
+ alert(getCurrentLanguage() === 'az' ? 'Zəhmət olmasa əvvəlcə daxil olun' : 'Please sign in first to analyze images');
11
+ navigateTo('login', { preventDefault: () => {} });
12
+ return;
13
+ }
14
+
15
  const currentImageFile = getCurrentImageFile();
16
  if (!currentImageFile) {
17
  alert(getCurrentLanguage() === 'az' ? 'Zəhmət olmasa əvvəlcə şəkil seçin' : 'Please select an image first');
static/js/auth.js CHANGED
@@ -37,6 +37,9 @@ function toggleAccountMenu() {
37
  function updateUIForLoggedIn(email) {
38
  const signInBtn = document.getElementById('sign-in-btn');
39
  const accountMenu = document.getElementById('account-menu');
 
 
 
40
  if (signInBtn) {
41
  signInBtn.textContent = email || 'Dashboard';
42
  signInBtn.onclick = (event) => {
@@ -48,19 +51,56 @@ function updateUIForLoggedIn(email) {
48
  accountMenu.classList.remove('hidden');
49
  accountMenu.classList.add('hidden');
50
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  updateTranslations();
52
  }
53
 
54
  function updateUIForLoggedOut() {
55
  const signInBtn = document.getElementById('sign-in-btn');
56
  const accountMenu = document.getElementById('account-menu');
 
 
 
57
  if (signInBtn) {
58
  signInBtn.textContent = 'Sign In';
59
- signInBtn.onclick = (event) => navigateTo('login', event);
 
 
 
 
60
  }
61
  if (accountMenu) {
62
  accountMenu.classList.add('hidden');
63
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  updateTranslations();
65
  }
66
 
@@ -68,7 +108,9 @@ async function handleLogout() {
68
  const result = await apiCall('/api/logout', { method: 'POST' });
69
  if (result.success) {
70
  updateUIForLoggedOut();
71
- navigateTo('home', { preventDefault: () => {} });
 
 
72
  } else {
73
  alert(result.data?.message || (getCurrentLanguage() === 'az' ? 'Sistemdən çıxışda xəta.' : 'Error logging out.'));
74
  }
@@ -90,7 +132,9 @@ async function handleLogin(event) {
90
  successDiv.classList.add('bg-green-100', 'text-green-700');
91
  updateUIForLoggedIn(email);
92
  setTimeout(() => {
93
- navigateTo('dashboard', event);
 
 
94
  successDiv.classList.add('hidden');
95
  document.getElementById('login-form').reset();
96
  }, 1500);
 
37
  function updateUIForLoggedIn(email) {
38
  const signInBtn = document.getElementById('sign-in-btn');
39
  const accountMenu = document.getElementById('account-menu');
40
+ const mobileSignInBtn = document.getElementById('mobile-sign-in-btn');
41
+ const mobileAccountMenu = document.getElementById('mobile-account-menu');
42
+
43
  if (signInBtn) {
44
  signInBtn.textContent = email || 'Dashboard';
45
  signInBtn.onclick = (event) => {
 
51
  accountMenu.classList.remove('hidden');
52
  accountMenu.classList.add('hidden');
53
  }
54
+
55
+ if (mobileSignInBtn) {
56
+ mobileSignInBtn.textContent = email || 'Dashboard';
57
+ mobileSignInBtn.onclick = (event) => {
58
+ event.preventDefault && event.preventDefault();
59
+ if (mobileAccountMenu) {
60
+ mobileAccountMenu.classList.toggle('hidden');
61
+ }
62
+ };
63
+ }
64
+ if (mobileAccountMenu) {
65
+ mobileAccountMenu.classList.add('hidden');
66
+ }
67
+
68
  updateTranslations();
69
  }
70
 
71
  function updateUIForLoggedOut() {
72
  const signInBtn = document.getElementById('sign-in-btn');
73
  const accountMenu = document.getElementById('account-menu');
74
+ const mobileSignInBtn = document.getElementById('mobile-sign-in-btn');
75
+ const mobileAccountMenu = document.getElementById('mobile-account-menu');
76
+
77
  if (signInBtn) {
78
  signInBtn.textContent = 'Sign In';
79
+ signInBtn.onclick = (event) => {
80
+ if (typeof window.navigateTo === 'function') {
81
+ window.navigateTo('login', event);
82
+ }
83
+ };
84
  }
85
  if (accountMenu) {
86
  accountMenu.classList.add('hidden');
87
  }
88
+
89
+ if (mobileSignInBtn) {
90
+ mobileSignInBtn.textContent = 'Sign In';
91
+ mobileSignInBtn.onclick = (event) => {
92
+ if (typeof window.navigateTo === 'function') {
93
+ window.navigateTo('login', event);
94
+ if (typeof window.closeMobileMenu === 'function') {
95
+ window.closeMobileMenu();
96
+ }
97
+ }
98
+ };
99
+ }
100
+ if (mobileAccountMenu) {
101
+ mobileAccountMenu.classList.add('hidden');
102
+ }
103
+
104
  updateTranslations();
105
  }
106
 
 
108
  const result = await apiCall('/api/logout', { method: 'POST' });
109
  if (result.success) {
110
  updateUIForLoggedOut();
111
+ if (typeof window.navigateTo === 'function') {
112
+ window.navigateTo('home', { preventDefault: () => {} });
113
+ }
114
  } else {
115
  alert(result.data?.message || (getCurrentLanguage() === 'az' ? 'Sistemdən çıxışda xəta.' : 'Error logging out.'));
116
  }
 
132
  successDiv.classList.add('bg-green-100', 'text-green-700');
133
  updateUIForLoggedIn(email);
134
  setTimeout(() => {
135
+ if (typeof window.navigateTo === 'function') {
136
+ window.navigateTo('dashboard', event);
137
+ }
138
  successDiv.classList.add('hidden');
139
  document.getElementById('login-form').reset();
140
  }, 1500);
static/js/dashboard.js CHANGED
@@ -1,9 +1,15 @@
1
  import { apiCall } from './auth.js';
2
  import { updateDarkModeGradients } from './darkmode.js';
 
3
 
4
  async function loadDashboard() {
5
  const authResult = await apiCall('/api/check-auth');
6
  if (!authResult.success || !authResult.data.authenticated) {
 
 
 
 
 
7
  return;
8
  }
9
  const imagesResult = await apiCall('/api/my-images');
 
1
  import { apiCall } from './auth.js';
2
  import { updateDarkModeGradients } from './darkmode.js';
3
+ import { getCurrentLanguage } from './i18n.js';
4
 
5
  async function loadDashboard() {
6
  const authResult = await apiCall('/api/check-auth');
7
  if (!authResult.success || !authResult.data.authenticated) {
8
+ alert(getCurrentLanguage() === 'az' ? 'Zəhmət olmasa əvvəlcə daxil olun' : 'Please sign in first to access the dashboard');
9
+ // Use global navigateTo function (defined in main.js)
10
+ if (typeof window.navigateTo === 'function') {
11
+ window.navigateTo('login', { preventDefault: () => {} });
12
+ }
13
  return;
14
  }
15
  const imagesResult = await apiCall('/api/my-images');
static/js/main.js CHANGED
@@ -31,17 +31,10 @@ initMenuEvents();
31
  initUpload();
32
  if (window.location.hash) {
33
  const page = window.location.hash.substring(1);
34
- const pageElement = document.getElementById(`${page}-page`);
35
- if (pageElement) {
36
- document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
37
- pageElement.classList.add('active');
38
- const pages = ['home', 'features', 'analyze', 'dashboard', 'gallery', 'contact', 'login'];
39
- const index = pages.indexOf(page);
40
- if (index >= 0) {
41
- document.querySelectorAll('.sidebar-dot').forEach(dot => dot.classList.remove('active'));
42
- const dots = document.querySelectorAll('.sidebar-dot');
43
- if (dots[index]) dots[index].classList.add('active');
44
- }
45
- }
46
  }
47
  initElementSdk();
 
31
  initUpload();
32
  if (window.location.hash) {
33
  const page = window.location.hash.substring(1);
34
+ // Use navigateTo to ensure authentication checks are performed
35
+ navigateTo(page, { preventDefault: () => {} });
36
+ } else {
37
+ // If no hash, ensure home page is shown
38
+ navigateTo('home', { preventDefault: () => {} });
 
 
 
 
 
 
 
39
  }
40
  initElementSdk();
static/js/menu.js CHANGED
@@ -59,6 +59,11 @@ function initMenuEvents() {
59
  if (accountBtn && accountMenu && !accountBtn.contains(e.target) && !accountMenu.contains(e.target)) {
60
  accountMenu.classList.add('hidden');
61
  }
 
 
 
 
 
62
  });
63
  }
64
 
 
59
  if (accountBtn && accountMenu && !accountBtn.contains(e.target) && !accountMenu.contains(e.target)) {
60
  accountMenu.classList.add('hidden');
61
  }
62
+ const mobileAccountBtn = document.getElementById('mobile-sign-in-btn');
63
+ const mobileAccountMenu = document.getElementById('mobile-account-menu');
64
+ if (mobileAccountBtn && mobileAccountMenu && !mobileAccountBtn.contains(e.target) && !mobileAccountMenu.contains(e.target)) {
65
+ mobileAccountMenu.classList.add('hidden');
66
+ }
67
  });
68
  }
69
 
static/js/navigation.js CHANGED
@@ -1,9 +1,22 @@
1
  import { loadDashboard } from './dashboard.js';
 
 
2
 
3
- function navigateTo(page, event) {
4
  if (event && event.preventDefault) {
5
  event.preventDefault();
6
  }
 
 
 
 
 
 
 
 
 
 
 
7
  document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
8
  const pageElement = document.getElementById(`${page}-page`);
9
  if (pageElement) {
 
1
  import { loadDashboard } from './dashboard.js';
2
+ import { apiCall } from './auth.js';
3
+ import { getCurrentLanguage } from './i18n.js';
4
 
5
+ async function navigateTo(page, event) {
6
  if (event && event.preventDefault) {
7
  event.preventDefault();
8
  }
9
+
10
+ // Check authentication for protected pages
11
+ const protectedPages = ['analyze', 'dashboard'];
12
+ if (protectedPages.includes(page)) {
13
+ const authResult = await apiCall('/api/check-auth');
14
+ if (!authResult.success || !authResult.data.authenticated) {
15
+ alert(getCurrentLanguage() === 'az' ? 'Zəhmət olmasa əvvəlcə daxil olun' : 'Please sign in first to access this page');
16
+ page = 'login';
17
+ }
18
+ }
19
+
20
  document.querySelectorAll('.page').forEach(p => p.classList.remove('active'));
21
  const pageElement = document.getElementById(`${page}-page`);
22
  if (pageElement) {
templates/base.html CHANGED
@@ -1,19 +1,19 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Agrovision - Future of Farming</title>
7
- <link rel="stylesheet" href="/static/styles.css">
8
- <script src="/_sdk/element_sdk.js"></script>
9
- <script src="https://cdn.tailwindcss.com"></script>
10
- <script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.3/build/qrcode.min.js"></script>
11
- </head>
12
- <body class="bg-gray-50">
13
- {% include 'components/dark_toggle.html' %}
14
- {% include 'components/header.html' %}
15
- {% block content %}{% endblock %}
16
- <script src="/static/translations.js"></script>
17
- <script type="module" src="/static/js/main.js"></script>
18
- </body>
19
- </html>
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Agrovision - Future of Farming</title>
7
+ <link rel="stylesheet" href="/static/styles.css">
8
+ <script src="/_sdk/element_sdk.js"></script>
9
+ <script src="https://cdn.tailwindcss.com"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.3/build/qrcode.min.js"></script>
11
+ </head>
12
+ <body class="bg-gray-50">
13
+ {% include 'components/dark_toggle.html' %}
14
+ {% include 'components/header.html' %}
15
+ {% block content %}{% endblock %}
16
+ <script src="/static/translations.js"></script>
17
+ <script type="module" src="/static/js/main.js"></script>
18
+ </body>
19
+ </html>
templates/components/header.html CHANGED
@@ -1,9 +1,9 @@
1
  <header class="fixed top-0 left-0 right-0 bg-white/95 backdrop-blur-sm shadow-sm z-50">
2
  <nav class="max-w-7xl mx-auto px-4 md:px-6 py-4">
3
  <div class="flex justify-between items-center">
4
- <div class="flex items-center space-x-2">
5
  <div class="w-10 h-10 bg-gradient-to-br from-green-500 to-orange-500 rounded-lg flex items-center justify-center text-white text-xl font-bold">A</div><span id="nav-title" class="text-xl md:text-2xl font-bold gradient-text">Agrovision</span>
6
- </div>
7
  <div class="hidden md:flex items-center space-x-8"><a href="#home" class="nav-item text-gray-700 font-medium" data-i18n="nav.home" onclick="navigateTo('home', event)">Home</a> <a href="#features" class="nav-item text-gray-700 font-medium" data-i18n="nav.features" onclick="navigateTo('features', event)">Features</a> <a href="#analyze" class="nav-item text-gray-700 font-medium" data-i18n="nav.analyze" onclick="navigateTo('analyze', event)">Analyze</a> <a href="#dashboard" class="nav-item text-gray-700 font-medium" data-i18n="nav.dashboard" onclick="navigateTo('dashboard', event)">Dashboard</a> <a href="#gallery" class="nav-item text-gray-700 font-medium" data-i18n="nav.gallery" onclick="navigateTo('gallery', event)">Gallery</a> <a href="#contact" class="nav-item text-gray-700 font-medium" data-i18n="nav.contact" onclick="navigateTo('contact', event)">Contact</a></div>
8
  <div class="hidden md:flex items-center space-x-4">
9
  <div class="relative">
@@ -26,26 +26,6 @@
26
  <svg id="close-icon" class="w-6 h-6 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
27
  </button>
28
  </div>
29
- <div id="mobile-menu" class="hidden md:hidden absolute top-full left-0 right-0 bg-white shadow-lg border-t border-gray-200 py-4 z-40">
30
- <div class="px-4 space-y-2">
31
- <a href="#home" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.home" onclick="navigateTo('home', event); closeMobileMenu();">Home</a>
32
- <a href="#features" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.features" onclick="navigateTo('features', event); closeMobileMenu();">Features</a>
33
- <a href="#analyze" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.analyze" onclick="navigateTo('analyze', event); closeMobileMenu();">Analyze</a>
34
- <a href="#dashboard" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.dashboard" onclick="navigateTo('dashboard', event); closeMobileMenu();">Dashboard</a>
35
- <a href="#gallery" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.gallery" onclick="navigateTo('gallery', event); closeMobileMenu();">Gallery</a>
36
- <a href="#contact" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.contact" onclick="navigateTo('contact', event); closeMobileMenu();">Contact</a>
37
- <div class="border-t border-gray-200 my-2"></div>
38
- <div class="px-4 py-2">
39
- <div class="relative mb-3">
40
- <button id="mobile-lang-switcher" class="w-full bg-gray-100 hover:bg-gray-200 text-gray-700 px-4 py-2 rounded-lg font-semibold transition flex items-center justify-between" onclick="toggleMobileLanguageMenu()"><span>Language</span><span id="mobile-current-lang">EN</span></button>
41
- <div id="mobile-lang-menu" class="hidden absolute top-full left-0 right-0 mt-2 bg-white rounded-lg shadow-lg border border-gray-200 py-2 z-50">
42
- <button class="w-full text-left px-4 py-2 hover:bg-gray-100 text-gray-700 font-medium" onclick="switchLanguage('en'); closeMobileMenu();">🇬🇧 English</button>
43
- <button class="w-full text-left px-4 py-2 hover:bg-gray-100 text-gray-700 font-medium" onclick="switchLanguage('az'); closeMobileMenu();">🇦🇿 Azərbaycanca</button>
44
- </div>
45
- </div>
46
- <button class="w-full btn-gradient-orange text-white px-6 py-3 rounded-lg font-semibold" onclick="navigateTo('login', event); closeMobileMenu();"> Sign In </button>
47
- </div>
48
- </div>
49
- </div>
50
  </nav>
51
  </header>
 
1
  <header class="fixed top-0 left-0 right-0 bg-white/95 backdrop-blur-sm shadow-sm z-50">
2
  <nav class="max-w-7xl mx-auto px-4 md:px-6 py-4">
3
  <div class="flex justify-between items-center">
4
+ <a href="#home" class="flex items-center space-x-2 cursor-pointer hover:opacity-80 transition-opacity" onclick="navigateTo('home', event)">
5
  <div class="w-10 h-10 bg-gradient-to-br from-green-500 to-orange-500 rounded-lg flex items-center justify-center text-white text-xl font-bold">A</div><span id="nav-title" class="text-xl md:text-2xl font-bold gradient-text">Agrovision</span>
6
+ </a>
7
  <div class="hidden md:flex items-center space-x-8"><a href="#home" class="nav-item text-gray-700 font-medium" data-i18n="nav.home" onclick="navigateTo('home', event)">Home</a> <a href="#features" class="nav-item text-gray-700 font-medium" data-i18n="nav.features" onclick="navigateTo('features', event)">Features</a> <a href="#analyze" class="nav-item text-gray-700 font-medium" data-i18n="nav.analyze" onclick="navigateTo('analyze', event)">Analyze</a> <a href="#dashboard" class="nav-item text-gray-700 font-medium" data-i18n="nav.dashboard" onclick="navigateTo('dashboard', event)">Dashboard</a> <a href="#gallery" class="nav-item text-gray-700 font-medium" data-i18n="nav.gallery" onclick="navigateTo('gallery', event)">Gallery</a> <a href="#contact" class="nav-item text-gray-700 font-medium" data-i18n="nav.contact" onclick="navigateTo('contact', event)">Contact</a></div>
8
  <div class="hidden md:flex items-center space-x-4">
9
  <div class="relative">
 
26
  <svg id="close-icon" class="w-6 h-6 hidden" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
27
  </button>
28
  </div>
29
+ {% include 'components/mobile_menu.html' %}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  </nav>
31
  </header>
templates/components/mobile_menu.html ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div id="mobile-menu" class="hidden md:hidden absolute top-full left-0 right-0 bg-white shadow-lg border-t border-gray-200 py-4 z-40">
2
+ <div class="px-4 space-y-2">
3
+ <a href="#home" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.home" onclick="navigateTo('home', event); closeMobileMenu();">Home</a>
4
+ <a href="#features" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.features" onclick="navigateTo('features', event); closeMobileMenu();">Features</a>
5
+ <a href="#analyze" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.analyze" onclick="navigateTo('analyze', event); closeMobileMenu();">Analyze</a>
6
+ <a href="#dashboard" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.dashboard" onclick="navigateTo('dashboard', event); closeMobileMenu();">Dashboard</a>
7
+ <a href="#gallery" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.gallery" onclick="navigateTo('gallery', event); closeMobileMenu();">Gallery</a>
8
+ <a href="#contact" class="block px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.contact" onclick="navigateTo('contact', event); closeMobileMenu();">Contact</a>
9
+ <div class="border-t border-gray-200 my-2"></div>
10
+ <div class="px-4 py-2">
11
+ <div class="relative mb-3">
12
+ <button id="mobile-lang-switcher" class="w-full bg-gray-100 hover:bg-gray-200 text-gray-700 px-4 py-2 rounded-lg font-semibold transition flex items-center justify-between" onclick="toggleMobileLanguageMenu()"><span>Language</span><span id="mobile-current-lang">EN</span></button>
13
+ <div id="mobile-lang-menu" class="hidden absolute top-full left-0 right-0 mt-2 bg-white rounded-lg shadow-lg border border-gray-200 py-2 z-50">
14
+ <button class="w-full text-left px-4 py-2 hover:bg-gray-100 text-gray-700 font-medium" onclick="switchLanguage('en'); closeMobileMenu();">🇬🇧 English</button>
15
+ <button class="w-full text-left px-4 py-2 hover:bg-gray-100 text-gray-700 font-medium" onclick="switchLanguage('az'); closeMobileMenu();">🇦🇿 Azərbaycanca</button>
16
+ </div>
17
+ </div>
18
+ <button id="mobile-sign-in-btn" class="w-full btn-gradient-orange text-white px-6 py-3 rounded-lg font-semibold" onclick="navigateTo('login', event); closeMobileMenu();"> Sign In </button>
19
+ <div id="mobile-account-menu" class="hidden mt-2 space-y-2">
20
+ <button class="w-full text-left px-4 py-3 rounded-lg text-gray-700 font-medium hover:bg-gray-100 transition" data-i18n="nav.dashboard" onclick="navigateTo('dashboard', event); closeMobileMenu();">Dashboard</button>
21
+ <button class="w-full text-left px-4 py-3 rounded-lg text-red-600 font-medium hover:bg-red-50 transition" data-i18n="nav.signout" onclick="handleLogout(); closeMobileMenu();">Sign out</button>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </div>
26
+