{"product_id":"skytech-password-wallet","title":"SkyTech Password Wallet","description":"\u003cdiv class=\"qMYqUG_convSearchResultHighlightRoot\"\u003e\n\u003cdiv class=\"\"\u003e\n\u003csection class=\"text-token-text-primary w-full focus:outline-none has-data-writing-block:pointer-events-none [\u0026amp;:has([data-writing-block])\u0026gt;*]:pointer-events-auto R6Vx5W_threadScrollVars scroll-mb-[calc(var(--scroll-root-safe-area-inset-bottom,0px)+var(--thread-response-height))] scroll-mt-[calc(var(--header-height)+min(200px,max(70px,20svh)))]\" dir=\"auto\"\u003e\n\u003cdiv class=\"text-base my-auto mx-auto pb-8 [--thread-content-margin:var(--thread-content-margin-xs,calc(var(--spacing)*4))] @w-sm\/main:[--thread-content-margin:var(--thread-content-margin-sm,calc(var(--spacing)*6))] @w-lg\/main:[--thread-content-margin:var(--thread-content-margin-lg,calc(var(--spacing)*16))] px-(--thread-content-margin)\"\u003e\n\u003cdiv class=\"[--thread-content-max-width:40rem] @w-lg\/main:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1 group\/turn-messages focus-visible:outline-hidden relative flex w-full min-w-0 flex-col agent-turn\"\u003e\n\u003cdiv class=\"flex max-w-full flex-col gap-4 grow\"\u003e\n\u003cdiv dir=\"auto\" class=\"min-h-8 text-message relative flex w-full flex-col items-end gap-2 text-start break-words whitespace-normal outline-none keyboard-focused:focus-ring [.text-message+\u0026amp;]:mt-1\"\u003e\n\u003cdiv class=\"flex w-full flex-col gap-1 empty:hidden\"\u003e\n\u003cdiv class=\"markdown prose dark:prose-invert wrap-break-word w-full dark markdown-new-styling\"\u003e\n\u003ch3 class=\"PDq2pG_selectionAnchorContainer\"\u003eSkyTech Pass Wallet\u003cspan class=\"PDq2pG_selectionAnchor\"\u003e\u003c\/span\u003e\n\u003c\/h3\u003e\n\u003cp\u003eجهاز \u003cstrong\u003eSkyTech Pass Wallet\u003c\/strong\u003e هو مدير كلمات مرور فعلي (Hardware) ومولد رموز مصادقة ثنائية (TOTP) يعمل بشكل غير متصل بالإنترنت. يعمل كلوحة مفاتيح USB (Plug \u0026amp; Play) لإدخال بيانات تسجيل الدخول تلقائيًا دون الحاجة إلى تثبيت أي برامج.\u003c\/p\u003e\n\u003ch3\u003eالمميزات\u003c\/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cstrong\u003eإدخال تلقائي آمن (Plug \u0026amp; Play):\u003c\/strong\u003e يعمل كلوحة مفاتيح USB فعلية لكتابة بياناتك بضغطة زر، مما يقلل مخاطر برمجيات التجسس.\u003c\/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eتخزين محلي مستقل (Offline):\u003c\/strong\u003e يحفظ كلمات المرور ويولد رموز المصادقة (TOTP) داخليًا بعيدًا عن الإنترنت والخدمات السحابية.\u003c\/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eإدارة لاسلكية سهلة:\u003c\/strong\u003e ينشئ شبكة Wi-Fi محلية خاصة ومؤقتة لإضافة وتعديل الحسابات عبر متصفح الهاتف بسهولة.\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003ch3\u003eالمكونات\u003c\/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cstrong\u003eالمعالج:\u003c\/strong\u003e لوحة ESP32-S3، تدعم USB مباشرة واستخدام الجهاز كلوحة مفاتيح (USB HID).\u003c\/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eالشاشة:\u003c\/strong\u003e شاشة OLED بحجم 0.96 بوصة، عالية التباين لعرض الحسابات ورموز TOTP بوضوح.\u003c\/li\u003e\n\u003cli style=\"text-align: left;\"\u003e\n\u003cstrong\u003eأدوات التحكم:\u003c\/strong\u003e مفتاحان ضاغطان (Push Buttons) للتنقل بين القوائم وتأكيد الإدخال.\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"mt-3 w-full empty:hidden has-[\u0026gt;_:empty]:hidden\"\u003e\n\u003cdiv class=\"text-center\" style=\"text-align: left;\"\u003e\n\u003cstrong\u003eالكـــــود:\u003cbr\u003e\u003c\/strong\u003e\u003cbr\u003e\n\u003cp\u003e\/\/Gmail TOTP\u003cbr\u003econst char* WIFI_SSID = \"Samsung s23\";\u003cbr\u003econst char* WIFI_PASSWORD = \"11111111\";\u003cbr\u003econst char* GMAIL_TOTP_BASE32 = \"aaaa bbbb cccc dddd eeee ffff gggg hhhh\";\u003c\/p\u003e\n\u003cp\u003e#include \u0026lt;WiFi.h\u0026gt;\u003cbr\u003e#include \u0026lt;WebServer.h\u0026gt;\u003cbr\u003e#include \u0026lt;DNSServer.h\u0026gt;\u003cbr\u003e#include \u0026lt;Preferences.h\u0026gt;\u003cbr\u003e#include \u0026lt;time.h\u0026gt;\u003cbr\u003e#include \u0026lt;TOTP.h\u0026gt;\u003cbr\u003e#include \"USB.h\"\u003cbr\u003e#include \"USBHIDKeyboard.h\"\u003c\/p\u003e\n\u003cp\u003e#include \u0026lt;Wire.h\u0026gt;\u003cbr\u003e#include \u0026lt;Adafruit_GFX.h\u0026gt;\u003cbr\u003e#include \u0026lt;Adafruit_SSD1306.h\u0026gt;\u003c\/p\u003e\n\u003cp\u003e#define SCREEN_WIDTH 128\u003cbr\u003e#define SCREEN_HEIGHT 64\u003cbr\u003e#define OLED_RESET -1\u003cbr\u003eAdafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, \u0026amp;Wire, OLED_RESET);\u003c\/p\u003e\n\u003cp\u003eUSBHIDKeyboard Keyboard;\u003cbr\u003eWebServer server(80);\u003cbr\u003eDNSServer dnsServer;\u003cbr\u003ePreferences prefs;\u003c\/p\u003e\n\u003cp\u003e\/\/ ===== Buttons =====\u003cbr\u003e#define BTN_OK_UP   11\u003cbr\u003e#define BTN_DOWN    10\u003cbr\u003e#define I2C_SDA    8\u003cbr\u003e#define I2C_SCL    9\u003c\/p\u003e\n\u003cp\u003e\/\/ ===== Wi-Fi \/ Time =====\u003cbr\u003econst char* NTP_SERVER_1 = \"pool.ntp.org\";\u003cbr\u003econst char* NTP_SERVER_2 = \"time.google.com\";\u003cbr\u003econst long GMT_OFFSET_SEC = 3 * 3600;   \/\/ Saudi Arabia\u003cbr\u003econst int DAYLIGHT_OFFSET_SEC = 0;\u003c\/p\u003e\n\u003cp\u003euint8_t gmailTotpSecret[64];\u003cbr\u003esize_t gmailTotpSecretLen = 0;\u003cbr\u003eTOTP* gmailTotp = nullptr;\u003c\/p\u003e\n\u003cp\u003e\/\/ ===== Timing =====\u003cbr\u003econst unsigned long DEBOUNCE_MS = 180;\u003cbr\u003econst unsigned long HOLD_TIME_MS = 700;\u003cbr\u003econst unsigned long USB_STARTUP_DELAY_MS = 800;   \/\/ was 3000\u003cbr\u003econst byte DNS_PORT = 53;\u003c\/p\u003e\n\u003cp\u003e\/\/ ===== Menu =====\u003cbr\u003eenum ItemType {\u003cbr\u003e  ITEM_SUBMENU,\u003cbr\u003e  ITEM_TEXT,\u003cbr\u003e  ITEM_TOTP,\u003cbr\u003e  ITEM_INFO\u003cbr\u003e};\u003c\/p\u003e\n\u003cp\u003estruct MenuItem {\u003cbr\u003e  const char* name;\u003cbr\u003e  ItemType type;\u003cbr\u003e  const char* textValue;\u003cbr\u003e  TOTP* totp;\u003cbr\u003e};\u003c\/p\u003e\n\u003cp\u003eenum MenuScreen {\u003cbr\u003e  SCREEN_MAIN,\u003cbr\u003e  SCREEN_PASSWORDS,\u003cbr\u003e  SCREEN_PASSWORD_ACTIONS,\u003cbr\u003e  SCREEN_TOTP,\u003cbr\u003e  SCREEN_TOTP_VIEW,\u003cbr\u003e  SCREEN_SETTINGS\u003cbr\u003e};\u003c\/p\u003e\n\u003cp\u003eMenuScreen currentScreen = SCREEN_MAIN;\u003cbr\u003eint selectedIndex = 0;\u003cbr\u003eint menuScrollOffset = 0;\u003c\/p\u003e\n\u003cp\u003eMenuItem mainMenuItems[] = {\u003cbr\u003e  {\"Passwords\", ITEM_SUBMENU, nullptr, nullptr},\u003cbr\u003e  {\"TOTP\",      ITEM_SUBMENU, nullptr, nullptr},\u003cbr\u003e  {\"Settings\",  ITEM_SUBMENU, nullptr, nullptr}\u003cbr\u003e};\u003c\/p\u003e\n\u003cp\u003econst int MAX_PASSWORD_ITEMS = 12;\u003c\/p\u003e\n\u003cp\u003eMenuItem passwordMenuItems[MAX_PASSWORD_ITEMS];\u003cbr\u003eint passwordMenuCount = 4;\u003c\/p\u003e\n\u003cp\u003echar passwordNameValues[MAX_PASSWORD_ITEMS][32] = {\u003cbr\u003e  \"Gmail\",\u003cbr\u003e  \"GitHub\",\u003cbr\u003e  \"AWS\",\u003cbr\u003e  \"Bank\"\u003cbr\u003e};\u003c\/p\u003e\n\u003cp\u003eMenuItem passwordActionMenuItems[] = {\u003cbr\u003e  {\"Username\",   ITEM_INFO, nullptr, nullptr},\u003cbr\u003e  {\"Password\",   ITEM_INFO, nullptr, nullptr},\u003cbr\u003e  {\"UserTabPass\", ITEM_INFO, nullptr, nullptr}\u003cbr\u003e};\u003c\/p\u003e\n\u003cp\u003eMenuItem totpMenuItems[] = {\u003cbr\u003e  {\"Google TOTP\", ITEM_TOTP, nullptr, nullptr}\u003cbr\u003e};\u003c\/p\u003e\n\u003cp\u003eMenuItem settingsMenuItems[] = {\u003cbr\u003e};\u003c\/p\u003e\n\u003cp\u003eMenuItem* getCurrentMenuItems() {\u003cbr\u003e  switch (currentScreen) {\u003cbr\u003e    case SCREEN_PASSWORDS:         return passwordMenuItems;\u003cbr\u003e    case SCREEN_PASSWORD_ACTIONS:  return passwordActionMenuItems;\u003cbr\u003e    case SCREEN_TOTP:              return totpMenuItems;\u003cbr\u003e    case SCREEN_SETTINGS:          return settingsMenuItems;\u003cbr\u003e    case SCREEN_MAIN:\u003cbr\u003e    default:                       return mainMenuItems;\u003cbr\u003e  }\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003eint getCurrentMenuCount() {\u003cbr\u003e  switch (currentScreen) {\u003cbr\u003e    case SCREEN_PASSWORDS:        return passwordMenuCount;\u003cbr\u003e    case SCREEN_PASSWORD_ACTIONS: return sizeof(passwordActionMenuItems) \/ sizeof(passwordActionMenuItems[0]);\u003cbr\u003e    case SCREEN_TOTP:             return sizeof(totpMenuItems) \/ sizeof(totpMenuItems[0]);\u003cbr\u003e    case SCREEN_SETTINGS:         return 0;\u003cbr\u003e    case SCREEN_MAIN:\u003cbr\u003e    default:                      return sizeof(mainMenuItems) \/ sizeof(mainMenuItems[0]);\u003cbr\u003e  }\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003econst char* getScreenTitle() {\u003cbr\u003e  switch (currentScreen) {\u003cbr\u003e    case SCREEN_PASSWORDS:        return \"Passwords\";\u003cbr\u003e    case SCREEN_PASSWORD_ACTIONS: return \"Send As\";\u003cbr\u003e    case SCREEN_TOTP:             return \"TOTP\";\u003cbr\u003e    case SCREEN_TOTP_VIEW:        return \"TOTP\";\u003cbr\u003e    case SCREEN_SETTINGS:         return \"Settings\";\u003cbr\u003e    case SCREEN_MAIN:\u003cbr\u003e    default:                      return \"Dr. Passwords\";\u003cbr\u003e  }\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003e\/\/ ===== Time sync state =====\u003cbr\u003ebool timeSynced = false;\u003cbr\u003eint activeTotpIndex = 0;\u003cbr\u003eunsigned long lastTotpRedraw = 0;\u003cbr\u003ebool settingsPortalActive = false;\u003cbr\u003eString settingsApPassword;\u003cbr\u003eint activePasswordIndex = 0;\u003c\/p\u003e\n\u003cp\u003echar passwordTextValues[MAX_PASSWORD_ITEMS][128] = {\u003cbr\u003e  \"MyGmailPassword123\",\u003cbr\u003e  \"MyGitHubPassword456\",\u003cbr\u003e  \"MyAwsPassword789\",\u003cbr\u003e  \"MyBankPassword000\"\u003cbr\u003e};\u003c\/p\u003e\n\u003cp\u003echar passwordUsernameValues[MAX_PASSWORD_ITEMS][128] = {\u003cbr\u003e  \"user.alpha01\",\u003cbr\u003e  \"bluefalcon77\",\u003cbr\u003e  \"cloud.user23\",\u003cbr\u003e  \"banking_hero\",\u003cbr\u003e  \"gamma.node\",\u003cbr\u003e  \"pixel.rider\",\u003cbr\u003e  \"tiger_login\",\u003cbr\u003e  \"neo.account\",\u003cbr\u003e  \"orbit.user\",\u003cbr\u003e  \"delta.signin\",\u003cbr\u003e  \"fastlane.id\",\u003cbr\u003e  \"quantum.user\"\u003cbr\u003e};\u003c\/p\u003e\n\u003cp\u003e\/\/ ===== Button states =====\u003cbr\u003ebool lastDownState = HIGH;\u003cbr\u003ebool btnPressed = false;\u003cbr\u003ebool holdTriggered = false;\u003cbr\u003eunsigned long btnPressStart = 0;\u003cbr\u003eunsigned long lastDownPress = 0;\u003cbr\u003ebool downHoldHandled = false;\u003c\/p\u003e\n\u003cp\u003e\/\/ ===== Base32 decode (for TOTP) =====\u003cbr\u003eint base32Value(char c) {\u003cbr\u003e  if (c \u0026gt;= 'A' \u0026amp;\u0026amp; c \u0026lt;= 'Z') return c - 'A';\u003cbr\u003e  if (c \u0026gt;= 'a' \u0026amp;\u0026amp; c \u0026lt;= 'z') return c - 'a';\u003cbr\u003e  if (c \u0026gt;= '2' \u0026amp;\u0026amp; c \u0026lt;= '7') return c - '2' + 26;\u003cbr\u003e  return -1;\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003esize_t decodeBase32(const char* input, uint8_t* output, size_t maxOutputLen) {\u003cbr\u003e  int buffer = 0;\u003cbr\u003e  int bitsLeft = 0;\u003cbr\u003e  size_t outLen = 0;\u003c\/p\u003e\n\u003cp\u003e  while (*input) {\u003cbr\u003e    char c = *input++;\u003cbr\u003e    if (c == ' ' || c == '=' || c == '-') continue;\u003c\/p\u003e\n\u003cp\u003e    int val = base32Value(c);\u003cbr\u003e    if (val \u0026lt; 0) continue;\u003c\/p\u003e\n\u003cp\u003e    buffer = (buffer \u0026lt;\u0026lt; 5) | val;\u003cbr\u003e    bitsLeft += 5;\u003c\/p\u003e\n\u003cp\u003e    if (bitsLeft \u0026gt;= 8) {\u003cbr\u003e      bitsLeft -= 8;\u003cbr\u003e      if (outLen \u0026gt;= maxOutputLen) return 0;\u003cbr\u003e      output[outLen++] = (buffer \u0026gt;\u0026gt; bitsLeft) \u0026amp; 0xFF;\u003cbr\u003e    }\u003cbr\u003e  }\u003cbr\u003e  return outLen;\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003ebool initTotp() {\u003cbr\u003e  gmailTotpSecretLen = decodeBase32(GMAIL_TOTP_BASE32, gmailTotpSecret, sizeof(gmailTotpSecret));\u003cbr\u003e  if (gmailTotpSecretLen == 0) return false;\u003cbr\u003e  gmailTotp = new TOTP(gmailTotpSecret, gmailTotpSecretLen);\u003cbr\u003e  return true;\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003e\/\/ ===== UI =====\u003cbr\u003evoid drawMenu() {\u003cbr\u003e  display.clearDisplay();\u003c\/p\u003e\n\u003cp\u003e  \/\/ رسم العنوان\u003cbr\u003e  display.setTextColor(SSD1306_WHITE);\u003cbr\u003e  display.setTextSize(1);\u003cbr\u003e  display.setCursor(0, 0);\u003cbr\u003e  display.println(getScreenTitle());\u003cbr\u003e  \u003cbr\u003e  \/\/ رسم خط فاصل تحت العنوان\u003cbr\u003e  display.drawLine(0, 10, 128, 10, SSD1306_WHITE);\u003c\/p\u003e\n\u003cp\u003e  MenuItem* items = getCurrentMenuItems();\u003cbr\u003e  int itemCount = getCurrentMenuCount();\u003c\/p\u003e\n\u003cp\u003e  const int startY = 14;\u003cbr\u003e  const int lineHeight = 12; \/\/ ارتفاع مناسب للخط بحجم 1\u003cbr\u003e  const int visibleItems = 4; \/\/ 4 عناصر كحد أقصى في الشاشة\u003c\/p\u003e\n\u003cp\u003e  if (selectedIndex \u0026lt; menuScrollOffset) {\u003cbr\u003e    menuScrollOffset = selectedIndex;\u003cbr\u003e  }\u003cbr\u003e  if (selectedIndex \u0026gt;= menuScrollOffset + visibleItems) {\u003cbr\u003e    menuScrollOffset = selectedIndex - visibleItems + 1;\u003cbr\u003e  }\u003cbr\u003e  if (menuScrollOffset \u0026lt; 0) menuScrollOffset = 0;\u003cbr\u003e  if (itemCount \u0026lt;= visibleItems) menuScrollOffset = 0;\u003c\/p\u003e\n\u003cp\u003e  int endIndex = menuScrollOffset + visibleItems;\u003cbr\u003e  if (endIndex \u0026gt; itemCount) endIndex = itemCount;\u003c\/p\u003e\n\u003cp\u003e  int y = startY;\u003cbr\u003e  for (int i = menuScrollOffset; i \u0026lt; endIndex; i++) {\u003cbr\u003e    display.setCursor(2, y);\u003cbr\u003e    if (i == selectedIndex) {\u003cbr\u003e      \/\/ رسم خلفية بيضاء مع نص أسود للعنصر المحدد لإبرازه\u003cbr\u003e      display.fillRect(0, y - 1, 118, lineHeight, SSD1306_WHITE);\u003cbr\u003e      display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);\u003cbr\u003e      display.print(\"\u0026gt; \");\u003cbr\u003e      display.println(items[i].name);\u003cbr\u003e    } else {\u003cbr\u003e      \/\/ نص أبيض عادي للعناصر غير المحددة\u003cbr\u003e      display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);\u003cbr\u003e      display.print(\"  \");\u003cbr\u003e      display.println(items[i].name);\u003cbr\u003e    }\u003cbr\u003e    y += lineHeight;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  \/\/ مؤشرات التمرير (أسهم صغيرة على يمين الشاشة)\u003cbr\u003e  display.setTextColor(SSD1306_WHITE);\u003cbr\u003e  if (menuScrollOffset \u0026gt; 0) {\u003cbr\u003e    display.setCursor(120, 14);\u003cbr\u003e    display.print(\"^\");\u003cbr\u003e  }\u003cbr\u003e  if (endIndex \u0026lt; itemCount) {\u003cbr\u003e    display.setCursor(120, 50);\u003cbr\u003e    display.print(\"v\");\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  display.display();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid showSendingScreen(const char* text) {\u003cbr\u003e  display.clearDisplay();\u003cbr\u003e  display.setTextColor(SSD1306_WHITE);\u003cbr\u003e  display.setTextSize(1);\u003cbr\u003e  \u003cbr\u003e  display.setCursor(10, 20);\u003cbr\u003e  display.println(\"Sending...\");\u003cbr\u003e  \u003cbr\u003e  display.setCursor(10, 40);\u003cbr\u003e  display.println(text);\u003cbr\u003e  display.display();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003ebool syncTimeOverWiFi() {\u003cbr\u003e  WiFi.mode(WIFI_STA);\u003c\/p\u003e\n\u003cp\u003e  while (true) {\u003cbr\u003e    WiFi.disconnect(true);\u003cbr\u003e    delay(200);\u003cbr\u003e    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);\u003c\/p\u003e\n\u003cp\u003e    unsigned long start = millis();\u003cbr\u003e    while (WiFi.status() != WL_CONNECTED \u0026amp;\u0026amp; millis() - start \u0026lt; 20000) {\u003cbr\u003e      delay(250);\u003cbr\u003e    }\u003c\/p\u003e\n\u003cp\u003e    if (WiFi.status() == WL_CONNECTED) {\u003cbr\u003e      configTime(GMT_OFFSET_SEC, DAYLIGHT_OFFSET_SEC, NTP_SERVER_1, NTP_SERVER_2);\u003c\/p\u003e\n\u003cp\u003e      struct tm timeinfo;\u003cbr\u003e      start = millis();\u003cbr\u003e      while (millis() - start \u0026lt; 20000) {\u003cbr\u003e        if (getLocalTime(\u0026amp;timeinfo)) {\u003cbr\u003e          WiFi.disconnect(true);\u003cbr\u003e          WiFi.mode(WIFI_OFF);\u003cbr\u003e          return true;\u003cbr\u003e        }\u003cbr\u003e        delay(250);\u003cbr\u003e      }\u003cbr\u003e    }\u003c\/p\u003e\n\u003cp\u003e    WiFi.disconnect(true);\u003cbr\u003e    delay(500);\u003cbr\u003e  }\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003ebool getCurrentUnixTime(time_t \u0026amp;unixTime) {\u003cbr\u003e  time(\u0026amp;unixTime);\u003cbr\u003e  return unixTime \u0026gt; 1700000000;\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid showStatusScreen(const char* title, const char* line2) {\u003cbr\u003e  display.clearDisplay();\u003cbr\u003e  display.setTextColor(SSD1306_WHITE);\u003cbr\u003e  display.setTextSize(1);\u003c\/p\u003e\n\u003cp\u003e  int titleWidth = strlen(title) * 6;\u003cbr\u003e  int titleX = (SCREEN_WIDTH - titleWidth) \/ 2;\u003cbr\u003e  if (titleX \u0026lt; 0) titleX = 0;\u003c\/p\u003e\n\u003cp\u003e  display.setCursor(titleX, 20);\u003cbr\u003e  display.println(title);\u003c\/p\u003e\n\u003cp\u003e  const char* dots = \"...........\";\u003cbr\u003e  int dotsLen = strlen(dots);\u003cbr\u003e  int phase = (millis() \/ 180) % ((dotsLen * 2) - 2);\u003cbr\u003e  int visibleCount = (phase \u0026lt; dotsLen) ? (phase + 1) : ((dotsLen * 2) - phase - 1);\u003c\/p\u003e\n\u003cp\u003e  int dotsWidth = visibleCount * 6;\u003cbr\u003e  int dotsX = (SCREEN_WIDTH - dotsWidth) \/ 2;\u003cbr\u003e  if (dotsX \u0026lt; 0) dotsX = 0;\u003c\/p\u003e\n\u003cp\u003e  display.setCursor(dotsX, 40);\u003cbr\u003e  for (int i = 0; i \u0026lt; visibleCount; i++) {\u003cbr\u003e    display.print('.');\u003cbr\u003e  }\u003cbr\u003e  display.display();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid showTotpCodeScreen(const char* title, const char* code, int secondsRemaining) {\u003cbr\u003e  display.clearDisplay();\u003cbr\u003e  \u003cbr\u003e  \/\/ العنوان\u003cbr\u003e  display.setTextColor(SSD1306_WHITE);\u003cbr\u003e  display.setTextSize(1);\u003cbr\u003e  const char* displayTitle = title;\u003cbr\u003e  if (strcmp(title, \"Gmail TOTP\") == 0) {\u003cbr\u003e    displayTitle = \"Google\";\u003cbr\u003e  }\u003cbr\u003e  int titleWidth = strlen(displayTitle) * 6;\u003cbr\u003e  int titleX = (SCREEN_WIDTH - titleWidth) \/ 2;\u003cbr\u003e  if (titleX \u0026lt; 0) titleX = 0;\u003cbr\u003e  display.setCursor(titleX, 0);\u003cbr\u003e  display.println(displayTitle);\u003c\/p\u003e\n\u003cp\u003e  \/\/ كود TOTP (بخط كبير الحجم 2)\u003cbr\u003e  display.setTextSize(2);\u003cbr\u003e  int codeWidth = strlen(code) * 12; \u003cbr\u003e  int codeX = (SCREEN_WIDTH - codeWidth) \/ 2;\u003cbr\u003e  if (codeX \u0026lt; 0) codeX = 0;\u003cbr\u003e  display.setCursor(codeX, 22);\u003cbr\u003e  display.println(code);\u003c\/p\u003e\n\u003cp\u003e  \/\/ شريط التقدم (الزمن المتبقي)\u003cbr\u003e  const int period = 30;\u003cbr\u003e  int barWidth = 96;\u003cbr\u003e  int barX = 4;\u003cbr\u003e  int progressWidth = (secondsRemaining * barWidth) \/ period;\u003cbr\u003e  if (progressWidth \u0026lt; 0) progressWidth = 0;\u003cbr\u003e  \u003cbr\u003e  \/\/ رسم إطار الشريط ثم تعبئته بناءً على الوقت المتبقي\u003cbr\u003e  display.drawRect(barX, 50, barWidth, 10, SSD1306_WHITE);\u003cbr\u003e  if (progressWidth \u0026gt; 0) {\u003cbr\u003e    display.fillRect(barX + 2, 52, progressWidth - 4, 6, SSD1306_WHITE);\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  \/\/ رسم الثواني المتبقية كنص بجانب الشريط\u003cbr\u003e  display.setTextSize(1);\u003cbr\u003e  display.setCursor(barX + barWidth + 8, 51);\u003cbr\u003e  display.print(secondsRemaining);\u003cbr\u003e  display.print(\"s\");\u003c\/p\u003e\n\u003cp\u003e  display.display();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003e\u003cbr\u003eString htmlEscape(const char* input) {\u003cbr\u003e  String s = input ? input : \"\";\u003cbr\u003e  s.replace(\"\u0026amp;\", \"\u0026amp;amp;\");\u003cbr\u003e  s.replace(\"\u0026lt;\", \"\u0026amp;lt;\");\u003cbr\u003e  s.replace(\"\u0026gt;\", \"\u0026amp;gt;\");\u003cbr\u003e  s.replace(\"\\\"\", \"\u0026amp;quot;\");\u003cbr\u003e  return s;\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003eString generateApPassword() {\u003cbr\u003e  const char charset[] = \"ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!@#$%^\u0026amp;*\";\u003cbr\u003e  const int passwordLength = 16;\u003c\/p\u003e\n\u003cp\u003e  String result = \"\";\u003cbr\u003e  result.reserve(passwordLength);\u003c\/p\u003e\n\u003cp\u003e  for (int i = 0; i \u0026lt; passwordLength; i++) {\u003cbr\u003e    result += charset[esp_random() % (sizeof(charset) - 1)];\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  return result;\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid refreshPasswordMenuItems() {\u003cbr\u003e  for (int i = 0; i \u0026lt; passwordMenuCount; i++) {\u003cbr\u003e    passwordMenuItems[i].name = passwordNameValues[i];\u003cbr\u003e    passwordMenuItems[i].type = ITEM_TEXT;\u003cbr\u003e    passwordMenuItems[i].textValue = passwordTextValues[i];\u003cbr\u003e    passwordMenuItems[i].totp = nullptr;\u003cbr\u003e  }\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid loadSavedPasswords() {\u003cbr\u003e  prefs.begin(\"vault\", true);\u003c\/p\u003e\n\u003cp\u003e  int storedCount = prefs.getInt(\"count\", 4);\u003cbr\u003e  if (storedCount \u0026lt; 1) storedCount = 1;\u003cbr\u003e  if (storedCount \u0026gt; MAX_PASSWORD_ITEMS) storedCount = MAX_PASSWORD_ITEMS;\u003cbr\u003e  passwordMenuCount = storedCount;\u003c\/p\u003e\n\u003cp\u003e  for (int i = 0; i \u0026lt; passwordMenuCount; i++) {\u003cbr\u003e    String nameKey = \"name\" + String(i);\u003cbr\u003e    String userKey = \"user\" + String(i);\u003cbr\u003e    String passKey = \"pass\" + String(i);\u003c\/p\u003e\n\u003cp\u003e    String defaultName = passwordNameValues[i];\u003cbr\u003e    String defaultUser = passwordUsernameValues[i];\u003cbr\u003e    String defaultPass = passwordTextValues[i];\u003c\/p\u003e\n\u003cp\u003e    String loadedName = prefs.getString(nameKey.c_str(), defaultName);\u003cbr\u003e    String loadedUser = prefs.getString(userKey.c_str(), defaultUser);\u003cbr\u003e    String loadedPass = prefs.getString(passKey.c_str(), defaultPass);\u003c\/p\u003e\n\u003cp\u003e    loadedName.toCharArray(passwordNameValues[i], sizeof(passwordNameValues[i]));\u003cbr\u003e    loadedUser.toCharArray(passwordUsernameValues[i], sizeof(passwordUsernameValues[i]));\u003cbr\u003e    loadedPass.toCharArray(passwordTextValues[i], sizeof(passwordTextValues[i]));\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  prefs.end();\u003cbr\u003e  refreshPasswordMenuItems();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003e\u003cbr\u003evoid savePasswordsToPreferences() {\u003cbr\u003e  prefs.begin(\"vault\", false);\u003cbr\u003e  prefs.clear();\u003cbr\u003e  prefs.putInt(\"count\", passwordMenuCount);\u003c\/p\u003e\n\u003cp\u003e  for (int i = 0; i \u0026lt; passwordMenuCount; i++) {\u003cbr\u003e    String nameKey = \"name\" + String(i);\u003cbr\u003e    String userKey = \"user\" + String(i);\u003cbr\u003e    String passKey = \"pass\" + String(i);\u003cbr\u003e    prefs.putString(nameKey.c_str(), passwordNameValues[i]);\u003cbr\u003e    prefs.putString(userKey.c_str(), passwordUsernameValues[i]);\u003cbr\u003e    prefs.putString(passKey.c_str(), passwordTextValues[i]);\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  prefs.end();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid drawSettingsPortalScreen() {\u003cbr\u003e  display.clearDisplay();\u003cbr\u003e  display.setTextColor(SSD1306_WHITE);\u003cbr\u003e  \u003cbr\u003e  \/\/ العنوان\u003cbr\u003e  display.setTextSize(1);\u003cbr\u003e  const char* title = \"Settings Portal\";\u003cbr\u003e  int titleX = (SCREEN_WIDTH - (strlen(title) * 6)) \/ 2;\u003cbr\u003e  if (titleX \u0026lt; 0) titleX = 0;\u003cbr\u003e  display.setCursor(titleX, 0);\u003cbr\u003e  display.println(title);\u003cbr\u003e  display.drawLine(0, 10, 128, 10, SSD1306_WHITE);\u003c\/p\u003e\n\u003cp\u003e  \/\/ تفاصيل نقطة الاتصال\u003cbr\u003e  display.setCursor(0, 18);\u003cbr\u003e  display.print(\"SSID: Dr. Passwords\");\u003c\/p\u003e\n\u003cp\u003e  display.setCursor(0, 32);\u003cbr\u003e  display.print(\"PASS: Press OK\");\u003c\/p\u003e\n\u003cp\u003e  \/\/ التعليمات السفلية\u003cbr\u003e  display.setCursor(0, 50);\u003cbr\u003e  display.println(\"Hold DOWN to close\");\u003c\/p\u003e\n\u003cp\u003e  display.display();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid handlePortalRoot() {\u003cbr\u003e  int editIndex = -1;\u003cbr\u003e  if (server.hasArg(\"edit\")) {\u003cbr\u003e    editIndex = server.arg(\"edit\").toInt();\u003cbr\u003e    if (editIndex \u0026lt; 0 || editIndex \u0026gt;= passwordMenuCount) {\u003cbr\u003e      editIndex = -1;\u003cbr\u003e    }\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  String formName = \"\";\u003cbr\u003e  String formUser = \"\";\u003cbr\u003e  String formPass = \"\";\u003cbr\u003e  bool isEditMode = (editIndex \u0026gt;= 0);\u003c\/p\u003e\n\u003cp\u003e  \/\/ Generate default random password for new entries\u003cbr\u003e  if (!isEditMode) {\u003cbr\u003e    const char charset[] = \"ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!@#$%^\u0026amp;*\";\u003cbr\u003e    for (int i = 0; i \u0026lt; 16; i++) {\u003cbr\u003e      formPass += charset[esp_random() % (sizeof(charset) - 1)];\u003cbr\u003e    }\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (isEditMode) {\u003cbr\u003e    formName = htmlEscape(passwordNameValues[editIndex]);\u003cbr\u003e    formUser = htmlEscape(passwordUsernameValues[editIndex]);\u003cbr\u003e    formPass = \"\";\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  String html = \"\";\u003cbr\u003e  html += \"\u0026lt;!doctype html\u0026gt;\u0026lt;html\u0026gt;\u0026lt;head\u0026gt;\u0026lt;meta name='viewport' content='width=device-width,initial-scale=1'\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;title\u0026gt;Dr. Passwords\u0026lt;\/title\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;style\u0026gt;\";\u003cbr\u003e  html += \"body{margin:0;font-family:Arial,sans-serif;background:#0b0b0b;color:#f5f5f5;padding:22px;}\";\u003cbr\u003e  html += \".wrap{max-width:980px;margin:0 auto;}\";\u003cbr\u003e  html += \"h1{margin:0 0 18px 0;text-align:center;font-size:28px;font-weight:700;color:#ffffff;}\";\u003cbr\u003e  html += \".card{background:#161616;border:1px solid rgba(255,255,255,0.08);border-radius:20px;padding:24px;margin-bottom:22px;box-shadow:0 10px 24px rgba(0,0,0,0.35);} \";\u003cbr\u003e  html += \"h2{margin:0 0 18px 0;font-size:18px;color:#ffffff;}\";\u003cbr\u003e  html += \"label{display:block;margin:14px 0 8px 0;font-weight:600;color:#d7d7d7;}\";\u003cbr\u003e  html += \"input{width:100%;padding:14px 16px;border-radius:12px;border:1px solid rgba(255,255,255,0.10);background:#0f0f0f;color:#fff;box-sizing:border-box;font-size:15px;outline:none;}\";\u003cbr\u003e  html += \"input::placeholder{color:#8d8d8d;}\";\u003cbr\u003e  html += \".actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:22px;}\";\u003cbr\u003e  html += \".btn{display:inline-block;padding:13px 22px;border:none;border-radius:12px;font-size:15px;font-weight:700;text-decoration:none;cursor:pointer;}\";\u003cbr\u003e  html += \".btn-primary{background:#4d8ef7;color:#fff;}\";\u003cbr\u003e  html += \".btn-secondary{background:#4b4b4b;color:#fff;}\";\u003cbr\u003e  html += \".btn-edit{background:#4d8ef7;color:#fff;padding:10px 18px;border-radius:10px;text-decoration:none;}\";\u003cbr\u003e  html += \".btn-delete{background:#ef4b3f;color:#fff;padding:10px 18px;border-radius:10px;text-decoration:none;display:inline-block;}\";\u003cbr\u003e  html += \"table{width:100%;border-collapse:collapse;overflow:hidden;border-radius:14px;}\";\u003cbr\u003e  html += \"th,td{padding:16px 14px;border:1px solid rgba(255,255,255,0.08);text-align:left;vertical-align:middle;}\";\u003cbr\u003e  html += \"th{background:#202020;color:#f2f2f2;font-size:15px;}\";\u003cbr\u003e  html += \"td{background:#161616;}\";\u003cbr\u003e  html += \".table-actions{display:flex;gap:10px;flex-wrap:wrap;align-items:center;}\";\u003cbr\u003e  html += \".muted{color:#bdbdbd;font-size:14px;margin-top:8px;}\";\u003cbr\u003e  html += \"@media (max-width:700px){body{padding:14px;} .card{padding:18px;} th,td{padding:12px 10px;font-size:14px;} .table-actions{flex-direction:column;align-items:stretch;}}\";\u003cbr\u003e  html += \"\u0026lt;\/style\u0026gt;\u0026lt;\/head\u0026gt;\u0026lt;body\u0026gt;\u0026lt;div class='wrap'\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;h1\u0026gt;Password Management\u0026lt;\/h1\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;div class='card'\u0026gt;\u0026lt;h2\u0026gt;\";\u003c\/p\u003e\n\u003cp\u003e  html += isEditMode ? \"Edit Saved Password\" : \"Add New Password\";\u003cbr\u003e  html += \"\u0026lt;\/h2\u0026gt;\u0026lt;form method='POST' action='\/save'\u0026gt;\";\u003c\/p\u003e\n\u003cp\u003e  if (isEditMode) {\u003cbr\u003e    html += \"\u0026lt;input type='hidden' name='edit_index' value='\" + String(editIndex) + \"'\u0026gt;\";\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  html += \"\u0026lt;label\u0026gt;Name\u0026lt;\/label\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;input name='item_name' placeholder='Example: Gmail' value='\" + formName + \"'\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;label\u0026gt;Username\u0026lt;\/label\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;input name='item_user' placeholder='Enter username' value='\" + formUser + \"'\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;label\u0026gt;Password\u0026lt;\/label\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;input id='pwd' name='item_pass' type='text' placeholder='Enter new password' value='\" + formPass + \"'\u0026gt;\";\u003c\/p\u003e\n\u003cp\u003e  \/\/ Password generator UI\u003cbr\u003e  html += \"\u0026lt;div style='margin-top:16px;'\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;div style='margin-bottom:8px;color:#cfcfcf;'\u0026gt;Password Length: \u0026lt;span id='lenVal'\u0026gt;16\u0026lt;\/span\u0026gt;\u0026lt;\/div\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;input id='len' type='range' min='4' max='64' value='16' style='width:100%;'\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;div style='display:flex;justify-content:space-between;color:#8d8d8d;font-size:12px;'\u0026gt;\u0026lt;span\u0026gt;4\u0026lt;\/span\u0026gt;\u0026lt;span\u0026gt;64\u0026lt;\/span\u0026gt;\u0026lt;\/div\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;div style='margin-top:10px;'\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;button type='button' class='btn btn-secondary' onclick='gen()'\u0026gt;Regenerate\u0026lt;\/button\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;\/div\u0026gt;\u0026lt;\/div\u0026gt;\";\u003c\/p\u003e\n\u003cp\u003e  \/\/ Inline JS for generation\u003cbr\u003e  html += \"\u0026lt;script\u0026gt;\";\u003cbr\u003e  html += \"const cs='ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz23456789!@#$%^\u0026amp;*';\";\u003cbr\u003e  html += \"function gen(){var l=parseInt(document.getElementById('len').value)||16;var s='';for(var i=0;i\u0026lt;l;i++){s+=cs[Math.floor(Math.random()*cs.length)];}document.getElementById('pwd').value=s;document.getElementById('lenVal').textContent=l;}\";\u003cbr\u003e  html += \"document.addEventListener('DOMContentLoaded',function(){var r=document.getElementById('len');var v=document.getElementById('lenVal');if(r\u0026amp;\u0026amp;v){v.textContent=r.value;r.addEventListener('input',function(){v.textContent=this.value;});}});\";\u003cbr\u003e  html += \"\u0026lt;\/script\u0026gt;\";\u003c\/p\u003e\n\u003cp\u003e  html += \"\u0026lt;div class='actions'\u0026gt;\";\u003cbr\u003e  html += \"\u0026lt;button class='btn btn-primary' type='submit'\u0026gt;\";\u003cbr\u003e  html += isEditMode ? \"Save Changes\" : \"Add Password\";\u003cbr\u003e  html += \"\u0026lt;\/button\u0026gt;\";\u003cbr\u003e  if (isEditMode) {\u003cbr\u003e    html += \"\u0026lt;a class='btn btn-secondary' href=\"\/ku\"\u0026gt;Cancel\u0026lt;\/a\u0026gt;\";\u003cbr\u003e  }\u003cbr\u003e  html += \"\u0026lt;\/div\u0026gt;\u0026lt;\/form\u0026gt;\u0026lt;\/div\u0026gt;\";\u003c\/p\u003e\n\u003cp\u003e  html += \"\u0026lt;div class='card'\u0026gt;\u0026lt;h2\u0026gt;Saved Passwords\u0026lt;\/h2\u0026gt;\";\u003cbr\u003e  if (passwordMenuCount == 0) {\u003cbr\u003e    html += \"\u0026lt;p class='muted'\u0026gt;No saved passwords yet.\u0026lt;\/p\u0026gt;\";\u003cbr\u003e  } else {\u003cbr\u003e    html += \"\u0026lt;table\u0026gt;\u0026lt;tr\u0026gt;\u0026lt;th\u0026gt;Name\u0026lt;\/th\u0026gt;\u0026lt;th\u0026gt;Username\u0026lt;\/th\u0026gt;\u0026lt;th\u0026gt;Actions\u0026lt;\/th\u0026gt;\u0026lt;\/tr\u0026gt;\";\u003cbr\u003e    for (int i = 0; i \u0026lt; passwordMenuCount; i++) {\u003cbr\u003e      html += \"\u0026lt;tr\u0026gt;\";\u003cbr\u003e      html += \"\u0026lt;td\u0026gt;\" + htmlEscape(passwordNameValues[i]) + \"\u0026lt;\/td\u0026gt;\";\u003cbr\u003e      html += \"\u0026lt;td\u0026gt;\" + htmlEscape(passwordUsernameValues[i]) + \"\u0026lt;\/td\u0026gt;\";\u003cbr\u003e      html += \"\u0026lt;td\u0026gt;\u0026lt;div class='table-actions'\u0026gt;\";\u003cbr\u003e      html += \"\u0026lt;a class='btn-edit' href='\/?edit=\" + String(i) + \"'\u0026gt;Edit\u0026lt;\/a\u0026gt;\";\u003cbr\u003e      html += \"\u0026lt;a class='btn-delete' href='\/delete_now?index=\" + String(i) + \"\u0026amp;ts=\" + String(millis()) + \"'\u0026gt;Delete\u0026lt;\/a\u0026gt;\";\u003cbr\u003e      html += \"\u0026lt;\/div\u0026gt;\u0026lt;\/td\u0026gt;\";\u003cbr\u003e      html += \"\u0026lt;\/tr\u0026gt;\";\u003cbr\u003e    }\u003cbr\u003e    html += \"\u0026lt;\/table\u0026gt;\";\u003cbr\u003e  }\u003cbr\u003e  html += \"\u0026lt;\/div\u0026gt;\u0026lt;\/div\u0026gt;\u0026lt;\/body\u0026gt;\u0026lt;\/html\u0026gt;\";\u003c\/p\u003e\n\u003cp\u003e  server.sendHeader(\"Cache-Control\", \"no-store, no-cache, must-revalidate, max-age=0\");\u003cbr\u003e  server.sendHeader(\"Pragma\", \"no-cache\");\u003cbr\u003e  server.sendHeader(\"Expires\", \"-1\");\u003cbr\u003e  server.send(200, \"text\/html\", html);\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid handlePortalSave() {\u003cbr\u003e  String itemName = server.arg(\"item_name\");\u003cbr\u003e  String itemUser = server.arg(\"item_user\");\u003cbr\u003e  String itemPass = server.arg(\"item_pass\");\u003cbr\u003e  itemName.trim();\u003cbr\u003e  itemUser.trim();\u003cbr\u003e  itemPass.trim();\u003c\/p\u003e\n\u003cp\u003e  if (itemName.length() == 0) {\u003cbr\u003e    server.send(200, \"text\/html\", \"\u0026lt;!doctype html\u0026gt;\u0026lt;html\u0026gt;\u0026lt;body style='background:#0b0b0b;color:#fff;font-family:Arial;padding:24px;'\u0026gt;\u0026lt;h2\u0026gt;Name is required\u0026lt;\/h2\u0026gt;\u0026lt;p\u0026gt;\u0026lt;a href=\"\/ku\" style='color:#7fc0ff;'\u0026gt;Back\u0026lt;\/a\u0026gt;\u0026lt;\/p\u0026gt;\u0026lt;\/body\u0026gt;\u0026lt;\/html\u0026gt;\");\u003cbr\u003e    return;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  int targetIndex = -1;\u003cbr\u003e  if (server.hasArg(\"edit_index\")) {\u003cbr\u003e    targetIndex = server.arg(\"edit_index\").toInt();\u003cbr\u003e    if (targetIndex \u0026lt; 0 || targetIndex \u0026gt;= passwordMenuCount) {\u003cbr\u003e      targetIndex = -1;\u003cbr\u003e    }\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (targetIndex \u0026gt;= 0) {\u003cbr\u003e    itemName.toCharArray(passwordNameValues[targetIndex], sizeof(passwordNameValues[targetIndex]));\u003cbr\u003e    itemUser.toCharArray(passwordUsernameValues[targetIndex], sizeof(passwordUsernameValues[targetIndex]));\u003cbr\u003e    if (itemPass.length() \u0026gt; 0) {\u003cbr\u003e      itemPass.toCharArray(passwordTextValues[targetIndex], sizeof(passwordTextValues[targetIndex]));\u003cbr\u003e    }\u003cbr\u003e  } else {\u003cbr\u003e    if (itemPass.length() == 0) {\u003cbr\u003e      server.send(200, \"text\/html\", \"\u0026lt;!doctype html\u0026gt;\u0026lt;html\u0026gt;\u0026lt;body style='background:#0b0b0b;color:#fff;font-family:Arial;padding:24px;'\u0026gt;\u0026lt;h2\u0026gt;Password is required for new items\u0026lt;\/h2\u0026gt;\u0026lt;p\u0026gt;\u0026lt;a href=\"\/ku\" style='color:#7fc0ff;'\u0026gt;Back\u0026lt;\/a\u0026gt;\u0026lt;\/p\u0026gt;\u0026lt;\/body\u0026gt;\u0026lt;\/html\u0026gt;\");\u003cbr\u003e      return;\u003cbr\u003e    }\u003c\/p\u003e\n\u003cp\u003e    if (passwordMenuCount \u0026gt;= MAX_PASSWORD_ITEMS) {\u003cbr\u003e      server.send(200, \"text\/html\", \"\u0026lt;!doctype html\u0026gt;\u0026lt;html\u0026gt;\u0026lt;body style='background:#0b0b0b;color:#fff;font-family:Arial;padding:24px;'\u0026gt;\u0026lt;h2\u0026gt;Storage full\u0026lt;\/h2\u0026gt;\u0026lt;p\u0026gt;Maximum password items reached.\u0026lt;\/p\u0026gt;\u0026lt;p\u0026gt;\u0026lt;a href=\"\/ku\" style='color:#7fc0ff;'\u0026gt;Back\u0026lt;\/a\u0026gt;\u0026lt;\/p\u0026gt;\u0026lt;\/body\u0026gt;\u0026lt;\/html\u0026gt;\");\u003cbr\u003e      return;\u003cbr\u003e    }\u003c\/p\u003e\n\u003cp\u003e    itemName.toCharArray(passwordNameValues[passwordMenuCount], sizeof(passwordNameValues[passwordMenuCount]));\u003cbr\u003e    itemUser.toCharArray(passwordUsernameValues[passwordMenuCount], sizeof(passwordUsernameValues[passwordMenuCount]));\u003cbr\u003e    itemPass.toCharArray(passwordTextValues[passwordMenuCount], sizeof(passwordTextValues[passwordMenuCount]));\u003cbr\u003e    passwordMenuCount++;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  refreshPasswordMenuItems();\u003cbr\u003e  savePasswordsToPreferences();\u003cbr\u003e  handlePortalRoot();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid stopSettingsPortal();\u003c\/p\u003e\n\u003cp\u003evoid startSettingsPortal() {\u003cbr\u003e  stopSettingsPortal();\u003cbr\u003e  WiFi.disconnect(true, true);\u003cbr\u003e  WiFi.softAPdisconnect(true);\u003cbr\u003e  delay(200);\u003cbr\u003e  WiFi.mode(WIFI_AP);\u003cbr\u003e  delay(100);\u003c\/p\u003e\n\u003cp\u003e  bool apStarted = WiFi.softAP(\"Dr. Passwords\", settingsApPassword.c_str());\u003cbr\u003e  delay(300);\u003c\/p\u003e\n\u003cp\u003e  if (!apStarted) {\u003cbr\u003e    display.clearDisplay();\u003cbr\u003e    display.setTextColor(SSD1306_WHITE);\u003cbr\u003e    display.setTextSize(1);\u003cbr\u003e    display.setCursor(10, 20);\u003cbr\u003e    display.println(\"AP Start Failed\");\u003cbr\u003e    display.setCursor(10, 40);\u003cbr\u003e    display.println(\"Check AP Password\");\u003cbr\u003e    display.display();\u003cbr\u003e    delay(1200);\u003cbr\u003e    currentScreen = SCREEN_MAIN;\u003cbr\u003e    drawMenu();\u003cbr\u003e    return;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  server.stop();\u003cbr\u003e  dnsServer.stop();\u003c\/p\u003e\n\u003cp\u003e  dnsServer.start(DNS_PORT, \"*\", WiFi.softAPIP());\u003cbr\u003e  server.on(\"\/\", HTTP_GET, handlePortalRoot);\u003cbr\u003e  server.on(\"\/generate_204\", HTTP_GET, handlePortalRoot);\u003cbr\u003e  server.on(\"\/hotspot-detect.html\", HTTP_GET, handlePortalRoot);\u003cbr\u003e  server.on(\"\/ncsi.txt\", HTTP_GET, handlePortalRoot);\u003cbr\u003e  server.on(\"\/save\", HTTP_POST, handlePortalSave);\u003cbr\u003e  server.on(\"\/delete_now\", HTTP_GET, handlePortalDeleteNow);\u003cbr\u003e  server.onNotFound(handlePortalRoot);\u003cbr\u003e  server.begin();\u003c\/p\u003e\n\u003cp\u003e  settingsPortalActive = true;\u003cbr\u003e  drawSettingsPortalScreen();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid handlePortalDeleteNow() {\u003cbr\u003e  if (!server.hasArg(\"index\")) {\u003cbr\u003e    handlePortalRoot();\u003cbr\u003e    return;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  int deleteIndex = server.arg(\"index\").toInt();\u003cbr\u003e  if (deleteIndex \u0026lt; 0 || deleteIndex \u0026gt;= passwordMenuCount) {\u003cbr\u003e    handlePortalRoot();\u003cbr\u003e    return;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  for (int i = deleteIndex; i \u0026lt; passwordMenuCount - 1; i++) {\u003cbr\u003e    strlcpy(passwordNameValues[i], passwordNameValues[i + 1], sizeof(passwordNameValues[i]));\u003cbr\u003e    strlcpy(passwordUsernameValues[i], passwordUsernameValues[i + 1], sizeof(passwordUsernameValues[i]));\u003cbr\u003e    strlcpy(passwordTextValues[i], passwordTextValues[i + 1], sizeof(passwordTextValues[i]));\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  passwordMenuCount--;\u003cbr\u003e  if (passwordMenuCount \u0026lt; 0) passwordMenuCount = 0;\u003c\/p\u003e\n\u003cp\u003e  if (passwordMenuCount \u0026lt; MAX_PASSWORD_ITEMS) {\u003cbr\u003e    passwordNameValues[passwordMenuCount][0] = ' ';\u003cbr\u003e    passwordUsernameValues[passwordMenuCount][0] = ' ';\u003cbr\u003e    passwordTextValues[passwordMenuCount][0] = ' ';\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (selectedIndex \u0026gt;= passwordMenuCount \u0026amp;\u0026amp; passwordMenuCount \u0026gt; 0) {\u003cbr\u003e    selectedIndex = passwordMenuCount - 1;\u003cbr\u003e  }\u003cbr\u003e  if (selectedIndex \u0026lt; 0) selectedIndex = 0;\u003c\/p\u003e\n\u003cp\u003e  refreshPasswordMenuItems();\u003cbr\u003e  savePasswordsToPreferences();\u003cbr\u003e  handlePortalRoot();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid stopSettingsPortal() {\u003cbr\u003e  if (!settingsPortalActive) return;\u003cbr\u003e  dnsServer.stop();\u003cbr\u003e  server.stop();\u003cbr\u003e  WiFi.softAPdisconnect(true);\u003cbr\u003e  WiFi.mode(WIFI_OFF);\u003cbr\u003e  settingsPortalActive = false;\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid processSettingsPortal() {\u003cbr\u003e  if (!settingsPortalActive) return;\u003cbr\u003e  dnsServer.processNextRequest();\u003cbr\u003e  server.handleClient();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid drawBootScreen() {\u003cbr\u003e  display.clearDisplay();\u003cbr\u003e  display.setTextColor(SSD1306_WHITE);\u003cbr\u003e  \u003cbr\u003e  \/\/ تصغير الخط ليناسب الشاشة\u003cbr\u003e  display.setTextSize(1); \u003c\/p\u003e\n\u003cp\u003e  const char* title = \"Dr. Passwords\";\u003cbr\u003e  int charWidth = 6;\u003cbr\u003e  int textWidth = strlen(title) * charWidth;\u003cbr\u003e  int x = (SCREEN_WIDTH - textWidth) \/ 2;\u003cbr\u003e  int y = (SCREEN_HEIGHT \/ 2) - 4;\u003c\/p\u003e\n\u003cp\u003e  display.setCursor(x, y);\u003cbr\u003e  display.println(title);\u003cbr\u003e  display.display(); \/\/ تحديث الشاشة\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid moveUp() {\u003cbr\u003e  int itemCount = getCurrentMenuCount();\u003cbr\u003e  selectedIndex--;\u003cbr\u003e  if (selectedIndex \u0026lt; 0) selectedIndex = itemCount - 1;\u003cbr\u003e  drawMenu();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid moveDown() {\u003cbr\u003e  int itemCount = getCurrentMenuCount();\u003cbr\u003e  selectedIndex++;\u003cbr\u003e  if (selectedIndex \u0026gt;= itemCount) selectedIndex = 0;\u003cbr\u003e  drawMenu();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid sendSelectedItem() {\u003cbr\u003e  MenuItem* items = getCurrentMenuItems();\u003cbr\u003e  MenuItem \u0026amp;item = items[selectedIndex];\u003c\/p\u003e\n\u003cp\u003e  if (currentScreen == SCREEN_TOTP_VIEW) {\u003cbr\u003e    time_t now;\u003cbr\u003e    if (!getCurrentUnixTime(now)) return;\u003c\/p\u003e\n\u003cp\u003e    char* code = totpMenuItems[activeTotpIndex].totp-\u0026gt;getCode(now);\u003cbr\u003e    Keyboard.print(code);\u003cbr\u003e    return;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (settingsPortalActive) {\u003cbr\u003e    Keyboard.print(settingsApPassword);\u003cbr\u003e    return;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (currentScreen == SCREEN_PASSWORD_ACTIONS) {\u003cbr\u003e    showSendingScreen(passwordMenuItems[activePasswordIndex].name);\u003cbr\u003e    delay(250);\u003c\/p\u003e\n\u003cp\u003e    if (selectedIndex == 0) {\u003cbr\u003e      Keyboard.print(passwordUsernameValues[activePasswordIndex]);\u003cbr\u003e    } else if (selectedIndex == 1) {\u003cbr\u003e      Keyboard.print(passwordTextValues[activePasswordIndex]);\u003cbr\u003e    } else if (selectedIndex == 2) {\u003cbr\u003e      Keyboard.print(passwordUsernameValues[activePasswordIndex]);\u003cbr\u003e      Keyboard.write(KEY_TAB);\u003cbr\u003e      Keyboard.print(passwordTextValues[activePasswordIndex]);\u003cbr\u003e    } else if (selectedIndex == 1) {\u003cbr\u003e      Keyboard.print(passwordUsernameValues[activePasswordIndex]);\u003cbr\u003e    } else if (selectedIndex == 2) {\u003cbr\u003e      Keyboard.print(passwordUsernameValues[activePasswordIndex]);\u003cbr\u003e      Keyboard.write(KEY_TAB);\u003cbr\u003e      Keyboard.print(passwordTextValues[activePasswordIndex]);\u003cbr\u003e    }\u003c\/p\u003e\n\u003cp\u003e    delay(400);\u003cbr\u003e    drawMenu();\u003cbr\u003e    return;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (item.type == ITEM_SUBMENU) {\u003cbr\u003e    if (currentScreen == SCREEN_MAIN) {\u003cbr\u003e      if (selectedIndex == 0) {\u003cbr\u003e        currentScreen = SCREEN_PASSWORDS;\u003cbr\u003e        selectedIndex = 0;\u003cbr\u003e        menuScrollOffset = 0;\u003cbr\u003e        drawMenu();\u003cbr\u003e      } else if (selectedIndex == 1) {\u003cbr\u003e        if (!timeSynced) {\u003cbr\u003e          showStatusScreen(\"Connecting WiFi\", \"TOTP\");\u003cbr\u003e          syncTimeOverWiFi();\u003cbr\u003e          timeSynced = true;\u003cbr\u003e        }\u003cbr\u003e        activeTotpIndex = 0;\u003cbr\u003e        currentScreen = SCREEN_TOTP_VIEW;\u003cbr\u003e        lastTotpRedraw = 0;\u003cbr\u003e      } else if (selectedIndex == 2) {\u003cbr\u003e        selectedIndex = 0;\u003cbr\u003e        menuScrollOffset = 0;\u003cbr\u003e        startSettingsPortal();\u003cbr\u003e      }\u003cbr\u003e    }\u003cbr\u003e    return;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (item.type == ITEM_INFO) {\u003cbr\u003e    return;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (item.type == ITEM_TEXT) {\u003cbr\u003e    activePasswordIndex = selectedIndex;\u003cbr\u003e    currentScreen = SCREEN_PASSWORD_ACTIONS;\u003cbr\u003e    selectedIndex = 0;\u003cbr\u003e    menuScrollOffset = 0;\u003cbr\u003e    drawMenu();\u003cbr\u003e    return;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (item.type == ITEM_TOTP) {\u003cbr\u003e    if (!timeSynced) {\u003cbr\u003e      showStatusScreen(\"Connecting WiFi\", item.name);\u003cbr\u003e      syncTimeOverWiFi();\u003cbr\u003e      timeSynced = true;\u003cbr\u003e    }\u003c\/p\u003e\n\u003cp\u003e    activeTotpIndex = selectedIndex;\u003cbr\u003e    currentScreen = SCREEN_TOTP_VIEW;\u003cbr\u003e    lastTotpRedraw = 0;\u003cbr\u003e    return;\u003cbr\u003e  }\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid setup() {\u003cbr\u003e  \/\/ 1. تعريف الأزرار\u003cbr\u003e  pinMode(BTN_OK_UP, INPUT_PULLUP);\u003cbr\u003e  pinMode(BTN_DOWN, INPUT_PULLUP);\u003c\/p\u003e\n\u003cp\u003e  \/\/ 2. تشغيل الشاشة أوووولاً قبل أي شيء آخر!\u003cbr\u003e  Wire.begin(I2C_SDA, I2C_SCL);\u003cbr\u003e  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {\u003cbr\u003e    for(;;); \/\/ توقف هنا إذا لم يتم العثور على الشاشة\u003cbr\u003e  }\u003cbr\u003e  display.clearDisplay();\u003cbr\u003e  \u003cbr\u003e  \/\/ 3. عرض شاشة الإقلاع فوراً لنعرف أن اللوحة تعمل\u003cbr\u003e  drawBootScreen();\u003cbr\u003e  delay(1000); \/\/ ننتظر ثانية لنستمتع برؤية الشعار\u003c\/p\u003e\n\u003cp\u003e  \/\/ 4. الآن نقوم بإنشاء كلمة مرور البوابة وقراءة الذاكرة بأمان\u003cbr\u003e  settingsApPassword = generateApPassword();\u003cbr\u003e  \/\/Uncomment For Easy Tests\u003cbr\u003e  \/\/settingsApPassword = \"12345678\";\u003cbr\u003e  \u003cbr\u003e  loadSavedPasswords();\u003c\/p\u003e\n\u003cp\u003e  \/\/ 5. تهيئة رمز الـ TOTP\u003cbr\u003e  if (!initTotp()) {\u003cbr\u003e    display.clearDisplay();\u003cbr\u003e    display.setTextColor(SSD1306_WHITE);\u003cbr\u003e    display.setTextSize(1);\u003cbr\u003e    display.setCursor(10, 20);\u003cbr\u003e    display.println(\"TOTP Error\");\u003cbr\u003e    display.setCursor(10, 35);\u003cbr\u003e    display.println(\"Invalid Base32\");\u003cbr\u003e    display.display();\u003cbr\u003e    while (true) delay(1000);\u003cbr\u003e  }\u003cbr\u003e  totpMenuItems[0].totp = gmailTotp;\u003c\/p\u003e\n\u003cp\u003e  \/\/ 6. تشغيل لوحة المفاتيح والـ USB\u003cbr\u003e  Keyboard.begin();\u003cbr\u003e  USB.begin();\u003cbr\u003e  delay(USB_STARTUP_DELAY_MS);\u003c\/p\u003e\n\u003cp\u003e  \/\/ 7. أخيراً، عرض القائمة الرئيسية لتكون جاهزة للاستخدام\u003cbr\u003e  drawMenu();\u003cbr\u003e}\u003c\/p\u003e\n\u003cp\u003evoid loop() {\u003cbr\u003e  processSettingsPortal();\u003cbr\u003e  bool okUpState = digitalRead(BTN_OK_UP);\u003cbr\u003e  bool downState = digitalRead(BTN_DOWN);\u003cbr\u003e  unsigned long nowMs = millis();\u003c\/p\u003e\n\u003cp\u003e  if (currentScreen == SCREEN_TOTP_VIEW) {\u003cbr\u003e    time_t now;\u003cbr\u003e    if (getCurrentUnixTime(now)) {\u003cbr\u003e      int secondsRemaining = 30 - (now % 30);\u003cbr\u003e      if (secondsRemaining == 30) secondsRemaining = 0;\u003c\/p\u003e\n\u003cp\u003e      if (lastTotpRedraw != (unsigned long)now) {\u003cbr\u003e        char* code = totpMenuItems[activeTotpIndex].totp-\u0026gt;getCode(now);\u003cbr\u003e        showTotpCodeScreen(totpMenuItems[activeTotpIndex].name, code, secondsRemaining);\u003cbr\u003e        lastTotpRedraw = (unsigned long)now;\u003cbr\u003e      }\u003cbr\u003e    }\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (okUpState == LOW) {\u003cbr\u003e    if (!btnPressed) {\u003cbr\u003e      btnPressed = true;\u003cbr\u003e      btnPressStart = nowMs;\u003cbr\u003e      holdTriggered = false;\u003cbr\u003e    } else {\u003cbr\u003e      if (!holdTriggered \u0026amp;\u0026amp; (nowMs - btnPressStart \u0026gt;= HOLD_TIME_MS)) {\u003cbr\u003e        holdTriggered = true;\u003cbr\u003e        sendSelectedItem();\u003cbr\u003e      }\u003cbr\u003e    }\u003cbr\u003e  } else {\u003cbr\u003e    if (btnPressed \u0026amp;\u0026amp; !holdTriggered) {\u003cbr\u003e      if (currentScreen != SCREEN_TOTP_VIEW \u0026amp;\u0026amp; !settingsPortalActive) {\u003cbr\u003e        moveDown();\u003cbr\u003e      }\u003cbr\u003e    }\u003cbr\u003e    btnPressed = false;\u003cbr\u003e    holdTriggered = false;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  if (downState == LOW) {\u003cbr\u003e    if (lastDownState == HIGH) {\u003cbr\u003e      lastDownPress = nowMs;\u003cbr\u003e      downHoldHandled = false;\u003cbr\u003e    }\u003c\/p\u003e\n\u003cp\u003e    if (!downHoldHandled \u0026amp;\u0026amp; (nowMs - lastDownPress \u0026gt;= HOLD_TIME_MS)) {\u003cbr\u003e      downHoldHandled = true;\u003c\/p\u003e\n\u003cp\u003e      if (currentScreen == SCREEN_TOTP_VIEW) {\u003cbr\u003e        currentScreen = SCREEN_TOTP;\u003cbr\u003e        selectedIndex = 0;\u003cbr\u003e        menuScrollOffset = 0;\u003cbr\u003e        drawMenu();\u003cbr\u003e      } else if (currentScreen == SCREEN_PASSWORD_ACTIONS) {\u003cbr\u003e        currentScreen = SCREEN_PASSWORDS;\u003cbr\u003e        selectedIndex = activePasswordIndex;\u003cbr\u003e        drawMenu();\u003cbr\u003e      } else if (settingsPortalActive) {\u003cbr\u003e        stopSettingsPortal();\u003cbr\u003e        currentScreen = SCREEN_MAIN;\u003cbr\u003e        selectedIndex = 0;\u003cbr\u003e        menuScrollOffset = 0;\u003cbr\u003e        drawMenu();\u003cbr\u003e      } else if (currentScreen != SCREEN_MAIN) {\u003cbr\u003e        currentScreen = SCREEN_MAIN;\u003cbr\u003e        selectedIndex = 0;\u003cbr\u003e        menuScrollOffset = 0;\u003cbr\u003e        drawMenu();\u003cbr\u003e      }\u003cbr\u003e    }\u003cbr\u003e  } else {\u003cbr\u003e    if (lastDownState == LOW \u0026amp;\u0026amp; !downHoldHandled \u0026amp;\u0026amp; (nowMs - lastDownPress \u0026lt; HOLD_TIME_MS)) {\u003cbr\u003e      if (currentScreen != SCREEN_TOTP_VIEW \u0026amp;\u0026amp; !settingsPortalActive) {\u003cbr\u003e        moveUp();\u003cbr\u003e      }\u003cbr\u003e    }\u003cbr\u003e    downHoldHandled = false;\u003cbr\u003e  }\u003c\/p\u003e\n\u003cp\u003e  lastDownState = downState;\u003c\/p\u003e\n\u003cp\u003e  delay(20);\u003cbr\u003e}\u003c\/p\u003e\n\u003cbr\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"[--thread-content-max-width:40rem] @w-lg\/main:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1\"\u003e\n\u003cdiv\u003e\u003cbr\u003e\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/section\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv class=\"pointer-events-none -mt-px h-px translate-y-(--scroll-root-safe-area-inset-bottom)\"\u003e\u003cbr\u003e\u003c\/div\u003e","brand":"SkyTech","offers":[{"title":"Default Title","offer_id":48884374700185,"sku":null,"price":200000.0,"currency_code":"IQD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0708\/8131\/2921\/files\/photo_2026-08-17_20-04-52.jpg?v=1786986309","url":"https:\/\/skyteches.com\/ku\/products\/skytech-password-wallet","provider":"SkyTech","version":"1.0","type":"link"}