{"id":7,"date":"2026-02-10T17:11:22","date_gmt":"2026-02-10T17:11:22","guid":{"rendered":"https:\/\/visit-centralmacedonia.click\/?page_id=7"},"modified":"2026-02-19T13:27:23","modified_gmt":"2026-02-19T13:27:23","slug":"pkm","status":"publish","type":"page","link":"https:\/\/visit-centralmacedonia.click\/es\/","title":{"rendered":"PKM"},"content":{"rendered":"<div data-elementor-type=\"wp-post\" data-elementor-id=\"7\" class=\"elementor elementor-7\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-668aaba e-flex e-con-boxed e-con e-parent\" data-id=\"668aaba\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-6b4ca0c elementor-widget elementor-widget-html\" data-id=\"6b4ca0c\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\n<!--\n  ========================================\n  WORDPRESS UPLOAD INSTRUCTIONS\n  ========================================\n  \n  1. Upload these files to WordPress Media Library or via FTP:\n     - logo_pkm.jpg (or current logo image)\n     - ChatGPT Image Feb 10, 2026, 08_51_06 PM.png (background image)\n     - 855564-hd_1920_1080_24fps.mp4 (video)\n     - All WebP image files from the gallery-webp\/ folder\n  \n  2. Upload these JSON files (via FTP or cPanel File Manager):\n     - pois.json to: \/wp-content\/uploads\/pois.json\n     - gallery-webp\/metadata.json to: \/wp-content\/uploads\/Gallery\/metadata.json\n  \n  3. Update the CONFIG object in the <script> section (search for \"CONFIG\"):\n     - Set galleryPath to match where you uploaded the gallery images\n       Example: 'https:\/\/yoursite.com\/wp-content\/uploads\/Gallery\/'\n       (must end with \/)\n  \n  4. Paste this entire HTML into a WordPress Custom HTML block or page\n  \n  NOTE: The gallery loads images dynamically from metadata.json.\n  To add\/remove\/edit gallery items, edit gallery-webp\/metadata.json and re-upload it.\n  \n  ========================================\n-->\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Central Macedonia<\/title>\n  <!-- Google Fonts: Roboto with Greek subset -->\n  <link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\n  <link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\n  <link href=\"https:\/\/fonts.googleapis.com\/css2?family=Roboto:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;1,400;1,500&subset=greek,greek-ext,latin,latin-ext&display=swap\" rel=\"stylesheet\">\n  <!-- Leaflet CSS\/JS deferred - loaded on demand when map tab is opened -->\n  <style>\n    :root {\n      \/* Background Image Settings - Edit these values *\/\n      --bg-image-opacity: 1;\n      --bg-overlay-color: 255, 255, 255; \/* RGB values *\/\n      --bg-overlay-opacity: 0.30;\n      --bg-blur: 0px; \/* Try values like 5px, 10px *\/\n      --bg-brightness: 100%; \/* Try 80%, 120% *\/\n      --bg-contrast: 100%; \/* Try 80%, 120% *\/\n      --tab-bar-height: 50px;\n      --gallery-modes-height: 52px;\n    }\n    \n    * {\n      margin: 0;\n      padding: 0;\n      box-sizing: border-box;\n      -webkit-tap-highlight-color: transparent;\n    }\n    html {\n      height: 100vh;\n      overflow: hidden;\n      scroll-behavior: smooth;\n      -webkit-font-smoothing: antialiased;\n      -moz-osx-font-smoothing: grayscale;\n      overscroll-behavior-y: none;\n      overscroll-behavior-x: none;\n    }\n    body {\n      font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', 'Inter', Arial, sans-serif;\n      background: #fff;\n      margin: 0;\n      padding: 0;\n      height: 100vh;\n      overflow: hidden;\n      position: relative;\n      -webkit-font-smoothing: antialiased;\n      -moz-osx-font-smoothing: grayscale;\n      text-rendering: optimizeLegibility;\n      overscroll-behavior-y: none;\n      overscroll-behavior-x: none;\n      color: #1a1a1a;\n    }\n    body::before {\n      content: '';\n      position: fixed;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      background-image: url('ChatGPT%20Image%20Feb%2010,%202026,%2008_41_06%20PM.png');\n      background-size: cover;\n      background-position: center;\n      background-repeat: no-repeat;\n      opacity: var(--bg-image-opacity);\n      filter: blur(var(--bg-blur)) brightness(var(--bg-brightness)) contrast(var(--bg-contrast));\n      z-index: -2;\n      transform: translate3d(0, 0, 0);\n    }\n    body::after {\n      content: '';\n      position: fixed;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      background-color: rgba(var(--bg-overlay-color), var(--bg-overlay-opacity));\n      z-index: -1;\n    }\n    .phone-container {\n      width: 100%;\n      height: 100vh;\n      background: transparent;\n      position: relative;\n      display: flex;\n      flex-direction: column;\n      max-width: 100%;\n      overflow: hidden;\n    }\n    .status-bar {\n      display: none;\n    }\n    .view-container {\n      flex: 1;\n      position: relative;\n      overflow: hidden;\n      height: calc(100vh - var(--tab-bar-height));\n      overscroll-behavior-y: auto;\n    }\n    .view {\n      position: absolute;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      overflow-y: auto;\n      overflow-x: hidden;\n      \/* Fully hidden when not active \u2014 no GPU layer, no visibility, no paint *\/\n      display: none !important;\n      visibility: hidden;\n      opacity: 0;\n      pointer-events: none;\n      -webkit-overflow-scrolling: touch;\n      overscroll-behavior-y: contain;\n      overscroll-behavior-x: none;\n      scroll-behavior: smooth;\n      -ms-scroll-chaining: none;\n      scroll-snap-type: none;\n      touch-action: pan-y;\n    }\n    .view.active {\n      display: block !important;\n      visibility: visible;\n      opacity: 1;\n      pointer-events: auto;\n      z-index: 1;\n      \/* GPU acceleration only on the active view *\/\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      -webkit-overflow-scrolling: touch;\n      animation: fadeInView 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n    }\n    @keyframes fadeInView {\n      from { opacity: 0; transform: translate3d(0, 8px, 0); }\n      to { opacity: 1; transform: translate3d(0, 0, 0); }\n    }\n    \n    \/* Home View *\/\n    #home {\n      text-align: center;\n      padding: 0 20px 16px;\n      background: transparent;\n    }\n    .logo-section {\n      margin-bottom: 14px;\n    }\n    .logo-section img {\n      width: 120px;\n      height: 120px;\n      object-fit: contain;\n      margin-bottom: 10px;\n      filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.1));\n    }\n    .logo-section h1 {\n      font-size: 18px;\n      font-weight: 800;\n      color: #1562AC;\n      margin-bottom: 4px;\n      letter-spacing: 0.8px;\n      text-transform: uppercase;\n    }\n    .logo-section p {\n      font-size: 13px;\n      color: #555;\n      letter-spacing: 0.2px;\n      line-height: 1.4;\n    }\n    .logo-section p strong {\n      font-weight: 700;\n      color: #1562AC;\n    }\n    .button-list {\n      display: flex;\n      flex-direction: column;\n      gap: 8px;\n      margin-bottom: 14px;\n    }\n    .link-button {\n      background: rgba(255, 255, 255, 0.92);\n      backdrop-filter: blur(12px);\n      -webkit-backdrop-filter: blur(12px);\n      border: 1px solid rgba(0, 0, 0, 0.06);\n      border-radius: 14px;\n      padding: 12px 16px;\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      cursor: pointer;\n      transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      font-size: 14px;\n      font-weight: 600;\n      color: #2c2c2c;\n      touch-action: manipulation;\n      user-select: none;\n      -webkit-user-select: none;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04), 0 4px 12px rgba(0, 0, 0, 0.03);\n      letter-spacing: 0.2px;\n    }\n    .link-button:hover {\n      border-color: rgba(21, 98, 172, 0.15);\n      box-shadow: 0 2px 8px rgba(21, 98, 172, 0.08), 0 8px 24px rgba(0, 0, 0, 0.06);\n      transform: translate3d(0, -2px, 0);\n      background: rgba(255, 255, 255, 0.98);\n      color: #2c2c2c;\n    }\n    .link-button:active {\n      transform: translate3d(0, 0, 0) scale(0.98);\n      background: rgba(248, 248, 250, 0.95);\n      box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n      color: #2c2c2c;\n    }\n    .button-content {\n      display: flex;\n      align-items: center;\n      justify-content: flex-start;\n      gap: 14px;\n      flex: 1;\n    }\n    .button-text {\n      display: flex;\n      flex-direction: column;\n      align-items: flex-start;\n      gap: 2px;\n    }\n    .button-username {\n      font-size: 11px;\n      font-weight: 400;\n      color: #888;\n      letter-spacing: 0.1px;\n    }\n    .button-icon {\n      width: 22px;\n      height: 22px;\n      color: #1562AC;\n      flex-shrink: 0;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      opacity: 0.85;\n    }\n    .chevron-icon {\n      width: 16px;\n      height: 16px;\n      opacity: 0.3;\n      flex-shrink: 0;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      transition: opacity 0.2s ease, transform 0.2s ease;\n    }\n    .link-button:hover .chevron-icon {\n      opacity: 0.5;\n      transform: translateX(2px);\n    }\n    .link-button:hover .button-username {\n      color: #888;\n    }\n    .link-button:hover .button-icon {\n      color: #1562AC;\n    }\n    .video-card {\n      background: #000;\n      border-radius: 16px;\n      overflow: hidden;\n      position: relative;\n      box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12), 0 1px 3px rgba(0, 0, 0, 0.08);\n      margin-bottom: 28px;\n    }\n    .video-play-overlay {\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      transform: translate(-50%, -50%);\n      width: 72px;\n      height: 72px;\n      background: rgba(0, 0, 0, 0.45);\n      backdrop-filter: blur(8px);\n      -webkit-backdrop-filter: blur(8px);\n      border: 2.5px solid rgba(255, 255, 255, 0.35);\n      border-radius: 50%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      cursor: pointer;\n      z-index: 3;\n      transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      pointer-events: none;\n      will-change: transform, opacity;\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3), inset 0 0 0 1px rgba(255, 255, 255, 0.08);\n    }\n    .video-play-overlay.show {\n      pointer-events: auto;\n      animation: playPulse 2.5s ease-in-out 1s 2;\n    }\n    @keyframes playPulse {\n      0%, 100% { box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3), inset 0 0 0 1px rgba(255, 255, 255, 0.08); }\n      50% { box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3), inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 0 8px rgba(255, 255, 255, 0.12); }\n    }\n    .video-play-overlay.hide {\n      opacity: 0;\n      visibility: hidden;\n      transform: translate(-50%, -50%) scale(0.7);\n    }\n    .video-play-overlay:hover {\n      background: rgba(0, 0, 0, 0.55);\n      border-color: rgba(255, 255, 255, 0.6);\n      transform: translate(-50%, -50%) scale(1.1);\n      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4), inset 0 0 0 1px rgba(255, 255, 255, 0.15);\n    }\n    .video-play-overlay:active {\n      transform: translate(-50%, -50%) scale(1.02);\n      background: rgba(0, 0, 0, 0.6);\n    }\n    .video-play-overlay svg {\n      width: 30px;\n      height: 30px;\n      fill: white;\n      margin-left: 3px;\n      filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3));\n    }\n    .video-card:fullscreen {\n      border-radius: 0;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n    .video-player {\n      width: 100%;\n      display: block;\n      background: #000;\n      transition: transform 0.3s ease;\n    }\n    .video-card:fullscreen .video-player {\n      width: auto;\n      height: auto;\n      max-width: 100vw;\n      max-height: 100vh;\n      object-fit: contain;\n    }\n    .video-card:fullscreen .video-player.rotated-90,\n    .video-card:fullscreen .video-player.rotated-270 {\n      max-width: 100vh;\n      max-height: 100vw;\n    }\n    .video-controls {\n      position: absolute;\n      bottom: 0;\n      left: 0;\n      right: 0;\n      background: linear-gradient(to top, rgba(0, 0, 0, 0.85) 0%, rgba(0, 0, 0, 0.5) 50%, transparent 100%);\n      padding: 20px 15px 15px;\n      display: flex;\n      align-items: center;\n      gap: 12px;\n      opacity: 0;\n      transition: opacity 0.3s ease;\n      z-index: 2;\n    }\n    .video-card:hover .video-controls,\n    .video-card.show-controls .video-controls {\n      opacity: 1;\n    }\n    .video-controls button {\n      background: none;\n      border: none;\n      color: white;\n      cursor: pointer;\n      padding: 5px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      transition: transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.15s ease;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      touch-action: manipulation;\n    }\n    .video-controls button:hover {\n      transform: translate3d(0, 0, 0) scale(1.15);\n    }\n    .video-controls button:active {\n      transform: translate3d(0, 0, 0) scale(0.95);\n      opacity: 0.8;\n    }\n    .video-controls button svg {\n      width: 24px;\n      height: 24px;\n    }\n    .progress-bar {\n      flex: 1;\n      height: 4px;\n      background: rgba(255,255,255,0.3);\n      border-radius: 2px;\n      cursor: pointer;\n      position: relative;\n      overflow: hidden;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n    }\n    .progress-bar:hover {\n      height: 6px;\n      transition: height 0.15s ease;\n    }\n    .progress-bar-fill {\n      height: 100%;\n      background: #fff;\n      border-radius: 2px;\n      width: 0%;\n      transition: width 0.1s linear;\n      will-change: width;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n    }\n    .time-display {\n      color: rgba(255, 255, 255, 0.9);\n      font-size: 11px;\n      font-weight: 600;\n      min-width: 80px;\n      text-align: center;\n      letter-spacing: 0.3px;\n      font-variant-numeric: tabular-nums;\n    }\n    .fullscreen-btn {\n      margin-left: auto;\n    }\n    .rotate-btn-left,\n    .rotate-btn-right {\n      display: none;\n    }\n    .video-card:fullscreen .rotate-btn-left,\n    .video-card:fullscreen .rotate-btn-right {\n      display: flex;\n    }\n\n    \/* Gallery View *\/\n    #gallery {\n      padding: 0 0 80px 0;\n    }\n    .header {\n      display: none;\n    }\n    .header h2 {\n      font-size: 28px;\n      font-weight: 700;\n      color: #333;\n    }\n    .view-modes {\n      display: flex;\n      gap: 6px;\n      padding: 8px 12px;\n      background: rgba(255, 255, 255, 0.92);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      position: sticky;\n      top: 0;\n      z-index: 5;\n      border-bottom: 1px solid rgba(0, 0, 0, 0.06);\n      margin-bottom: 0;\n      justify-content: center;\n      align-items: center;\n    }\n    .gallery-back-btn {\n      position: absolute;\n      left: 12px;\n      background: transparent;\n      border: none;\n      padding: 6px;\n      cursor: pointer;\n      display: none;\n      align-items: center;\n      justify-content: center;\n      color: #262626;\n      transition: all 0.2s ease;\n      touch-action: manipulation;\n    }\n    .gallery-back-btn svg {\n      width: 24px;\n      height: 24px;\n    }\n    .gallery-back-btn:active {\n      transform: scale(0.9);\n    }\n    body.tab-gallery.one-one-active .gallery-back-btn {\n      display: flex;\n    }\n    .tab-gallery #gallery {\n      padding-top: var(--gallery-modes-height);\n      transform: none;\n    }\n    .tab-gallery .view-modes {\n      position: fixed;\n      top: 0;\n      left: 50%;\n      transform: translateX(-50%);\n      width: 100%;\n      max-width: 1280px;\n      z-index: 1000;\n    }\n    .view-mode-btn {\n      background: transparent;\n      border: none;\n      border-radius: 0;\n      padding: 6px 12px;\n      font-size: 12px;\n      font-weight: 600;\n      color: #999;\n      cursor: pointer;\n      transition: all 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);\n      text-transform: uppercase;\n      letter-spacing: 0.5px;\n      position: relative;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      touch-action: manipulation;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n    .view-mode-btn svg {\n      display: block;\n    }\n    .view-mode-btn.active {\n      background: transparent;\n      border-color: transparent;\n      color: #262626;\n    }\n    .view-mode-btn.active::after {\n      content: '';\n      position: absolute;\n      bottom: 0;\n      left: 50%;\n      transform: translateX(-50%);\n      width: 100%;\n      height: 2px;\n      background: #1562AC;\n      animation: slideIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n    }\n    @keyframes slideIn {\n      from { width: 0; }\n      to { width: 100%; }\n    }\n    .view-mode-btn:active {\n      transform: translate3d(0, 0, 0) scale(0.95);\n    }\n    .gallery-grid {\n      display: flex;\n      flex-direction: column;\n      gap: 20px;\n      opacity: 1;\n      transition: opacity 0.3s ease;\n    }\n    \/* Grid Layout (3 columns) *\/\n    .gallery-grid.grid-mode {\n      display: grid;\n      grid-template-columns: repeat(3, 1fr);\n      gap: 2px;\n    }\n    .gallery-grid.grid-mode .gallery-item {\n      box-shadow: none;\n      border-radius: 0;\n    }\n    .gallery-grid.grid-mode .gallery-content {\n      display: none;\n    }\n    .gallery-grid.grid-mode .gallery-image {\n      border-radius: 0;\n    }\n    .gallery-grid.grid-mode .gallery-image:hover {\n      transform: none;\n    }\n    \/* 1-1 Layout (default) *\/\n    .gallery-grid.one-one-mode {\n      display: flex;\n      flex-direction: column;\n      gap: 0;\n    }\n    .gallery-grid.one-one-mode .gallery-item {\n      border-radius: 0;\n      box-shadow: none;\n      border-bottom: 1px solid rgba(0, 0, 0, 0.06);\n    }\n    .gallery-grid.one-one-mode .gallery-image {\n      border-radius: 0;\n    }\n    \/* List Layout *\/\n    .gallery-grid.list-mode {\n      display: flex;\n      flex-direction: column;\n      gap: 0;\n    }\n    .gallery-grid.list-mode .gallery-item {\n      display: flex;\n      flex-direction: row;\n      align-items: center;\n      padding: 8px 12px;\n      border-bottom: 1px solid rgba(0, 0, 0, 0.06);\n      border-radius: 0;\n    }\n    .gallery-grid.list-mode .gallery-image {\n      width: 80px;\n      height: 80px;\n      min-width: 80px;\n      aspect-ratio: 1;\n      border-radius: 4px;\n    }\n    .gallery-grid.list-mode .gallery-content {\n      padding: 0 8px 0 12px;\n      flex: 1;\n    }\n    .gallery-grid.list-mode .gallery-title {\n      font-size: 13px;\n      margin-bottom: 2px;\n    }\n    .gallery-grid.list-mode .gallery-caption {\n      font-size: 12px;\n      margin-bottom: 2px;\n    }\n    .gallery-grid.list-mode .gallery-description {\n      font-size: 12px;\n    }\n    .gallery-item {\n      background: #fff;\n      border-radius: 0;\n      overflow: hidden;\n      box-shadow: none;\n      content-visibility: auto;\n      contain-intrinsic-size: auto 400px;\n    }\n    .gallery-image {\n      width: 100%;\n      aspect-ratio: 1;\n      object-fit: cover;\n      display: block;\n      cursor: pointer;\n      transition: transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1), filter 0.15s ease, opacity 0.3s ease;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      touch-action: manipulation;\n      background: #f0f0f0;\n    }\n    .gallery-image.loading {\n      opacity: 0;\n    }\n    .gallery-image.loaded {\n      opacity: 1;\n    }\n    .gallery-image:active {\n      transform: translate3d(0, 0, 0) scale(0.97);\n      filter: brightness(0.95);\n    }\n    .gallery-content {\n      padding: 12px 16px;\n    }\n    .gallery-title {\n      font-size: 15px;\n      font-weight: 600;\n      color: #262626;\n      margin-bottom: 6px;\n    }\n    .gallery-caption {\n      font-size: 13px;\n      font-weight: 600;\n      color: #1562AC;\n      margin-bottom: 6px;\n    }\n    .gallery-description {\n      font-size: 14px;\n      color: #444;\n      line-height: 1.5;\n    }\n    .gallery-description.collapsed {\n      display: -webkit-box;\n      -webkit-line-clamp: 2;\n      -webkit-box-orient: vertical;\n      overflow: hidden;\n    }\n    .view-more-btn {\n      background: none;\n      border: none;\n      color: #8e8e8e;\n      font-size: 14px;\n      font-weight: 400;\n      cursor: pointer;\n      padding: 4px 0 0 0;\n      margin-top: 4px;\n    }\n    \/* Carousel\/Slides *\/\n    .image-carousel {\n      position: relative;\n      width: 100%;\n      aspect-ratio: 1;\n      overflow: hidden;\n    }\n    .carousel-track {\n      display: flex;\n      transition: transform 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      height: 100%;\n      will-change: transform;\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n    }\n    .carousel-slide {\n      min-width: 100%;\n      height: 100%;\n    }\n    .carousel-slide img {\n      width: 100%;\n      height: 100%;\n      object-fit: cover;\n      cursor: pointer;\n      background: #f0f0f0;\n      transition: opacity 0.3s ease, transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1);\n    }\n    .carousel-slide img.loading {\n      opacity: 0;\n    }\n    .carousel-slide img.loaded {\n      opacity: 1;\n    }\n    .carousel-slide img:active {\n      transform: scale(0.98);\n    }\n    .carousel-indicators {\n      position: absolute;\n      bottom: 12px;\n      left: 50%;\n      transform: translateX(-50%);\n      display: flex;\n      gap: 6px;\n      z-index: 2;\n    }\n    .carousel-dot {\n      width: 6px;\n      height: 6px;\n      border-radius: 50%;\n      background: rgba(255, 255, 255, 0.5);\n      cursor: pointer;\n      transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      touch-action: manipulation;\n    }\n    .carousel-dot:active {\n      transform: translate3d(0, 0, 0) scale(0.8);\n    }\n    .carousel-dot.active {\n      background: #fff;\n      width: 8px;\n      height: 8px;\n      box-shadow: 0 0 8px rgba(255, 255, 255, 0.6);\n    }\n    .carousel-nav {\n      position: absolute;\n      top: 50%;\n      transform: translateY(-50%);\n      background: rgba(0, 0, 0, 0.35);\n      backdrop-filter: blur(8px);\n      -webkit-backdrop-filter: blur(8px);\n      border: 1px solid rgba(255, 255, 255, 0.12);\n      color: white;\n      width: 36px;\n      height: 36px;\n      border-radius: 50%;\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      z-index: 2;\n      opacity: 0;\n      transition: opacity 0.25s ease, transform 0.15s cubic-bezier(0.25, 0.46, 0.45, 0.94), background 0.15s ease;\n      pointer-events: auto;\n      will-change: transform, opacity;\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      touch-action: manipulation;\n      padding: 0;\n    }\n    .carousel-nav svg {\n      width: 18px;\n      height: 18px;\n      stroke: white;\n      stroke-width: 2.5;\n      fill: none;\n      display: block;\n    }\n    .image-carousel:hover .carousel-nav,\n    .carousel-nav:hover,\n    .carousel-nav:focus {\n      opacity: 1;\n    }\n    .carousel-nav:active {\n      transform: translateY(-50%) scale(0.9);\n      background: rgba(0, 0, 0, 0.7);\n    }\n    @media (hover: none) {\n      .carousel-nav {\n        opacity: 0.7;\n      }\n      .carousel-nav:active {\n        opacity: 1;\n        transform: translateY(-50%) scale(0.9);\n      }\n    }\n    .carousel-nav.prev {\n      left: 8px;\n    }\n    .carousel-nav.next {\n      right: 8px;\n    }\n    .gallery-grid.grid-mode .carousel-nav,\n    .gallery-grid.grid-mode .carousel-indicators {\n      display: none;\n    }\n    \/* Image Popup Modal *\/\n    .image-modal {\n      display: none;\n      position: fixed;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      background: rgba(0, 0, 0, 0);\n      z-index: 1000;\n      align-items: center;\n      justify-content: center;\n      padding: 20px;\n      transition: background 0.25s ease;\n      backdrop-filter: blur(0px);\n      -webkit-backdrop-filter: blur(0px);\n    }\n    .image-modal.active {\n      display: flex;\n      background: rgba(0, 0, 0, 0.9);\n      backdrop-filter: blur(8px);\n      -webkit-backdrop-filter: blur(8px);\n      animation: fadeInModal 0.25s cubic-bezier(0.4, 0, 0.2, 1);\n    }\n    @keyframes fadeInModal {\n      from { opacity: 0; }\n      to { opacity: 1; }\n    }\n    .modal-content {\n      background: #fff;\n      border-radius: 20px;\n      max-width: 90%;\n      max-height: 90vh;\n      overflow-y: auto;\n      position: relative;\n      transform: translate3d(0, 0, 0) scale(1);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      animation: scaleInModal 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n      -webkit-overflow-scrolling: touch;\n      overscroll-behavior-y: auto;\n      box-shadow: 0 25px 50px rgba(0, 0, 0, 0.25);\n    }\n    @keyframes scaleInModal {\n      from { transform: translate3d(0, 20px, 0) scale(0.9); opacity: 0; }\n      to { transform: translate3d(0, 0, 0) scale(1); opacity: 1; }\n    }\n    .modal-close {\n      position: absolute;\n      top: 12px;\n      right: 12px;\n      background: rgba(0, 0, 0, 0.5);\n      backdrop-filter: blur(8px);\n      -webkit-backdrop-filter: blur(8px);\n      border: 1px solid rgba(255, 255, 255, 0.15);\n      color: white;\n      width: 36px;\n      height: 36px;\n      border-radius: 50%;\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      font-size: 20px;\n      line-height: 1;\n      z-index: 10;\n      transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      touch-action: manipulation;\n    }\n    .modal-close:hover {\n      background: rgba(0, 0, 0, 0.7);\n      transform: translate3d(0, 0, 0) rotate(90deg) scale(1.1);\n    }\n    .modal-close:active {\n      transform: translate3d(0, 0, 0) rotate(90deg) scale(0.9);\n    }\n    .modal-image {\n      width: 100%;\n      aspect-ratio: 1;\n      object-fit: cover;\n      display: block;\n      border-radius: 20px 20px 0 0;\n      background: #f0f0f0;\n      transition: opacity 0.3s ease;\n    }\n    .modal-image.loading {\n      opacity: 0;\n    }\n    .modal-image.loaded {\n      opacity: 1;\n    }\n    .modal-carousel {\n      position: relative;\n      width: 100%;\n      aspect-ratio: 1;\n      overflow: hidden;\n      border-radius: 20px 20px 0 0;\n    }\n    .modal-carousel .carousel-track {\n      display: flex;\n      transition: transform 0.35s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      height: 100%;\n      will-change: transform;\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n    }\n    .modal-carousel .carousel-slide {\n      min-width: 100%;\n      height: 100%;\n    }\n    .modal-carousel .carousel-slide img {\n      width: 100%;\n      height: 100%;\n      object-fit: cover;\n      background: #f0f0f0;\n      transition: opacity 0.3s ease;\n    }\n    .modal-carousel .carousel-slide img.loading {\n      opacity: 0;\n    }\n    .modal-carousel .carousel-slide img.loaded {\n      opacity: 1;\n    }\n    .modal-carousel .carousel-nav {\n      opacity: 0;\n      transition: opacity 0.25s ease, transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1), background 0.15s ease;\n      will-change: transform, opacity;\n    }\n    .modal-carousel:hover .carousel-nav,\n    .modal-carousel .carousel-nav:hover,\n    .modal-carousel .carousel-nav:focus {\n      opacity: 1;\n    }\n    .modal-carousel .carousel-nav:active {\n      transform: translateY(-50%) scale(0.9);\n      background: rgba(0, 0, 0, 0.7);\n    }\n    @media (hover: none) {\n      .modal-carousel .carousel-nav {\n        opacity: 0.7;\n      }\n      .modal-carousel .carousel-nav:active {\n        opacity: 1;\n        transform: translateY(-50%) scale(0.9);\n      }\n    }\n    .modal-text {\n      padding: 22px;\n    }\n    .modal-title {\n      font-size: 20px;\n      font-weight: 700;\n      color: #1a1a1a;\n      margin-bottom: 8px;\n      letter-spacing: -0.2px;\n    }\n    .modal-caption {\n      font-size: 15px;\n      font-weight: 600;\n      color: #1562AC;\n      margin-bottom: 10px;\n    }\n    .modal-description {\n      font-size: 14px;\n      color: #555;\n      line-height: 1.65;\n    }\n    .gallery-wrapper {\n      padding: 0;\n      overscroll-behavior-y: auto;\n    }\n\n    \/* POI Image Modal *\/\n    .poi-image-modal {\n      position: fixed;\n      top: 0;\n      left: 0;\n      width: 100%;\n      height: 100%;\n      background: rgba(0, 0, 0, 0.9);\n      z-index: 10000;\n      display: none;\n      align-items: center;\n      justify-content: center;\n      opacity: 0;\n      transition: opacity 0.3s ease;\n      -webkit-tap-highlight-color: transparent;\n    }\n    .poi-image-modal.active {\n      display: flex;\n      opacity: 1;\n    }\n    .poi-image-modal-content {\n      position: relative;\n      max-width: 90%;\n      max-height: 90%;\n      animation: zoomIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);\n    }\n    @keyframes zoomIn {\n      from { transform: scale(0.7); opacity: 0; }\n      to { transform: scale(1); opacity: 1; }\n    }\n    .poi-image-modal-content img {\n      width: 100%;\n      height: 100%;\n      object-fit: contain;\n      border-radius: 12px;\n    }\n    .poi-image-modal-close {\n      position: absolute;\n      top: 12px;\n      right: 12px;\n      background: rgba(0, 0, 0, 0.5);\n      backdrop-filter: blur(8px);\n      -webkit-backdrop-filter: blur(8px);\n      border: 1px solid rgba(255, 255, 255, 0.15);\n      color: white;\n      width: 36px;\n      height: 36px;\n      border-radius: 50%;\n      cursor: pointer;\n      font-size: 20px;\n      line-height: 1;\n      z-index: 10;\n      transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      touch-action: manipulation;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n    }\n    .poi-image-modal-close:hover {\n      background: rgba(0, 0, 0, 0.7);\n      transform: rotate(90deg) scale(1.1);\n    }\n    .poi-image-modal-close:active {\n      transform: rotate(90deg) scale(0.9);\n    }\n\n    \/* Map View *\/\n    #map {\n      position: relative;\n      background: #fff;\n      padding-bottom: 80px;\n    }\n    .map-filter-bar {\n      position: absolute;\n      top: 62px;\n      left: 12px;\n      right: 110px;\n      z-index: 100;\n      background: rgba(255, 255, 255, 0.95);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      border-radius: 14px;\n      padding: 6px 10px;\n      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.04);\n      display: flex;\n      flex-wrap: nowrap;\n      align-items: center;\n      gap: 8px;\n      height: 40px;\n      overflow: hidden;\n      -webkit-overflow-scrolling: touch;\n      scrollbar-width: none;\n    }\n    .map-filter-bar::-webkit-scrollbar {\n      display: none;\n    }\n    .map-filter-label {\n      font-size: 13px;\n      font-weight: 600;\n      color: #666;\n      white-space: nowrap;\n      user-select: none;\n      display: flex;\n      align-items: center;\n      gap: 4px;\n    }\n    .map-filter-label svg {\n      width: 16px;\n      height: 16px;\n      color: #666;\n    }\n    .map-filter-select {\n      flex: 1;\n      min-width: 0;\n      height: 30px;\n      border: 1.5px solid rgba(0, 0, 0, 0.1);\n      border-radius: 10px;\n      padding: 4px 10px;\n      font-size: 13px;\n      font-weight: 600;\n      color: #333;\n      background: rgba(255, 255, 255, 0.8);\n      outline: none;\n      transition: border-color 0.2s ease, box-shadow 0.2s ease;\n      cursor: pointer;\n      -webkit-appearance: none;\n      -moz-appearance: none;\n      appearance: none;\n      background-image: url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='12' height='12' viewBox='0 0 24 24' fill='%23666'%3E%3Cpath d='M7 10l5 5 5-5z'\/%3E%3C\/svg%3E\");\n      background-repeat: no-repeat;\n      background-position: right 8px center;\n      padding-right: 26px;\n    }\n    .map-filter-select:focus {\n      border-color: #1562AC;\n      box-shadow: 0 0 0 3px rgba(21, 98, 172, 0.12);\n    }\n    .map-filter-select:hover {\n      border-color: rgba(0, 0, 0, 0.2);\n    }\n    .filter-color-dot {\n      display: inline-block;\n      width: 8px;\n      height: 8px;\n      border-radius: 50%;\n      margin-right: 6px;\n      flex-shrink: 0;\n    }\n    \/* Search Bar *\/\n    .map-search-bar {\n      position: absolute;\n      top: 12px;\n      left: 12px;\n      right: 110px;\n      z-index: 99;\n      background: rgba(255, 255, 255, 0.92);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      border-radius: 14px;\n      padding: 0;\n      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.04);\n      display: flex;\n      align-items: center;\n      padding-left: 14px;\n      padding-right: 8px;\n      max-width: 100%;\n      height: 42px;\n    }\n    .map-search-bar svg {\n      width: 18px;\n      height: 18px;\n      color: #999;\n      margin-right: 8px;\n      flex-shrink: 0;\n    }\n    .map-search-bar input {\n      border: none;\n      outline: none;\n      background: transparent;\n      flex: 1;\n      font-size: 14px;\n      color: #333;\n      min-width: 0;\n    }\n    .map-search-bar input::placeholder {\n      color: #999;\n    }\n    .map-search-clear {\n      background: none;\n      border: none;\n      color: #999;\n      cursor: pointer;\n      padding: 6px;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      font-size: 16px;\n      transition: color 0.2s ease;\n    }\n    .map-search-clear:hover {\n      color: #333;\n    }\n    .search-suggestions {\n      position: absolute;\n      top: 100%;\n      left: 0;\n      right: 0;\n      margin-top: 6px;\n      background: rgba(255, 255, 255, 0.96);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      border-radius: 14px;\n      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.04);\n      max-height: 260px;\n      overflow-y: auto;\n      display: none;\n      z-index: 100;\n      padding: 6px 0;\n    }\n    .search-suggestions.visible {\n      display: block;\n    }\n    .search-suggestions::-webkit-scrollbar {\n      width: 4px;\n    }\n    .search-suggestions::-webkit-scrollbar-thumb {\n      background: rgba(0,0,0,0.15);\n      border-radius: 4px;\n    }\n    .search-suggestion-item {\n      display: flex;\n      align-items: center;\n      gap: 10px;\n      padding: 10px 14px;\n      cursor: pointer;\n      transition: background 0.15s ease;\n    }\n    .search-suggestion-item:hover,\n    .search-suggestion-item.active {\n      background: rgba(0, 0, 0, 0.05);\n    }\n    .search-suggestion-icon {\n      width: 28px;\n      height: 28px;\n      border-radius: 50%;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      flex-shrink: 0;\n    }\n    .search-suggestion-icon svg {\n      width: 14px;\n      height: 14px;\n    }\n    .search-suggestion-text {\n      flex: 1;\n      min-width: 0;\n    }\n    .search-suggestion-name {\n      font-size: 13.5px;\n      font-weight: 500;\n      color: #222;\n      white-space: nowrap;\n      overflow: hidden;\n      text-overflow: ellipsis;\n    }\n    .search-suggestion-name mark {\n      background: rgba(255, 200, 50, 0.4);\n      color: inherit;\n      border-radius: 2px;\n      padding: 0 1px;\n    }\n    .search-suggestion-category {\n      font-size: 11px;\n      color: #888;\n      margin-top: 1px;\n    }\n    .search-suggestion-empty {\n      padding: 14px;\n      text-align: center;\n      color: #999;\n      font-size: 13px;\n    }\n    .filter-chip {\n      background: rgba(255, 255, 255, 0.9);\n      border: 1.5px solid rgba(0, 0, 0, 0.08);\n      border-radius: 20px;\n      padding: 6px 12px;\n      font-size: 13px;\n      font-weight: 500;\n      cursor: pointer;\n      white-space: nowrap;\n      flex-shrink: 0;\n      transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      color: #555;\n      user-select: none;\n    }\n    .filter-chip:hover {\n      background: rgba(245, 245, 248, 0.95);\n      transform: scale(1.05);\n    }\n    .filter-chip:active {\n      transform: scale(0.95);\n    }\n    .filter-chip.active {\n      background: #1562AC;\n      border-color: #1562AC;\n      color: white;\n    }\n    .filter-chip .count {\n      opacity: 0.7;\n      margin-left: 4px;\n      font-size: 12px;\n    }\n    .map-type-controls {\n      position: absolute;\n      top: 12px;\n      right: 12px;\n      z-index: 100;\n      display: flex;\n      flex-direction: column;\n      gap: 6px;\n      background: rgba(255, 255, 255, 0.92);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      border-radius: 12px;\n      padding: 6px;\n      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.04);\n    }\n    .map-type-btn {\n      background: transparent;\n      border: 1.5px solid transparent;\n      border-radius: 8px;\n      padding: 8px 12px;\n      font-size: 11px;\n      font-weight: 600;\n      cursor: pointer;\n      transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      color: #555;\n      min-width: 70px;\n      text-align: center;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      touch-action: manipulation;\n      letter-spacing: 0.2px;\n    }\n    .map-type-btn.active {\n      background: #1562AC;\n      color: white;\n      border-color: #1562AC;\n      transform: translate3d(0, 0, 0);\n      box-shadow: 0 2px 8px rgba(21, 98, 172, 0.25);\n    }\n    .map-type-btn:active {\n      transform: translate3d(0, 0, 0) scale(0.92);\n    }\n    .map-zoom-controls {\n      position: absolute;\n      bottom: 280px;\n      right: 12px;\n      z-index: 100;\n      display: flex;\n      flex-direction: column;\n      gap: 1px;\n      background: rgba(255, 255, 255, 0.92);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      border-radius: 12px;\n      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.04);\n      overflow: hidden;\n    }\n    \/* City center button *\/\n    .map-center-btn {\n      position: absolute;\n      bottom: 420px;\n      right: 12px;\n      z-index: 100;\n      width: 42px;\n      height: 42px;\n      padding: 0;\n      background: rgba(255, 255, 255, 0.92);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      border: none;\n      border-radius: 12px;\n      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.04);\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      color: #333;\n      font-size: 0;\n      line-height: 0;\n      transition: background 0.15s ease, transform 0.15s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      touch-action: manipulation;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n    }\n    .map-center-btn:active {\n      background: rgba(0, 0, 0, 0.05);\n      transform: translate3d(0, 0, 0) scale(0.9);\n    }\n    .map-center-btn svg {\n      width: 20px;\n      height: 20px;\n      color: #333;\n      display: block;\n      flex-shrink: 0;\n    }\n    \/* My Location button *\/\n    .map-location-btn {\n      position: absolute;\n      bottom: 370px;\n      right: 12px;\n      z-index: 100;\n      width: 42px;\n      height: 42px;\n      padding: 0;\n      background: rgba(255, 255, 255, 0.92);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      border: none;\n      border-radius: 12px;\n      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.04);\n      cursor: pointer;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      color: #333;\n      font-size: 0;\n      line-height: 0;\n      transition: background 0.15s ease, transform 0.15s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      touch-action: manipulation;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n    }\n    .map-location-btn:active {\n      background: rgba(0, 0, 0, 0.05);\n      transform: translate3d(0, 0, 0) scale(0.9);\n    }\n    .map-location-btn svg {\n      width: 20px;\n      height: 20px;\n      color: #333;\n      display: block;\n      flex-shrink: 0;\n      transition: color 0.2s ease;\n    }\n    .map-location-btn.locating {\n      animation: locatingPulse 1.2s ease-in-out infinite;\n    }\n    .map-location-btn.locating svg {\n      color: #1562AC;\n    }\n    .map-location-btn.located svg {\n      color: #1562AC;\n    }\n    @keyframes locatingPulse {\n      0%, 100% { box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.04); }\n      50% { box-shadow: 0 2px 12px rgba(21, 98, 172, 0.3), 0 0 0 3px rgba(21, 98, 172, 0.15); }\n    }\n    \/* GPS accuracy banner *\/\n    .gps-accuracy-banner {\n      position: absolute;\n      top: 110px;\n      left: 12px;\n      z-index: 99;\n      display: flex;\n      align-items: center;\n      gap: 8px;\n      padding: 8px 14px;\n      border-radius: 12px;\n      font-size: 12px;\n      font-weight: 600;\n      letter-spacing: 0.2px;\n      background: rgba(255, 255, 255, 0.92);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08), 0 0 0 1px rgba(0, 0, 0, 0.04);\n      opacity: 0;\n      transform: translateY(-8px);\n      transition: opacity 0.3s ease, transform 0.3s ease;\n      pointer-events: none;\n    }\n    .gps-accuracy-banner.visible {\n      opacity: 1;\n      transform: translateY(0);\n      pointer-events: auto;\n    }\n    .gps-accuracy-dot {\n      width: 10px;\n      height: 10px;\n      border-radius: 50%;\n      flex-shrink: 0;\n    }\n    .gps-accuracy-banner.high .gps-accuracy-dot { background: #34C759; }\n    .gps-accuracy-banner.medium .gps-accuracy-dot { background: #FF9500; }\n    .gps-accuracy-banner.low .gps-accuracy-dot { background: #FF3B30; }\n    .gps-accuracy-banner .gps-dismiss {\n      background: none;\n      border: none;\n      font-size: 16px;\n      cursor: pointer;\n      color: #999;\n      padding: 0 0 0 4px;\n      line-height: 1;\n    }\n    .map-zoom-btn {\n      background: transparent;\n      border: none;\n      width: 42px;\n      height: 42px;\n      font-size: 22px;\n      font-weight: 300;\n      cursor: pointer;\n      transition: background 0.15s ease, transform 0.15s cubic-bezier(0.25, 0.46, 0.45, 0.94);\n      color: #333;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      touch-action: manipulation;\n    }\n    .map-zoom-btn:active {\n      background: rgba(0, 0, 0, 0.05);\n      transform: translate3d(0, 0, 0) scale(0.9);\n    }\n    .map-zoom-btn:first-child {\n      border-bottom: 1px solid rgba(0, 0, 0, 0.06);\n    }\n    .map-container {\n      position: relative;\n      width: 100%;\n      height: calc(100vh - var(--tab-bar-height));\n      overflow: hidden;\n    }\n    #mapBackground {\n      width: 100%;\n      height: 100%;\n      z-index: 1;\n    }\n    .leaflet-container {\n      background: #e3f2fd;\n      touch-action: pan-x pan-y;\n      transform: translate3d(0, 0, 0);\n      will-change: auto;\n      cursor: grab;\n    }\n    .leaflet-container:active {\n      cursor: grabbing;\n    }\n    .leaflet-tile-pane {\n      will-change: transform;\n    }\n    .leaflet-tile {\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      image-rendering: -webkit-optimize-contrast;\n      image-rendering: crisp-edges;\n    }\n    .leaflet-tile-optimized {\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n    }\n    .leaflet-zoom-animated {\n      will-change: transform;\n    }\n    .leaflet-fade-anim .leaflet-tile {\n      will-change: opacity;\n    }\n    .leaflet-marker-icon {\n      pointer-events: auto !important;\n      cursor: pointer !important;\n      transform: translate3d(0, 0, 0);\n      will-change: transform;\n    }\n    .custom-pin {\n      cursor: pointer;\n      transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), filter 0.25s ease;\n      pointer-events: all !important;\n      transform: translate3d(0, 0, 0);\n      will-change: transform;\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n    }\n    .custom-pin svg,\n    .custom-pin circle,\n    .custom-pin path,\n    .custom-pin rect {\n      pointer-events: none;\n      transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);\n    }\n    .custom-pin:hover {\n      transform: translate3d(0, 0, 0) scale(1.25);\n      z-index: 1000 !important;\n      filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.2));\n    }\n    .custom-pin:active {\n      transform: translate3d(0, 0, 0) scale(1.15);\n    }\n    .custom-pin.active-pin {\n      transform: translate3d(0, 0, 0) scale(1.45);\n      z-index: 1001 !important;\n      filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.9)) drop-shadow(0 4px 12px rgba(0, 0, 0, 0.4));\n      animation: pinBounceIn 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);\n    }\n    .custom-pin.active-pin > div {\n      box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.95), 0 0 0 6px currentColor, 0 4px 16px rgba(0, 0, 0, 0.3) !important;\n      border-color: white !important;\n    }\n    .custom-pin.active-pin::after {\n      content: '';\n      position: absolute;\n      top: 50%;\n      left: 50%;\n      width: 48px;\n      height: 48px;\n      transform: translate(-50%, -50%);\n      border-radius: 50%;\n      border: 2px solid rgba(255, 255, 255, 0.6);\n      animation: pingRing 1.5s cubic-bezier(0, 0, 0.2, 1) infinite;\n      pointer-events: none;\n    }\n    @keyframes pinBounceIn {\n      0% { transform: translate3d(0, 0, 0) scale(1); }\n      40% { transform: translate3d(0, -8px, 0) scale(1.55); }\n      70% { transform: translate3d(0, 0, 0) scale(1.4); }\n      100% { transform: translate3d(0, 0, 0) scale(1.45); }\n    }\n    @keyframes pingRing {\n      0% { width: 48px; height: 48px; opacity: 0.7; }\n      100% { width: 72px; height: 72px; opacity: 0; }\n    }\n    .leaflet-pane {\n      z-index: 400 !important;\n    }\n    .leaflet-marker-pane {\n      z-index: 600 !important;\n    }\n    .map-pin {\n      position: absolute;\n      width: 36px;\n      height: 36px;\n      z-index: 50;\n      cursor: pointer;\n      transition: transform 0.2s ease, z-index 0s;\n    }\n    .map-pin:hover {\n      transform: scale(1.2);\n      z-index: 60;\n    }\n    .map-pin.active-pin {\n      transform: scale(1.3);\n      z-index: 70;\n      filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.3));\n    }\n    .location-card {\n      position: fixed;\n      bottom: calc(var(--tab-bar-height) + clamp(20px, 10vh, 100px) + env(safe-area-inset-bottom, 0px));\n      left: 20px;\n      right: 20px;\n      background: rgba(255, 255, 255, 0.95);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      border-radius: 18px;\n      padding: 16px;\n      display: flex;\n      gap: 12px;\n      box-shadow: 0 4px 24px rgba(0, 0, 0, 0.1), 0 0 0 1px rgba(0, 0, 0, 0.04);\n      z-index: 10000;\n      max-height: 250px;\n      overflow: visible;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s ease;\n    }\n    .tab-map .map-zoom-controls {\n      bottom: calc(180px + clamp(20px, 10vh, 100px) + var(--tab-bar-height) + env(safe-area-inset-bottom, 0px));\n    }\n    .tab-map .map-location-btn {\n      bottom: calc(270px + clamp(20px, 10vh, 100px) + var(--tab-bar-height) + env(safe-area-inset-bottom, 0px));\n    }\n    .tab-map .map-center-btn {\n      bottom: calc(320px + clamp(20px, 10vh, 100px) + var(--tab-bar-height) + env(safe-area-inset-bottom, 0px));\n    }\n    .location-card.updating {\n      animation: cardUpdate 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n    }\n    @keyframes cardUpdate {\n      0% { transform: translate3d(0, 0, 0) scale(1); }\n      50% { transform: translate3d(0, -4px, 0) scale(1.02); box-shadow: 0 8px 24px rgba(0,0,0,0.2); }\n      100% { transform: translate3d(0, 0, 0) scale(1); }\n    }\n    .location-thumbnail {\n      width: 70px;\n      height: 70px;\n      border-radius: 12px;\n      flex-shrink: 0;\n      object-fit: cover;\n    }\n    .location-info {\n      flex: 1;\n      overflow: hidden;\n    }\n    .location-info h3 {\n      font-size: 15px;\n      font-weight: 700;\n      color: #1a1a1a;\n      margin-bottom: 4px;\n      overflow: hidden;\n      text-overflow: ellipsis;\n      white-space: nowrap;\n      letter-spacing: -0.1px;\n    }\n    .location-info p {\n      font-size: 13px;\n      color: #888;\n      overflow: hidden;\n      text-overflow: ellipsis;\n      white-space: nowrap;\n    }\n    .rating {\n      display: flex;\n      align-items: center;\n      gap: 4px;\n      margin-top: 6px;\n      flex-wrap: wrap;\n    }\n    .stars {\n      color: #ffc107;\n      font-size: 13px;\n    }\n    .reviews {\n      font-size: 11px;\n      color: #999;\n    }\n\n    \/* Bottom Tab Bar *\/\n    .tab-bar {\n      height: var(--tab-bar-height);\n      background: rgba(255, 255, 255, 0.85);\n      backdrop-filter: saturate(180%) blur(20px);\n      -webkit-backdrop-filter: saturate(180%) blur(20px);\n      border-top: 1px solid rgba(0, 0, 0, 0.08);\n      display: flex;\n      align-items: center;\n      justify-content: space-around;\n      padding-bottom: 0;\n      position: fixed;\n      bottom: 0;\n      left: 0;\n      right: 0;\n      z-index: 9999 !important;\n      transform: translate3d(0, 0, 0);\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n      will-change: auto;\n    }\n    .tab-button {\n      display: flex;\n      flex-direction: column;\n      align-items: center;\n      gap: 2px;\n      background: none;\n      border: none;\n      cursor: pointer;\n      padding: 6px 14px;\n      border-radius: 12px;\n      transition: transform 0.12s cubic-bezier(0.34, 1.56, 0.64, 1), background 0.2s ease, color 0.2s ease;\n      touch-action: manipulation;\n      user-select: none;\n      -webkit-user-select: none;\n      -webkit-tap-highlight-color: transparent;\n      transform: translate3d(0, 0, 0);\n      will-change: transform;\n      backface-visibility: hidden;\n      -webkit-backface-visibility: hidden;\n    }\n    .tab-button:focus {\n      outline: none;\n    }\n    .tab-button:active {\n      transform: translate3d(0, 0, 0) scale(0.90);\n    }\n    .tab-icon {\n      width: 22px;\n      height: 22px;\n    }\n    .tab-label {\n      font-size: 9px;\n      font-weight: 600;\n      letter-spacing: 0.3px;\n    }\n    .tab-button.active {\n      background: rgba(21, 98, 172, 0.10);\n    }\n    .tab-button.active .tab-icon {\n      color: #1562AC;\n    }\n    .tab-button.active .tab-label {\n      color: #1562AC;\n    }\n    .tab-button:not(.active) .tab-icon {\n      color: #999;\n    }\n    .tab-button:not(.active) .tab-label {\n      color: #999;\n    }\n    \n    \/* Hide scrollbar globally *\/\n    html, body, .view, .phone-container {\n      scrollbar-width: none;\n    }\n    html::-webkit-scrollbar, body::-webkit-scrollbar, .view::-webkit-scrollbar, .phone-container::-webkit-scrollbar {\n      display: none;\n    }\n    \n    \/* ========================================\n       DESKTOP RESPONSIVE LAYOUT\n       ======================================== *\/\n\n    \/* Tablet and up *\/\n    @media (min-width: 768px) {\n      .phone-container {\n        max-width: 1280px;\n        margin: 0 auto;\n      }\n\n      \/* --- HOME VIEW: Centered linktree column --- *\/\n      #home {\n        display: flex;\n        flex-direction: column;\n        align-items: center;\n        padding: 20px 20px 20px;\n      }\n      .logo-section {\n        margin-bottom: 20px;\n      }\n      .logo-section img {\n        width: 140px;\n        height: 140px;\n      }\n      .logo-section h1 {\n        font-size: 22px;\n        letter-spacing: 1px;\n      }\n      .logo-section p {\n        font-size: 15px;\n      }\n      .button-list {\n        width: 100%;\n        max-width: 520px;\n        gap: 10px;\n        margin-bottom: 20px;\n      }\n      .link-button {\n        padding: 14px 20px;\n        font-size: 15px;\n        border-radius: 16px;\n      }\n      .video-card {\n        width: 100%;\n        max-width: 520px;\n        border-radius: 20px;\n      }\n\n      \/* --- GALLERY VIEW --- *\/\n      .gallery-grid.grid-mode {\n        grid-template-columns: repeat(4, 1fr);\n        gap: 3px;\n      }\n      .gallery-grid.one-one-mode {\n        max-width: 620px;\n        margin: 0 auto;\n      }\n      .gallery-grid.one-one-mode .gallery-content {\n        padding: 16px 20px;\n      }\n      .gallery-grid.list-mode {\n        max-width: 720px;\n        margin: 0 auto;\n      }\n      .gallery-grid.list-mode .gallery-item {\n        padding: 12px 16px;\n      }\n      .gallery-grid.list-mode .gallery-image {\n        width: 100px;\n        height: 100px;\n        min-width: 100px;\n        border-radius: 6px;\n      }\n\n      \/* --- IMAGE MODAL --- *\/\n      .modal-content {\n        max-width: 600px;\n      }\n      .modal-text {\n        padding: 28px;\n      }\n      .modal-title {\n        font-size: 22px;\n      }\n      .modal-description {\n        font-size: 15px;\n        line-height: 1.7;\n      }\n\n      \/* --- MAP VIEW --- *\/\n      .location-card {\n        left: 50%;\n        right: auto;\n        transform: translateX(-50%);\n        width: 100%;\n        max-width: 480px;\n        padding: 18px;\n        border-radius: 20px;\n      }\n      .location-card.updating {\n        animation: cardUpdateDesktop 0.4s cubic-bezier(0.4, 0, 0.2, 1);\n      }\n      @keyframes cardUpdateDesktop {\n        0% { transform: translateX(-50%) scale(1); }\n        50% { transform: translateX(-50%) translateY(-4px) scale(1.02); box-shadow: 0 8px 24px rgba(0,0,0,0.2); }\n        100% { transform: translateX(-50%) scale(1); }\n      }\n\n      \/* --- TAB BAR --- *\/\n      .tab-bar {\n        max-width: 1280px;\n        left: 50%;\n        transform: translateX(-50%);\n        border-radius: 18px 18px 0 0;\n        border: 1px solid rgba(0, 0, 0, 0.06);\n        border-bottom: none;\n      }\n      .tab-button {\n        flex-direction: row;\n        gap: 6px;\n        padding: 8px 20px;\n        border-radius: 12px;\n        transition: background 0.2s ease, color 0.2s ease, transform 0.12s cubic-bezier(0.34, 1.56, 0.64, 1);\n      }\n      .tab-button:hover:not(.active) {\n        background: rgba(21, 98, 172, 0.06);\n      }\n      .tab-button:hover:not(.active) .tab-icon,\n      .tab-button:hover:not(.active) .tab-label {\n        color: #1562AC;\n      }\n      .tab-button.active {\n        background: rgba(21, 98, 172, 0.10);\n      }\n      .tab-icon {\n        width: 20px;\n        height: 20px;\n      }\n      .tab-label {\n        font-size: 12px;\n        letter-spacing: 0.4px;\n      }\n\n      \/* Gallery modes bar \u2013 constrain with container *\/\n      .tab-gallery .view-modes {\n        max-width: 1280px;\n        border-radius: 0;\n      }\n    }\n\n    \/* Large desktops *\/\n    @media (min-width: 1024px) {\n      .logo-section img {\n        width: 160px;\n        height: 160px;\n      }\n      .logo-section h1 {\n        font-size: 24px;\n      }\n      .button-list {\n        max-width: 560px;\n      }\n      .video-card {\n        max-width: 560px;\n      }\n\n      \/* Gallery 5 columns on wide screens *\/\n      .gallery-grid.grid-mode {\n        grid-template-columns: repeat(5, 1fr);\n      }\n\n      \/* Map search & filter widen *\/\n      .map-search-bar {\n        max-width: 460px;\n      }\n      .map-filter-bar {\n        max-width: 460px;\n      }\n    }\n\n    \/* Extra-wide *\/\n    @media (min-width: 1440px) {\n      .gallery-grid.grid-mode {\n        grid-template-columns: repeat(6, 1fr);\n        gap: 4px;\n      }\n      .gallery-grid.one-one-mode {\n        max-width: 680px;\n      }\n    }\n\n    \/* Smooth scrolling - no snap *\/\n    @media (hover: none) {\n      .view {\n        scroll-snap-type: none;\n        scroll-padding-top: 0;\n        \/* iOS momentum scrolling *\/\n        -webkit-overflow-scrolling: touch;\n      }\n    }\n\n    \/* Desktop gallery hover effects *\/\n    @media (hover: hover) and (min-width: 768px) {\n      .gallery-grid.grid-mode .gallery-item {\n        position: relative;\n        cursor: pointer;\n        overflow: hidden;\n      }\n      .gallery-grid.grid-mode .gallery-item::after {\n        content: '';\n        position: absolute;\n        inset: 0;\n        background: rgba(0, 0, 0, 0);\n        transition: background 0.2s ease;\n        pointer-events: none;\n      }\n      .gallery-grid.grid-mode .gallery-item:hover::after {\n        background: rgba(0, 0, 0, 0.06);\n      }\n      .gallery-grid.grid-mode .gallery-image {\n        transition: transform 0.3s ease;\n      }\n      .gallery-grid.grid-mode .gallery-item:hover .gallery-image {\n        transform: scale(1.03);\n      }\n      .gallery-grid.list-mode .gallery-item {\n        transition: background 0.15s ease;\n      }\n      .gallery-grid.list-mode .gallery-item:hover {\n        background: rgba(0, 0, 0, 0.02);\n      }\n    }\n\n    \/* TranslatePress Language Switcher & Accessibility Widgets - Only visible on Home tab *\/\n    #trp-floater-ls.trp-top-right {\n      right: 1.5% !important;\n    }\n    \n    #trp-floater-ls,\n    .cya11y-widget,\n    #cya11y-widget-icon,\n    #cya11y-menu-btn,\n    .cya11y-widget-icon,\n    .cya11y-menu-btn,\n    [id*=\"cya11y\"],\n    [class*=\"cya11y\"] {\n      display: none !important;\n      visibility: hidden !important;\n      opacity: 0 !important;\n      pointer-events: none !important;\n    }\n    \n    body.tab-home #trp-floater-ls,\n    body.tab-home .cya11y-widget,\n    body.tab-home #cya11y-widget-icon,\n    body.tab-home #cya11y-menu-btn,\n    body.tab-home .cya11y-widget-icon,\n    body.tab-home .cya11y-menu-btn,\n    body.tab-home [id*=\"cya11y\"],\n    body.tab-home [class*=\"cya11y\"] {\n      display: block !important;\n      visibility: visible !important;\n      opacity: 1 !important;\n      pointer-events: auto !important;\n    }\n  <\/style>\n<\/head>\n<body>\n  <!-- =============================================\n       TRANSLATEPRESS TRANSLATABLE STRINGS\n       All UI text is placed here so TranslatePress\n       can discover and translate it server-side.\n       JavaScript reads from these elements at runtime.\n       ============================================= -->\n  <div id=\"trp-translatable-strings\" style=\"display:none\" aria-hidden=\"true\">\n    <!-- Home button labels -->\n    <span id=\"trp-official-website\">Official Website<\/span>\n    <span id=\"trp-follow-facebook\">Follow us on Facebook<\/span>\n    <span id=\"trp-follow-instagram\">Follow us on Instagram<\/span>\n    <span id=\"trp-subscribe-youtube\">Subscribe on YouTube<\/span>\n    <span id=\"trp-explore-map\">Explore Map<\/span>\n    <span id=\"trp-view-photos\">View Photos<\/span>\n    <!-- Social usernames -->\n    <span id=\"trp-username-facebook\">Visit Central Macedonia<\/span>\n    <span id=\"trp-username-instagram\">@visit_central_macedonia<\/span>\n    <span id=\"trp-username-youtube\">Visit Central Macedonia<\/span>\n    <!-- Tab labels -->\n    <span id=\"trp-tab-home\">Home<\/span>\n    <span id=\"trp-tab-gallery\">Gallery<\/span>\n    <span id=\"trp-tab-map\">Map<\/span>\n    <!-- Gallery -->\n    <span id=\"trp-gallery-heading\">Gallery<\/span>\n    <span id=\"trp-view-more\">View more<\/span>\n    <span id=\"trp-view-less\">View less<\/span>\n    <!-- Map controls -->\n    <span id=\"trp-map-normal\">Normal<\/span>\n    <span id=\"trp-map-satellite\">Satellite<\/span>\n    <span id=\"trp-map-hybrid\">Hybrid<\/span>\n    <span id=\"trp-map-terrain\">Terrain<\/span>\n    <span id=\"trp-search-placeholder\">Search places...<\/span>\n    <span id=\"trp-back-to-center\">Back to city center<\/span>\n    <span id=\"trp-show-location\">Show my location<\/span>\n    <!-- Search -->\n    <span id=\"trp-no-places-found\">No places found<\/span>\n    <span id=\"trp-more-results\">more results<\/span>\n    <!-- POI card -->\n    <span id=\"trp-learn-more\">Learn More<\/span>\n    <span id=\"trp-directions\">Directions<\/span>\n    <span id=\"trp-reviews\">reviews<\/span>\n    <!-- Filter -->\n    <span id=\"trp-filter-label\">Filter<\/span>\n    <span id=\"trp-all-categories\">All Categories<\/span>\n    <!-- GPS accuracy -->\n    <span id=\"trp-gps-high\">High accuracy<\/span>\n    <span id=\"trp-gps-medium\">Medium accuracy<\/span>\n    <span id=\"trp-gps-low\">Low accuracy<\/span>\n    <span id=\"trp-location-denied\">Location access denied. Please allow location in your browser settings.<\/span>\n    <!-- Alt text & misc -->\n    <span id=\"trp-logo-alt\">Central Macedonia logo<\/span>\n    <span id=\"trp-video-unsupported\">Your browser does not support the video tag.<\/span>\n    <!-- Category labels -->\n    <span id=\"trp-cat-museum\">Museums<\/span>\n    <span id=\"trp-cat-landmark\">Landmarks<\/span>\n    <span id=\"trp-cat-culture\">Culture<\/span>\n    <span id=\"trp-cat-beach\">Beaches<\/span>\n    <span id=\"trp-cat-church\">Churches<\/span>\n    <span id=\"trp-cat-traditional_settlement\">Traditional Settlements<\/span>\n    <span id=\"trp-cat-architecture\">Architecture<\/span>\n    <span id=\"trp-cat-archaeological\">Archaeological Sites<\/span>\n    <span id=\"trp-cat-nature\">Nature<\/span>\n    <span id=\"trp-cat-park\">Parks<\/span>\n    <span id=\"trp-cat-activities\">Activities<\/span>\n    <span id=\"trp-cat-cave\">Caves<\/span>\n    <span id=\"trp-cat-ski_resort\">Ski Resorts<\/span>\n    <span id=\"trp-cat-lake\">Lakes<\/span>\n    <span id=\"trp-cat-mountain\">Mountains<\/span>\n    <span id=\"trp-cat-wetland\">Wetlands<\/span>\n    <span id=\"trp-cat-thermal_spa\">Thermal Spas<\/span>\n    <span id=\"trp-cat-canyon\">Canyons<\/span>\n    <span id=\"trp-cat-other\">Other<\/span>\n  <\/div>\n\n  <div class=\"phone-container\">\n    <!-- View Container -->\n    <div class=\"view-container\">\n      <!-- Home View -->\n      <div id=\"home\" class=\"view active\">\n        <div class=\"logo-section\">\n          <img decoding=\"async\" id=\"logoImage\" src=\"ChatGPT Image Feb 10, 2026, 08_51_06 PM.png\" alt=\"Central Macedonia logo\">\n        <\/div>\n\n        <div class=\"button-list\">\n          <button class=\"link-button\" onclick=\"openLink('https:\/\/visit-centralmacedonia.gr\/')\">\n            <div class=\"button-content\">\n              <svg class=\"button-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <circle cx=\"12\" cy=\"12\" r=\"10\"\/>\n                <path d=\"M2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z\"\/>\n              <\/svg>\n              <div class=\"button-text\">\n                <span>Official Website<\/span>\n                <span class=\"button-username\">visit-centralmacedonia.gr<\/span>\n              <\/div>\n            <\/div>\n            <svg class=\"chevron-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n              <path d=\"M9 18l6-6-6-6\"\/>\n            <\/svg>\n          <\/button>\n\n          <button class=\"link-button\" onclick=\"openLink('https:\/\/www.facebook.com\/profile.php?id=100066835621541')\">\n            <div class=\"button-content\">\n              <svg class=\"button-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n                <path d=\"M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z\"\/>\n              <\/svg>\n              <div class=\"button-text\">\n                <span>Follow us on Facebook<\/span>\n                <span class=\"button-username\">Visit Central Macedonia<\/span>\n              <\/div>\n            <\/div>\n            <svg class=\"chevron-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n              <path d=\"M9 18l6-6-6-6\"\/>\n            <\/svg>\n          <\/button>\n\n          <button class=\"link-button\" onclick=\"openLink('https:\/\/www.instagram.com\/visit_central_macedonia\/')\">\n            <div class=\"button-content\">\n              <svg class=\"button-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <rect x=\"2\" y=\"2\" width=\"20\" height=\"20\" rx=\"5\" ry=\"5\"\/>\n                <path d=\"M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z\"\/>\n                <line x1=\"17.5\" y1=\"6.5\" x2=\"17.51\" y2=\"6.5\"\/>\n              <\/svg>\n              <div class=\"button-text\">\n                <span>Follow us on Instagram<\/span>\n                <span class=\"button-username\">@visit_central_macedonia<\/span>\n              <\/div>\n            <\/div>\n            <svg class=\"chevron-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n              <path d=\"M9 18l6-6-6-6\"\/>\n            <\/svg>\n          <\/button>\n\n          <button class=\"link-button\" onclick=\"openLink('https:\/\/www.youtube.com\/c\/VisitCentralMacedonia')\">\n            <div class=\"button-content\">\n              <svg class=\"button-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n                <path d=\"M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z\"\/>\n              <\/svg>\n              <div class=\"button-text\">\n                <span>Subscribe on YouTube<\/span>\n                <span class=\"button-username\">Visit Central Macedonia<\/span>\n              <\/div>\n            <\/div>\n            <svg class=\"chevron-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n              <path d=\"M9 18l6-6-6-6\"\/>\n            <\/svg>\n          <\/button>\n\n          <button class=\"link-button\" onclick=\"switchTab('map')\">\n            <div class=\"button-content\">\n              <svg class=\"button-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <path d=\"M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z\"\/>\n                <circle cx=\"12\" cy=\"10\" r=\"3\"\/>\n              <\/svg>\n              <span>Explore Map<\/span>\n            <\/div>\n            <svg class=\"chevron-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n              <path d=\"M9 18l6-6-6-6\"\/>\n            <\/svg>\n          <\/button>\n\n          <button class=\"link-button\" onclick=\"switchTab('gallery')\">\n            <div class=\"button-content\">\n              <svg class=\"button-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n                <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"\/>\n                <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"\/>\n                <path d=\"M21 15l-5-5L5 21\"\/>\n              <\/svg>\n              <span>View Photos<\/span>\n            <\/div>\n            <svg class=\"chevron-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n              <path d=\"M9 18l6-6-6-6\"\/>\n            <\/svg>\n          <\/button>\n        <\/div>\n\n        <div class=\"video-card\" id=\"videoCard\">\n          <video class=\"video-player\" id=\"mainVideo\" preload=\"none\" poster=\"\">\n            <source id=\"videoSource\" src=\"855564-hd_1920_1080_24fps.mp4\" type=\"video\/mp4\">\n            Your browser does not support the video tag.\n          <\/video>\n          <div class=\"video-play-overlay show\" id=\"videoPlayOverlay\" onclick=\"togglePlay()\">\n            <svg viewBox=\"0 0 24 24\">\n              <path d=\"M8 5v14l11-7z\"\/>\n            <\/svg>\n          <\/div>\n          <div class=\"video-controls\">\n            <button id=\"playPauseBtn\" onclick=\"togglePlay()\">\n              <svg id=\"playIcon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n                <path d=\"M8 5v14l11-7z\"\/>\n              <\/svg>\n              <svg id=\"pauseIcon\" viewBox=\"0 0 24 24\" fill=\"currentColor\" style=\"display: none;\">\n                <path d=\"M6 4h4v16H6V4zm8 0h4v16h-4V4z\"\/>\n              <\/svg>\n            <\/button>\n            <div class=\"progress-bar\" id=\"progressBar\" onclick=\"seek(event)\">\n              <div class=\"progress-bar-fill\" id=\"progressFill\"><\/div>\n            <\/div>\n            <span class=\"time-display\" id=\"timeDisplay\">0:00 \/ 0:00<\/span>\n            <button class=\"rotate-btn-left\" onclick=\"rotateVideo(-90)\">\n              <svg viewBox=\"0 0 24 24\" fill=\"currentColor\">\n                <path d=\"M8.45 5.55L13 1v3.07C16.94 4.56 20 7.92 20 12s-3.05 7.44-7 7.93v-2.02c2.84-.48 5-2.94 5-5.91s-2.16-5.43-5-5.91V10L8.45 5.55zM4.07 11c.17-1.39.72-2.73 1.62-3.89l1.42 1.42c-.54.75-.88 1.6-1.02 2.47H4.07zM11 17.9v2.02c-1.39-.17-2.74-.71-3.9-1.61l1.44-1.44c.75.54 1.59.89 2.46 1.03zm-3.89-2.42l-1.42 1.41c-.9-1.16-1.45-2.5-1.62-3.89h2.02c.14.87.48 1.72 1.02 2.48z\"\/>\n              <\/svg>\n            <\/button>\n            <button class=\"rotate-btn-right\" onclick=\"rotateVideo(90)\">\n              <svg viewBox=\"0 0 24 24\" fill=\"currentColor\">\n                <path d=\"M15.55 5.55L11 1v3.07C7.06 4.56 4 7.92 4 12s3.05 7.44 7 7.93v-2.02c-2.84-.48-5-2.94-5-5.91s2.16-5.43 5-5.91V10l4.55-4.45zM19.93 11c-.17-1.39-.72-2.73-1.62-3.89l-1.42 1.42c.54.75.88 1.6 1.02 2.47h2.02zM13 17.9v2.02c1.39-.17 2.74-.71 3.9-1.61l-1.44-1.44c-.75.54-1.59.89-2.46 1.03zm3.89-2.42l1.42 1.41c.9-1.16 1.45-2.5 1.62-3.89h-2.02c-.14.87-.48 1.72-1.02 2.48z\"\/>\n              <\/svg>\n            <\/button>\n            <button class=\"fullscreen-btn\" onclick=\"toggleFullscreen()\">\n              <svg viewBox=\"0 0 24 24\" fill=\"currentColor\">\n                <path d=\"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z\"\/>\n              <\/svg>\n            <\/button>\n          <\/div>\n        <\/div>\n        <div style=\"height: 20px;\"><\/div>\n      <\/div>\n\n      <!-- Gallery View -->\n      <div id=\"gallery\" class=\"view\">\n        <div class=\"header\">\n          <h2>Gallery<\/h2>\n        <\/div>\n        <div class=\"view-modes\">\n          <button class=\"gallery-back-btn\" onclick=\"backToGridView()\">\n            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n              <polyline points=\"15 18 9 12 15 6\"\/>\n            <\/svg>\n          <\/button>\n          <button class=\"view-mode-btn active\" onclick=\"setViewMode('grid')\">\n            <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n              <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"\/>\n              <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"\/>\n              <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"\/>\n              <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"\/>\n            <\/svg>\n          <\/button>\n          <button class=\"view-mode-btn\" onclick=\"setViewMode('one-one')\">\n            <svg viewBox=\"0 0 24 24\" width=\"20\" height=\"20\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n              <rect x=\"4\" y=\"4\" width=\"16\" height=\"6\" rx=\"1\"\/>\n              <rect x=\"4\" y=\"14\" width=\"16\" height=\"6\" rx=\"1\"\/>\n            <\/svg>\n          <\/button>\n        <\/div>\n        <div class=\"gallery-wrapper\">\n          <div class=\"gallery-grid grid-mode\" id=\"galleryGrid\">\n            <!-- Gallery items will be loaded dynamically -->\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <!-- Image Popup Modal -->\n      <div class=\"image-modal\" id=\"imageModal\" onclick=\"closeModal(event)\">\n        <div class=\"modal-content\" onclick=\"event.stopPropagation()\">\n          <button class=\"modal-close\" onclick=\"closeModal()\">&times;<\/button>\n          <div id=\"modalImageContainer\">\n            <!-- Dynamic content: single image or carousel -->\n          <\/div>\n          <div class=\"modal-text\">\n            <div class=\"modal-title\" id=\"modalTitle\"><\/div>\n            <div class=\"modal-caption\" id=\"modalCaption\"><\/div>\n            <div class=\"modal-description\" id=\"modalDescription\"><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <!-- Map View -->\n      <div id=\"map\" class=\"view\">\n      <!-- Search Bar -->\n      <div class=\"map-search-bar\" id=\"searchBar\">\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n          <circle cx=\"11\" cy=\"11\" r=\"8\"\/>\n          <path d=\"m21 21-4.35-4.35\"\/>\n        <\/svg>\n        <input type=\"text\" id=\"searchInput\" placeholder=\"Search places...\" onkeyup=\"handleSearch(this.value)\" onkeydown=\"handleSearchKeydown(event)\" onfocus=\"showSuggestionsIfQuery()\" onkeypress=\"if(event.key==='Enter')event.preventDefault()\" autocomplete=\"off\">\n        <button class=\"map-search-clear\" onclick=\"clearSearch()\" id=\"clearBtn\" style=\"display: none;\">\u2715<\/button>\n        <div class=\"search-suggestions\" id=\"searchSuggestions\"><\/div>\n      <\/div>\n      \n      <!-- Filter Bar -->\n      <div class=\"map-filter-bar\" id=\"filterBar\">\n          <!-- Filter chips will be inserted here by JavaScript -->\n        <\/div>\n        \n        <!-- Map Type Controls -->\n        <div class=\"map-type-controls\">\n          <button class=\"map-type-btn active\" onclick=\"changeMapType('normal', this)\">Normal<\/button>\n          <button class=\"map-type-btn\" onclick=\"changeMapType('satellite', this)\">Satellite<\/button>\n          <button class=\"map-type-btn\" onclick=\"changeMapType('hybrid', this)\">Hybrid<\/button>\n          <button class=\"map-type-btn\" onclick=\"changeMapType('terrain', this)\">Terrain<\/button>\n        <\/div>\n        \n        <!-- Zoom Controls -->\n        <div class=\"map-zoom-controls\">\n          <button class=\"map-zoom-btn\" onclick=\"zoomMap(0.2)\">+<\/button>\n          <button class=\"map-zoom-btn\" onclick=\"zoomMap(-0.2)\">\u2212<\/button>\n        <\/div>\n        \n        <!-- City Center Button -->\n        <button class=\"map-center-btn\" onclick=\"flyToCityCenter()\" title=\"Back to city center\">\n          <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n            <path d=\"M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-4 0a1 1 0 01-1-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 01-1 1h-2z\"\/>\n          <\/svg>\n        <\/button>\n        \n        <!-- My Location Button -->\n        <button class=\"map-location-btn\" id=\"myLocationBtn\" onclick=\"toggleMyLocation()\" title=\"Show my location\">\n          <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n            <circle cx=\"12\" cy=\"12\" r=\"3\"\/>\n            <path d=\"M12 2v3M12 19v3M2 12h3M19 12h3\"\/>\n            <circle cx=\"12\" cy=\"12\" r=\"8\" stroke-dasharray=\"2 2\" opacity=\"0.4\"\/>\n          <\/svg>\n        <\/button>\n        \n        <!-- GPS Accuracy Banner -->\n        <div class=\"gps-accuracy-banner\" id=\"gpsAccuracyBanner\">\n          <span class=\"gps-accuracy-dot\"><\/span>\n          <span class=\"gps-accuracy-text\">GPS: --<\/span>\n          <button class=\"gps-dismiss\" onclick=\"dismissGpsBanner()\">&times;<\/button>\n        <\/div>\n        \n        <div class=\"map-container\" id=\"mapContainer\">\n          <div id=\"mapBackground\"><\/div>\n        <\/div>\n        \n        <div class=\"location-card\">\n          <!-- Card will be dynamically updated -->\n        <\/div>\n      <\/div>\n      \n      <!-- POI Image Modal -->\n      <div class=\"poi-image-modal\" id=\"poiImageModal\" onclick=\"closePOIImageModal(event)\">\n        <div class=\"poi-image-modal-content\" onclick=\"event.stopPropagation()\">\n          <button class=\"poi-image-modal-close\" onclick=\"closePOIImageModal()\">&times;<\/button>\n          <img decoding=\"async\" id=\"poiModalImage\" src=\"\" alt=\"POI Image\">\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- Bottom Tab Bar -->\n    <div class=\"tab-bar\">\n      <button class=\"tab-button active\" data-target=\"home\" onclick=\"switchTab('home')\">\n        <svg class=\"tab-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n          <path d=\"M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z\"\/>\n        <\/svg>\n        <span class=\"tab-label\">Home<\/span>\n      <\/button>\n      <button class=\"tab-button\" data-target=\"gallery\" onclick=\"switchTab('gallery')\">\n        <svg class=\"tab-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n          <rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"\/>\n          <rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"\/>\n          <rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"\/>\n          <rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"\/>\n        <\/svg>\n        <span class=\"tab-label\">Gallery<\/span>\n      <\/button>\n      <button class=\"tab-button\" data-target=\"map\" onclick=\"switchTab('map')\">\n        <svg class=\"tab-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n          <path d=\"M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z\"\/>\n        <\/svg>\n        <span class=\"tab-label\">Map<\/span>\n      <\/button>\n    <\/div>\n  <\/div>\n\n  <script>\n    \/\/ ========================================\n    \/\/ CONFIGURATION: WordPress Version\n    \/\/ ========================================\n    \/\/ ========================================\n    \/\/ CONFIGURATION: Update these paths for WordPress\n    \/\/ ========================================\n    const CONFIG = {\n      \/\/ Background image (also used as logo)\n      backgroundImage: 'https:\/\/visit-centralmacedonia.click\/wp-content\/uploads\/BACKGROUND\/background_0-scaled.jpg',\n      logoImage: 'https:\/\/visit-centralmacedonia.click\/wp-content\/uploads\/LOGO\/logo_pkm.jpg',\n      \n      \/\/ Video file\n      videoFile: 'https:\/\/visit-centralmacedonia.click\/wp-content\/uploads\/VIDEO\/GREAT-IN-GENERAL_master-with-english-subs.mp4',\n      \n      \/\/ POI data JSON file\n      poisJsonFile: 'https:\/\/visit-centralmacedonia.click\/wp-content\/uploads\/2026\/02\/pois.json',\n      \n      \/\/ Gallery folder path (prefix for all gallery images) - now using WebP\n      galleryPath: 'https:\/\/visit-centralmacedonia.click\/wp-content\/uploads\/Gallery\/',\n      \n      \/\/ Offline Map Tiles Paths\n      offlineTilesPaths: {\n        arcgis: 'https:\/\/visit-centralmacedonia.click\/wp-content\/uploads\/POI\/arcgis\/',\n        cartodb: 'https:\/\/visit-centralmacedonia.click\/wp-content\/uploads\/POI\/cartodb\/',\n        opentopomap: 'https:\/\/visit-centralmacedonia.click\/wp-content\/uploads\/POI\/opentopomap\/',\n        osm: 'https:\/\/visit-centralmacedonia.click\/wp-content\/uploads\/POI\/osm\/'\n      },\n      \n      \/\/ Use offline tiles (set to false to use online tiles)\n      useOfflineTiles: true,\n      \n      \/\/ Online Map Tiles URLs (fallback, used when useOfflineTiles is false)\n      onlineTilesPaths: {\n        arcgis: 'https:\/\/server.arcgisonline.com\/ArcGIS\/rest\/services\/World_Imagery\/MapServer\/tile\/{z}\/{y}\/{x}',\n        cartodb: 'https:\/\/{s}.basemaps.cartocdn.com\/light_all\/{z}\/{x}\/{y}{r}.png',\n        opentopomap: 'https:\/\/{s}.tile.opentopomap.org\/{z}\/{x}\/{y}.png',\n        osm: 'https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png'\n      },\n      \n      \/\/ WordPress Upload URLs (update these after uploading to WordPress)\n      \/\/ Example: 'https:\/\/yoursite.com\/wp-content\/uploads\/2026\/02\/'\n      wordpressMediaUrl: '',  \/\/ Leave empty for local, or set to your WP media URL\n      wordpressUploadsUrl: '' \/\/ For pois.json, e.g., 'https:\/\/yoursite.com\/wp-content\/uploads\/'\n    };\n    \n    \/\/ Helper function to get full path\n    function getMediaPath(filename) {\n      return CONFIG.wordpressMediaUrl ? CONFIG.wordpressMediaUrl + filename : filename;\n    }\n    \n    function getUploadPath(filename) {\n      return CONFIG.wordpressUploadsUrl ? CONFIG.wordpressUploadsUrl + filename : filename;\n    }\n    \n    \/\/ Update background image dynamically\n    document.addEventListener('DOMContentLoaded', () => {\n      const bodyBefore = document.createElement('style');\n      bodyBefore.textContent = `\n        body::before {\n          background-image: url('${getMediaPath(CONFIG.backgroundImage)}') !important;\n        }\n      `;\n      document.head.appendChild(bodyBefore);\n    });\n\n    \/\/ ========================================\n    \/\/ TRANSLATEPRESS: Helper to read translated strings from hidden container\n    \/\/ ========================================\n    function trp(key) {\n      const el = document.getElementById('trp-' + key);\n      return el ? el.textContent.trim() : key;\n    }\n\n    \/\/ Sync all static UI text from the translatable hidden container\n    \/\/ so that TranslatePress translations propagate to visible elements\n    document.addEventListener('DOMContentLoaded', () => {\n      \/\/ Home button labels \u2014 select only the main label span in each button\n      const linkButtons = document.querySelectorAll('.button-list .link-button');\n      const buttonKeys = [\n        'official-website',\n        'follow-facebook',\n        'follow-instagram',\n        'subscribe-youtube',\n        'explore-map',\n        'view-photos'\n      ];\n      linkButtons.forEach((btn, idx) => {\n        if (buttonKeys[idx]) {\n          \/\/ The label is always the first span that's NOT .button-username\n          const labelSpan = btn.querySelector('.button-content .button-text span:first-child') \n                         || btn.querySelector('.button-content span');\n          if (labelSpan) labelSpan.textContent = trp(buttonKeys[idx]);\n        }\n      });\n\n      \/\/ Tab labels\n      const tabLabels = document.querySelectorAll('.tab-bar .tab-label');\n      const tabKeys = ['tab-home', 'tab-gallery', 'tab-map'];\n      tabKeys.forEach((key, idx) => {\n        if (tabLabels[idx]) tabLabels[idx].textContent = trp(key);\n      });\n\n      \/\/ Gallery heading\n      const galleryH2 = document.querySelector('#gallery .header h2');\n      if (galleryH2) galleryH2.textContent = trp('gallery-heading');\n\n      \/\/ Map type buttons\n      const mapTypeBtns = document.querySelectorAll('.map-type-controls .map-type-btn');\n      const mapTypeKeys = ['map-normal', 'map-satellite', 'map-hybrid', 'map-terrain'];\n      mapTypeKeys.forEach((key, idx) => {\n        if (mapTypeBtns[idx]) mapTypeBtns[idx].textContent = trp(key);\n      });\n\n      \/\/ Search placeholder\n      const searchInput = document.getElementById('searchInput');\n      if (searchInput) searchInput.placeholder = trp('search-placeholder');\n\n      \/\/ Button title attributes\n      const centerBtn = document.querySelector('.map-center-btn');\n      if (centerBtn) centerBtn.title = trp('back-to-center');\n      const locBtn = document.getElementById('myLocationBtn');\n      if (locBtn) locBtn.title = trp('show-location');\n\n      \/\/ Logo alt text\n      const logo = document.getElementById('logoImage');\n      if (logo) logo.alt = trp('logo-alt');\n    });\n\n    \/\/ ========================================\n    \/\/ END CONFIGURATION\n    \/\/ ========================================\n    document.body.classList.add('tab-home');\n\n    function switchTab(target) {\n      \/\/ Smooth tab switching with performance optimization\n      requestAnimationFrame(() => {\n        \/\/ Remove active class from all views\n        document.querySelectorAll('.view').forEach(view => {\n          view.classList.remove('active');\n        });\n        \n        \/\/ Add active class to target view\n        const targetView = document.getElementById(target);\n        targetView.classList.add('active');\n        \n        \/\/ Scroll to top smoothly\n        targetView.scrollTop = 0;\n        \n        \/\/ Update tab button states\n        document.querySelectorAll('.tab-button').forEach(btn => {\n          btn.classList.remove('active');\n        });\n        document.querySelector(`[data-target=\"${target}\"]`).classList.add('active');\n\n        document.body.classList.remove('tab-home', 'tab-gallery', 'tab-map', 'one-one-active');\n        document.body.classList.add(`tab-${target}`);\n        \n        \/\/ Fix map display when switching to map tab\n        if (target === 'map') {\n          ensureMapReady().then(() => {\n            if (map) {\n              setTimeout(() => {\n                map.invalidateSize();\n                console.log('Map size recalculated on tab switch');\n              }, 150);\n            }\n          });\n          \/\/ Resume GPS watch if it was paused when leaving\n          if (isLocating && locationWatchId === null) {\n            locationWatchId = navigator.geolocation.watchPosition(\n              onLocationSuccess,\n              onLocationWatchError,\n              { enableHighAccuracy: true, timeout: 15000, maximumAge: 3000 }\n            );\n          }\n        } else {\n          \/\/ Leaving map tab \u2014 pause GPS watch to save battery\n          if (isLocating && locationWatchId !== null) {\n            navigator.geolocation.clearWatch(locationWatchId);\n            locationWatchId = null;\n          }\n        }\n      });\n    }\n\n    \/\/ Deep link mappings for social apps (mobile)\n    const deepLinks = {\n      'instagram.com': (url) => {\n        const match = url.match(\/instagram\\.com\\\/([^\/?#]+)\/);\n        return match ? 'instagram:\/\/user?username=' + match[1] : null;\n      },\n      'facebook.com': (url) => {\n        const match = url.match(\/[?&]id=(\\d+)\/);\n        return match ? 'fb:\/\/profile\/' + match[1] : null;\n      },\n      'youtube.com': (url) => {\n        const match = url.match(\/youtube\\.com\\\/c\\\/([^\/?#]+)\/);\n        return match ? 'vnd.youtube:\/\/www.youtube.com\/c\/' + match[1] : null;\n      }\n    };\n\n    function openLink(url) {\n      \/\/ Check if on mobile\n      const isMobile = \/iPhone|iPad|iPod|Android\/i.test(navigator.userAgent);\n\n      if (isMobile) {\n        \/\/ Try deep link for known social apps\n        for (const [domain, getDeepLink] of Object.entries(deepLinks)) {\n          if (url.includes(domain)) {\n            const deepLink = getDeepLink(url);\n            if (deepLink) {\n              \/\/ Try deep link; fall back to web URL after timeout\n              const start = Date.now();\n              window.location.href = deepLink;\n              setTimeout(() => {\n                \/\/ If still here after 1.5s, app didn't open \u2014 use web\n                if (Date.now() - start < 2000) {\n                  window.open(url, '_blank');\n                }\n              }, 1500);\n              return;\n            }\n          }\n        }\n      }\n\n      \/\/ Default: open as normal link\n      const a = document.createElement('a');\n      a.href = url;\n      a.target = '_blank';\n      a.rel = 'noopener noreferrer';\n      document.body.appendChild(a);\n      a.click();\n      document.body.removeChild(a);\n    }\n\n    \/\/ Video Player Functions\n    const video = document.getElementById('mainVideo');\n    const videoCard = document.getElementById('videoCard');\n    const playIcon = document.getElementById('playIcon');\n    const pauseIcon = document.getElementById('pauseIcon');\n    const progressFill = document.getElementById('progressFill');\n    const timeDisplay = document.getElementById('timeDisplay');\n    const videoPlayOverlay = document.getElementById('videoPlayOverlay');\n    let rotation = 0;\n\n    function togglePlay() {\n      if (video.paused) {\n        video.play();\n        playIcon.style.display = 'none';\n        pauseIcon.style.display = 'block';\n        videoPlayOverlay.classList.add('hide');\n        videoPlayOverlay.classList.remove('show');\n      } else {\n        video.pause();\n        playIcon.style.display = 'block';\n        pauseIcon.style.display = 'none';\n        videoPlayOverlay.classList.add('show');\n        videoPlayOverlay.classList.remove('hide');\n      }\n    }\n\n    \/\/ Update overlay when video plays\/pauses\n    video.addEventListener('play', () => {\n      videoPlayOverlay.classList.add('hide');\n      videoPlayOverlay.classList.remove('show');\n    });\n    video.addEventListener('pause', () => {\n      videoPlayOverlay.classList.add('show');\n      videoPlayOverlay.classList.remove('hide');\n    });\n\n    function toggleFullscreen() {\n      if (!document.fullscreenElement) {\n        videoCard.requestFullscreen().catch(err => {\n          console.log('Error attempting to enable fullscreen:', err);\n        });\n      } else {\n        document.exitFullscreen();\n      }\n    }\n\n    function rotateVideo(degrees) {\n      rotation = (rotation + degrees) % 360;\n      if (rotation < 0) rotation += 360;\n      video.style.transform = `rotate(${rotation}deg)`;\n      \n      \/\/ Adjust sizing for rotated orientations\n      video.classList.remove('rotated-90', 'rotated-270');\n      if (rotation === 90) {\n        video.classList.add('rotated-90');\n      } else if (rotation === 270) {\n        video.classList.add('rotated-270');\n      }\n    }\n\n    \/\/ Reset rotation when exiting fullscreen\n    document.addEventListener('fullscreenchange', () => {\n      if (!document.fullscreenElement) {\n        rotation = 0;\n        video.style.transform = 'rotate(0deg)';\n        video.classList.remove('rotated-90', 'rotated-270');\n      }\n    });\n\n    function seek(event) {\n      const progressBar = document.getElementById('progressBar');\n      const rect = progressBar.getBoundingClientRect();\n      const pos = (event.clientX - rect.left) \/ rect.width;\n      video.currentTime = pos * video.duration;\n    }\n\n    function formatTime(seconds) {\n      const mins = Math.floor(seconds \/ 60);\n      const secs = Math.floor(seconds % 60);\n      return `${mins}:${secs.toString().padStart(2, '0')}`;\n    }\n\n    \/\/ Update progress bar and time\n    video.addEventListener('timeupdate', () => {\n      requestAnimationFrame(() => {\n        const progress = (video.currentTime \/ video.duration) * 100;\n        progressFill.style.width = progress + '%';\n        timeDisplay.textContent = `${formatTime(video.currentTime)} \/ ${formatTime(video.duration)}`;\n      });\n    });\n\n    \/\/ Show controls on touch\/click for mobile\n    videoCard.addEventListener('click', (e) => {\n      if (e.target === video) {\n        videoCard.classList.toggle('show-controls');\n      }\n    });\n\n    \/\/ Update time display when metadata loads\n    video.addEventListener('loadedmetadata', () => {\n      timeDisplay.textContent = `0:00 \/ ${formatTime(video.duration)}`;\n    });\n\n    \/\/ Update logo and video sources\n    document.addEventListener('DOMContentLoaded', () => {\n      const logoImg = document.getElementById('logoImage');\n      if (logoImg) logoImg.src = getMediaPath(CONFIG.logoImage);\n      \n      const videoSource = document.getElementById('videoSource');\n      if (videoSource) {\n        videoSource.src = getMediaPath(CONFIG.videoFile);\n        document.getElementById('mainVideo').load();\n      }\n    });\n    \n    \/\/ Gallery Data - Dynamically loaded from metadata\n    let galleryData = { images: [] };\n\n    \/\/ Load gallery metadata from JSON file\n    async function loadGalleryMetadata() {\n      try {\n        console.log('Fetching gallery metadata from:', CONFIG.galleryPath + 'metadata.json');\n        const response = await fetch(CONFIG.galleryPath + 'metadata.json');\n        \n        if (!response.ok) {\n          throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n        }\n        \n        const metadata = await response.json();\n        console.log('Raw metadata:', metadata);\n        \n        \/\/ Use metadata directly (it already has the correct format)\n        galleryData.images = metadata.images.map(img => ({\n          files: img.files || [],\n          title: img.title || '',\n          description: img.description || '',\n          caption: img.caption || '',\n          alt: img.alt || img.title || ''\n        }));\n        \n        console.log(`\u2713 Loaded ${galleryData.images.length} gallery items from metadata`);\n        console.log('Gallery data:', galleryData);\n        loadGallery();\n      } catch (error) {\n        console.error('Failed to load gallery metadata:', error);\n        \/\/ Fallback to minimal hardcoded data\n        galleryData = {\n          images: [\n            {\n              files: [\"ancient-amfipolis.webp\"],\n              title: \"Lion of Amphipolis\",\n              description: \"The magnificent Lion of Amphipolis, a 4th-century BC tomb monument standing guard over the ancient city of Amphipolis in Central Macedonia.\",\n              caption: \"The iconic Lion of Amphipolis monument\",\n              alt: \"Lion of Amphipolis\"\n            }\n          ]\n        };\n        console.warn('Using fallback gallery data');\n        loadGallery();\n      }\n    }\n\n    \/\/ Gallery Functions - with lazy loading via IntersectionObserver\n    let galleryObserver = null;\n    \n    function setupGalleryObserver() {\n      if (galleryObserver) galleryObserver.disconnect();\n      \n      galleryObserver = new IntersectionObserver((entries) => {\n        entries.forEach(entry => {\n          if (entry.isIntersecting) {\n            const item = entry.target;\n            \/\/ Load images that haven't been loaded yet\n            const lazyImages = item.querySelectorAll('img[data-src]');\n            lazyImages.forEach(img => {\n              img.src = img.dataset.src;\n              img.removeAttribute('data-src');\n            });\n            galleryObserver.unobserve(item);\n          }\n        });\n      }, {\n        rootMargin: '200px 0px', \/\/ Start loading 200px before visible\n        threshold: 0.01\n      });\n    }\n    \n    function loadGallery() {\n      const galleryGrid = document.getElementById('galleryGrid');\n      \n      \/\/ Clear existing gallery items\n      galleryGrid.innerHTML = '';\n      \n      console.log(`Loading ${galleryData.images.length} gallery items...`);\n      \n      \/\/ Setup IntersectionObserver for lazy loading\n      setupGalleryObserver();\n      \n      \/\/ Use DocumentFragment for batch DOM insertion\n      const fragment = document.createDocumentFragment();\n      \n      galleryData.images.forEach((image, index) => {\n        const item = document.createElement('div');\n        item.className = 'gallery-item';\n        \n        const descId = `desc-${index}`;\n        const hasMultipleImages = image.files.length > 1;\n        \n        \/\/ Build carousel HTML - images use data-src for lazy loading\n        let carouselHTML = '';\n        if (hasMultipleImages) {\n          const slidesHTML = image.files.map((file, slideIndex) => \n            `<div class=\"carousel-slide\">\n              <img data-src=\"${getGalleryPath(file)}\" alt=\"${image.title}\" class=\"gallery-image loading\" loading=\"lazy\" onload=\"this.classList.remove('loading'); this.classList.add('loaded');\" onclick=\"openImageInOneOne(${index}, ${slideIndex})\" data-index=\"${index}\" data-slide=\"${slideIndex}\">\n            <\/div>`\n          ).join('');\n          \n          const dotsHTML = image.files.map((_, slideIndex) => \n            `<span class=\"carousel-dot ${slideIndex === 0 ? 'active' : ''}\" onclick=\"goToSlide(${index}, ${slideIndex})\"><\/span>`\n          ).join('');\n          \n          carouselHTML = `\n            <div class=\"image-carousel\" id=\"carousel-${index}\">\n              <div class=\"carousel-track\" id=\"track-${index}\">\n                ${slidesHTML}\n              <\/div>\n              <button class=\"carousel-nav prev\" onclick=\"prevSlide(${index})\">\n                <svg viewBox=\"0 0 24 24\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                  <polyline points=\"15 18 9 12 15 6\"\/>\n                <\/svg>\n              <\/button>\n              <button class=\"carousel-nav next\" onclick=\"nextSlide(${index})\">\n                <svg viewBox=\"0 0 24 24\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                  <polyline points=\"9 18 15 12 9 6\"\/>\n                <\/svg>\n              <\/button>\n              <div class=\"carousel-indicators\">\n                ${dotsHTML}\n              <\/div>\n            <\/div>\n          `;\n        } else {\n          carouselHTML = `<img data-src=\"${getGalleryPath(image.files[0])}\" alt=\"${image.title}\" class=\"gallery-image loading\" loading=\"lazy\" onload=\"this.classList.remove('loading'); this.classList.add('loaded');\" onclick=\"openImageInOneOne(${index}, 0)\" data-index=\"${index}\" data-slide=\"0\">`;\n        }\n        \n        item.innerHTML = `\n          ${carouselHTML}\n          <div class=\"gallery-content\">\n            <div class=\"gallery-title\">${image.title}<\/div>\n            <div class=\"gallery-caption\">${image.caption}<\/div>\n            <div class=\"gallery-description collapsed\" id=\"${descId}\">${image.description}<\/div>\n            <button class=\"view-more-btn\" id=\"btn-${index}\" onclick=\"toggleDescription('${descId}', this)\" style=\"display: none;\">${trp('view-more')}<\/button>\n          <\/div>\n        `;\n        \n        fragment.appendChild(item);\n        \n        \/\/ Observe each item for lazy loading\n        galleryObserver.observe(item);\n      });\n      \n      \/\/ Single DOM write\n      galleryGrid.appendChild(fragment);\n      \n      \/\/ Check which descriptions need \"view more\" button after rendering\n      setTimeout(() => {\n        galleryData.images.forEach((image, index) => {\n          const descElement = document.getElementById(`desc-${index}`);\n          const btnElement = document.getElementById(`btn-${index}`);\n          \n          if (descElement && btnElement) {\n            \/\/ Check if content is truncated\n            const isTruncated = descElement.scrollHeight > descElement.clientHeight;\n            if (isTruncated) {\n              btnElement.style.display = 'block';\n            }\n          }\n        });\n        \n        \/\/ Setup touch gestures after rendering\n        setupTouchGestures();\n      }, 100);\n    }\n\n    \/\/ Carousel navigation\n    let currentSlides = {};\n    let modalCurrentSlide = 0;\n    let touchStartX = 0;\n    let touchEndX = 0;\n\n    function initSlide(index) {\n      if (currentSlides[index] === undefined) {\n        currentSlides[index] = 0;\n      }\n    }\n\n    function updateCarousel(index) {\n      requestAnimationFrame(() => {\n        const track = document.getElementById(`track-${index}`);\n        const dots = document.querySelectorAll(`#carousel-${index} .carousel-dot`);\n        \n        if (track) {\n          track.style.transform = `translate3d(-${currentSlides[index] * 100}%, 0, 0)`;\n        }\n        \n        dots.forEach((dot, i) => {\n          dot.classList.toggle('active', i === currentSlides[index]);\n        });\n      });\n    }\n\n    function nextSlide(index) {\n      initSlide(index);\n      const maxSlides = galleryData.images[index].files.length;\n      if (currentSlides[index] < maxSlides - 1) {\n        currentSlides[index]++;\n        updateCarousel(index);\n      }\n    }\n\n    function prevSlide(index) {\n      initSlide(index);\n      if (currentSlides[index] > 0) {\n        currentSlides[index]--;\n        updateCarousel(index);\n      }\n    }\n\n    function goToSlide(index, slideIndex) {\n      currentSlides[index] = slideIndex;\n      updateCarousel(index);\n    }\n\n    \/\/ Touch gesture support for carousels\n    function setupTouchGestures() {\n      document.querySelectorAll('.image-carousel').forEach((carousel) => {\n        const carouselId = carousel.id; \/\/ e.g., \"carousel-0\"\n        const index = parseInt(carouselId.split('-')[1]);\n        \n        let carouselTouchStartX = 0;\n        let carouselTouchEndX = 0;\n        \n        carousel.addEventListener('touchstart', (e) => {\n          carouselTouchStartX = e.changedTouches[0].screenX;\n        }, { passive: true });\n\n        carousel.addEventListener('touchend', (e) => {\n          carouselTouchEndX = e.changedTouches[0].screenX;\n          const swipeThreshold = 40;\n          const swipeDistance = carouselTouchStartX - carouselTouchEndX;\n          \n          if (Math.abs(swipeDistance) > swipeThreshold) {\n            if (swipeDistance > 0) {\n              nextSlide(index);\n            } else {\n              prevSlide(index);\n            }\n          }\n        }, { passive: true });\n      });\n    }\n\n    function handleSwipe(index) {\n      const swipeThreshold = 40;\n      const swipeDistance = touchStartX - touchEndX;\n      \n      if (Math.abs(swipeDistance) > swipeThreshold) {\n        if (swipeDistance > 0) {\n          nextSlide(index);\n        } else {\n          prevSlide(index);\n        }\n      }\n    }\n\n    \/\/ Modal carousel functions\n    function updateModalCarousel(imageIndex) {\n      requestAnimationFrame(() => {\n        const track = document.getElementById('modal-track');\n        const dots = document.querySelectorAll('.modal-carousel .carousel-dot');\n        \n        if (track) {\n          track.style.transform = `translate3d(-${modalCurrentSlide * 100}%, 0, 0)`;\n        }\n        \n        dots.forEach((dot, i) => {\n          dot.classList.toggle('active', i === modalCurrentSlide);\n        });\n      });\n    }\n\n    function nextModalSlide(imageIndex) {\n      const maxSlides = galleryData.images[imageIndex].files.length;\n      if (modalCurrentSlide < maxSlides - 1) {\n        modalCurrentSlide++;\n        updateModalCarousel(imageIndex);\n      }\n    }\n\n    function prevModalSlide(imageIndex) {\n      const maxSlides = galleryData.images[imageIndex].files.length;\n      if (modalCurrentSlide > 0) {\n        modalCurrentSlide--;\n        updateModalCarousel(imageIndex);\n      }\n    }\n\n    function goToModalSlide(imageIndex, slideIndex) {\n      modalCurrentSlide = slideIndex;\n      updateModalCarousel(imageIndex);\n    }\n\n    function setupModalTouchGestures(imageIndex) {\n      const modalCarousel = document.querySelector('.modal-carousel');\n      if (!modalCarousel) return;\n\n      let modalTouchStartX = 0;\n      let modalTouchEndX = 0;\n\n      modalCarousel.addEventListener('touchstart', (e) => {\n        modalTouchStartX = e.changedTouches[0].screenX;\n      }, { passive: true });\n\n      modalCarousel.addEventListener('touchend', (e) => {\n        modalTouchEndX = e.changedTouches[0].screenX;\n        const swipeThreshold = 40;\n        const swipeDistance = modalTouchStartX - modalTouchEndX;\n        \n        if (Math.abs(swipeDistance) > swipeThreshold) {\n          if (swipeDistance > 0) {\n            nextModalSlide(imageIndex);\n          } else {\n            prevModalSlide(imageIndex);\n          }\n        }\n      }, { passive: true });\n    }\n\n    \/\/ Toggle description expansion\n    function toggleDescription(descId, button) {\n      const desc = document.getElementById(descId);\n      if (desc.classList.contains('collapsed')) {\n        desc.classList.remove('collapsed');\n        button.textContent = trp('view-less');\n      } else {\n        desc.classList.add('collapsed');\n        button.textContent = trp('view-more');\n      }\n    }\n\n    \/\/ Open image modal\n    function openModal(index, slideIndex = 0) {\n      const image = galleryData.images[index];\n      const modal = document.getElementById('imageModal');\n      const container = document.getElementById('modalImageContainer');\n      \n      modalCurrentSlide = slideIndex;\n      \n      \/\/ Build carousel or single image\n      if (image.files.length > 1) {\n        const slidesHTML = image.files.map((file) => \n          `<div class=\"carousel-slide\">\n            <img decoding=\"async\" src=\"${getGalleryPath(file)}\" alt=\"${image.title}\" class=\"loading\" loading=\"lazy\" onload=\"this.classList.remove('loading'); this.classList.add('loaded');\">\n          <\/div>`\n        ).join('');\n        \n        const dotsHTML = image.files.map((_, i) => \n          `<span class=\"carousel-dot ${i === slideIndex ? 'active' : ''}\" onclick=\"goToModalSlide(${index}, ${i})\"><\/span>`\n        ).join('');\n        \n        container.innerHTML = `\n          <div class=\"modal-carousel\">\n            <div class=\"carousel-track\" id=\"modal-track\">\n              ${slidesHTML}\n            <\/div>\n            <button class=\"carousel-nav prev\" onclick=\"prevModalSlide(${index})\">\n              <svg viewBox=\"0 0 24 24\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                <polyline points=\"15 18 9 12 15 6\"\/>\n              <\/svg>\n            <\/button>\n            <button class=\"carousel-nav next\" onclick=\"nextModalSlide(${index})\">\n              <svg viewBox=\"0 0 24 24\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n                <polyline points=\"9 18 15 12 9 6\"\/>\n              <\/svg>\n            <\/button>\n            <div class=\"carousel-indicators\">\n              ${dotsHTML}\n            <\/div>\n          <\/div>\n        `;\n        \n        \/\/ Set initial slide position\n        setTimeout(() => {\n          updateModalCarousel(index);\n          setupModalTouchGestures(index);\n        }, 10);\n      } else {\n        container.innerHTML = `<img decoding=\"async\" class=\"modal-image loading\" src=\"${getGalleryPath(image.files[0])}\" alt=\"${image.title}\" loading=\"lazy\" onload=\"this.classList.remove('loading'); this.classList.add('loaded');\">`;\n      }\n      \n      document.getElementById('modalTitle').textContent = image.title;\n      document.getElementById('modalCaption').textContent = image.caption;\n      document.getElementById('modalDescription').textContent = image.description;\n      \n      modal.classList.add('active');\n      document.body.style.overflow = 'hidden';\n    }\n\n    \/\/ Close image modal\n    function closeModal(event) {\n      if (event && event.target.closest('.modal-content') && event.target.className !== 'modal-close') {\n        return;\n      }\n      \n      const modal = document.getElementById('imageModal');\n      modal.classList.remove('active');\n      document.body.style.overflow = '';\n    }\n\n    \/\/ Set view mode\n    function setViewMode(mode) {\n      const galleryGrid = document.getElementById('galleryGrid');\n      \n      \/\/ Remove all mode classes\n      galleryGrid.classList.remove('grid-mode', 'one-one-mode', 'list-mode');\n      \n      \/\/ Add new mode class\n      galleryGrid.classList.add(mode + '-mode');\n      \n      \/\/ Update button states\n      document.querySelectorAll('.view-mode-btn').forEach(btn => {\n        btn.classList.remove('active');\n      });\n      event.target.classList.add('active');\n      \n      \/\/ Update body class for back button visibility\n      const body = document.body;\n      if (mode === 'one-one') {\n        body.classList.add('one-one-active');\n      } else {\n        body.classList.remove('one-one-active');\n      }\n    }\n    \n    \/\/ Open image in one-one view (Instagram style)\n    function openImageInOneOne(index, slideIndex = 0) {\n      const galleryGrid = document.getElementById('galleryGrid');\n      const galleryView = document.getElementById('gallery');\n      \n      \/\/ Check if already in one-one mode\n      if (!galleryGrid.classList.contains('one-one-mode')) {\n        \/\/ Hide content during transition using opacity for instant effect\n        galleryGrid.style.opacity = '0';\n        galleryGrid.style.pointerEvents = 'none';\n        \n        \/\/ Disable smooth scrolling temporarily for instant scroll\n        const originalScrollBehavior = galleryView.style.scrollBehavior;\n        galleryView.style.scrollBehavior = 'auto';\n        \n        \/\/ Switch to one-one mode immediately\n        galleryGrid.classList.remove('grid-mode', 'list-mode');\n        galleryGrid.classList.add('one-one-mode');\n        \n        \/\/ Update button states\n        document.querySelectorAll('.view-mode-btn').forEach(btn => {\n          btn.classList.remove('active');\n        });\n        document.querySelector('.view-mode-btn[onclick*=\\\"one-one\\\"]').classList.add('active');\n        \n        \/\/ Add class for back button visibility\n        document.body.classList.add('one-one-active');\n        \n        \/\/ Force synchronous layout and scroll before showing\n        const galleryItems = document.querySelectorAll('.gallery-item');\n        if (galleryItems[index]) {\n          \/\/ Force layout calculation\n          galleryGrid.offsetHeight;\n          \n          \/\/ Calculate exact position to center the item in viewport\n          const itemOffset = galleryItems[index].offsetTop;\n          const itemHeight = galleryItems[index].offsetHeight;\n          const viewportHeight = galleryView.clientHeight;\n          \n          \/\/ Center the item: item top + (item height \/ 2) - (viewport height \/ 2)\n          const centeredScrollTop = itemOffset + (itemHeight \/ 2) - (viewportHeight \/ 2);\n          galleryView.scrollTop = centeredScrollTop;\n          \n          \/\/ Force another layout to ensure scroll completed\n          galleryView.offsetHeight;\n          \n          \/\/ Show content at final position - instant reveal\n          galleryGrid.style.opacity = '1';\n          galleryGrid.style.pointerEvents = 'auto';\n          \n          \/\/ Restore smooth scrolling for normal navigation\n          galleryView.style.scrollBehavior = originalScrollBehavior;\n        }\n      }\n      \n      \/\/ If there are multiple images, set the slide\n      if (galleryData.images[index].files.length > 1) {\n        goToSlide(index, slideIndex);\n      }\n    }\n    \n    \/\/ Back to grid view\n    function backToGridView() {\n      const galleryGrid = document.getElementById('galleryGrid');\n      \n      \/\/ Switch to grid mode\n      galleryGrid.classList.remove('one-one-mode', 'list-mode');\n      galleryGrid.classList.add('grid-mode');\n      \n      \/\/ Update button states\n      document.querySelectorAll('.view-mode-btn').forEach(btn => {\n        btn.classList.remove('active');\n      });\n      document.querySelector('.view-mode-btn[onclick*=\\\"grid\\\"]').classList.add('active');\n      \n      \/\/ Remove class for back button visibility\n      document.body.classList.remove('one-one-active');\n      \n      \/\/ Scroll to top instantly (no animation)\n      window.scrollTo({ top: 0, behavior: 'auto' });\n    }\n\n    \/\/ Helper to get gallery image path\n    function getGalleryPath(filename) {\n      return CONFIG.galleryPath + filename;\n    }\n    \n    \/\/ POI Image Modal Functions\n    function openPOIImageModal(imageUrl, altText) {\n      const modal = document.getElementById('poiImageModal');\n      const img = document.getElementById('poiModalImage');\n      \n      img.src = imageUrl;\n      img.alt = altText || 'POI Image';\n      \n      modal.classList.add('active');\n      document.body.style.overflow = 'hidden';\n    }\n    \n    function closePOIImageModal(event) {\n      \/\/ Close only if clicking outside the content or on close button\n      if (event && event.target.closest('.poi-image-modal-content') && event.target.className !== 'poi-image-modal-close') {\n        return;\n      }\n      \n      const modal = document.getElementById('poiImageModal');\n      modal.classList.remove('active');\n      document.body.style.overflow = '';\n    }\n    \n    \/\/ Load gallery metadata and initialize\n    loadGalleryMetadata();\n\n    \/\/ Map POI Data (loaded dynamically from pois.json)\n    let mapPOIs = [];\n\n    let currentFilters = ['all'];\n    let activePOI = 1;\n    let currentMapType = 'normal';\n    \n    \/\/ Leaflet map instance\n    let map = null;\n    let markers = {};\n    let tileLayers = {};\n    \n    \/\/ Category display mapping (used in dropdown + cards)\n    \/\/ Category labels - read from TranslatePress-translatable hidden container\n    function buildCategoryLabels() {\n      const keys = ['museum','landmark','culture','beach','church','traditional_settlement','architecture','archaeological','nature','park','activities','cave','ski_resort','lake','mountain','wetland','thermal_spa','canyon','other'];\n      const labels = {};\n      keys.forEach(k => { labels[k] = trp('cat-' + k); });\n      return labels;\n    }\n    const categoryLabels = buildCategoryLabels();\n\n    function toTitleFromKey(key) {\n      return String(key || '')\n        .split('_')\n        .filter(Boolean)\n        .map(part => part.charAt(0).toUpperCase() + part.slice(1))\n        .join(' ');\n    }\n\n    function getCategoryLabel(category) {\n      return categoryLabels[category] || toTitleFromKey(category) || 'Other';\n    }\n\n    \/\/ Category color mapping (reuse existing palette)\n    const categoryColors = {\n      museum: '#FF6B6B',\n      landmark: '#FF6B6B',\n      culture: '#4ECDC4',\n      beach: '#45B7D1',\n      church: '#A29BFE',\n      traditional_settlement: '#74B9FF',\n      architecture: '#6C5CE7',\n      archaeological: '#FD79A8',\n      nature: '#96CEB4',\n      park: '#96CEB4',\n      activities: '#FF7675',\n      cave: '#FFEAA7',\n      ski_resort: '#A29BFE',\n      lake: '#45B7D1',\n      mountain: '#FD79A8',\n      wetland: '#4ECDC4',\n      thermal_spa: '#74B9FF',\n      canyon: '#6C5CE7',\n      other: '#95A5A6'\n    };\n\n    \/\/ Category emoji icons for map markers\n    const categoryIcons = {\n      museum: '\ud83c\udfdb\ufe0f',\n      landmark: '\ud83d\udccd',\n      culture: '\ud83c\udfad',\n      beach: '\ud83c\udfd6\ufe0f',\n      church: '\u26ea',\n      traditional_settlement: '\ud83c\udfd8\ufe0f',\n      architecture: '\ud83c\udfd7\ufe0f',\n      archaeological: '\ud83c\udffa',\n      nature: '\ud83c\udf3f',\n      park: '\ud83c\udf32',\n      activities: '\ud83c\udfc3',\n      cave: '\ud83d\udd73\ufe0f',\n      ski_resort: '\u26f7\ufe0f',\n      lake: '\ud83d\udca7',\n      mountain: '\u26f0\ufe0f',\n      wetland: '\ud83c\udf0a',\n      thermal_spa: '\u2668\ufe0f',\n      canyon: '\ud83c\udfdc\ufe0f',\n      other: '\ud83d\udccc'\n    };\n\n    function getCategoryIcon(category, color) {\n      const icon = categoryIcons[category] || categoryIcons.other;\n      return `\n        <div style=\"\n          width: 34px;\n          height: 34px;\n          background: ${color};\n          border-radius: 50%;\n          display: flex;\n          align-items: center;\n          justify-content: center;\n          box-shadow: 0 2px 8px rgba(0,0,0,0.3);\n          border: 2.5px solid rgba(255,255,255,0.9);\n          font-size: 18px;\n          line-height: 1;\n        \">${icon}<\/div>\n      `;\n    }\n\n    \/\/ Default map center (Thessaloniki \/ Central Macedonia)\n    const MAP_DEFAULT_CENTER = [40.6401, 22.9444];\n    const MAP_DEFAULT_ZOOM = 9;\n\n    function flyToCityCenter() {\n      if (!map) return;\n      map.flyTo(MAP_DEFAULT_CENTER, MAP_DEFAULT_ZOOM, {\n        duration: 1,\n        easeLinearity: 0.25\n      });\n    }\n\n    \/\/ Offline tile zoom ranges (min\/max zoom levels available offline)\n    const offlineZoomRanges = {\n      osm: { min: 7, max: 15 },\n      arcgis: { min: 7, max: 12 },\n      cartodb: { min: 7, max: 12 },\n      opentopomap: { min: 7, max: 12 }\n    };\n\n    \/\/ Map type zoom limits (now higher since online tiles fill the gaps)\n    const mapTypeZoomLimits = {\n      normal: 19,      \/\/ OSM offline: 7-15, online beyond\n      satellite: 18,   \/\/ ArcGIS offline: 7-12, online beyond\n      hybrid: 18,      \/\/ ArcGIS + CartoDB offline: 7-12, online beyond\n      terrain: 17      \/\/ OpenTopoMap offline: 7-12, online beyond\n    };\n\n    \/\/ Change map type\n    function changeMapType(type, el) {\n      if (!map) return;\n      \n      currentMapType = type;\n      \n      \/\/ Remove current layer\n      Object.values(tileLayers).forEach(layer => map.removeLayer(layer));\n      \n      \/\/ Add new layer\n      if (tileLayers[type]) {\n        tileLayers[type].addTo(map);\n      }\n      \n      \/\/ Update map max zoom based on available tiles\n      const maxZoom = mapTypeZoomLimits[type] || 15;\n      map.setMaxZoom(maxZoom);\n      \n      \/\/ If current zoom exceeds new limit, zoom out\n      if (map.getZoom() > maxZoom) {\n        map.setZoom(maxZoom);\n      }\n      \n      \/\/ Update button states\n      document.querySelectorAll('.map-type-btn').forEach(btn => {\n        btn.classList.remove('active');\n      });\n      if (el) el.classList.add('active');\n    }\n    \n    \/\/ Zoom map\n    function zoomMap(delta) {\n      if (!map) return;\n      const currentZoom = map.getZoom();\n      map.setZoom(currentZoom + (delta > 0 ? 1 : -1));\n    }\n    \n    \/\/ Initialize map\n    function initializeMap() {\n      \/\/ Register custom HybridOffline tile layer (Leaflet is now loaded)\n      if (!L.TileLayer.HybridOffline) {\n        L.TileLayer.HybridOffline = L.TileLayer.extend({\n          initialize: function(offlineUrl, onlineUrl, options) {\n            this._offlineUrl = offlineUrl;\n            this._onlineUrl = onlineUrl;\n            this._offlineMinZoom = options.offlineMinZoom || 7;\n            this._offlineMaxZoom = options.offlineMaxZoom || 12;\n            L.TileLayer.prototype.initialize.call(this, offlineUrl, options);\n          },\n          getTileUrl: function(coords) {\n            var zoom = coords.z;\n            if (zoom >= this._offlineMinZoom && zoom <= this._offlineMaxZoom) {\n              this._url = this._offlineUrl;\n            } else {\n              this._url = this._onlineUrl;\n            }\n            return L.TileLayer.prototype.getTileUrl.call(this, coords);\n          }\n        });\n\n        L.tileLayer.hybridOffline = function(offlineUrl, onlineUrl, options) {\n          return new L.TileLayer.HybridOffline(offlineUrl, onlineUrl, options);\n        };\n      }\n\n      \/\/ Center on Central Macedonia (Thessaloniki area)\n      map = L.map('mapBackground', {\n        center: MAP_DEFAULT_CENTER,\n        zoom: MAP_DEFAULT_ZOOM,\n        maxZoom: 19,\n        minZoom: 1,\n        zoomControl: false,\n        attributionControl: true,\n        preferCanvas: true,\n        zoomSnap: 0.25,\n        zoomDelta: 0.5,\n        wheelPxPerZoomLevel: 120,\n        zoomAnimation: true,\n        zoomAnimationThreshold: 4,\n        fadeAnimation: true,\n        markerZoomAnimation: true,\n        inertia: true,\n        inertiaDeceleration: 2400,\n        inertiaMaxSpeed: 2000,\n        easeLinearity: 0.2,\n        worldCopyJump: false,\n        maxBoundsViscosity: 0.3,\n        tap: true,\n        tapTolerance: 20,\n        touchZoom: 'center',\n        bounceAtZoomLimits: false,\n        smoothWheelZoom: true,\n        smoothSensitivity: 1.5\n      });\n      \n      \/\/ Define tile layers with hybrid offline\/online support\n      \/\/ Uses offline tiles when zoom is within available range, online otherwise\n      tileLayers.normal = L.tileLayer.hybridOffline(\n        CONFIG.offlineTilesPaths.osm + '{z}\/{x}\/{y}.png',\n        CONFIG.onlineTilesPaths.osm,\n        {\n          attribution: '&copy; <a href=\"https:\/\/www.openstreetmap.org\/copyright\">OpenStreetMap<\/a>',\n          maxZoom: 19,\n          minZoom: 1,\n          subdomains: ['a', 'b', 'c'],\n          offlineMinZoom: offlineZoomRanges.osm.min,\n          offlineMaxZoom: offlineZoomRanges.osm.max,\n          keepBuffer: 2,\n          updateWhenIdle: false,\n          updateWhenZooming: false,\n          updateInterval: 100,\n          tileSize: 256,\n          crossOrigin: false,\n          className: 'leaflet-tile-optimized',\n          noWrap: false\n        }\n      );\n      \n      tileLayers.satellite = L.tileLayer.hybridOffline(\n        CONFIG.offlineTilesPaths.arcgis + '{z}\/{x}\/{y}.png',\n        CONFIG.onlineTilesPaths.arcgis,\n        {\n          attribution: '&copy; Esri',\n          maxZoom: 18,\n          minZoom: 1,\n          offlineMinZoom: offlineZoomRanges.arcgis.min,\n          offlineMaxZoom: offlineZoomRanges.arcgis.max,\n          keepBuffer: 2,\n          updateWhenIdle: false,\n          updateWhenZooming: false,\n          updateInterval: 100,\n          tileSize: 256,\n          crossOrigin: false,\n          className: 'leaflet-tile-optimized',\n          noWrap: false\n        }\n      );\n      \n      tileLayers.hybrid = L.layerGroup([\n        L.tileLayer.hybridOffline(\n          CONFIG.offlineTilesPaths.arcgis + '{z}\/{x}\/{y}.png',\n          CONFIG.onlineTilesPaths.arcgis,\n          {\n            attribution: '&copy; Esri',\n            maxZoom: 18,\n            minZoom: 1,\n            offlineMinZoom: offlineZoomRanges.arcgis.min,\n            offlineMaxZoom: offlineZoomRanges.arcgis.max,\n            keepBuffer: 2,\n            updateWhenIdle: false,\n            updateWhenZooming: false,\n            updateInterval: 100,\n            className: 'leaflet-tile-optimized',\n            noWrap: false\n          }\n        ),\n        L.tileLayer.hybridOffline(\n          CONFIG.offlineTilesPaths.cartodb + '{z}\/{x}\/{y}.png',\n          CONFIG.onlineTilesPaths.cartodb,\n          {\n            attribution: '&copy; CartoDB',\n            maxZoom: 18,\n            minZoom: 1,\n            subdomains: ['a', 'b', 'c', 'd'],\n            offlineMinZoom: offlineZoomRanges.cartodb.min,\n            offlineMaxZoom: offlineZoomRanges.cartodb.max,\n            keepBuffer: 2,\n            updateWhenIdle: false,\n            updateWhenZooming: false,\n            updateInterval: 100,\n            className: 'leaflet-tile-optimized',\n            noWrap: false\n          }\n        )\n      ]);\n      \n      tileLayers.terrain = L.tileLayer.hybridOffline(\n        CONFIG.offlineTilesPaths.opentopomap + '{z}\/{x}\/{y}.png',\n        CONFIG.onlineTilesPaths.opentopomap,\n        {\n          attribution: '&copy; <a href=\"https:\/\/opentopomap.org\">OpenTopoMap<\/a>',\n          maxZoom: 17,\n          minZoom: 1,\n          subdomains: ['a', 'b', 'c'],\n          offlineMinZoom: offlineZoomRanges.opentopomap.min,\n          offlineMaxZoom: offlineZoomRanges.opentopomap.max,\n          keepBuffer: 2,\n          updateWhenIdle: false,\n          updateWhenZooming: false,\n          updateInterval: 100,\n          className: 'leaflet-tile-optimized',\n          noWrap: false\n        }\n      );\n      \n      \/\/ Add default layer\n      tileLayers.normal.addTo(map);\n      \n      \/\/ Force map to recalculate size\n      setTimeout(() => {\n        map.invalidateSize();\n      }, 100);\n      \n      console.log('Map initialized with', mapPOIs.length, 'POIs');\n      \n      \/\/ Add POI markers\n      if (!mapPOIs || mapPOIs.length === 0) {\n        console.warn('No POI data available to display');\n        return;\n      }\n      \n      mapPOIs.forEach((poi, index) => {\n        const color = categoryColors[poi.category] || '#2196F3';\n        \n        \/\/ Create custom icon with category-specific design\n        const iconHtml = `\n          <div class=\"custom-pin\" data-poi-id=\"${poi.id}\">\n            ${getCategoryIcon(poi.category, color)}\n          <\/div>\n        `;\n        \n        const icon = L.divIcon({\n          html: iconHtml,\n          className: '',\n          iconSize: [32, 32],\n          iconAnchor: [16, 16]\n        });\n        \n        \/\/ Use real coordinates from POI data\n        const lat = poi.lat;\n        const lng = poi.lng;\n        \n        const marker = L.marker([lat, lng], { \n          icon: icon,\n          interactive: true,\n          keyboard: true,\n          riseOnHover: true,\n          riseOffset: 250\n        })\n          .addTo(map)\n          .on('click', () => selectPOI(poi.id));\n        \n        markers[poi.id] = { marker, poi, element: null };\n      });\n      \n      \/\/ Show first POI if available\n      if (mapPOIs.length > 0) {\n        updateLocationCard(mapPOIs[0]);\n      }\n      \n      \/\/ Update marker elements after they're added to DOM\n      setTimeout(() => {\n        Object.keys(markers).forEach(poiId => {\n          const markerElement = document.querySelector(`[data-poi-id=\"${poiId}\"]`);\n          if (markerElement) {\n            markers[poiId].element = markerElement;\n          }\n        });\n        if (mapPOIs.length > 0) {\n          selectPOI(mapPOIs[0].id);\n        }\n        \/\/ Force map refresh after markers are added\n        map.invalidateSize();\n        \n        \/\/ Initialize filter bar\n        initializeFilterBar();\n      }, 200);\n    }\n\n\n\n    \/\/ ========================================\n    \/\/ MY LOCATION \/ GPS\n    \/\/ ========================================\n    let myLocationMarker = null;\n    let myLocationCircle = null;\n    let locationWatchId = null;\n    let isLocating = false;\n    let _lastLocUpdate = 0;\n    let _lastLocLat = null;\n    let _lastLocLng = null;\n    const LOC_THROTTLE_MS = 800;     \/\/ min interval between DOM updates\n    const LOC_MIN_MOVE_DEG = 0.00002; \/\/ ~2 m \u2014 skip updates smaller than this\n\n    function toggleMyLocation() {\n      \/\/ Already tracking \u2192 re-center on current position\n      if (isLocating && myLocationMarker) {\n        const ll = myLocationMarker.getLatLng();\n        map.flyTo(ll, Math.max(map.getZoom(), 15), { duration: 0.6 });\n        return;\n      }\n      \/\/ Already tracking but no fix yet \u2192 stop\n      if (isLocating) {\n        stopLocationTracking();\n        return;\n      }\n\n      if (!navigator.geolocation) {\n        alert('Geolocation is not supported by your browser.');\n        return;\n      }\n\n      const btn = document.getElementById('myLocationBtn');\n      btn.classList.add('locating');\n      isLocating = true;\n\n      \/\/ watchPosition already fires once immediately \u2014 no need for getCurrentPosition\n      locationWatchId = navigator.geolocation.watchPosition(\n        onLocationSuccess,\n        onLocationWatchError,\n        { enableHighAccuracy: true, timeout: 15000, maximumAge: 3000 }\n      );\n    }\n\n    function onLocationSuccess(pos) {\n      const btn = document.getElementById('myLocationBtn');\n      btn.classList.remove('locating');\n      btn.classList.add('located');\n\n      const now = performance.now();\n      const lat = pos.coords.latitude;\n      const lng = pos.coords.longitude;\n\n      \/\/ Throttle: skip if called too soon and position barely changed\n      if (_lastLocLat !== null && now - _lastLocUpdate < LOC_THROTTLE_MS) {\n        const dLat = Math.abs(lat - _lastLocLat);\n        const dLng = Math.abs(lng - _lastLocLng);\n        if (dLat < LOC_MIN_MOVE_DEG && dLng < LOC_MIN_MOVE_DEG) return;\n      }\n      _lastLocUpdate = now;\n      _lastLocLat = lat;\n      _lastLocLng = lng;\n\n      showUserLocation(pos);\n    }\n\n    function showUserLocation(position) {\n      if (!map) return;\n      const lat = position.coords.latitude;\n      const lng = position.coords.longitude;\n      const accuracy = position.coords.accuracy; \/\/ metres\n\n      \/\/ Update existing marker \/ circle\n      if (myLocationMarker) {\n        myLocationMarker.setLatLng([lat, lng]);\n        myLocationCircle.setLatLng([lat, lng]);\n        myLocationCircle.setRadius(accuracy);\n      } else {\n        \/\/ Blue dot marker\n        const locationIcon = L.divIcon({\n          html: '<div style=\"width:16px;height:16px;background:#1562AC;border:3px solid #fff;border-radius:50%;box-shadow:0 0 0 2px rgba(21,98,172,.3),0 2px 8px rgba(0,0,0,.25)\"><\/div>',\n          className: '',\n          iconSize: [16, 16],\n          iconAnchor: [8, 8]\n        });\n        myLocationMarker = L.marker([lat, lng], {\n          icon: locationIcon,\n          interactive: false,\n          zIndexOffset: 2000\n        }).addTo(map);\n\n        \/\/ Accuracy circle (canvas renderer for performance)\n        myLocationCircle = L.circle([lat, lng], {\n          radius: accuracy,\n          color: '#1562AC',\n          fillColor: '#1562AC',\n          fillOpacity: 0.08,\n          weight: 1.5,\n          opacity: 0.3,\n          interactive: false\n        }).addTo(map);\n\n        \/\/ Fly to position only on first fix\n        map.flyTo([lat, lng], Math.max(map.getZoom(), 14), {\n          duration: 0.8,\n          easeLinearity: 0.25\n        });\n      }\n\n      \/\/ Update accuracy banner\n      updateGpsAccuracy(accuracy);\n    }\n\n    function updateGpsAccuracy(accuracy) {\n      const banner = document.getElementById('gpsAccuracyBanner');\n      const text = banner.querySelector('.gps-accuracy-text');\n      const level = accuracy <= 10 ? 'high' : accuracy <= 50 ? 'medium' : 'low';\n      banner.className = 'gps-accuracy-banner visible ' + level;\n      const accText = accuracy < 1000\n        ? Math.round(accuracy) + ' m'\n        : (accuracy \/ 1000).toFixed(1) + ' km';\n      const labels = { high: trp('gps-high'), medium: trp('gps-medium'), low: trp('gps-low') };\n      text.textContent = 'GPS: \u00b1' + accText + ' \u2014 ' + labels[level];\n    }\n\n    function dismissGpsBanner() {\n      document.getElementById('gpsAccuracyBanner').classList.remove('visible');\n    }\n\n    \/\/ Watch errors \u2014 only fatal (permission denied) should kill tracking\n    function onLocationWatchError(err) {\n      if (err.code === 1) {\n        \/\/ PERMISSION_DENIED \u2014 stop everything\n        stopLocationTracking();\n        alert(trp('location-denied'));\n      } else {\n        \/\/ POSITION_UNAVAILABLE \/ TIMEOUT \u2014 transient, keep watching\n        console.warn('GPS transient error:', err.message);\n      }\n    }\n\n    function stopLocationTracking() {\n      if (locationWatchId !== null) {\n        navigator.geolocation.clearWatch(locationWatchId);\n        locationWatchId = null;\n      }\n      if (myLocationMarker && map) {\n        map.removeLayer(myLocationMarker);\n        myLocationMarker = null;\n      }\n      if (myLocationCircle && map) {\n        map.removeLayer(myLocationCircle);\n        myLocationCircle = null;\n      }\n      isLocating = false;\n      _lastLocLat = null;\n      _lastLocLng = null;\n      const btn = document.getElementById('myLocationBtn');\n      if (btn) btn.classList.remove('locating', 'located');\n      const banner = document.getElementById('gpsAccuracyBanner');\n      if (banner) banner.classList.remove('visible');\n    }\n\n    \/\/ Select a POI\n    function selectPOI(poiId) {\n      const poi = mapPOIs.find(p => p.id === poiId);\n      if (!poi) return;\n\n      activePOI = poiId;\n      \n      \/\/ Update active pin styling with requestAnimationFrame for smooth transitions\n      requestAnimationFrame(() => {\n        document.querySelectorAll('.custom-pin').forEach(pin => {\n          pin.classList.remove('active-pin');\n        });\n        \n        const markerData = markers[poiId];\n        if (markerData && markerData.element) {\n          markerData.element.classList.add('active-pin');\n        }\n\n        \/\/ Update location card\n        updateLocationCard(poi);\n        \n        \/\/ Pan map to marker with smooth animation\n        if (map && markerData && markerData.marker) {\n          map.flyTo(markerData.marker.getLatLng(), map.getZoom(), {\n            duration: 0.6,\n            easeLinearity: 0.25\n          });\n        }\n      });\n    }\n\n    \/\/ Update location card with POI data\n    function updateLocationCard(poi) {\n      const card = document.querySelector('.location-card');\n      \n      \/\/ Add updating animation\n      card.classList.add('updating');\n      setTimeout(() => card.classList.remove('updating'), 400);\n      \n      const rating = poi.rating || 5;\n      const reviews = poi.reviews || \"1K\";\n      const stars = '\u2605'.repeat(rating) + '\u2606'.repeat(5 - rating);\n      \n      \/\/ Use image if available, otherwise use colored placeholder\n      const thumbnailHTML = poi.imageUrl \n        ? `<img decoding=\"async\" class=\"location-thumbnail\" src=\"${poi.imageUrl}\" alt=\"${poi.name}\" style=\"width: 70px; height: 70px; object-fit: cover; border-radius: 10px; cursor: pointer;\" onclick=\"openPOIImageModal('${poi.imageUrl}', '${poi.name}')\">`\n        : `<div class=\"location-thumbnail\" style=\"background: ${categoryColors[poi.category] || '#2196F3'}; display: flex; align-items: center; justify-content: center; color: white; font-size: 32px; font-weight: 700;\">${poi.id}<\/div>`;\n      \n      requestAnimationFrame(() => {\n        card.innerHTML = `\n          ${thumbnailHTML}\n          <div class=\"location-info\">\n            <h3>${poi.name}<\/h3>\n            <p>${getCategoryLabel(poi.category)}<\/p>\n            <div class=\"rating\">\n              <span class=\"stars\">${stars}<\/span>\n              <span class=\"reviews\">(${reviews} ${trp('reviews')})<\/span>\n            <\/div>\n            <div style=\"margin-top: 8px; display: flex; gap: 8px;\">\n              <button onclick=\"window.open('${poi.url}', '_blank')\" style=\"background: #2196F3; color: white; border: none; padding: 6px 12px; border-radius: 6px; font-size: 12px; font-weight: 600; cursor: pointer; transition: all 0.15s ease; transform: translate3d(0,0,0); touch-action: manipulation;\" onmousedown=\"this.style.transform='scale(0.95)';\" onmouseup=\"this.style.transform='scale(1)';\" ontouchstart=\"this.style.transform='scale(0.95)';\" ontouchend=\"this.style.transform='scale(1)';\">${trp('learn-more')}<\/button>\n              <button onclick=\"window.open('https:\/\/www.google.com\/maps\/search\/${encodeURIComponent(poi.name + ' Central Macedonia Greece')}', '_blank')\" style=\"background: #4CAF50; color: white; border: none; padding: 6px 12px; border-radius: 6px; font-size: 12px; font-weight: 600; cursor: pointer; transition: all 0.15s ease; transform: translate3d(0,0,0); touch-action: manipulation;\" onmousedown=\"this.style.transform='scale(0.95)';\" onmouseup=\"this.style.transform='scale(1)';\" ontouchstart=\"this.style.transform='scale(0.95)';\" ontouchend=\"this.style.transform='scale(1)';\">${trp('directions')}<\/button>\n            <\/div>\n          <\/div>\n        `;\n      });\n    }\n\n    \/\/ Filter POIs by categories (supports multiple)\n    function filterPOIs(categories) {\n      currentFilters = categories;\n      \n      Object.keys(markers).forEach(poiId => {\n        const markerData = markers[poiId];\n        const poi = markerData.poi;\n        \n        \/\/ Show if 'all' is selected OR if poi category is in selected categories\n        if (categories.includes('all') || categories.includes(poi.category)) {\n          if (!map.hasLayer(markerData.marker)) {\n            map.addLayer(markerData.marker);\n          }\n        } else {\n          if (map.hasLayer(markerData.marker)) {\n            map.removeLayer(markerData.marker);\n          }\n        }\n      });\n    }\n\n    \/\/ Search functionality\n    let searchResults = [];\n    let activeSuggestionIndex = -1;\n    \n    function handleSearch(query) {\n      const clearBtn = document.getElementById('clearBtn');\n      \n      if (query.trim().length === 0) {\n        searchResults = [];\n        clearBtn.style.display = 'none';\n        hideSuggestions();\n        \/\/ Show all POIs if search is empty\n        filterPOIs(currentFilters);\n        return;\n      }\n      \n      clearBtn.style.display = 'flex';\n      const lowerQuery = query.toLowerCase();\n      \n      \/\/ Search through POIs by name and description\n      searchResults = mapPOIs.filter(poi => {\n        const name = (poi.name || '').toLowerCase();\n        const description = (poi.description || '').toLowerCase();\n        const category = (poi.category || '').toLowerCase();\n        \n        return name.includes(lowerQuery) || \n               description.includes(lowerQuery) || \n               category.includes(lowerQuery);\n      });\n      \n      \/\/ Show suggestions dropdown\n      activeSuggestionIndex = -1;\n      showSuggestions(searchResults, lowerQuery);\n      \n      \/\/ Show only search results on map\n      displaySearchResults(searchResults);\n    }\n    \n    function showSuggestions(results, query) {\n      const container = document.getElementById('searchSuggestions');\n      if (!container) return;\n      \n      if (results.length === 0) {\n        container.innerHTML = '<div class=\"search-suggestion-empty\">' + trp('no-places-found') + '<\/div>';\n        container.classList.add('visible');\n        return;\n      }\n      \n      \/\/ Show max 8 suggestions\n      const limited = results.slice(0, 8);\n      \n      container.innerHTML = limited.map((poi, i) => {\n        const color = categoryColors[poi.category] || '#95A5A6';\n        const icon = categoryIcons[poi.category] || categoryIcons.other;\n        const catLabel = getCategoryLabel(poi.category);\n        const highlightedName = highlightMatch(poi.name || 'Unknown', query);\n        \n        return `<div class=\"search-suggestion-item\" data-poi-id=\"${poi.id}\" data-index=\"${i}\" onclick=\"selectSuggestion(${poi.id})\" onmouseenter=\"activeSuggestionIndex=${i};updateSuggestionHighlight()\">\n          <div class=\"search-suggestion-icon\" style=\"background:${color}\">${icon}<\/div>\n          <div class=\"search-suggestion-text\">\n            <div class=\"search-suggestion-name\">${highlightedName}<\/div>\n            <div class=\"search-suggestion-category\">${catLabel}<\/div>\n          <\/div>\n        <\/div>`;\n      }).join('');\n      \n      if (results.length > 8) {\n        container.innerHTML += `<div class=\"search-suggestion-empty\">+${results.length - 8} ${trp('more-results')}<\/div>`;\n      }\n      \n      container.classList.add('visible');\n    }\n    \n    function highlightMatch(text, query) {\n      if (!query) return text;\n      const escaped = query.replace(\/[.*+?^${}()|[\\]\\\\]\/g, '\\\\$&');\n      const regex = new RegExp(`(${escaped})`, 'gi');\n      return text.replace(regex, '<mark>$1<\/mark>');\n    }\n    \n    function hideSuggestions() {\n      const container = document.getElementById('searchSuggestions');\n      if (container) {\n        container.classList.remove('visible');\n        activeSuggestionIndex = -1;\n      }\n    }\n    \n    function showSuggestionsIfQuery() {\n      const input = document.getElementById('searchInput');\n      if (input && input.value.trim().length > 0 && searchResults.length > 0) {\n        showSuggestions(searchResults, input.value.trim().toLowerCase());\n      }\n    }\n    \n    function selectSuggestion(poiId) {\n      const poi = mapPOIs.find(p => p.id === poiId);\n      if (!poi) return;\n      \n      \/\/ Set input to selected name\n      const input = document.getElementById('searchInput');\n      if (input) input.value = poi.name || '';\n      \n      hideSuggestions();\n      \n      \/\/ Show this POI on map and fly to it\n      selectPOI(poiId);\n      if (map && poi.lat && poi.lng) {\n        map.flyTo([poi.lat, poi.lng], 14, { duration: 0.8 });\n      }\n    }\n    \n    function handleSearchKeydown(e) {\n      const container = document.getElementById('searchSuggestions');\n      if (!container || !container.classList.contains('visible')) return;\n      \n      const items = container.querySelectorAll('.search-suggestion-item');\n      if (items.length === 0) return;\n      \n      if (e.key === 'ArrowDown') {\n        e.preventDefault();\n        activeSuggestionIndex = Math.min(activeSuggestionIndex + 1, items.length - 1);\n        updateSuggestionHighlight();\n      } else if (e.key === 'ArrowUp') {\n        e.preventDefault();\n        activeSuggestionIndex = Math.max(activeSuggestionIndex - 1, -1);\n        updateSuggestionHighlight();\n      } else if (e.key === 'Enter' && activeSuggestionIndex >= 0) {\n        e.preventDefault();\n        const activeItem = items[activeSuggestionIndex];\n        if (activeItem) {\n          const poiId = parseInt(activeItem.dataset.poiId);\n          selectSuggestion(poiId);\n        }\n      } else if (e.key === 'Escape') {\n        hideSuggestions();\n      }\n    }\n    \n    function updateSuggestionHighlight() {\n      const container = document.getElementById('searchSuggestions');\n      if (!container) return;\n      const items = container.querySelectorAll('.search-suggestion-item');\n      items.forEach((item, i) => {\n        item.classList.toggle('active', i === activeSuggestionIndex);\n      });\n      \/\/ Scroll active item into view\n      if (activeSuggestionIndex >= 0 && items[activeSuggestionIndex]) {\n        items[activeSuggestionIndex].scrollIntoView({ block: 'nearest' });\n      }\n    }\n    \n    \/\/ Close suggestions when clicking outside\n    document.addEventListener('click', function(e) {\n      const searchBar = document.getElementById('searchBar');\n      if (searchBar && !searchBar.contains(e.target)) {\n        hideSuggestions();\n      }\n    });\n    \n    function clearSearch() {\n      document.getElementById('searchInput').value = '';\n      document.getElementById('clearBtn').style.display = 'none';\n      searchResults = [];\n      hideSuggestions();\n      filterPOIs(currentFilters);\n    }\n    \n    function displaySearchResults(results) {\n      \/\/ Hide all markers first\n      Object.keys(markers).forEach(poiId => {\n        const markerData = markers[poiId];\n        if (markerData && markerData.marker) {\n          if (map.hasLayer(markerData.marker)) {\n            map.removeLayer(markerData.marker);\n          }\n        }\n      });\n      \n      \/\/ Show only search result markers\n      results.forEach(poi => {\n        const markerData = markers[poi.id];\n        if (markerData && markerData.marker && !map.hasLayer(markerData.marker)) {\n          map.addLayer(markerData.marker);\n        }\n      });\n      \n      \/\/ Select first result\n      if (results.length > 0) {\n        selectPOI(results[0].id);\n      }\n    }\n\n    function setCategoryFilter(selectedCategory) {\n      const value = selectedCategory || 'all';\n      currentFilters = value === 'all' ? ['all'] : [value];\n      filterPOIs(currentFilters);\n    }\n\n    \/\/ Category emoji for dropdown readability\n    const categoryEmoji = {\n      museum: '\ud83c\udfdb\ufe0f',\n      landmark: '\ud83d\udccd',\n      culture: '\ud83c\udfad',\n      beach: '\ud83c\udfd6\ufe0f',\n      church: '\u26ea',\n      traditional_settlement: '\ud83c\udfd8\ufe0f',\n      architecture: '\ud83c\udfd7\ufe0f',\n      archaeological: '\ud83c\udffa',\n      nature: '\ud83c\udf3f',\n      park: '\ud83c\udf32',\n      activities: '\ud83c\udfc3',\n      cave: '\ud83d\udd73\ufe0f',\n      ski_resort: '\u26f7\ufe0f',\n      lake: '\ud83d\udca7',\n      mountain: '\u26f0\ufe0f',\n      wetland: '\ud83c\udf0a',\n      thermal_spa: '\u2668\ufe0f',\n      canyon: '\ud83c\udfdc\ufe0f',\n      other: '\ud83d\udccc'\n    };\n\n    \/\/ Initialize filter bar with a dropdown\n    function initializeFilterBar() {\n      const filterBar = document.getElementById('filterBar');\n      if (!filterBar || !mapPOIs) return;\n\n      const counts = mapPOIs.reduce((acc, poi) => {\n        const key = poi.category || 'other';\n        acc[key] = (acc[key] || 0) + 1;\n        return acc;\n      }, {});\n\n      const categoryKeys = Object.keys(counts)\n        .filter(k => k && k !== 'shopping')\n        .sort((a, b) => getCategoryLabel(a).localeCompare(getCategoryLabel(b)));\n\n      const options = [\n        `<option value=\"all\">\ud83d\udccb ${trp('all-categories')} (${mapPOIs.length})<\/option>`,\n        ...categoryKeys.map(key => {\n          const label = getCategoryLabel(key);\n          const count = counts[key] || 0;\n          const emoji = categoryEmoji[key] || '\ud83d\udccc';\n          return `<option value=\"${key}\">${emoji} ${label} (${count})<\/option>`;\n        })\n      ].join('');\n\n      filterBar.innerHTML = `\n        <div class=\"map-filter-label\">\n          <svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z\"\/><\/svg>\n          ${trp('filter-label')}\n        <\/div>\n        <select id=\"categorySelect\" class=\"map-filter-select\" onchange=\"setCategoryFilter(this.value)\">\n          ${options}\n        <\/select>\n      `;\n\n      const select = document.getElementById('categorySelect');\n      if (select) {\n        select.value = (currentFilters && currentFilters.length === 1) ? currentFilters[0] : 'all';\n      }\n    }\n\n    \/\/ ========================================\n    \/\/ DEFERRED LOADING: Leaflet + Map + POIs\n    \/\/ ========================================\n    let leafletLoaded = false;\n    let mapInitialized = false;\n    let poisDataCache = null;\n    \n    function loadLeaflet() {\n      return new Promise((resolve, reject) => {\n        if (leafletLoaded) { resolve(); return; }\n        \n        \/\/ Load CSS\n        const link = document.createElement('link');\n        link.rel = 'stylesheet';\n        link.href = 'https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.css';\n        link.integrity = 'sha256-p4NxAoJBhIIN+hmNHrzRCf9tD\/miZyoHS5obTRR9BMY=';\n        link.crossOrigin = '';\n        document.head.appendChild(link);\n        \n        \/\/ Load JS\n        const script = document.createElement('script');\n        script.src = 'https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.js';\n        script.integrity = 'sha256-20nQCchB9co0qIjJZRGuk2\/Z9VM+kNiyxNV1lvTlZBo=';\n        script.crossOrigin = '';\n        script.onload = () => {\n          leafletLoaded = true;\n          console.log('\u2705 Leaflet loaded on demand');\n          resolve();\n        };\n        script.onerror = reject;\n        document.head.appendChild(script);\n      });\n    }\n    \n    function loadPOIData() {\n      if (poisDataCache) return Promise.resolve(poisDataCache);\n      \n      const poisUrl = getUploadPath(CONFIG.poisJsonFile);\n      console.log('Starting to load POI data from:', poisUrl);\n      return fetch(poisUrl)\n        .then(response => {\n          console.log('Response received:', response.status, response.statusText);\n          if (!response.ok) {\n            throw new Error(`HTTP error! status: ${response.status}`);\n          }\n          return response.json();\n        })\n        .then(data => {\n          console.log('POI data parsed:', data);\n          if (!data || !data.pois || !Array.isArray(data.pois)) {\n            throw new Error('Invalid POI data format');\n          }\n          \n          mapPOIs = data.pois.map(poi => ({\n            id: poi.id,\n            name: poi.name,\n            category: poi.category,\n            description: poi.subtitle,\n            rating: 5,\n            reviews: \"1K\",\n            url: poi.url,\n            imageUrl: poi.imageUrl,\n            lat: poi.coordinates.lat,\n            lng: poi.coordinates.lng\n          }));\n          \n          poisDataCache = mapPOIs;\n          console.log(`\u2705 Successfully loaded ${mapPOIs.length} POIs from database`);\n          return mapPOIs;\n        })\n        .catch(error => {\n          console.error('\u274c Error loading POI data:', error);\n          mapPOIs = [];\n          return mapPOIs;\n        });\n    }\n    \n    \/\/ Load map resources only when map tab is opened\n    async function ensureMapReady() {\n      if (mapInitialized) return;\n      \n      try {\n        await Promise.all([loadLeaflet(), loadPOIData()]);\n        initializeMap();\n        mapInitialized = true;\n      } catch (error) {\n        console.error('Failed to initialize map:', error);\n      }\n    }\n  <\/script>\n<\/body>\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-7","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/visit-centralmacedonia.click\/es\/wp-json\/wp\/v2\/pages\/7","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/visit-centralmacedonia.click\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/visit-centralmacedonia.click\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/visit-centralmacedonia.click\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visit-centralmacedonia.click\/es\/wp-json\/wp\/v2\/comments?post=7"}],"version-history":[{"count":386,"href":"https:\/\/visit-centralmacedonia.click\/es\/wp-json\/wp\/v2\/pages\/7\/revisions"}],"predecessor-version":[{"id":1318,"href":"https:\/\/visit-centralmacedonia.click\/es\/wp-json\/wp\/v2\/pages\/7\/revisions\/1318"}],"wp:attachment":[{"href":"https:\/\/visit-centralmacedonia.click\/es\/wp-json\/wp\/v2\/media?parent=7"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}