      const API = 'api.php';
      let authToken = null;
      let deviceId = getDeviceId();
      // PERF: lazy-load audio only when needed — don't preload at startup
      let _attendanceAudio = null;
      function getAttendanceAudio() {
        if (!_attendanceAudio) {
          _attendanceAudio = new Audio('att_sound.mp3');
        }
        return _attendanceAudio;
      }
      let scannedToken = null;
      let selfieBase64 = null;
      let userLocation = null;
      let userWorkNature = localStorage.getItem('emp_work_nature') || 'internal';
      let scanStream = null;
      let selfieStream = null;
      let scanInterval = null;
      /** Active bottom-nav tab name — used to show report/holiday links only on «حضور / انصراف». */
      let employeeActiveTab = 'direct';
      let _empScreenFlagReport = false;
      let _empScreenFlagHolidays = false;

      // ── TRANSLATIONS ──────────────────────────────────────────────────
      const i18n = {
        ar: {
          nav_scan: "مسح QR",
          nav_direct: "حضور / انصراف",
          nav_history: "السجل",
          nav_leave: "الطلبات",
          nav_contacts: "جهات الاتصال",
          nav_settings: "إعدادات",
          contacts_title: "جهات الاتصال",
          contacts_refresh: "↻ تحديث",
          contacts_search_ph: "ابحث بالاسم أو الهاتف أو الفرع أو القسم...",
          contacts_loading: "جارٍ التحميل...",
          contacts_empty: "لا توجد نتائج",
          contacts_meta: "{shown} / {total}",
          account_settings: "إعدادات الحساب",
          language_pref: "تفضيلات اللغة (Language)",
          logout: "تسجيل الخروج",
          messages: "رسائل الإدارة",
          close: "إغلاق",
          no_messages: "لا توجد رسائل",
          mark_read: "تحديد كمقروءة",
          read: "مقروءة",
          mark_all_read: "تعيين الكل كمقروء",
          delete_all: "أرشفة الكل",
          delete_permanent: "حذف نهائي",
          delete_permanent_all: "حذف نهائي للكل",
          notif_filter_all: "الكل",
          notif_filter_unread: "غير المقروء",
          notif_filter_archived: "المؤرشفة",
          notif_unread_count: "{n} غير مقروء",
          notif_read_done: "تم التحديث",
          notif_delete_all_done: "تمت أرشفة جميع الرسائل",
          confirm_delete_all_notif: "هل تريد أرشفة جميع الرسائل؟",
          confirm_delete_perm_notif: "حذف هذه الرسالة نهائياً من الأرشيف؟",
          confirm_delete_perm_all_notif: "حذف كل الرسائل المؤرشفة نهائياً؟",
          delete_notif: "أرشفة",
          new_messages: "لديك {n} رسالة جديدة من الإدارة",
          lang_updated: "تم تحديث اللغة",
          error_fields: "الرجاء إدخال البيانات",
          login_btn: "تسجيل الدخول",
          direct_title: "اختر نوع التسجيل",
          direct_sub: "يرجى تحديد ما إذا كنت تسجل حضورك (دخول) أم انصرافك (خروج)",
          btn_in: "↑ تسجيل حضور",
          btn_out: "↓ تسجيل انصراف",
          btn_retake: "إلغاء وإعادة المحاولة",
          history_title: "سجل الحضور",
          history_refresh: "↻ تحديث",
          history_loading: "جارٍ التحميل...",
          leave_title: "طلب إجازة",
          leave_from: "من تاريخ",
          leave_to: "إلى تاريخ",
          leave_reason: "السبب",
          leave_reason_placeholder: "أدخل سبب الإجازة...",
          leave_submit: "إرسال الطلب",
          leave_history: "طلباتي السابقة",
          new_leave_request: "+ طلب جديد",
          support_title: "الدعم الفني",
          support_reset_pwa: "تحديث التطبيق / تنظيف الكاش",
          visit_details: "تفاصيل المأمورية / اسم العميل",
          visit_details_placeholder: "ادخل تفاصيل المأمورية هنا...",
          visit_details_err: "يرجى إدخال تفاصيل المأمورية",
          delete: "حذف",
          confirm_delete: "هل أنت متأكد من حذف هذا السجل؟",
          record_deleted: "تم حذف السجل",
          profile_title: "الملف الشخصي",
          add_photo: "إضافة صورة",
          phone_num: "رقم الهاتف",
          email_addr: "البريد الإلكتروني",
          save_changes: "حفظ التعديلات",
          profile_updated: "تم تحديث الملف الشخصي",
          leave_type: "نوع الإجازة",
          annual: "سنوية",
          casual: "عارضة",
          sick: "مرضية",
          permission: "إذن",
          leave_request_kind: "نوع الطلب",
          leave_kind_leave: "إجازة",
          leave_kind_permission: "إذن (فترة زمنية)",
          leave_kind_mission: "مأمورية",
          leave_title_permission: "طلب إذن",
          leave_title_mission: "طلب مأمورية",
          leave_reason_mission: "سبب المأمورية",
          leave_reason_mission_placeholder: "صف وجهة أو سبب المأمورية…",
          permission_times_hint_mission: "تُعامل كإذن زمني وتُراجع من الإدارة. سبب المأمورية مطلوب.",
          permission_date: "تاريخ الإذن",
          permission_from: "من الساعة",
          permission_to: "إلى الساعة",
          permission_times_hint: "يُراجع المدير الطلب. الإذن لا يخصم رصيد الإجازات السنوية أو العارضة أو المرضية.",
          permission_time_invalid: "وقت النهاية يجب أن يكون بعد وقت البداية.",
          leave_days_preview: "عدد الأيام المحتسبة: {n}",
          leave_hours_preview: "المدة المحتسبة: {dur}",
          leave_preview_pending: "اختر التواريخ والأوقات لمعرفة المدة",
          leave_dates_invalid: "تاريخ النهاية يجب أن يكون في نفس يوم البداية أو بعده",
          edit_note: "تعديل الملاحظات",
          update_note: "تحديث",
          note_updated: "تم تحديث الملاحظات بنجاح",
          err_network_unreachable: "تعذّر الاتصال بالخادم. تحقق من الإنترنت أو أعد المحاولة بعد قليل.",
          err_bad_server_response: "استجابة غير متوقعة من الخادم. إن استمر ذلك، تواصل مع الدعم الفني.",
          err_gateway_html: "الخادم أو الجدار الناري أعاد صفحة ويب بدل البيانات. غالباً بسبب حجم الطلب أو إعدادات الاستضافة.",
          err_payload_too_large: "حجم بيانات الصورة كبير جداً للخادم. تم تصغير الصورة تلقائياً؛ إن تكرر الخطأ أبلغ الإدارة.",
          err_empty_server_response: "لم يصل رد من الخادم. حاول مرة أخرى.",
          err_request_aborted: "تم إلغاء الطلب.",
          err_unauthorized: "انتهت الجلسة أو رمز الدخول غير صالح. سجّل الدخول مرة أخرى.",
          err_forbidden: "تم رفض الطلب. تحقق من الصلاحيات أو ربط الجهاز.",
          err_not_found: "البيانات المطلوبة غير موجودة.",
          err_rate_limited: "طلبات كثيرة. انتظر قليلاً ثم أعد المحاولة.",
          err_server: "خطأ في الخادم ({status}). حاول لاحقاً.",
          err_unknown: "حدث خطأ غير متوقع. حاول مرة أخرى.",
          cam_permission_denied: "تم رفض إذن الكاميرا. اسمح بالوصول من إعدادات المتصفح أو التطبيق.",
          cam_not_found: "لم يُعثر على كاميرا على هذا الجهاز.",
          cam_generic_err: "تعذّر تشغيل الكاميرا.",
          news_push_section: "تنبيهات أخبار الإدارة",
          news_push_help: "فعّل الإشعارات لتصلك تنبيهات عند نشر أخبار جديدة على الشريط الإخباري.",
          employee_push_phone_hint: "لتظهر التنبيهات خارج التطبيق (شاشة القفل): استخدم HTTPS، أضف التطبيق للشاشة الرئيسية، فعّل الأزرار أعلاه، واسمح بالإشعارات في إعدادات المتصفح والجوال. على iOS غالباً يلزم تثبيت الويب كتطبيق لدعم Web Push.",
          news_push_enable: "تفعيل تنبيهات الأخبار",
          news_push_disable: "إيقاف تنبيهات الأخبار",
          news_push_subscribed: "تم تفعيل تنبيهات الأخبار",
          news_push_denied: "تم رفض الإشعارات من المتصفح",
          news_push_server_off: "مفاتيح Web Push غير مضبوطة على الخادم (VAPID). اطلب من المسؤول ضبطها من Master أو المتغيرات البيئية.",
          news_push_need_composer: "المفاتيح جاهزة لكن مكتبة الخادم غير مثبتة (composer install في مجلد hr). تم حفظ الاشتراك؛ التنبيهات تعمل بعد التثبيت.",
          news_push_need_https: "التنبيهات تحتاج اتصالاً آمناً (HTTPS)",
          install_app: "تثبيت تطبيق الموظف",
          pwa_dual_hint: "يُفترض أن يُثبَّت التطبيقان منفصلَين (Chrome/Edge): لكل منهما scope و start_url مختلفان في الـ manifest. إن ظهرت رسالة التثبيت اليدوي، افتح صفحة الموظف في تبويب عادي وليس من داخل تطبيق المدير.",
          pwa_already_installed: "التطبيق مثبت بالفعل",
          install_app_manual: "افتح صفحة الدخول في تبويب Chrome عادي (ليس من داخل تطبيق المدير)، ثم القائمة ⋮ ← تثبيت التطبيق أو إضافة للشاشة الرئيسية. بعد تحديث الموقع احذف الأيقونات القديمة وأعد التثبيت إن لزم.",
          boot_title: "جاري تجهيز التطبيق",
          boot_subtitle: "نتحقق من الاتصال بالخادم ونحدّد موقعك مسبقاً لتعمل أزرار الحضور والمسح بسلاسة حتى على إنترنت بطيء.",
          boot_device: "تهيئة الجهاز…",
          boot_network: "الاتصال بالخادم…",
          boot_network_ok: "تم الاتصال بالخادم.",
          boot_network_fail: "تعذّر الوصول للخادم. تحقق من الشبكة ثم أعد المحاولة، أو المتابعة على مسؤوليتك.",
          boot_location: "تحديد الموقع (GPS)…",
          boot_location_done: "تم تحديد الموقع.",
          boot_location_done_acc: "تم تحديد موقعك (±{accuracy}م).",
          boot_location_warn: "لم يُحدد الموقع بعد (صلاحية أو إشارة). يمكنك المتابعة؛ قد يُطلب السماح بالموقع عند التسجيل.",
          boot_location_badge_loading: "📡 جارٍ تحديد الموقع...",
          boot_libs: "تحميل مكتبات المسح…",
          boot_ready: "جاهز.",
          boot_retry: "إعادة المحاولة",
          boot_skip: "المتابعة على أي حال",
          boot_skip_warn: "تم تخطي التحقق من الشبكة. قد لا يعمل تسجيل الدخول حتى يتوفر اتصال.",
          boot_wait: "انتظر حتى يكتمل شريط التحميل أعلاه.",
          boot_network_auto: "تأخر التحقق من الشبكة — نتابع تلقائياً لفتح تسجيل الدخول.",
          boot_opening: "جارٍ فتح التطبيق…"
        },
        en: {
          nav_scan: "Scan QR",
          nav_direct: "Check In/Out",
          nav_history: "History",
          nav_leave: "Requests",
          nav_contacts: "Contacts",
          nav_settings: "Settings",
          contacts_title: "Contacts",
          contacts_refresh: "↻ Refresh",
          contacts_search_ph: "Search by name, phone, branch, or department...",
          contacts_loading: "Loading...",
          contacts_empty: "No results",
          contacts_meta: "{shown} / {total}",
          account_settings: "Account Settings",
          language_pref: "Language Preference",
          logout: "Logout",
          messages: "Admin Messages",
          close: "Close",
          no_messages: "No messages",
          mark_read: "Mark as read",
          read: "Read",
          mark_all_read: "Mark all read",
          delete_all: "Archive all",
          delete_permanent: "Delete permanently",
          delete_permanent_all: "Delete permanently all",
          notif_filter_all: "All",
          notif_filter_unread: "Unread",
          notif_filter_archived: "Archived",
          notif_unread_count: "{n} unread",
          notif_read_done: "Updated",
          notif_delete_all_done: "All messages archived",
          confirm_delete_all_notif: "Archive all messages?",
          confirm_delete_perm_notif: "Permanently delete this archived message?",
          confirm_delete_perm_all_notif: "Permanently delete all archived messages?",
          delete_notif: "Archive",
          new_messages: "You have {n} new admin messages",
          lang_updated: "Language updated",
          error_fields: "Please enter your data",
          login_btn: "Login",
          direct_title: "Select Record Type",
          direct_sub: "Please specify if you are checking in or out",
          btn_in: "↑ Check In",
          btn_out: "↓ Check Out",
          btn_retake: "Cancel & Retake",
          history_title: "Attendance History",
          history_refresh: "↻ Refresh",
          history_loading: "Loading...",
          leave_title: "Leave Request",
          leave_from: "From Date",
          leave_to: "To Date",
          leave_reason: "Reason",
          leave_reason_placeholder: "Enter reason...",
          leave_submit: "Submit Request",
          leave_history: "My Previous Requests",
          new_leave_request: "+ New Request",
          support_title: "Technical Support",
          support_reset_pwa: "Update app / clear cache",
          visit_details: "Mission Details / Client Name",
          visit_details_placeholder: "Enter mission details here...",
          visit_details_err: "Please enter mission details",
          delete: "Delete",
          confirm_delete: "Are you sure you want to delete this record?",
          record_deleted: "Record deleted",
          profile_title: "My Profile",
          add_photo: "Add Photo",
          phone_num: "Phone Number",
          email_addr: "Email Address",
          save_changes: "Save Changes",
          profile_updated: "Profile updated",
          leave_type: "Leave Type",
          annual: "Annual",
          casual: "Casual",
          sick: "Sick",
          permission: "Permission",
          leave_request_kind: "Request type",
          leave_kind_leave: "Leave",
          leave_kind_permission: "Permission (time window)",
          leave_kind_mission: "Field mission",
          leave_title_permission: "Permission request",
          leave_title_mission: "Field mission request",
          leave_reason_mission: "Mission reason",
          leave_reason_mission_placeholder: "Describe destination or mission purpose…",
          permission_times_hint_mission: "Processed like a time permission and reviewed by admin. Mission reason is required.",
          permission_date: "Permission date",
          permission_from: "From time",
          permission_to: "To time",
          permission_times_hint: "Admin will review. Permissions do not deduct annual/casual/sick leave balance.",
          permission_time_invalid: "End time must be after start time.",
          leave_days_preview: "Calculated days: {n}",
          leave_hours_preview: "Calculated duration: {dur}",
          leave_preview_pending: "Select dates and times to see duration",
          leave_dates_invalid: "End date must be on or after the start date",
          edit_note: "Edit note",
          update_note: "Update",
          note_updated: "Note updated",
          err_network_unreachable: "Could not reach the server. Check your internet and try again.",
          err_bad_server_response: "Unexpected response from the server. If this continues, contact support.",
          err_gateway_html: "The server or firewall returned a web page instead of data—often due to request size or hosting limits.",
          err_payload_too_large: "The request body is too large for the server. Try again; if it persists, ask IT to raise upload limits.",
          err_empty_server_response: "Empty response from the server. Please try again.",
          err_request_aborted: "Request was cancelled.",
          err_unauthorized: "Session expired or login is invalid. Please sign in again.",
          err_forbidden: "Request was denied. Check permissions or device binding.",
          err_not_found: "The requested data was not found.",
          err_rate_limited: "Too many requests. Wait a moment and try again.",
          err_server: "Server error ({status}). Try again later.",
          err_unknown: "Something went wrong. Please try again.",
          cam_permission_denied: "Camera permission denied. Allow access in browser or app settings.",
          cam_not_found: "No camera was found on this device.",
          cam_generic_err: "Could not start the camera.",
          news_push_section: "Company news alerts",
          news_push_help: "Enable notifications to get alerted when HR posts new ticker items.",
          employee_push_phone_hint: "For lock-screen alerts: use HTTPS, add this site to your Home Screen as an app, enable the buttons above, and allow notifications in browser and OS settings. iOS usually requires the installed web app for Web Push.",
          news_push_enable: "Enable news alerts",
          news_push_disable: "Disable news alerts",
          news_push_subscribed: "News alerts enabled",
          news_push_denied: "Notifications were blocked",
          news_push_server_off: "Web Push keys are not set on the server (VAPID). Ask your admin to configure them in Master or via environment variables.",
          news_push_need_composer: "Keys are set but the server PHP library is missing (run composer install in the hr folder). Subscription saved; alerts work after install.",
          news_push_need_https: "Push requires HTTPS (or localhost)",
          install_app: "Install employee app",
          pwa_dual_hint: "Each app uses a different manifest scope and start URL so Chrome can offer two installs. If you only see the manual-install message, open the employee page in a normal browser tab—not inside the admin PWA.",
          pwa_already_installed: "App is already installed",
          install_app_manual: "Open this page in a normal Chrome tab (not inside the admin app window), then Menu ⋮ → Install app or Add to Home screen. After a site update, remove old shortcuts and reinstall if needed.",
          boot_title: "Preparing the app",
          boot_subtitle: "We verify the server connection and warm up GPS so check-in and QR work smoothly, even on slow networks.",
          boot_device: "Preparing this device…",
          boot_network: "Connecting to server…",
          boot_network_ok: "Server reached.",
          boot_network_fail: "Cannot reach the server. Check your connection and retry, or continue at your own risk.",
          boot_location: "Getting location (GPS)…",
          boot_location_done: "Location acquired.",
          boot_location_done_acc: "Location acquired (±{accuracy} m).",
          boot_location_warn: "Location not ready yet (permission or signal). You can continue; the browser may ask again when you record attendance.",
          boot_location_badge_loading: "📡 Getting location...",
          boot_libs: "Loading scanner libraries…",
          boot_ready: "Ready.",
          boot_retry: "Retry",
          boot_skip: "Continue anyway",
          boot_skip_warn: "Skipped server check. Login may fail until you have a connection.",
          boot_wait: "Please wait until the loading bar finishes.",
          boot_network_auto: "Server check timed out — continuing so you can sign in.",
          boot_opening: "Opening the app…"
        }
      };

      /** Known English API messages → Arabic (employee app default). */
      const SERVER_MSG_EN_TO_AR = {
        'Invalid credentials': 'اسم المستخدم أو كلمة المرور غير صحيحة.',
        'Missing or invalid token': 'انتهت الجلسة. سجّل الدخول مرة أخرى.',
        'Token expired or invalid': 'انتهت صلاحية الجلسة. سجّل الدخول مرة أخرى.',
        'Device ID required': 'معرّف الجهاز غير متوفر. أعد تحميل الصفحة أو أعد تسجيل الدخول.',
        'Device ID and Remember Token required': 'بيانات الجلسة غير مكتملة. سجّل الدخول مرة أخرى.',
        'Invalid session': 'الجلسة غير صالحة. سجّل الدخول مرة أخرى.',
        'Company account suspended': 'تم تعليق حساب الشركة. تواصل مع الإدارة.',
        'Account suspended': 'تم تعليق الحساب. تواصل مع الإدارة.',
        'Employee not found': 'لم يُعثر على بيانات الموظف.',
        'Forbidden': 'غير مصرح بتنفيذ هذا الإجراء.',
        'Invalid or expired QR code': 'رمز QR منتهي أو غير صالح. اطلب من الإدارة عرض رمز جديد.',
        'QR code expired or invalid. Please refresh.': 'انتهت صلاحية رمز QR أو أنه غير صالح. اطلب من الإدارة تحديث الرمز على الشاشة.',
        'Invalid attendance type': 'نوع التسجيل غير صالح.',
        'Database connection failed': 'الخادم مشغول مؤقتاً. حاول بعد قليل.',
        'Old password is incorrect': 'كلمة المرور الحالية غير صحيحة.',
        'New password must be at least 6 characters': 'كلمة المرور الجديدة يجب أن تكون 6 أحرف على الأقل.',
        'Both old and new passwords are required': 'أدخل كلمة المرور الحالية والجديدة.',
        'Password changed successfully': 'تم تغيير كلمة المرور بنجاح.',
        'Record not found': 'السجل غير موجود.',
        'Unauthorized': 'غير مصرح بتنفيذ هذا الإجراء.',
        'Deletion time window (60s) expired': 'انتهت مهلة حذف السجل (خلال 60 ثانية من وقت التسجيل فقط).',
        'Record ID required': 'معرّف السجل غير مُرسل.',
        'Note content required': 'يرجى إدخال نص الملاحظة.',
        'Leave request submitted': 'تم إرسال طلب الإجازة بنجاح.',
        'Note updated successfully': 'تم تحديث الملاحظة بنجاح.',
        'Record deleted successfully': 'تم حذف السجل بنجاح.',
        'Attendance recorded': 'تم تسجيل الحضور بنجاح.',
        'Profile updated successfully': 'تم تحديث الملف الشخصي بنجاح.',
        'Nothing updated': 'لم يُجرَ أي تعديل.',
        'Server error. Please try again.': 'خطأ في الخادم. حاول مرة أخرى لاحقاً.'
      };

      /** Short Arabic messages from API → English (when UI language is English). */
      const SERVER_MSG_AR_TO_EN = {
        'جاري المعالجة.. يرجى الانتظار': 'Processing… please wait a moment.',
        'هذا الحساب مرتبط بجهاز آخر. تواصل مع الإدارة لإعادة ضبط الربط.': 'This account is linked to another device. Contact HR to reset device binding.',
        'لا يمكن تعديل الملاحظات إلا في نفس اليوم': 'Notes can only be edited on the same calendar day as the attendance record.'
      };

      function t(key, params = {}) {
        const lang = document.documentElement.lang || 'ar';
        let text = i18n[lang][key] || key;
        for (const [k, v] of Object.entries(params)) {
          text = text.replace(`{${k}}`, v);
        }
        return text;
      }

      function updateUITranslations() {
        document.querySelectorAll('[data-i18n]').forEach(el => {
          el.textContent = t(el.getAttribute('data-i18n'));
        });
        document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
          el.placeholder = t(el.getAttribute('data-i18n-placeholder'));
        });
      }

      // ── DEVICE FINGERPRINTING (Advanced Hardware-Based) ─────────────────

      // Simple FNV-1a hash — no external libs needed
      function simpleHash(str) {
        let hash = 2166136261;
        for (let i = 0; i < str.length; i++) {
          hash ^= str.charCodeAt(i);
          hash = (hash * 16777619) >>> 0;
        }
        return hash.toString(16).padStart(8, '0');
      }

      // Get WebGL GPU renderer — most stable hardware fingerprint
      function getGpuFingerprint() {
        try {
          const canvas = document.createElement('canvas');
          const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
          if (!gl) return 'no-webgl';
          const ext = gl.getExtension('WEBGL_debug_renderer_info');
          if (ext) {
            const renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) || '';
            const vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL) || '';
            return simpleHash(renderer + '|' + vendor);
          }
          // Fallback: use renderer string without extension
          return simpleHash(gl.getParameter(gl.RENDERER) || 'webgl');
        } catch (e) { return 'gpu-err'; }
      }

      // Build stable hardware fingerprint from device characteristics
      // These properties are consistent across browsers on the same machine
      function generateHardwareFingerprint() {
        const parts = [
          screen.width + 'x' + screen.height,           // screen resolution
          screen.colorDepth,                             // color depth
          navigator.hardwareConcurrency || 0,            // CPU cores
          navigator.deviceMemory || 0,                   // RAM (if available)
          navigator.platform || '',                      // OS platform
          screen.pixelDepth || 0,                        // pixel depth
          getGpuFingerprint(),                           // GPU fingerprint (strongest)
        ];
        // Note: Removed timezone and languages to ensure stability across updates/travel
        return simpleHash(parts.join('||'));
      }

      // Cookie helpers
      function setCookie(name, value, days) {
        const maxAge = days * 24 * 3600;
        // SameSite=Lax works cross-browser on same domain;
        // path=/ ensures all pages under domain see the cookie
        document.cookie = `${name}=${encodeURIComponent(value)}; max-age=${maxAge}; path=/; SameSite=Lax`;
      }

      function getCookie(name) {
        const v = document.cookie.split('; ').find(r => r.startsWith(name + '='));
        return v ? decodeURIComponent(v.split('=')[1]) : null;
      }

      function deleteCookie(name) {
        document.cookie = `${name}=; max-age=0; path=/; SameSite=Lax`;
      }

      // Main device ID getter — returns "FP:{fpHash}:R:{randomSeed}"
      // The FP part is stable across browsers; R part is random per-device
      function getDeviceId() {
        const fpHash = generateHardwareFingerprint();

        // Try Cookie first, then LocalStorage
        let stored = getCookie('hr_device_id') || localStorage.getItem('device_fingerprint');

        if (stored) {
          // If it's the new format, verify the fingerprint portion
          if (stored.startsWith('FP:')) {
            const storedFp = stored.split(':')[1];
            if (storedFp === fpHash) {
              // Fingerprint still matches — keep using this ID
              setCookie('hr_device_id', stored, 730);
              localStorage.setItem('device_fingerprint', stored);
              return stored;
            }
            // If fingerprint changed, we'll still keep the stored ID for now
            // and let the server decide if it's "close enough" or if it needs update.
            // This prevents generating a totally new ID and triggering "Mismatch" errors unnecessarily.
            return stored;
          }
          // If it's an old format ID, we keep it to maintain backward compatibility
          return stored;
        }

        // No stored ID — generate new one with current fingerprint
        const randomSeed = Math.random().toString(36).substring(2, 10);
        const newId = `FP:${fpHash}:R:${randomSeed}`;

        setCookie('hr_device_id', newId, 730);
        localStorage.setItem('device_fingerprint', newId);

        return newId;
      }

      // Update device ID after successful login (refresh cookie + merge fingerprint)
      function refreshDeviceStorage(id) {
        setCookie('hr_device_id', id, 730);
        localStorage.setItem('device_fingerprint', id);
      }

      // ── API ───────────────────────────────────────────────────────────
      const DEFAULT_AVATAR = "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%238899b4'%3E%3Cpath d='M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z'/%3E%3C/svg%3E";
      function handleImgError(img) {
        img.onerror = null;
        img.src = DEFAULT_AVATAR;
      }

      function hrproMediaUrl(path) {
        if (!path || typeof path !== 'string') return '';
        if (typeof window.hrproResolveUploadUrl === 'function') return window.hrproResolveUploadUrl(path);
        try {
          return new URL(path.trim(), window.location.href).href;
        } catch (e) {
          return path;
        }
      }

      function localizeServerMessage(msg) {
        const s = String(msg == null ? '' : msg).trim();
        if (!s) return t('err_unknown');
        const lang = document.documentElement.lang || 'ar';
        if (lang === 'ar') {
          if (SERVER_MSG_EN_TO_AR[s]) return SERVER_MSG_EN_TO_AR[s];
          const lower = s.toLowerCase();
          const hit = Object.keys(SERVER_MSG_EN_TO_AR).find(k => k.toLowerCase() === lower);
          if (hit) return SERVER_MSG_EN_TO_AR[hit];
          const fieldReq = /^Field '([^']+)' is required$/i.exec(s);
          if (fieldReq) {
            const f = fieldReq[1];
            const labels = { start_date: 'تاريخ البداية', end_date: 'تاريخ النهاية', reason: 'السبب', leave_type: 'نوع الإجازة', note: 'الملاحظة' };
            return `الحقل مطلوب: ${labels[f] || f}`;
          }
          return msg;
        }
        if (SERVER_MSG_AR_TO_EN[s]) return SERVER_MSG_AR_TO_EN[s];
        return msg;
      }

      function fallbackHttpMessage(status) {
        const st = parseInt(status, 10) || 0;
        if (st === 401) return t('err_unauthorized');
        if (st === 403) return t('err_forbidden');
        if (st === 404) return t('err_not_found');
        if (st === 429) return t('err_rate_limited');
        if (st >= 500) return t('err_server', { status: st });
        return t('err_unknown');
      }

      /** User-facing error text after any api() call. */
      function apiErrorMessage(res) {
        if (!res || typeof res !== 'object') return t('err_unknown');
        if (res.message != null && String(res.message).trim() !== '') {
          return localizeServerMessage(res.message);
        }
        return fallbackHttpMessage(res._httpStatus);
      }

      async function api(method, endpoint, body = null) {
        const opts = {
          method,
          headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + (authToken || ''),
            'X-Device-ID': deviceId
          }
        };
        if (body) opts.body = JSON.stringify(body);
        const endpointStr = String(endpoint || '');
        const qIdx = endpointStr.indexOf('?');
        const routePart = qIdx >= 0 ? endpointStr.slice(0, qIdx) : endpointStr;
        const queryPart = qIdx >= 0 ? endpointStr.slice(qIdx + 1) : '';
        const url = `${API}?route=${encodeURIComponent(routePart)}${queryPart ? `&${queryPart}` : ''}`;
        let r;
        try {
          r = await fetch(url, opts);
        } catch (e) {
          const n = e && e.name;
          if (n === 'AbortError') {
            return { success: false, message: t('err_request_aborted'), _networkError: true, _httpStatus: 0 };
          }
          return { success: false, message: t('err_network_unreachable'), _networkError: true, _httpStatus: 0 };
        }

        let text;
        try {
          text = await r.text();
        } catch (e) {
          return { success: false, message: t('err_network_unreachable'), _networkError: true, _httpStatus: r.status || 0 };
        }

        if (!text || !String(text).trim()) {
          return {
            success: false,
            message: fallbackHttpMessage(r.status),
            _httpStatus: r.status,
            _emptyBody: true
          };
        }

        let data;
        try {
          data = JSON.parse(text);
        } catch (e) {
          const head = String(text).trim().slice(0, 240).toLowerCase();
          if (head.startsWith('<!doctype') || head.startsWith('<html') || head.includes('<body')) {
            return {
              success: false,
              message: t('err_gateway_html'),
              _httpStatus: r.status,
              _parseError: true
            };
          }
          if (r.status === 413 || r.status === 431) {
            return {
              success: false,
              message: t('err_payload_too_large'),
              _httpStatus: r.status,
              _parseError: true
            };
          }
          return {
            success: false,
            message: t('err_bad_server_response'),
            _httpStatus: r.status,
            _parseError: true
          };
        }

        if (Array.isArray(data)) {
          return { success: r.ok, data, _httpStatus: r.status };
        }
        if (typeof data !== 'object' || data === null) {
          return { success: false, message: t('err_bad_server_response'), _httpStatus: r.status, _parseError: true };
        }

        data._httpStatus = r.status;
        if (!r.ok && (data.message === undefined || data.message === null || String(data.message).trim() === '')) {
          data.success = false;
          data.message = fallbackHttpMessage(r.status);
        }
        return data;
      }

      // ── AUTH ──────────────────────────────────────────────────────────
      function logout() {
        stopCompanyNewsPolling();
        localStorage.removeItem('emp_token');
        localStorage.removeItem('emp_name');
        localStorage.removeItem('emp_photo');
        localStorage.removeItem('emp_company_logo');
        deleteCookie('emp_remember_token');
        // DO NOT delete hr_device_id or device_fingerprint
        location.reload();
      }

      async function doLogin() {
        const username = document.getElementById('loginUser').value.trim();
        const password = document.getElementById('loginPass').value;
        if (!username || !password) return showNotif('الرجاء إدخال البيانات', 'error');
        const btn = document.getElementById('loginSubmitBtn');
        if (!btn) return;
        if (btn.disabled) return showNotif(t('boot_wait'), 'warning');
        btn.innerHTML = '<div class="spinner"></div>';
        btn.disabled = true;
        const res = await api('POST', 'auth/employee-login', { username, password, device_id: deviceId });
        btn.innerHTML = t('login_btn') || 'تسجيل الدخول';
        btn.disabled = false;
        if (res.success) {
          authToken = res.data.token;
          localStorage.setItem('emp_token', authToken);
          localStorage.setItem('user_lang', res.data.language || 'ar');
          localStorage.setItem('emp_work_nature', res.data.work_nature || 'internal');
          localStorage.setItem('emp_name', res.data.name || '');
          localStorage.setItem('emp_photo', res.data.photo_url || '');
          localStorage.setItem('emp_company_logo', res.data.company_logo || '');
          localStorage.setItem('emp_phone', res.data.phone || '');
          localStorage.setItem('emp_email', res.data.email || '');
          localStorage.setItem('emp_dept', res.data.department || '');
          if (res.data.timezone) { localStorage.setItem('emp_timezone', res.data.timezone); updateClock(); }
          userWorkNature = res.data.work_nature || 'internal';

          // Save persistent remember token for auto-login
          if (res.data.remember_token) {
            setCookie('emp_remember_token', res.data.remember_token, 30); // 30 days
          }

          // If server returned a refreshed device_id (auto-update after FP match), store it
          if (res.data.device_id) {
            deviceId = res.data.device_id;
          }
          refreshDeviceStorage(deviceId);

          applyLanguage(res.data.language || 'ar');
          localStorage.removeItem('must_change_password');
          launchApp(res.data.name, res.data.company_logo, res.data.photo_url);
        } else showNotif(apiErrorMessage(res), 'error');
      }

      function applyAccountPhotoIfBound(res) {
        const p = res && res.data && typeof res.data.photo_url === 'string' ? res.data.photo_url.trim() : '';
        if (!p) return;
        localStorage.setItem('emp_photo', p);
        const avatar = document.getElementById('headerAvatar');
        if (!avatar) return;
        const url = hrproMediaUrl(p);
        const img = new Image();
        img.onload = () => {
          avatar.style.backgroundImage = `url("${url.replace(/"/g, '\\"')}")`;
          avatar.style.backgroundSize = 'cover';
          avatar.textContent = '';
        };
        img.onerror = () => {
          avatar.style.backgroundImage = `url("${DEFAULT_AVATAR}")`;
          avatar.style.backgroundSize = 'cover';
          avatar.textContent = '';
        };
        img.src = url;
      }

      // Central app launcher — called from both doLogin() and auto-login
      function launchApp(name, companyLogo, photoUrl) {
        document.getElementById('loginScreen').style.display = 'none';
        document.getElementById('welcomeScreen').style.display = 'none';
        document.getElementById('appShell').style.display = 'flex';
        document.getElementById('headerName').textContent = name || 'موظف';

        const avatar = document.getElementById('headerAvatar');
        const rawPhoto = photoUrl || localStorage.getItem('emp_photo') || '';
        const photo = rawPhoto ? hrproMediaUrl(rawPhoto) : '';
        if (photo) {
          const img = new Image();
          img.onload = () => {
            avatar.style.backgroundImage = `url("${photo.replace(/"/g, '\\"')}")`;
            avatar.style.backgroundSize = 'cover';
            avatar.textContent = '';
          };
          img.onerror = () => {
            avatar.style.backgroundImage = `url("${DEFAULT_AVATAR}")`;
            avatar.style.backgroundSize = 'cover';
            avatar.textContent = '';
          };
          img.src = photo;
        } else {
          avatar.style.backgroundImage = 'none';
          avatar.textContent = (name || 'م')[0];
        }

        const logoRaw = companyLogo || localStorage.getItem('emp_company_logo');
        if (logoRaw) {
          localStorage.setItem('emp_company_logo', logoRaw);
          const logo = hrproMediaUrl(logoRaw);
          const headers = document.querySelectorAll('.header-logo, .login-app-name');
          headers.forEach(h => h.innerHTML = `<img src="${logo.replace(/"/g, '&quot;')}" onerror="handleImgError(this)" style="max-height:45px; max-width:160px; border-radius:4px; object-fit: contain;" alt="Company Logo">`);
          const circle = document.querySelector('.login-logo-circle');
          if (circle) circle.style.display = 'none';
        }

        requestLocation();
        loadMessages();
        loadTodayLogs();
        loadCompanyNewsTicker();
        void loadTeamManagerMeta();
        startCompanyNewsPolling();
        void refreshEmployeeScreenFlags();
        void ensureEmployeeNewsPushSubscription().catch(() => {});
        setTimeout(() => employeeApplyDeepLinkFromUrl(), 120);
      }

      function applyEmpQuickLinksVisibility() {
        const wrap = document.getElementById('empQuickLinks');
        const lr = document.getElementById('linkEmpReport');
        const lh = document.getElementById('linkEmpHolidays');
        if (!wrap || !lr || !lh) return;
        const sr = _empScreenFlagReport;
        const sh = _empScreenFlagHolidays;
        lr.style.display = sr ? 'inline-flex' : 'none';
        lh.style.display = sh ? 'inline-flex' : 'none';
        const showBar = employeeActiveTab === 'direct' && (sr || sh);
        wrap.style.display = showBar ? 'flex' : 'none';
      }

      async function refreshEmployeeScreenFlags() {
        try {
          const res = await api('GET', 'employees/me/screen-flags');
          if (!res.success || !res.data) {
            _empScreenFlagReport = false;
            _empScreenFlagHolidays = false;
            applyEmpQuickLinksVisibility();
            return;
          }
          const f = res.data;
          const sr = f.show_employee_report === true || f.show_employee_report === 1;
          const sh = f.show_public_holidays === true || f.show_public_holidays === 1;
          _empScreenFlagReport = sr;
          _empScreenFlagHolidays = sh;
          localStorage.setItem('hrpro_show_employee_report', sr ? 'true' : 'false');
          localStorage.setItem('hrpro_show_public_holidays', sh ? 'true' : 'false');
          applyEmpQuickLinksVisibility();
        } catch (e) {
          _empScreenFlagReport = false;
          _empScreenFlagHolidays = false;
          try {
            applyEmpQuickLinksVisibility();
          } catch (e2) { /* ignore */ }
        }
      }

      function employeeFindNavTriggerForTab(tabName) {
        const idMap = { scan: 'navScan', direct: 'navDirect', history: 'navHistory', leave: 'navLeave', contacts: 'navContacts', profile: 'navProfile' };
        const nid = idMap[tabName];
        if (nid) {
          const el = document.getElementById(nid);
          if (el) return el;
        }
        return document.querySelector('.nav-btn[onclick*="showTab(\'' + tabName + '\'"]');
      }

      function employeeStripDeepLinkParams() {
        try {
          const clean = new URL(location.href);
          clean.searchParams.delete('open_tab');
          clean.searchParams.delete('tab');
          history.replaceState({}, '', clean.pathname + clean.search);
        } catch (e) { /* ignore */ }
      }

      function employeeApplyDeepLinkFromUrl() {
        if (!authToken) return;
        try {
          const p = new URLSearchParams(window.location.search);
          const tab = String(p.get('open_tab') || p.get('tab') || '').trim().toLowerCase();
          if (!tab) return;
          if (tab === 'news') {
            loadCompanyNewsTicker();
            setTimeout(() => {
              const wrap = document.getElementById('newsTickerWrap');
              if (!wrap) return;
              wrap.scrollIntoView({ behavior: 'smooth', block: 'start' });
              const prev = wrap.style.boxShadow;
              wrap.style.transition = 'box-shadow 0.35s ease';
              wrap.style.boxShadow = '0 0 0 3px var(--accent, #06b6d4), 0 0 24px rgba(6,182,212,0.35)';
              setTimeout(() => {
                wrap.style.boxShadow = prev;
                wrap.style.transition = '';
              }, 2500);
            }, 200);
            employeeStripDeepLinkParams();
            return;
          }
          if (tab === 'messages') {
            openMessagesModal();
            employeeStripDeepLinkParams();
            return;
          }
          if (document.getElementById('tab-' + tab)) {
            const nav = employeeFindNavTriggerForTab(tab);
            showTab(tab, nav || null);
          }
          employeeStripDeepLinkParams();
        } catch (e) { /* ignore */ }
      }

      // ── LOCATION ──────────────────────────────────────────────────────
      function requestLocation() {
        if (!navigator.geolocation) return;
        navigator.geolocation.watchPosition(
          pos => { userLocation = { lat: pos.coords.latitude, lng: pos.coords.longitude, accuracy: pos.coords.accuracy || 0 }; },
          () => { },
          { enableHighAccuracy: true, maximumAge: 30000 }
        );
      }

      // ── QR SCANNER (jsQR loaded on demand — not in <head>) ─────────────
      let _jsqrLoadPromise = null;
      function ensureJsQrLoaded() {
        if (typeof jsQR === 'function') return Promise.resolve();
        if (_jsqrLoadPromise) return _jsqrLoadPromise;
        _jsqrLoadPromise = new Promise((resolve, reject) => {
          const sc = document.createElement('script');
          sc.src = 'https://unpkg.com/jsqr@1.4.0/dist/jsQR.js';
          sc.async = true;
          sc.onload = () => resolve();
          sc.onerror = () => {
            _jsqrLoadPromise = null;
            reject(new Error('jsQR load failed'));
          };
          document.head.appendChild(sc);
        });
        return _jsqrLoadPromise;
      }

      async function startScanner() {
        try {
          await ensureJsQrLoaded();
        } catch (e) {
          showNotif(t('err_network_unreachable'), 'error');
          return;
        }
        document.getElementById('scanIdle').style.display = 'none';
        document.getElementById('scanActive').style.display = 'flex';
        try {
          scanStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment', width: 640, height: 640 } });
          const video = document.getElementById('video');
          video.srcObject = scanStream;
          await video.play();
          scanInterval = setInterval(scanFrame, 250);
        } catch (e) {
          const en = e && e.name;
          if (en === 'NotAllowedError' || en === 'PermissionDeniedError') showNotif(t('cam_permission_denied'), 'error');
          else if (en === 'NotFoundError' || en === 'DevicesNotFoundError') showNotif(t('cam_not_found'), 'error');
          else showNotif(t('cam_generic_err'), 'error');
          stopScanner();
        }
      }

      function scanFrame() {
        if (typeof jsQR !== 'function') return;
        const video = document.getElementById('video');
        if (video.readyState !== video.HAVE_ENOUGH_DATA) return;
        const canvas = document.getElementById('canvas');
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(video, 0, 0);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        const code = jsQR(imageData.data, imageData.width, imageData.height, { inversionAttempts: 'dontInvert' });
        if (code) {
          clearInterval(scanInterval);
          stopScanner();
          processQR(code.data);
        }
      }

      function stopScanner() {
        clearInterval(scanInterval);
        if (scanStream) { scanStream.getTracks().forEach(t => t.stop()); scanStream = null; }
        document.getElementById('scanActive').style.display = 'none';
        if (document.getElementById('selfieCapture').style.display === 'none' &&
          document.getElementById('confirmAttend').style.display === 'none') {
          document.getElementById('scanIdle').style.display = 'block';
        }
      }

      async function processQR(data) {
        let parsed;
        try { parsed = JSON.parse(data); } catch (e) { return showNotif('رمز QR غير صالح', 'error'); }
        if (!parsed.token) return showNotif('رمز QR غير مكتمل', 'error');

        showNotif('جارٍ التحقق من الرمز...', 'warning');
        const res = await api('POST', 'qr/validate', { token: parsed.token });
        if (!res.success) return showNotif(apiErrorMessage(res), 'error');

        scannedToken = parsed.token;
        showNotif('✓ رمز QR صالح', 'success');
        setTimeout(() => startSelfie(), 500);
      }

      // ── SELFIE ────────────────────────────────────────────────────────
      async function startSelfie() {
        document.getElementById('scanIdle').style.display = 'none';
        document.getElementById('selfieCapture').style.display = 'flex';
        try {
          selfieStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'user', width: 640, height: 640 } });
          const v = document.getElementById('selfieVideo');
          v.srcObject = selfieStream;
          await v.play();
        } catch (e) {
          const en = e && e.name;
          if (en === 'NotAllowedError' || en === 'PermissionDeniedError') showNotif(t('cam_permission_denied'), 'error');
          else if (en === 'NotFoundError' || en === 'DevicesNotFoundError') showNotif(t('cam_not_found'), 'error');
          else showNotif(t('cam_generic_err'), 'error');
          resetScan();
        }
      }

      function compressCanvasToJpegDataUrl(sourceCanvas, maxEdge, quality) {
        const w = sourceCanvas.width;
        const h = sourceCanvas.height;
        if (!w || !h) return sourceCanvas.toDataURL('image/jpeg', quality);
        const scale = Math.min(1, maxEdge / Math.max(w, h));
        if (scale >= 0.99) return sourceCanvas.toDataURL('image/jpeg', quality);
        const tw = Math.max(1, Math.round(w * scale));
        const th = Math.max(1, Math.round(h * scale));
        const out = document.createElement('canvas');
        out.width = tw;
        out.height = th;
        out.getContext('2d').drawImage(sourceCanvas, 0, 0, tw, th);
        return out.toDataURL('image/jpeg', quality);
      }

      async function captureSelfie() {
        const video = document.getElementById('selfieVideo');
        const canvas = document.getElementById('selfieCanvas');
        const ctx = canvas.getContext('2d');
        ctx.save();
        ctx.scale(-1, 1);
        ctx.drawImage(video, -canvas.width, 0, canvas.width, canvas.height);
        ctx.restore();
        selfieBase64 = compressCanvasToJpegDataUrl(canvas, 480, 0.52);

        if (selfieStream) { selfieStream.getTracks().forEach(t => t.stop()); selfieStream = null; }
        document.getElementById('selfieCapture').style.display = 'none';

        const preview = document.getElementById('confirmAttend');
        document.getElementById('selfiePreview').src = selfieBase64;
        if (userLocation) {
          document.getElementById('locInfo').textContent = `📍 موقعك: ${userLocation.lat.toFixed(4)}, ${userLocation.lng.toFixed(4)}`;
        } else {
          document.getElementById('locInfo').textContent = '⚠️ لم يتم تحديد الموقع';
        }
        preview.style.display = 'flex';

        // Force check work nature visibility
        const isExternal = (localStorage.getItem('emp_work_nature') || userWorkNature) === 'external';
        const fieldWrap = document.getElementById('externalFieldQR');
        if (isExternal && fieldWrap) {
          fieldWrap.style.setProperty('display', 'block', 'important');
        } else if (fieldWrap) {
          fieldWrap.style.display = 'none';
        }
      }

      async function submitAttendance(type) {
        const btns = document.querySelectorAll('#confirmAttend .btn-attend');

        const isExternal = (localStorage.getItem('emp_work_nature') || userWorkNature) === 'external';
        let visitDetails = null;
        if (isExternal) {
          visitDetails = document.getElementById('visitDetailsQR').value.trim();
          if (!visitDetails) return showNotif(t('visit_details_err'), 'error');
        }

        btns.forEach(b => { b.disabled = true; });
        const activeBtn = type === 'check_in' ? btns[0] : btns[1];
        activeBtn.innerHTML = '<div class="spinner"></div>';

        const res = await api('POST', 'attendance', {
          type,
          qr_token: scannedToken,
          selfie: selfieBase64,
          latitude: userLocation?.lat || 0,
          longitude: userLocation?.lng || 0,
          gps_accuracy: userLocation?.accuracy || 0,
          device_id: deviceId,
          visit_details: visitDetails
        });

        btns.forEach(b => { b.disabled = false; });
        if (type === 'check_in') activeBtn.innerHTML = '↑ دخول'; else activeBtn.innerHTML = '↓ خروج';

        if (res.success) {
          // Play sound
          playAttendanceSound();
          applyAccountPhotoIfBound(res);

          const branchName = res.data?.branch_name;
          const msg = branchName
            ? `تم تسجيل بصمتك بنجاح من فرع: ${branchName}`
            : 'تم تسجيل بصمتك بنجاح من موقعك الحالي';
          showNotif(msg, 'success');
          loadTodayLogs();
          setTimeout(resetScan, 2000);
        } else {
          showNotif(apiErrorMessage(res), 'error');
          btns.forEach(b => b.disabled = false);
        }
      }

      function resetScan() {
        scannedToken = null;
        selfieBase64 = null;
        document.getElementById('selfieCapture').style.display = 'none';
        document.getElementById('confirmAttend').style.display = 'none';
        document.getElementById('scanIdle').style.display = 'block';
        loadTodayLogs();
      }

      async function loadTodayLogs() {
        const res = await api('GET', 'attendance/summary');
        if (res.success && res.data.work_nature) {
          localStorage.setItem('emp_work_nature', res.data.work_nature);
          userWorkNature = res.data.work_nature;
        }
        try { syncLeaveMissionOptionVisibility(); } catch (e) { /* no-op */ }
        const logsData = (res.data && res.data.logs) ? res.data.logs : (Array.isArray(res.data) ? res.data : []);

        const containers = document.querySelectorAll('.today-logs-container');
        if (!res.success || !logsData.length) {
          containers.forEach(c => c.innerHTML = '<div class="today-log-empty">لم يتم تسجيل حضور اليوم بعد</div>');
          return;
        }

        const today = new Date().toISOString().substring(0, 10);
        const todayRecords = logsData.filter(r => r.timestamp.startsWith(today));

        if (todayRecords.length === 0) {
          containers.forEach(c => c.innerHTML = '<div class="today-log-empty">لم يتم تسجيل حضور اليوم بعد</div>');
          return;
        }

        const html = todayRecords.map(r => {
          const isIn = r.type === 'check_in';
          return `
        <div class="today-log-item ${isIn ? 'in' : 'out'}">
          <div class="today-log-type">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
              ${isIn ? '<path d="M12 19V5M5 12l7-7 7 7"/>' : '<path d="M12 5v14M5 12l7 7 7-7"/>'}
            </svg>
            ${isIn ? 'حضور' : 'انصراف'}
          </div>
          <div class="today-log-time">${r.timestamp.substring(11, 16)}</div>
        </div>
      `}).join('');

        containers.forEach(c => c.innerHTML = html);
      }

      // ── HISTORY ───────────────────────────────────────────────────────
      async function loadHistory() {
        const lang = document.documentElement.lang || 'ar';
        const res = await api('GET', 'attendance/summary');
        if (res.success && res.data.work_nature) {
          localStorage.setItem('emp_work_nature', res.data.work_nature);
          userWorkNature = res.data.work_nature;
        }
        const logsData = (res.data && res.data.logs) ? res.data.logs : (Array.isArray(res.data) ? res.data : []);

        const list = document.getElementById('historyList');
        if (!res.success || !logsData.length) {
          list.innerHTML = '<p style="text-align:center;color:var(--text-muted);padding:40px;" data-i18n="no_history">لا يوجد سجل حضور</p>';
          return;
        }
        list.innerHTML = logsData.map(r => {
          const isQR = r.qr_token && r.qr_token !== 'DIRECT';
          const typeLabel = r.type === 'check_in' ? t('btn_in').replace('↑ ', '') : t('btn_out').replace('↓ ', '');
          const methodBadge = isQR ? '📷 QR' : '👤 ' + (lang === 'ar' ? 'مباشر' : 'Direct');

          // Calculate age for delete button (60 seconds rule)
          const recordTime = new Date(r.timestamp.replace(' ', 'T')).getTime();
          const now = new Date().getTime();
          const ageSeconds = (now - recordTime) / 1000;
          const canDelete = ageSeconds < 60;
          
          // Can edit note only today
          const recordDate = r.timestamp.substring(0, 10);
          const t_now = new Date();
          const todayDate = t_now.getFullYear() + '-' + String(t_now.getMonth() + 1).padStart(2, '0') + '-' + String(t_now.getDate()).padStart(2, '0');
          const canEditNote = recordDate === todayDate;

          const noteHtml = r.visit_details ? `<div class="hi-note" style="margin-top:6px; font-size:12px; color:var(--text-muted); background:rgba(255,255,255,0.03); padding:8px; border-radius:8px; border:1px solid var(--border); display:flex; align-items:flex-start; gap:8px;">
            <div style="flex:1;">${r.visit_details}</div>
            ${canEditNote ? `<button class="btn-edit-note" onclick="openEditNoteModal(${r.id}, \`${r.visit_details.replace(/`/g, '\\`').replace(/\n/g, '\\n')}\`)" style="background:transparent; border:none; color:var(--accent); cursor:pointer; font-size:14px; padding:2px;">✎</button>` : ''}
          </div>` : (canEditNote ? `<div style="margin-top:6px; text-align:right;"><button onclick="openEditNoteModal(${r.id}, '')" style="background:transparent; border:none; color:var(--text-muted); cursor:pointer; font-size:11px; text-decoration:underline;">+ إضافة ملاحظة</button></div>` : '');

          return `
    <div class="history-item ${r.location_status === 'alert' ? 'alert' : ''}" style="flex-direction:column; align-items:stretch;">
      <div style="display:flex; justify-content:space-between; align-items:center; width:100%;">
        <div class="hi-left">
          <div class="hi-icon ${r.type === 'check_in' ? 'in' : 'out'}">${r.type === 'check_in' ? '↑' : '↓'}</div>
          <div>
            <div class="hi-type">${typeLabel} <span style="font-size:11px;color:var(--text-muted);">${methodBadge}</span></div>
            <div class="hi-time">${r.timestamp.replace('T', ' ').substring(0, 16)}</div>
          </div>
        </div>
        <div class="hi-right" style="text-align:right;">
          <div class="hi-dist" style="margin-bottom:4px">${r.distance_meters != null ? Math.round(r.distance_meters) + 'م' : '—'}</div>
          <div style="display:flex; align-items:center; gap:8px; justify-content:flex-end;">
            <span class="badge ${r.location_status === 'alert' ? 'badge-alert' : 'badge-ok'}">${r.location_status === 'alert' ? (lang === 'ar' ? '⚠ تحذير' : '⚠ Alert') : (lang === 'ar' ? '✓ موافق' : '✓ OK')}</span>
            ${canDelete ? `<button class="btn-delete-log" onclick="deleteHistoryRecord(${r.id})" title="${t('delete')}">🗑</button>` : ''}
          </div>
        </div>
      </div>
      ${noteHtml}
    </div>
    `;
        }).join('');
      }

      function openEditNoteModal(id, currentNote) {
        document.getElementById('editNoteId').value = id;
        document.getElementById('editNoteText').value = currentNote;
        openModal('noteEditModal');
      }

      async function saveEmployeeNote() {
        const id = document.getElementById('editNoteId').value;
        const note = document.getElementById('editNoteText').value.trim();
        if (!id) return;
        
        const res = await api('PUT', `attendance/employee-note/${id}`, { note });
        if (res.success) {
          showNotif(t('note_updated'), 'success');
          closeModal('noteEditModal');
          loadHistory();
        } else {
          showNotif(apiErrorMessage(res), 'error');
        }
      }

      async function deleteHistoryRecord(id) {
        if (!confirm(t('confirm_delete'))) return;
        const res = await api('DELETE', `attendance/${id}`);
        if (res.success) {
          showNotif(t('record_deleted'), 'success');
          loadHistory();
        } else {
          showNotif(apiErrorMessage(res), 'error');
        }
      }

      // ── LEAVE ─────────────────────────────────────────────────────────
      function toHHMM(val) {
        if (!val) return '';
        const v = String(val).trim();
        if (/^\d{2}:\d{2}$/.test(v)) return v;
        if (/^\d{2}:\d{2}:\d{2}$/.test(v)) return v.slice(0, 5);
        const m = v.match(/^(\d{1,2}):(\d{2})/);
        return m ? `${String(m[1]).padStart(2, '0')}:${m[2]}` : '';
      }

      function calcLeaveCalendarDays(from, to) {
        if (!from || !to) return null;
        const d1 = new Date(from + 'T12:00:00');
        const d2 = new Date(to + 'T12:00:00');
        if (isNaN(d1.getTime()) || isNaN(d2.getTime())) return null;
        if (d2 < d1) return null;
        return Math.round((d2 - d1) / 86400000) + 1;
      }

      function calcPermissionDurationMinutes(pf, pt) {
        const a = toHHMM(pf);
        const b = toHHMM(pt);
        if (!a || !b) return null;
        const refDate = '2000-01-01';
        const t1 = new Date(`${refDate}T${a.length === 5 ? a + ':00' : a}`);
        const t2 = new Date(`${refDate}T${b.length === 5 ? b + ':00' : b}`);
        if (isNaN(t1.getTime()) || isNaN(t2.getTime()) || !(t2 > t1)) return null;
        return Math.round((t2 - t1) / 60000);
      }

      function formatDurationMinutes(totalMinutes) {
        const mins = Math.max(0, Math.round(Number(totalMinutes) || 0));
        if (mins <= 0) return '—';
        const h = Math.floor(mins / 60);
        const m = mins % 60;
        const isAr = (document.documentElement.lang || 'ar').toLowerCase().startsWith('ar');
        if (isAr) return `${h}س ${String(m).padStart(2, '0')}د`;
        return `${h}h ${String(m).padStart(2, '0')}m`;
      }

      let _leavePreviewListenersBound = false;

      function wireLeavePreviewListeners() {
        if (_leavePreviewListenersBound) return;
        _leavePreviewListenersBound = true;
        ['leaveFrom', 'leaveTo', 'leavePermFrom', 'leavePermTo'].forEach((id) => {
          const el = document.getElementById(id);
          if (!el) return;
          el.addEventListener('input', updateLeaveRequestPreview);
          el.addEventListener('change', updateLeaveRequestPreview);
        });
      }

      function updateLeaveRequestPreview() {
        const kind = document.getElementById('leaveRequestKind')?.value || 'leave';
        const daysEl = document.getElementById('leaveDaysPreview');
        const hoursEl = document.getElementById('leaveHoursPreview');
        const permBlock = kind === 'permission' || kind === 'mission';

        if (daysEl) {
          if (permBlock) {
            daysEl.style.display = 'none';
            daysEl.textContent = '';
            daysEl.classList.remove('is-warning');
          } else {
            daysEl.style.display = '';
            const from = document.getElementById('leaveFrom')?.value || '';
            const to = document.getElementById('leaveTo')?.value || '';
            if (!from || !to) {
              daysEl.textContent = t('leave_preview_pending');
              daysEl.classList.remove('is-warning');
            } else if (new Date(to + 'T12:00:00') < new Date(from + 'T12:00:00')) {
              daysEl.textContent = t('leave_dates_invalid');
              daysEl.classList.add('is-warning');
            } else {
              const n = calcLeaveCalendarDays(from, to);
              if (n == null) {
                daysEl.textContent = t('leave_preview_pending');
                daysEl.classList.remove('is-warning');
              } else {
                daysEl.textContent = t('leave_days_preview', { n: String(n) });
                daysEl.classList.remove('is-warning');
              }
            }
          }
        }

        if (hoursEl) {
          if (!permBlock) {
            hoursEl.style.display = 'none';
            hoursEl.textContent = '';
            hoursEl.classList.remove('is-warning');
          } else {
            hoursEl.style.display = '';
            const pf = document.getElementById('leavePermFrom')?.value || '';
            const pt = document.getElementById('leavePermTo')?.value || '';
            if (!pf || !pt) {
              hoursEl.textContent = t('leave_preview_pending');
              hoursEl.classList.remove('is-warning');
            } else {
              const mins = calcPermissionDurationMinutes(pf, pt);
              if (mins == null) {
                hoursEl.textContent = t('permission_time_invalid');
                hoursEl.classList.add('is-warning');
              } else {
                hoursEl.textContent = t('leave_hours_preview', { dur: formatDurationMinutes(mins) });
                hoursEl.classList.remove('is-warning');
              }
            }
          }
        }
      }

      try { wireLeavePreviewListeners(); } catch (e) { /* DOM not ready */ }

      function syncLeaveMissionOptionVisibility() {
        const opt = document.getElementById('leaveKindMissionOption');
        const sel = document.getElementById('leaveRequestKind');
        if (!opt || !sel) return;
        const isExternal = (localStorage.getItem('emp_work_nature') || userWorkNature) === 'external';
        opt.hidden = isExternal;
        opt.style.display = isExternal ? 'none' : '';
        if (isExternal && sel.value === 'mission') {
          sel.value = 'leave';
          updateEmployeeLeaveFormMode();
        }
      }

      function openEmployeeLeaveModal() {
        wireLeavePreviewListeners();
        syncLeaveMissionOptionVisibility();
        const rk = document.getElementById('leaveRequestKind');
        if (rk) rk.value = 'leave';
        updateEmployeeLeaveFormMode();
        updateLeaveRequestPreview();
        openModal('leaveModal');
      }

      function updateEmployeeLeaveFormMode() {
        syncLeaveMissionOptionVisibility();
        const kind = document.getElementById('leaveRequestKind')?.value || 'leave';
        const blockL = document.getElementById('leaveFieldsLeave');
        const blockP = document.getElementById('leaveFieldsPermission');
        const title = document.getElementById('leaveModalTitle');
        const reasonLab = document.getElementById('leaveReasonLabel');
        const reasonTa = document.getElementById('leaveReason');
        const hintEl = document.getElementById('leavePermTimesHint');
        const permBlock = kind === 'permission' || kind === 'mission';
        if (permBlock) {
          if (blockL) blockL.style.display = 'none';
          if (blockP) blockP.style.display = '';
          if (title) {
            if (kind === 'mission') title.textContent = t('leave_title_mission');
            else title.textContent = t('leave_title_permission');
          }
          if (reasonLab) {
            reasonLab.textContent = kind === 'mission' ? t('leave_reason_mission') : t('leave_reason');
          }
          if (reasonTa) {
            reasonTa.placeholder = kind === 'mission' ? t('leave_reason_mission_placeholder') : t('leave_reason_placeholder');
          }
          if (hintEl) {
            hintEl.textContent = kind === 'mission' ? t('permission_times_hint_mission') : t('permission_times_hint');
          }
          const pd = document.getElementById('leavePermDate');
          const today = new Date().toISOString().slice(0, 10);
          if (pd && !pd.value) pd.value = today;
        } else {
          if (blockL) blockL.style.display = '';
          if (blockP) blockP.style.display = 'none';
          if (title) title.textContent = t('leave_title');
          if (reasonLab) reasonLab.textContent = t('leave_reason');
          if (reasonTa) reasonTa.placeholder = t('leave_reason_placeholder');
        }
        updateLeaveRequestPreview();
      }

      async function submitLeave() {
        const submitBtn = document.getElementById('leaveSubmitBtn');
        if (submitBtn && submitBtn.disabled) return;
        if (submitBtn) submitBtn.disabled = true;
        const kind = document.getElementById('leaveRequestKind')?.value || 'leave';
        const reason = document.getElementById('leaveReason').value.trim();
        let body;
        if (kind === 'permission' || kind === 'mission') {
          const d = document.getElementById('leavePermDate').value;
          const pf = toHHMM(document.getElementById('leavePermFrom').value);
          const pt = toHHMM(document.getElementById('leavePermTo').value);
          if (!d || !pf || !pt || !reason) {
            if (submitBtn) submitBtn.disabled = false;
            return showNotif(t('error_fields'), 'error');
          }
          const t1 = new Date(`${d}T${pf.length === 5 ? pf + ':00' : pf}`);
          const t2 = new Date(`${d}T${pt.length === 5 ? pt + ':00' : pt}`);
          if (!(t2 > t1)) {
            if (submitBtn) submitBtn.disabled = false;
            return showNotif(t('permission_time_invalid'), 'error');
          }
          body = {
            request_kind: 'permission',
            start_date: d,
            end_date: d,
            permission_from: pf,
            permission_to: pt,
            reason,
            leave_type: 'permission'
          };
          if (kind === 'mission') {
            body.permission_kind = 'mission';
          }
        } else {
          body = {
            start_date: document.getElementById('leaveFrom').value,
            end_date: document.getElementById('leaveTo').value,
            leave_type: document.getElementById('leaveType').value,
            reason
          };
          if (!body.start_date || !body.end_date || !body.reason) {
            if (submitBtn) submitBtn.disabled = false;
            return showNotif(t('error_fields'), 'error');
          }
        }
        const res = await api('POST', 'leave', body);
        if (res.success) {
          showNotif('✓ تم إرسال الطلب', 'success');
          document.getElementById('leaveFrom').value = '';
          document.getElementById('leaveTo').value = '';
          document.getElementById('leaveReason').value = '';
          const pd = document.getElementById('leavePermDate');
          if (pd) pd.value = '';
          document.getElementById('leavePermFrom').value = '';
          document.getElementById('leavePermTo').value = '';
          updateLeaveRequestPreview();
          closeModal('leaveModal');
          loadLeaveHistory();
        } else showNotif(apiErrorMessage(res), 'error');
        if (submitBtn) submitBtn.disabled = false;
      }

      function leaveRowIsPermission(r) {
        if (!r) return false;
        const lt = String(r.leave_type || '').toLowerCase();
        if (lt === 'permission') return true;
        const pf = String(r.permission_from || '').trim();
        const pt = String(r.permission_to || '').trim();
        return pf.length > 0 && pt.length > 0;
      }

      function leaveTypeBadgeHtml(r) {
        if (leaveRowIsPermission(r)) {
          const extra = (r.permission_from && r.permission_to)
            ? (' · ' + String(r.permission_from) + '–' + String(r.permission_to))
            : '';
          const isMission = String(r.permission_kind || '').toLowerCase() === 'mission';
          const label = isMission ? t('leave_kind_mission') : t('permission');
          return label + extra;
        }
        const lt = String(r.leave_type || 'annual').toLowerCase();
        return t(lt) || lt;
      }

      async function loadLeaveHistory() {
        const res = await api('GET', 'leave');
        const list = document.getElementById('leaveList');
        if (!res.success || !res.data.length) {
          list.innerHTML = '<p style="text-align:center;color:var(--text-muted);padding:20px;">لا يوجد طلبات إجازة</p>';
          return;
        }
        list.innerHTML = res.data.map(r => {
          const typeBadge = leaveTypeBadgeHtml(r);
          const dateLine = leaveRowIsPermission(r) && r.start_date === r.end_date
            ? `${r.start_date}`
            : `${r.start_date} ← ${r.end_date}`;
          return `
    <div class="leave-item">
      <div style="display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:8px;">
        <div class="leave-dates" style="margin:0;">${dateLine}</div>
        <div class="badge" style="background:var(--accentG); color:var(--accent); border:1px solid var(--border);">${typeBadge}</div>
      </div>
      <div class="leave-reason">${r.reason}</div>
      <div style="display:flex;align-items:center;justify-content:space-between;">
        <span class="badge badge-${r.status}">${{ pending: '⏳ قيد المراجعة', approved: '✓ موافق عليها', rejected: '✗ مرفوضة' }[r.status]}</span>
        <span style="font-size:11px;color:var(--text-muted)">${r.created_at.substring(0, 10)}</span>
      </div>
      ${r.admin_note ? `<div style="margin-top:8px;font-size:12px;color:var(--text-muted);background:var(--surface2);padding:8px;border-radius:8px;">ملاحظة: ${r.admin_note}</div>` : ''}
    </div>
  `;
        }).join('');
      }

      // ── TABS ──────────────────────────────────────────────────────────
      function showTab(name, el) {
        if (name === 'contacts') {
          window.location.href = 'https://tsbd.com.au/hr/contacts.html';
          return;
        }
        employeeActiveTab = name;
        ['scan', 'direct', 'history', 'team', 'leave', 'contacts', 'profile'].forEach(t => {
          const el2 = document.getElementById('tab-' + t);
          if (el2) el2.style.display = t === name ? 'block' : 'none';
        });
        document.querySelectorAll('.nav-btn').forEach(b => b.classList.remove('active'));
        if (el) el.classList.add('active');
        if (name === 'history') loadHistory();
        if (name === 'team') loadTeamAttendance();
        if (name === 'leave') loadLeaveHistory();
        if (name === 'contacts') loadContacts(false);
        if (name === 'scan' || name === 'direct') loadTodayLogs();
        if (name !== 'scan') stopScanner();
        if (name !== 'direct') stopDirectSelfie();
        applyEmpQuickLinksVisibility();
      }

      // ── TEAM (Supervisor Monitoring) ─────────────────────────────
      let _teamMemberIdsCache = [];

      function teamEsc(s) {
        return String(s ?? '')
          .replace(/&/g, '&amp;')
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;')
          .replace(/'/g, '&#39;');
      }

      function teamEnsureDateInputs() {
        const fromEl = document.getElementById('teamFrom');
        const toEl = document.getElementById('teamTo');
        const today = new Date();
        const to = today.toISOString().slice(0, 10);
        const fromD = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
        const from = fromD.toISOString().slice(0, 10);
        if (fromEl && !fromEl.value) fromEl.value = from;
        if (toEl && !toEl.value) toEl.value = to;
        return { from: fromEl?.value || from, to: toEl?.value || to };
      }

      async function loadTeamManagerMeta() {
        const btn = document.getElementById('btnTeamMonitor');
        const meta = document.getElementById('teamMeta');
        if (!btn || !authToken) return;

        btn.style.display = 'none';
        if (meta) meta.textContent = '';

        const res = await api('GET', 'team/manager-meta');
        if (!res || !res.success || !res.data) {
          return;
        }

        _teamMemberIdsCache = Array.isArray(res.data.team_member_ids) ? res.data.team_member_ids : [];
        const hasTeam = !!res.data.has_team && _teamMemberIdsCache.length > 0;
        if (hasTeam) {
          btn.style.display = 'inline-flex';
          if (meta) meta.textContent = `أعضاء الفريق: ${_teamMemberIdsCache.length}`;
        }
      }

      async function loadTeamAttendance() {
        const list = document.getElementById('teamAttendanceList');
        if (!list) return;

        teamEnsureDateInputs();
        const from = document.getElementById('teamFrom')?.value;
        const to = document.getElementById('teamTo')?.value;

        list.innerHTML = '<p style="text-align:center;color:var(--text-muted);padding:40px;">جارٍ التحميل...</p>';

        const url = `${API}?route=${encodeURIComponent('team/attendance')}&from=${encodeURIComponent(from || '')}&to=${encodeURIComponent(to || '')}`;
        let res;
        const ctrl = new AbortController();
        const timeoutId = setTimeout(() => ctrl.abort(), 20000);
        try {
          const r = await fetch(url, {
            method: 'GET',
            headers: {
              'Authorization': 'Bearer ' + (authToken || ''),
              'X-Device-ID': deviceId,
              'Accept': 'application/json'
            },
            signal: ctrl.signal
          });
          const txt = await r.text();
          let parsed = null;
          try { parsed = JSON.parse(txt); } catch (e) { parsed = null; }
          res = parsed && typeof parsed === 'object'
            ? parsed
            : { success: false, message: t('err_gateway_html') || 'Invalid server response' };
          if (typeof res.success !== 'boolean') res.success = r.ok;
          if (!res.success && !res.message) res.message = fallbackHttpMessage(r.status);
        } catch (e) {
          const isAbort = e && e.name === 'AbortError';
          res = { success: false, message: isAbort ? 'التحميل استغرق وقتا طويلا. حاول مرة أخرى.' : (t('err_network_unreachable') || 'Network error') };
        } finally {
          clearTimeout(timeoutId);
        }
        if (!res || !res.success || !res.data) {
          list.innerHTML = `<p style="text-align:center;color:var(--danger);padding:40px;">${teamEsc(res?.message || t('err_unknown'))}</p>`;
          return;
        }

        const logsData = Array.isArray(res.data.logs) ? res.data.logs : [];
        _teamMemberIdsCache = Array.isArray(res.data.team_member_ids) ? res.data.team_member_ids : _teamMemberIdsCache;

        if (!logsData.length) {
          list.innerHTML = '<p style="text-align:center;color:var(--text-muted);padding:40px;">لا توجد سجلات ضمن الفترة.</p>';
          const meta = document.getElementById('teamMeta');
          if (meta) meta.textContent = `أعضاء الفريق: ${_teamMemberIdsCache.length || 0}`;
          return;
        }

        list.innerHTML = logsData.map(r => {
          const typeLabel = r.type === 'check_in'
            ? t('btn_in').replace('↑ ', '')
            : t('btn_out').replace('↓ ', '');

          const isQR = r.qr_token && r.qr_token !== 'DIRECT';
          const methodBadge = isQR ? '📷 QR' : '👤 ' + (lang === 'ar' ? 'مباشر' : 'Direct');

          const badgeBg = r.location_status === 'alert' ? 'rgba(239, 68, 68, 0.14)' : 'rgba(34, 197, 94, 0.14)';
          const badgeColor = r.location_status === 'alert' ? 'var(--danger)' : 'var(--accent)';
          const badgeText = r.location_status === 'alert'
            ? (lang === 'ar' ? '⚠ تحذير' : '⚠ Alert')
            : (lang === 'ar' ? '✓ موافق' : '✓ OK');

          const noteRaw = r.visit_details || r.notes || '';
          const noteText = noteRaw ? teamEsc(noteRaw).replace(/\n/g, '<br>') : '';

          return `
            <div class="history-item ${r.location_status === 'alert' ? 'alert' : ''}" style="flex-direction:column; align-items:stretch;">
              <div style="display:flex; justify-content:space-between; align-items:center; width:100%;">
                <div class="hi-left">
                  <div class="hi-icon ${r.type === 'check_in' ? 'in' : 'out'}">${r.type === 'check_in' ? '↑' : '↓'}</div>
                  <div>
                    <div class="hi-type">
                      ${typeLabel}
                      <span style="font-size:11px;color:var(--text-muted);">${methodBadge}</span>
                    </div>
                    <div class="hi-time">${teamEsc(r.timestamp || '').replace('T', ' ').substring(0, 16)}</div>
                    <div style="font-size:11px;color:var(--text-muted);margin-top:2px;">
                      ${teamEsc(r.name || '—')}${r.employee_code ? ` (${teamEsc(r.employee_code)})` : ''}
                    </div>
                  </div>
                </div>
                <div class="hi-right" style="text-align:right;">
                  <div class="hi-dist" style="margin-bottom:4px">
                    ${r.distance_meters != null ? Math.round(r.distance_meters) + 'م' : '—'}
                  </div>
                  <div style="display:flex; align-items:center; gap:8px; justify-content:flex-end;">
                    <span class="badge" style="background:${badgeBg};color:${badgeColor};border:1px solid var(--border);font-weight:700;">
                      ${teamEsc(badgeText)}
                    </span>
                  </div>
                </div>
              </div>
              ${noteText ? `
                <div class="hi-note" style="margin-top:6px; font-size:12px; color:var(--text-muted); background:rgba(255,255,255,0.03); padding:8px; border-radius:8px; border:1px solid var(--border); display:flex; align-items:flex-start; gap:8px;">
                  <div style="flex:1;">${noteText}</div>
                </div>
              ` : ''}
            </div>
          `;
        }).join('');
      }

      // ── CONTACTS ───────────────────────────────────────────────────────
      let _contactsUiBound = false;
      let _contactsLoading = false;
      let _contactsLoadedAt = 0;
      let _contactsAll = [];
      let _contactsLastQuery = '';

      function contactsInitUi() {
        if (_contactsUiBound) return;
        const inp = document.getElementById('contactsSearch');
        if (inp) {
          inp.addEventListener('input', function () {
            _contactsLastQuery = inp.value || '';
            contactsApplyFilter(_contactsLastQuery);
          });
        }
        _contactsUiBound = true;
      }

      function contactsEsc(s) {
        return String(s ?? '')
          .replace(/&/g, '&amp;')
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;');
      }

      function contactsDigitsOnly(v) {
        return String(v ?? '').replace(/[^\d+]/g, '').trim();
      }

      function contactsWaNumber(phone) {
        const d = String(phone ?? '').replace(/[^\d]/g, '');
        if (!d) return '';
        // Common Egypt heuristic: 01xxxxxxxxx → 20 + 1xxxxxxxxx
        if (d.startsWith('01') && d.length === 11) return '20' + d.slice(1);
        // Strip leading 00 if present
        if (d.startsWith('00') && d.length > 4) return d.slice(2);
        return d;
      }

      function contactsUpdateMeta(shown, total) {
        const m = document.getElementById('contactsMeta');
        if (!m) return;
        m.textContent = t('contacts_meta', { shown: String(shown), total: String(total) });
      }

      function contactsApplyFilter(query) {
        const list = document.getElementById('contactsList');
        if (!list) return;
        const total = Array.isArray(_contactsAll) ? _contactsAll.length : 0;

        const q = String(query ?? '').trim().toLowerCase();
        if (!q) {
          renderContacts(_contactsAll, total);
          return;
        }

        const filtered = _contactsAll.filter((e) => {
          const name = String(e?.name ?? '').toLowerCase();
          const phone = String(e?.phone ?? '').toLowerCase();
          const branch = String(e?.branch_name ?? '').toLowerCase();
          const dept = String(e?.department_name ?? '').toLowerCase();
          return name.includes(q) || phone.includes(q) || branch.includes(q) || dept.includes(q);
        });
        renderContacts(filtered, total);
      }

      function renderContacts(rows, totalCount) {
        const list = document.getElementById('contactsList');
        if (!list) return;
        const data = Array.isArray(rows) ? rows : [];

        contactsUpdateMeta(data.length, totalCount || data.length);

        if (!data.length) {
          list.innerHTML = `<div class="contact-empty">${contactsEsc(t('contacts_empty'))}</div>`;
          return;
        }

        list.innerHTML = data.map((e) => {
          const name = contactsEsc(e?.name || '');
          const branch = contactsEsc(e?.branch_name || '');
          const dept = contactsEsc(e?.department_name || '');
          const emailRaw = String(e?.email ?? '').trim();
          const phoneRaw = String(e?.phone ?? '').trim();

          const email = contactsEsc(emailRaw);
          const phone = contactsEsc(phoneRaw);

          const photoRaw = String(e?.photo_url ?? '').trim();
          const photo = photoRaw ? hrproMediaUrl(photoRaw) : '';
          const photoCss = photo ? photo.replace(/'/g, '%27').replace(/\)/g, '%29') : '';
          const avatarStyle = photoCss
            ? `style="background-image:url('${photoCss}');"`
            : `style="background-image:url('${DEFAULT_AVATAR}');"`;

          const mailHref = emailRaw ? `mailto:${encodeURIComponent(emailRaw)}` : '';
          const telHref = phoneRaw ? `tel:${encodeURIComponent(contactsDigitsOnly(phoneRaw) || phoneRaw)}` : '';
          const waNum = phoneRaw ? contactsWaNumber(phoneRaw) : '';
          const waHref = waNum ? `https://wa.me/${encodeURIComponent(waNum)}` : '';

          const mailBtn = mailHref
            ? `<a class="contact-link" href="${mailHref}" title="${contactsEsc(emailRaw)}" target="_blank" rel="noopener">✉️ ${email}</a>`
            : '';
          const telBtn = telHref
            ? `<a class="contact-link secondary" href="${telHref}" title="${contactsEsc(phoneRaw)}">📞 <span class="phone-num">${phone}</span></a>`
            : '';
          const waBtn = waHref
            ? `<a class="contact-link secondary" href="${waHref}" title="WhatsApp" target="_blank" rel="noopener">💬 WhatsApp</a>`
            : '';

          const avatarText = photoCss ? '' : (name ? name[0] : '');
          return `
            <div class="contact-item">
              <div class="contact-avatar" ${avatarStyle}>${avatarText}</div>
              <div class="contact-main">
                <div class="contact-name">${name}</div>
                <div class="contact-sub">
                  ${branch ? `<span>🏢 ${branch}</span>` : ''}
                  ${dept ? `<span>🧩 ${dept}</span>` : ''}
                  ${phoneRaw ? `<span>📱 <span class="phone-num">${phone}</span></span>` : ''}
                  ${emailRaw ? `<span>📧 ${email}</span>` : ''}
                </div>
              </div>
              <div class="contact-actions">
                ${mailBtn}
                ${telBtn}
                ${waBtn}
              </div>
            </div>
          `;
        }).join('');
      }

      async function loadContacts(force) {
        contactsInitUi();
        const list = document.getElementById('contactsList');
        if (!list) return;
        if (!authToken) return;

        const now = Date.now();
        if (!force && _contactsLoadedAt && (now - _contactsLoadedAt) < 5 * 60 * 1000 && Array.isArray(_contactsAll) && _contactsAll.length) {
          contactsApplyFilter(_contactsLastQuery);
          return;
        }

        if (_contactsLoading) return;
        _contactsLoading = true;
        list.innerHTML = `<div class="contact-empty">${contactsEsc(t('contacts_loading'))}</div>`;
        contactsUpdateMeta(0, 0);

        const res = await api('GET', 'employee/contacts');
        _contactsLoading = false;

        if (!res.success) {
          list.innerHTML = `<div class="contact-empty" style="color:var(--danger);border-style:solid;">${contactsEsc(apiErrorMessage(res))}</div>`;
          return;
        }

        const rows = Array.isArray(res.data) ? res.data : [];
        // Safety: ensure inactive never appear even if server misconfig
        const activeOnly = rows.filter(r => String(r?.is_active ?? '1') === '1' || r?.is_active === 1 || r?.is_active === true);
        const lang = document.documentElement.lang || 'ar';
        const loc = lang === 'en' ? 'en' : 'ar';
        activeOnly.sort((a, b) => String(a?.name ?? '').localeCompare(String(b?.name ?? ''), loc, { sensitivity: 'base' }));

        _contactsAll = activeOnly;
        _contactsLoadedAt = Date.now();

        contactsApplyFilter(_contactsLastQuery);
      }

      // ── DIRECT ATTENDANCE ──────────────────────────────────────────────
      let directStream = null;
      let directSelfieBase64 = null;

      async function startDirectSelfie() {
        document.getElementById('directIdle').style.display = 'none';
        document.getElementById('directSelfieCapture').style.display = 'flex';
        try {
          directStream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'user', width: 640, height: 640 } });
          const v = document.getElementById('directSelfieVideo');
          v.srcObject = directStream;
          await v.play();
        } catch (e) {
          const en = e && e.name;
          if (en === 'NotAllowedError' || en === 'PermissionDeniedError') showNotif(t('cam_permission_denied'), 'error');
          else if (en === 'NotFoundError' || en === 'DevicesNotFoundError') showNotif(t('cam_not_found'), 'error');
          else showNotif(t('cam_generic_err'), 'error');
          resetDirect();
        }
      }

      function stopDirectSelfie() {
        if (directStream) { directStream.getTracks().forEach(t => t.stop()); directStream = null; }
        const cap = document.getElementById('directSelfieCapture');
        const idle = document.getElementById('directIdle');
        if (cap) cap.style.display = 'none';
        if (idle) idle.style.display = 'block';
      }

      function captureDirectSelfie() {
        const video = document.getElementById('directSelfieVideo');
        const canvas = document.getElementById('directSelfieCanvas');
        const ctx = canvas.getContext('2d');
        ctx.save(); ctx.scale(-1, 1); ctx.drawImage(video, -canvas.width, 0, canvas.width, canvas.height); ctx.restore();
        directSelfieBase64 = compressCanvasToJpegDataUrl(canvas, 480, 0.52);
        if (directStream) { directStream.getTracks().forEach(t => t.stop()); directStream = null; }
        document.getElementById('directSelfieCapture').style.display = 'none';
        document.getElementById('directSelfiePreview').src = directSelfieBase64;
        if (userLocation) {
          document.getElementById('directLocInfo').textContent = `📍 موقعك: ${userLocation.lat.toFixed(4)}, ${userLocation.lng.toFixed(4)}`;
        } else {
          document.getElementById('directLocInfo').textContent = '⚠️ لم يتم تحديد الموقع';
        }
        document.getElementById('directConfirm').style.display = 'flex';

        // Force check work nature visibility
        const isExternal = (localStorage.getItem('emp_work_nature') || userWorkNature) === 'external';
        const fieldWrap = document.getElementById('externalFieldDirect');
        if (isExternal && fieldWrap) {
          fieldWrap.style.setProperty('display', 'block', 'important');
        } else if (fieldWrap) {
          fieldWrap.style.display = 'none';
        }
      }

      async function submitDirectAttendance(type) {
        const btns = document.querySelectorAll('#directConfirm .btn-attend');

        const isExternal = (localStorage.getItem('emp_work_nature') || userWorkNature) === 'external';
        let visitDetails = null;
        if (isExternal) {
          visitDetails = document.getElementById('visitDetailsDirect').value.trim();
          if (!visitDetails) return showNotif(t('visit_details_err'), 'error');
        }

        btns.forEach(b => b.disabled = true);
        const res = await api('POST', 'attendance/direct', {
          type,
          selfie: directSelfieBase64,
          latitude: userLocation?.lat || 0,
          longitude: userLocation?.lng || 0,
          gps_accuracy: userLocation?.accuracy || 0,
          device_id: deviceId,
          visit_details: visitDetails
        });
        btns.forEach(b => b.disabled = false);
        if (res.success) {
          // Play sound
          playAttendanceSound();
          applyAccountPhotoIfBound(res);

          const branchName = res.data?.branch_name;
          const msg = branchName
            ? `تم تسجيل بصمتك بنجاح من فرع: ${branchName}`
            : 'تم تسجيل بصمتك بنجاح من موقعك الحالي';
          showNotif(msg, 'success');
          loadTodayLogs();
          setTimeout(resetDirect, 2000);
        } else {
          showNotif(apiErrorMessage(res), 'error');
        }
      }

      function resetDirect() {
        directSelfieBase64 = null;
        document.getElementById('directSelfieCapture').style.display = 'none';
        document.getElementById('directConfirm').style.display = 'none';
        document.getElementById('directIdle').style.display = 'block';
      }


      // ── MODAL ─────────────────────────────────────────────────────────
      function openModal(id) { document.getElementById(id).classList.add('open'); }
      function closeModal(id) { document.getElementById(id).classList.remove('open'); }
      document.querySelectorAll('.modal-backdrop').forEach(bd => {
        bd.addEventListener('click', e => { if (e.target === bd) closeModal(bd.id); });
      });

      // ── MESSAGES (same flow as admin notifications: read / archive / purge) ──
      let empMsgItems = [];

      function isEmpMsgArchived(m) {
        if (!m) return false;
        return parseInt(m.is_deleted, 10) === 1 || m.is_deleted === true;
      }

      function updateEmpMsgBadge() {
        const n = empMsgItems.filter((m) => m && !isEmpMsgArchived(m) && parseInt(m.is_read, 10) === 0).length;
        const badge = document.getElementById('msgBadge');
        if (!badge) return;
        if (n > 0) {
          badge.style.display = 'flex';
          badge.textContent = n > 9 ? '9+' : String(n);
          badge.style.alignItems = 'center';
          badge.style.justifyContent = 'center';
          badge.style.width = 'auto';
          badge.style.minWidth = '16px';
          badge.style.height = '16px';
          badge.style.fontSize = '10px';
          badge.style.fontWeight = '700';
          badge.style.padding = '0 4px';
          badge.style.borderRadius = '8px';
        } else {
          badge.style.display = 'none';
        }
      }

      function updateEmpMsgUnreadLabel() {
        const el = document.getElementById('empMsgUnreadLabel');
        if (!el) return;
        const n = empMsgItems.filter((m) => m && !isEmpMsgArchived(m) && parseInt(m.is_read, 10) === 0).length;
        el.textContent = n > 0 ? `(${t('notif_unread_count', { n: String(n) })})` : '';
      }

      async function loadMessages() {
        const res = await api('GET', 'messages');
        if (!res.success) return;
        empMsgItems = Array.isArray(res.data) ? res.data : [];
        updateEmpMsgBadge();
        const unread = empMsgItems.filter((m) => m && !isEmpMsgArchived(m) && parseInt(m.is_read, 10) === 0).length;
        if (unread > 0) {
          showNotif(t('new_messages', { n: String(unread) }), 'success');
        }
        const modal = document.getElementById('messagesModal');
        if (modal && modal.classList.contains('open')) {
          renderEmpMsgList();
          updateEmpMsgUnreadLabel();
        }
      }

      async function refreshEmpMessagesData() {
        const res = await api('GET', 'messages');
        const box = document.getElementById('messagesList');
        if (!res.success) {
          if (box) {
            box.innerHTML = `<div style="padding:20px;color:var(--danger);text-align:center;">${apiErrorMessage(res)}</div>`;
          }
          return;
        }
        empMsgItems = Array.isArray(res.data) ? res.data : [];
        updateEmpMsgBadge();
        updateEmpMsgUnreadLabel();
        renderEmpMsgList();
        updateUITranslations();
      }

      function renderEmpMsgList() {
        const box = document.getElementById('messagesList');
        if (!box) return;
        const filterEl = document.getElementById('empMsgFilter');
        const mode = filterEl ? String(filterEl.value || 'all') : 'all';
        const filtered = empMsgItems.filter((row) => {
          if (!row) return false;
          const arch = isEmpMsgArchived(row);
          if (mode === 'archived') return arch;
          if (mode === 'unread') return !arch && parseInt(row.is_read, 10) === 0;
          return !arch;
        });
        const markAllBtn = document.getElementById('empMsgMarkAllBtn');
        const archAllBtn = document.getElementById('empMsgArchiveAllBtn');
        const purgeAllBtn = document.getElementById('empMsgPurgeAllBtn');
        const isArchMode = mode === 'archived';
        if (markAllBtn) markAllBtn.style.display = isArchMode ? 'none' : 'inline-block';
        if (archAllBtn) archAllBtn.style.display = isArchMode ? 'none' : 'inline-block';
        if (purgeAllBtn) purgeAllBtn.style.display = isArchMode ? 'inline-block' : 'none';
        if (!filtered.length) {
          box.innerHTML = `<div style="padding:24px;text-align:center;color:var(--text-muted);">${t('no_messages')}</div>`;
          return;
        }
        box.innerHTML = filtered.map((row) => {
          const read = parseInt(row.is_read, 10) === 1 || row.is_read === true;
          const arch = isEmpMsgArchived(row);
          const body = String(row.message || '').replace(/</g, '&lt;').replace(/\n/g, '<br>');
          const actions = arch
            ? `<button type="button" class="emp-msg-purge-btn" data-id="${row.id}" style="padding:5px 9px;font-size:11px;color:var(--danger);border:none;background:transparent;cursor:pointer;">${t('delete_permanent')}</button>`
            : `<div style="display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end;">
                ${read ? '' : `<button type="button" class="emp-msg-read-btn" data-id="${row.id}" style="padding:5px 9px;font-size:11px;color:var(--accent);border:none;background:transparent;cursor:pointer;">${t('mark_read')}</button>`}
                <button type="button" class="emp-msg-archive-btn" data-id="${row.id}" style="padding:5px 9px;font-size:11px;color:var(--danger);border:none;background:transparent;cursor:pointer;">${t('delete_notif')}</button>
              </div>`;
          return `<div class="emp-msg-row" data-id="${row.id}" style="background:var(--bg);border:1px solid var(--border);border-radius:10px;padding:12px;position:relative;${!arch && !read ? 'border-inline-start:4px solid var(--accent);' : ''}${arch ? 'opacity:0.92;' : ''}">
            <p style="font-size:14px;color:var(--text);margin:0 0 8px;line-height:1.5;">${body}</p>
            <div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;">
              <span style="font-size:11px;color:var(--text-muted);font-family:var(--mono);">${String(row.created_at || '').substring(0, 16)}</span>
              ${actions}
            </div>
          </div>`;
        }).join('');
      }

      async function empMsgMarkAllRead() {
        const res = await api('PUT', 'messages/mark-read', { all: true });
        if (res.success) {
          showNotif(t('notif_read_done'), 'success');
          await refreshEmpMessagesData();
        } else {
          showNotif(apiErrorMessage(res), 'error');
        }
      }

      async function empMsgArchiveAll() {
        if (!window.confirm(t('confirm_delete_all_notif'))) return;
        const res = await api('PUT', 'messages/archive', { all: true });
        if (res.success) {
          showNotif(t('notif_delete_all_done'), 'success');
          await refreshEmpMessagesData();
        } else {
          showNotif(apiErrorMessage(res), 'error');
        }
      }

      async function empMsgPurgeAll() {
        if (!window.confirm(t('confirm_delete_perm_all_notif'))) return;
        const res = await api('PUT', 'messages/purge', { all: true });
        if (res.success) {
          showNotif(t('notif_read_done'), 'success');
          await refreshEmpMessagesData();
        } else {
          showNotif(apiErrorMessage(res), 'error');
        }
      }

      async function markAsRead(id) {
        const res = await api('PUT', `messages/${id}/read`);
        if (res.success) await refreshEmpMessagesData();
      }

      async function empMsgArchiveOne(id) {
        const res = await api('PUT', 'messages/archive', { ids: [id] });
        if (res.success) await refreshEmpMessagesData();
        else showNotif(apiErrorMessage(res), 'error');
      }

      async function empMsgPurgeOne(id) {
        if (!window.confirm(t('confirm_delete_perm_notif'))) return;
        const res = await api('PUT', 'messages/purge', { ids: [id] });
        if (res.success) await refreshEmpMessagesData();
        else showNotif(apiErrorMessage(res), 'error');
      }

      async function openMessagesModal() {
        openModal('messagesModal');
        const list = document.getElementById('messagesList');
        if (list) list.innerHTML = `<div style="padding:20px;text-align:center;color:var(--text-muted);">${t('history_loading')}</div>`;
        await refreshEmpMessagesData();
      }

      (function setupEmpMessagesDelegation() {
        const box = document.getElementById('messagesList');
        if (!box || box.dataset.hrproEmpMsgClick === '1') return;
        box.dataset.hrproEmpMsgClick = '1';
        box.addEventListener('click', async (e) => {
          const tEl = e.target && e.target.closest ? e.target.closest('.emp-msg-read-btn') : null;
          if (tEl) {
            e.preventDefault();
            await markAsRead(tEl.getAttribute('data-id'));
            return;
          }
          const aEl = e.target && e.target.closest ? e.target.closest('.emp-msg-archive-btn') : null;
          if (aEl) {
            e.preventDefault();
            await empMsgArchiveOne(aEl.getAttribute('data-id'));
            return;
          }
          const pEl = e.target && e.target.closest ? e.target.closest('.emp-msg-purge-btn') : null;
          if (pEl) {
            e.preventDefault();
            await empMsgPurgeOne(pEl.getAttribute('data-id'));
          }
        });
      })();

      // ── NOTIF ─────────────────────────────────────────────────────────
      let notifTimer;
      function showNotif(msg, type = 'success') {
        const n = document.getElementById('notif');
        n.textContent = msg;
        n.className = `notif show ${type}`;
        clearTimeout(notifTimer);
        notifTimer = setTimeout(() => n.classList.remove('show'), 3500);
      }

      // ── COMPANY NEWS TICKER + EMPLOYEE PUSH ───────────────────────────
      let companyNewsPollTimer = null;

      function escapeHtmlTicker(s) {
        return String(s)
          .replace(/&/g, '&amp;')
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;');
      }

      async function loadCompanyNewsTicker() {
        const wrap = document.getElementById('newsTickerWrap');
        const inner = document.getElementById('newsTickerInner');
        if (!wrap || !inner || !authToken) return;
        const res = await api('GET', 'company-news');
        if (!res.success || !Array.isArray(res.data) || !res.data.length) {
          wrap.classList.remove('is-visible');
          inner.innerHTML = '';
          return;
        }
        const parts = res.data
          .map(r => escapeHtmlTicker(r.message || '').replace(/\s+/g, ' ').trim())
          .filter(Boolean);
        if (!parts.length) {
          wrap.classList.remove('is-visible');
          inner.innerHTML = '';
          return;
        }
        const line = parts.join(' &nbsp;&nbsp;•&nbsp;&nbsp; ');
        inner.innerHTML =
          `<span class="news-ticker-seg">${line}</span><span class="news-ticker-seg" aria-hidden="true">${line}</span>`;
        const dur = Math.min(180, Math.max(18, Math.ceil(line.length * 0.07)));
        inner.style.animationDuration = dur + 's';
        wrap.classList.add('is-visible');
      }

      function startCompanyNewsPolling() {
        if (companyNewsPollTimer) clearInterval(companyNewsPollTimer);
        companyNewsPollTimer = setInterval(loadCompanyNewsTicker, 120000);
      }

      function stopCompanyNewsPolling() {
        if (companyNewsPollTimer) {
          clearInterval(companyNewsPollTimer);
          companyNewsPollTimer = null;
        }
      }

      function urlBase64ToUint8ArrayEmp(b64) {
        const padding = '='.repeat((4 - (b64.length % 4)) % 4);
        const base64 = (b64 + padding).replace(/-/g, '+').replace(/_/g, '/');
        const raw = window.atob(base64);
        const out = new Uint8Array(raw.length);
        for (let i = 0; i < raw.length; i++) out[i] = raw.charCodeAt(i);
        return out;
      }

      const LS_EMP_NEWS_PUSH_DECLINED = 'hrpro_emp_news_push_declined';
      const SS_EMP_NEWS_PUSH_PROMPTED = 'hrpro_emp_news_push_prompted';

      async function refreshEmpPushButtonsInProfile() {
        const unsub = document.getElementById('empPushUnsubBtn');
        if (!unsub) return;
        let has = false;
        try {
          if ('serviceWorker' in navigator) {
            const reg = await navigator.serviceWorker.ready;
            const sub = await reg.pushManager.getSubscription();
            has = !!sub;
          }
        } catch (e) { /* ignore */ }
        unsub.style.display = has ? 'block' : 'none';
      }

      async function employeePerformNewsPushSubscribe(vr, options) {
        const silent = options && options.silent;
        try {
          const reg = await navigator.serviceWorker.ready;
          const key = urlBase64ToUint8ArrayEmp(vr.data.publicKey);
          const sub = await reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: key });
          const res = await api('POST', 'employee/push-subscribe', { subscription: sub.toJSON() });
          if (res.success) {
            try { localStorage.removeItem(LS_EMP_NEWS_PUSH_DECLINED); } catch (e) { /* ignore */ }
            await refreshEmpPushButtonsInProfile();
            if (!silent) showNotif(t('news_push_subscribed'), 'success');
            return true;
          }
          if (!silent) showNotif(apiErrorMessage(res), 'error');
          return false;
        } catch (e) {
          if (!silent) showNotif(String((e && e.message) || e), 'error');
          return false;
        }
      }

      async function ensureEmployeeNewsPushSubscription() {
        try {
          if (!authToken) return;
          if (!('serviceWorker' in navigator) || !('PushManager' in window) || !('Notification' in window)) return;
          if (!(location.protocol === 'https:' || location.hostname === 'localhost')) return;

          let perm = Notification.permission;
          try {
            if (perm === 'granted') {
              localStorage.removeItem(LS_EMP_NEWS_PUSH_DECLINED);
            }
          } catch (e) { /* ignore */ }

          try {
            if (localStorage.getItem(LS_EMP_NEWS_PUSH_DECLINED) === '1') return;
          } catch (e) { /* ignore */ }

          perm = Notification.permission;
          if (perm === 'denied') {
            try { localStorage.setItem(LS_EMP_NEWS_PUSH_DECLINED, '1'); } catch (e) { /* ignore */ }
            return;
          }

          const vr = await api('GET', 'employee/push-vapid-public');
          if (!vr || !vr.success || !vr.data || !vr.data.publicKey) return;
          if (!vr.data.webpush_library_loaded) return;

          const reg = await navigator.serviceWorker.ready;
          let sub = await reg.pushManager.getSubscription();
          if (sub) {
            try { await api('POST', 'employee/push-subscribe', { subscription: sub.toJSON() }); } catch (e) { /* ignore */ }
            try { await refreshEmpPushButtonsInProfile(); } catch (e) { /* ignore */ }
            return;
          }

          perm = Notification.permission;
          if (perm === 'granted') {
            await employeePerformNewsPushSubscribe(vr, { silent: true });
            return;
          }

          try {
            if (sessionStorage.getItem(SS_EMP_NEWS_PUSH_PROMPTED) === '1') return;
            sessionStorage.setItem(SS_EMP_NEWS_PUSH_PROMPTED, '1');
          } catch (e) { /* ignore */ }

          try {
            perm = await Notification.requestPermission();
          } catch (e) {
            return;
          }
          if (perm === 'denied') {
            try { localStorage.setItem(LS_EMP_NEWS_PUSH_DECLINED, '1'); } catch (e) { /* ignore */ }
            return;
          }
          if (perm !== 'granted') return;

          await employeePerformNewsPushSubscribe(vr, { silent: true });
        } catch (e) {
          try { console.warn('ensureEmployeeNewsPushSubscription:', e && e.message ? e.message : e); } catch (ee) { /* ignore */ }
        }
      }

      async function subscribeEmployeeNewsPush() {
        if (!('PushManager' in window) || !('serviceWorker' in navigator)) {
          showNotif(t('news_push_need_https'), 'error');
          return;
        }
        if (!(location.protocol === 'https:' || location.hostname === 'localhost')) {
          showNotif(t('news_push_need_https'), 'error');
          return;
        }
        const vr = await api('GET', 'employee/push-vapid-public');
        if (!vr.success || !vr.data || !vr.data.publicKey) {
          showNotif(t('news_push_server_off'), 'warning');
          return;
        }
        if (!vr.data.webpush_library_loaded) {
          showNotif(t('news_push_need_composer'), 'warning');
        }
        const perm = await Notification.requestPermission();
        if (perm !== 'granted') {
          if (perm === 'denied') {
            try { localStorage.setItem(LS_EMP_NEWS_PUSH_DECLINED, '1'); } catch (e) { /* ignore */ }
          }
          showNotif(t('news_push_denied'), 'error');
          return;
        }
        await employeePerformNewsPushSubscribe(vr, { silent: false });
      }

      async function unsubscribeEmployeeNewsPush() {
        try {
          const reg = await navigator.serviceWorker.ready;
          const sub = await reg.pushManager.getSubscription();
          if (sub) {
            await api('POST', 'employee/push-unsubscribe', { endpoint: sub.endpoint });
            await sub.unsubscribe();
          }
        } catch (e) { /* ignore */ }
        await refreshEmpPushButtonsInProfile();
        showNotif('OK', 'success');
      }

      // ── PWA ───────────────────────────────────────────────────────────
      function hrproWatchSwUpdates(reg) {
        if (!reg || typeof reg.update !== 'function') return;
        const THROTTLE_MS = 30 * 60 * 1000;
        const INTERVAL_MS = 4 * 60 * 60 * 1000;
        let lastProbe = 0;
        const probeThrottled = () => {
          const now = Date.now();
          if (now - lastProbe < THROTTLE_MS) return;
          lastProbe = now;
          reg.update().catch(() => {});
        };
        reg.update().catch(() => {});
        lastProbe = Date.now();
        document.addEventListener('visibilitychange', () => {
          if (document.visibilityState === 'visible') probeThrottled();
        });
        window.addEventListener('focus', probeThrottled);
        setInterval(() => { reg.update().catch(() => {}); }, INTERVAL_MS);
      }
      if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('/hr/sw.js', { scope: '/hr/' })
          .then((reg) => { hrproWatchSwUpdates(reg); })
          .catch(() => { });
        navigator.serviceWorker.addEventListener('message', (event) => {
          const d = event.data;
          if (d && d.type === 'HRPRO_PUSH_NAV' && d.url) {
            window.location.href = d.url;
            return;
          }
          if (d && d.type === 'HRPRO_SW_UPDATED') {
            // Reload once to pick up fresh cached assets (prevents stale JS in installed PWA)
            try {
              const k = 'hrpro_sw_updated_once';
              if (sessionStorage.getItem(k) !== '1') {
                sessionStorage.setItem(k, '1');
                window.location.reload();
              }
            } catch (e) {
              window.location.reload();
            }
          }
        });
      }

      // ── CLOCK ─────────────────────────────────────────────────────────
      function updateClock() {
        const now = new Date();
        const tz = localStorage.getItem('emp_timezone') || 'Africa/Cairo';
        const lang = document.documentElement.lang || 'ar';
        const loc = lang === 'ar' ? 'ar-EG' : 'en-US';

        let dStr, tStr;
        try {
          dStr = new Intl.DateTimeFormat(loc, { weekday: 'long', day: 'numeric', month: 'long', timeZone: tz }).format(now);
          tStr = new Intl.DateTimeFormat(loc, { hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: tz }).format(now);
        } catch (e) {
          dStr = now.toLocaleDateString(loc, { weekday: 'long', day: 'numeric', month: 'long', timeZone: tz });
          tStr = now.toLocaleTimeString(loc, { hour: '2-digit', minute: '2-digit', second: '2-digit', timeZone: tz });
        }

        const cd = document.getElementById('clockDate');
        const ct = document.getElementById('clockTime');
        if (cd) cd.textContent = dStr;
        if (ct) ct.textContent = tStr;
      }
      setInterval(updateClock, 1000);
      updateClock();

      // ── LANGUAGE PREFERENCES ──────────────────────────────────────────
      function applyLanguage(lang) {
        document.documentElement.lang = lang;
        document.documentElement.dir = lang === 'ar' ? 'rtl' : 'ltr';
        const sel = document.getElementById('langSelect');
        if (sel) sel.value = lang;
        updateUITranslations();
        refreshEmployeePwaInstallVisibility();
        updateClock();
        try {
          if (typeof updateEmployeeLeaveFormMode === 'function') updateEmployeeLeaveFormMode();
          else if (typeof updateLeaveRequestPreview === 'function') updateLeaveRequestPreview();
        } catch (e) { /* ignore */ }
        document.dispatchEvent(new CustomEvent('hrpro-lang-changed', { detail: lang }));
      }

      async function updateLanguagePreference(lang) {
        applyLanguage(lang);
        localStorage.setItem('user_lang', lang);
        const res = await api('POST', 'user/language', { language: lang });
        if (res.success) {
          showNotif(lang === 'ar' ? 'تم تحديث اللغة' : 'Language updated', 'success');
        } else {
          showNotif(apiErrorMessage(res), 'error');
        }
      }

      // ── INIT — Smart Auto-Login with Welcome Screen ───────────────────
      function getTimeGreeting() {
        const h = new Date().getHours();
        if (h < 12) return 'صباح الخير،';
        if (h < 17) return 'مساء الخير،';
        return 'مساء النور،';
      }

      function showWelcomeScreen(name, photoUrl) {
        const ws = document.getElementById('welcomeScreen');
        ws.style.display = 'flex';
        document.getElementById('loginScreen').style.display = 'none';

        const avatar = document.getElementById('welcomeAvatar');
        const avatarText = document.getElementById('welcomeAvatarText');
        const rawW = photoUrl || localStorage.getItem('emp_photo') || '';
        const photo = rawW ? hrproMediaUrl(rawW) : '';

        if (photo) {
          avatar.style.backgroundImage = `url("${photo.replace(/"/g, '\\"')}")`;
          avatarText.style.display = 'none';
        } else {
          avatar.style.backgroundImage = 'none';
          avatarText.style.display = 'block';
          avatarText.textContent = (name || 'م')[0].toUpperCase();
        }

        // Show loading spinner briefly for effect
        setTimeout(() => {
          document.getElementById('welcomeLoading').style.display = 'none';
          const wc = document.getElementById('welcomeContent');
          wc.style.display = 'flex';
          document.getElementById('welcomeGreeting').textContent = getTimeGreeting();
          document.getElementById('welcomeName').textContent = name || 'الموظف';
        }, 900); // 0.9s loading feel
      }

      function enterFromWelcome() {
        // Animate button
        const btn = document.getElementById('welcomeEnterBtn');
        btn.innerHTML = '<div class="spinner" style="border-color:rgba(0,0,0,0.3);border-top-color:#000;"></div>';
        btn.disabled = true;
        setTimeout(() => {
          launchApp(
            localStorage.getItem('emp_name') || 'موظف',
            localStorage.getItem('emp_company_logo'),
            localStorage.getItem('emp_photo')
          );
        }, 400);
      }

      function switchUser() {
        stopCompanyNewsPolling();
        authToken = null;
        localStorage.removeItem('emp_token');
        localStorage.removeItem('emp_name');
        localStorage.removeItem('emp_photo');
        deleteCookie('emp_remember_token');
        document.getElementById('welcomeScreen').style.display = 'none';
        document.getElementById('loginScreen').style.display = 'flex';
        setLoginFormInteractive(true);
      }

      function applyStoredLangEarly() {
        try {
          const ul = localStorage.getItem('user_lang');
          if (ul === 'en' || ul === 'ar') {
            document.documentElement.lang = ul;
            document.documentElement.dir = ul === 'ar' ? 'rtl' : 'ltr';
          }
        } catch (e) { /* ignore */ }
      }

      function setLoginFormInteractive(enabled) {
        const u = document.getElementById('loginUser');
        const p = document.getElementById('loginPass');
        const b = document.getElementById('loginSubmitBtn');
        if (u) u.disabled = !enabled;
        if (p) p.disabled = !enabled;
        if (b) b.disabled = !enabled;
      }

      async function pingEmployeeApiOnce(timeoutMs) {
        const ac = new AbortController();
        const timer = setTimeout(() => ac.abort(), timeoutMs);
        try {
          const r = await fetch(`${API}?route=${encodeURIComponent('auth/employee-login')}`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'X-Device-ID': deviceId },
            body: JSON.stringify({ username: ' ', password: ' ', device_id: deviceId }),
            signal: ac.signal,
          });
          try {
            await r.text();
          } catch (e) { /* ignore body read errors */ }
          // أي استجابة HTTP من نفس المنشأ تعني أن الخادم يصل؛ الجسم قد يكون فارغاً عند بعض البروكسيات
          return typeof r.status === 'number' && r.status > 0 && r.status < 600;
        } catch (e) {
          return false;
        } finally {
          clearTimeout(timer);
        }
      }

      function primeGeolocationForLogin(timeoutMs) {
        if (!navigator.geolocation) {
          return Promise.resolve({ ok: false, reason: 'no-api' });
        }
        const innerTimeout = Math.min(11000, Math.max(4000, timeoutMs - 800));
        const hardCap = innerTimeout + 1200;
        const geoPromise = new Promise((resolve) => {
          navigator.geolocation.getCurrentPosition(
            (pos) => {
              userLocation = {
                lat: pos.coords.latitude,
                lng: pos.coords.longitude,
                accuracy: pos.coords.accuracy || 0,
              };
              resolve({ ok: true, accuracy: pos.coords.accuracy });
            },
            () => resolve({ ok: false, reason: 'unavailable' }),
            { enableHighAccuracy: true, maximumAge: 0, timeout: innerTimeout },
          );
        });
        return Promise.race([
          geoPromise,
          new Promise((resolve) => setTimeout(() => resolve({ ok: false, reason: 'timeout' }), hardCap)),
        ]);
      }

      function setGpsBootStatus(state, accuracy) {
        const scanSub = document.getElementById('statusSub');
        const directSub = document.getElementById('statusSubDirect');
        const badges = document.querySelectorAll('.gps-status-badge');
        if (state === 'loading') {
          badges.forEach((el) => {
            el.style.display = 'block';
            el.textContent = t('boot_location_badge_loading');
          });
          if (scanSub) scanSub.textContent = t('boot_location');
          if (directSub) directSub.textContent = t('boot_location');
          return;
        }
        if (state === 'ready') {
          badges.forEach((el) => {
            el.style.display = 'none';
          });
          const msg = `📍 ${typeof accuracy === 'number'
            ? t('boot_location_done_acc', { accuracy: Math.round(accuracy) })
            : t('boot_location_done')}`;
          if (scanSub) scanSub.textContent = msg;
          if (directSub) directSub.textContent = msg;
          return;
        }
        badges.forEach((el) => {
          el.style.display = 'block';
          el.textContent = t('boot_location_warn');
        });
        if (scanSub) scanSub.textContent = t('boot_location_warn');
        if (directSub) directSub.textContent = t('boot_location_warn');
      }

      async function runEmployeeEntryPrepare() {
        applyStoredLangEarly();
        updateUITranslations();
        setLoginFormInteractive(true);
        setGpsBootStatus('loading');

        const pingTask = (async () => {
          let netOk = false;
          for (let attempt = 0; attempt < 3; attempt++) {
            netOk = await pingEmployeeApiOnce(4500);
            if (netOk) break;
            await new Promise((r) => setTimeout(r, 300 + attempt * 200));
          }
          if (!netOk) {
            showNotif('⚠️ تعذّر الاتصال بالخادم — تحقق من الإنترنت', 'warning');
          }
          return netOk;
        })().catch(() => false);

        const geoTask = primeGeolocationForLogin(12000)
          .then((geo) => {
            if (geo && geo.ok) setGpsBootStatus('ready', geo.accuracy);
            else setGpsBootStatus('warn');
            return geo;
          })
          .catch(() => {
            setGpsBootStatus('warn');
            return { ok: false, reason: 'error' };
          });

        const jsQrTask = ensureJsQrLoaded().catch(() => {});

        Promise.allSettled([geoTask, jsQrTask, pingTask]);
      }

      async function initApp() {
        const savedToken = localStorage.getItem('emp_token');
        const rememberToken = getCookie('emp_remember_token');

        // 1. Try saved JWT token
        if (savedToken) {
          try {
            // JWT uses base64url (- and _ instead of + and /). atob() needs standard base64.
            const b64 = savedToken.split('.')[1].replace(/-/g, '+').replace(/_/g, '/');
            const payload = JSON.parse(atob(b64));
            if (payload.exp > Date.now() / 1000) {
              authToken = savedToken;
              const lang = localStorage.getItem('user_lang') || 'ar';
              if (payload.timezone) { localStorage.setItem('emp_timezone', payload.timezone); updateClock(); }
              applyLanguage(lang);
              const name = localStorage.getItem('emp_name') || payload.name || 'موظف';
              userWorkNature = localStorage.getItem('emp_work_nature') || 'internal';
              showWelcomeScreen(name);
              return;
            }
          } catch (e) { }
        }

        // 2. Try persistent remember token (Auto-Login)
        if (rememberToken) {
          document.getElementById('loginScreen').style.display = 'none';
          document.getElementById('welcomeScreen').style.display = 'flex';

          const res = await api('POST', 'auth/auto-verify', {
            remember_token: rememberToken,
            device_id: deviceId
          });

          if (res.success) {
            authToken = res.data.token;
            localStorage.setItem('emp_token', authToken);
            localStorage.setItem('emp_name', res.data.name);
            localStorage.setItem('emp_photo', res.data.photo_url);
            localStorage.setItem('emp_company_logo', res.data.company_logo || '');
            localStorage.setItem('emp_phone', res.data.phone || '');
            localStorage.setItem('emp_email', res.data.email || '');
            localStorage.setItem('emp_dept', res.data.department || '');
            localStorage.setItem('emp_work_nature', res.data.work_nature || 'internal');
            userWorkNature = res.data.work_nature || 'internal';
            if (res.data.timezone) {
              localStorage.setItem('emp_timezone', res.data.timezone);
              updateClock();
            }
            applyLanguage(res.data.language || 'ar');
            showWelcomeScreen(res.data.name, res.data.photo_url);
            localStorage.removeItem('must_change_password');
          } else {
            // Token invalid or device mismatch
            deleteCookie('emp_remember_token');
            document.getElementById('welcomeScreen').style.display = 'none';
            document.getElementById('loginScreen').style.display = 'flex';
          }
        }
      }

      (async function startEmployeeApp() {
        try {
          runEmployeeEntryPrepare();
        } catch (e) {
          try {
            console.error(e);
          } catch (e2) { /* ignore */ }
          setLoginFormInteractive(true);
          showNotif(t('err_network_unreachable'), 'error');
        }
        initApp();
      })();

      // ── PROFILE MANAGEMENT ─────────────────────────────────────────────
      function openProfileModal() {
        const name = localStorage.getItem('emp_name') || '';
        const dept = localStorage.getItem('emp_dept') || '';
        const phone = localStorage.getItem('emp_phone') || '';
        const email = localStorage.getItem('emp_email') || '';
        const photo = localStorage.getItem('emp_photo') || '';

        document.getElementById('profName').value = name;
        document.getElementById('profDept').value = dept;
        document.getElementById('profPhone').value = phone;
        document.getElementById('profEmail').value = email;

        renderProfilePhoto(photo);
        openModal('profileModal');
        refreshEmpPushButtonsInProfile();
      }

      function renderProfilePhoto(photoUrl) {
        const container = document.getElementById('profPhotoSection');
        if (photoUrl) {
          const src = hrproMediaUrl(photoUrl).replace(/"/g, '&quot;');
          container.innerHTML = `
          <div style="position:relative; display:inline-block;">
            <img src="${src}" style="width:120px; height:120px; border-radius:30px; object-fit:cover; border:3px solid var(--accent); box-shadow:0 8px 20px rgba(6,182,212,0.2);">
            <div style="position:absolute; bottom:-5px; right:-5px; background:var(--accent); color:white; width:28px; height:28px; border-radius:50%; display:flex; align-items:center; justify-content:center; border:2px solid var(--surface);">
               <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
            </div>
          </div>
        `;
        } else {
          container.innerHTML = `
          <div style="width:120px; height:120px; border-radius:30px; background:var(--surface2); margin:0 auto; display:flex; align-items:center; justify-content:center; border:2px dashed var(--border); transition:all 0.3s; cursor:pointer;" onclick="document.getElementById('profPhotoInput').click()" onmouseover="this.style.borderColor='var(--accent)'" onmouseout="this.style.borderColor='var(--border)'">
            <div style="text-align:center;">
              <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="opacity:0.3; margin-bottom:8px;"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg>
              <div style="font-size:11px; color:var(--textM);" data-i18n="add_photo">إضافة صورة</div>
            </div>
          </div>
          <input type="file" id="profPhotoInput" style="display:none;" accept="image/*" onchange="handleProfilePhotoSelect(event)">
        `;
        }
      }

      async function handleProfilePhotoSelect(event) {
        const file = event.target.files[0];
        if (!file) return;

        const reader = new FileReader();
        reader.onload = async (e) => {
          const base64 = e.target.result;
          showNotif('جارٍ حفظ الصورة...', 'warning');
          const res = await api('PUT', 'employees/profile', { photo_data: base64 });
          if (res.success) {
            showNotif(t('profile_updated'), 'success');
            // Update local storage and UI
            // Note: In a real app we'd get the actual new path from server, but here we'll just reload or fetch
            // For now, let's just refresh the page to be sure
            setTimeout(() => location.reload(), 1500);
          } else {
            showNotif(apiErrorMessage(res), 'error');
          }
        };
        reader.readAsDataURL(file);
      }

      async function saveProfile() {
        const phone = document.getElementById('profPhone').value.trim();
        const email = document.getElementById('profEmail').value.trim();

        showNotif('جارٍ الحفظ...', 'warning');
        const res = await api('PUT', 'employees/profile', { phone, email });
        if (res.success) {
          showNotif(t('profile_updated'), 'success');
          localStorage.setItem('emp_phone', phone);
          localStorage.setItem('emp_email', email);
          setTimeout(() => closeModal('profileModal'), 1000);
        } else {
          showNotif(apiErrorMessage(res), 'error');
        }
      }

      // ── PWA INSTALL (employee — login + welcome) ─────────────────────────
      let deferredPrompt;
      function isEmployeeStandalonePwa() {
        return window.matchMedia('(display-mode: standalone)').matches
          || window.navigator.standalone === true;
      }
      function refreshEmployeePwaInstallVisibility() {
        const standalone = isEmployeeStandalonePwa();
        const canPwa = location.protocol === 'https:' || location.hostname === 'localhost';
        const show = !standalone && canPwa;
        ['pwaInstallBtn', 'pwaInstallBtnWelcome'].forEach(id => {
          const el = document.getElementById(id);
          if (el) el.style.display = show ? 'flex' : 'none';
        });
        ['pwaDualHintLogin', 'pwaDualHintWelcome'].forEach(id => {
          const h = document.getElementById(id);
          if (h) h.style.display = show ? 'block' : 'none';
        });
      }
      window.addEventListener('beforeinstallprompt', (e) => {
        e.preventDefault();
        deferredPrompt = e;
        refreshEmployeePwaInstallVisibility();
      });

      async function installPWA() {
        if (isEmployeeStandalonePwa()) {
          showNotif(t('pwa_already_installed'), 'info');
          return;
        }
        if (!deferredPrompt) {
          showNotif(t('install_app_manual'), 'warning');
          return;
        }
        const dp = deferredPrompt;
        deferredPrompt = null;
        dp.prompt();
        await dp.userChoice;
        refreshEmployeePwaInstallVisibility();
      }

      window.addEventListener('appinstalled', () => {
        deferredPrompt = null;
        refreshEmployeePwaInstallVisibility();
      });

      refreshEmployeePwaInstallVisibility();

      // ── AUDIO UNLOCK ──────────────────────────────────────────────────
      function playAttendanceSound() {
        // PERF: getAttendanceAudio() creates Audio object only on first use
        const audio = getAttendanceAudio();
        if (audio) {
          audio.currentTime = 0;
          audio.play().catch(e => console.log('Audio playback failed:', e));
        }
      }

      // Unlock audio on first user interaction (critical for mobile)
      document.addEventListener('click', function unlockAudio() {
        const audio = getAttendanceAudio();
        if (audio) {
          audio.load(); // Warm up the audio in memory after first tap
          document.removeEventListener('click', unlockAudio);
        }
      }, { once: true });

      document.getElementById('loginPass').addEventListener('keydown', e => { if (e.key === 'Enter') doLogin(); });