// ============================================================================
// vk-core.jsx — design system + data for the Dream Travel (Black Sea) site.
// Themeable (dark/light), 7 languages (bg/ru/en/de/pl/he/cs + RTL), live weather.
// ============================================================================
const { useState: uS, useEffect: uE, useMemo: uM, useRef: uR, useCallback: uC } = React;

// ── THEME ────────────────────────────────────────────────────────────────
const FONTS = {
  WORD: "'Oswald', sans-serif",
  HEAD: "'Manrope', system-ui, sans-serif",
  BODY: "'Manrope', system-ui, sans-serif",
  MONO: "'JetBrains Mono', monospace",
};
const THEMES = {
  dark: {
    void: "#08080A", panel: "#0F0F12", panel2: "#15151A",
    ink: "#F3F1EC", sub: "rgba(243,241,236,0.58)", faint: "rgba(243,241,236,0.34)",
    line: "rgba(255,255,255,0.12)", line2: "rgba(255,255,255,0.06)",
    coral: "#FF5A2C", coralDim: "rgba(255,90,44,0.14)", sky: "#5BB0C9", sand: "#D8B978",
    glass: "rgba(8,8,10,0.82)", scrim: "rgba(8,8,10,0.6)",
  },
  light: {
    void: "#F1EEE7", panel: "#FFFFFF", panel2: "#E9E4DA",
    ink: "#17150F", sub: "rgba(23,21,15,0.62)", faint: "rgba(23,21,15,0.42)",
    line: "rgba(23,21,15,0.16)", line2: "rgba(23,21,15,0.07)",
    coral: "#DD4517", coralDim: "rgba(221,69,23,0.12)", sky: "#3E8FB0", sand: "#C9A45E",
    glass: "rgba(241,238,231,0.86)", scrim: "rgba(23,21,15,0.4)",
  },
};
const VK = Object.assign({}, FONTS, THEMES.dark);
function applyTheme(mode) { Object.assign(VK, THEMES[mode] || THEMES.dark); }

const LANGS = [["bg", "BG"], ["ru", "RU"], ["en", "EN"], ["de", "DE"], ["pl", "PL"], ["cs", "CZ"], ["he", "עב"]];
const RTL_LANGS = ["he"];

// ── i18n DICTIONARY (ru/en/de/pl/he) ──────────────────────────────────────
const TX = {
  nav_home:   { ru: "Главная", en: "Home", de: "Start", pl: "Start", he: "בית" , bg: "Начало" , cs: "Domů" },
  nav_exc:    { ru: "Экскурсии", en: "Excursions", de: "Touren", pl: "Wycieczki", he: "סיורים" , bg: "Екскурзии" , cs: "Výlety" },
  nav_finder: { ru: "AI-подбор", en: "AI Finder", de: "AI-Finder", pl: "Dobór AI", he: "בורר AI" , bg: "AI-избор" , cs: "AI-výběr" },
  nav_rental: { ru: "Аренда авто", en: "Car Rental", de: "Mietwagen", pl: "Wynajem aut", he: "השכרת רכב" , bg: "Коли под наем" , cs: "Půjčovna aut" },
  nav_contact:{ ru: "Контакты", en: "Contacts", de: "Kontakt", pl: "Kontakt", he: "צור קשר" , bg: "Контакти" , cs: "Kontakty" },
  contact_cta:{ ru: "Связаться", en: "Contact us", de: "Kontakt", pl: "Kontakt", he: "צרו קשר" , bg: "Свържете се" , cs: "Kontaktujte nás" },
  menu:       { ru: "Меню", en: "Menu", de: "Menü", pl: "Menu", he: "תפריט" , bg: "Меню" , cs: "Menu" },
  book:       { ru: "Забронировать", en: "Reserve", de: "Buchen", pl: "Rezerwuj", he: "להזמין" , bg: "Резервирай" , cs: "Rezervovat" },
  from:       { ru: "от", en: "from", de: "ab", pl: "od", he: "מ־" , bg: "от" , cs: "od" },
  per_day:    { ru: " / сутки", en: " / day", de: " / Tag", pl: " / dzień", he: " / יום" , bg: " / ден" , cs: " / den" },
  seats_left: { ru: "мест", en: "left", de: "frei", pl: "miejsc", he: "נותרו" , bg: "места" , cs: "míst" },
  adult_short:{ ru: "взр", en: "adult", de: "Erw.", pl: "doros.", he: "מבוגר" , bg: "възр" , cs: "dosp" },
  child_short:{ ru: "дет", en: "child", de: "Kind", pl: "dzie.", he: "ילד" , bg: "дете" , cs: "dítě" },
  days_label: { ru: "Дни", en: "Days", de: "Tage", pl: "Dni", he: "ימים" , bg: "Дни" , cs: "Dny" },
  all_exc:    { ru: "Все экскурсии", en: "All excursions", de: "Alle Touren", pl: "Wszystkie", he: "כל הסיורים" , bg: "Всички екскурзии" , cs: "Všechny výlety" },
  finder_cta: { ru: "Подобрать с AI", en: "AI Finder", de: "Mit AI finden", pl: "Dobór AI", he: "בחירה עם AI" , bg: "Избор с AI" , cs: "Výběr s AI" },
  sunny_beach:{ ru: "Солнечный берег", en: "Sunny Beach", de: "Sonnenstrand", pl: "Słoneczny Brzeg", he: "סאני ביץ'" , bg: "Слънчев бряг" , cs: "Slunečné pobřeží" },
  own_photo:  { ru: "⊠ своё фото", en: "⊠ own photo", de: "⊠ Eigenes Foto", pl: "⊠ własne zdjęcie", he: "⊠ תמונה משלך" , bg: "⊠ своя снимка" , cs: "⊠ vlastní foto" },
  scene_off:  { ru: "✕ сцена", en: "✕ scene", de: "✕ Szene", pl: "✕ scena", he: "✕ סצנה" , bg: "✕ сцена" , cs: "✕ scéna" },
  drop_photo: { ru: "Перетащи фото пляжа · погода", en: "Drop a beach photo · weather", de: "Strandfoto ablegen · Wetter", pl: "Upuść zdjęcie plaży · pogoda", he: "גרור תמונת חוף · מזג אוויר" , bg: "Пуснете снимка от плажа · време" , cs: "Vložte foto pláže · počasí" },

  home_t1:    { ru: "Солнечный берег —", en: "The Sunny Beach", de: "Sonnenstrand —", pl: "Słoneczny Brzeg —", he: "סאני ביץ' —" , bg: "Слънчев бряг —" , cs: "Slunečné pobřeží —" },
  home_t2:    { ru: "ваше путешествие", en: "Trip", de: "deine Reise", pl: "Twój wyjazd", he: "החופשה שלך" , bg: "вашето пътуване" , cs: "vaše cesta" },
  home_sub:   { ru: "Пиратские корабли, романтические прогулки морем и сказочные замки — экскурсии из Солнечного берега, которые невозможно забыть.", en: "Pirate ships, romantic sea cruises and fairy-tale castles — unforgettable excursions from Sunny Beach.", de: "Piratenschiffe, romantische Bootsfahrten und Märchenschlösser — unvergessliche Ausflüge ab Sonnenstrand.", pl: "Statki piratów, romantyczne rejsy i baśniowe zamki — niezapomniane wycieczki ze Słonecznego Brzegu.", he: "ספינות פיראטים, שייט רומנטי בים וטירות אגדה — סיורים בלתי נשכחים מסאני ביץ'." , bg: "Пиратски кораби, романтични морски разходки и приказни замъци — незабравими екскурзии от Слънчев бряг." , cs: "Pirátské lodě, romantické plavby po moři a pohádkové zámky — nezapomenutelné výlety ze Slunečného pobřeží." },
  dir_label:  { ru: "НАВИГАЦИЯ · 03 РАЗДЕЛА", en: "DIRECTORY · 03 SECTIONS", de: "VERZEICHNIS · 03", pl: "NAWIGACJA · 03", he: "ניווט · 03" , bg: "НАВИГАЦИЯ · 03 РАЗДЕЛА" , cs: "NAVIGACE · 03 SEKCE" },
  featured_h: { ru: "Выбор недели", en: "This week's pick", de: "Tipp der Woche", pl: "Wybór tygodnia", he: "הבחירה השבועית" , bg: "Избор на седмицата" , cs: "Tip týdne" },
  tile_exc_d: { ru: "Каталог морских и горных приключений", en: "Sea & mountain adventures", de: "Meer- & Bergabenteuer", pl: "Przygody morskie i górskie", he: "הרפתקאות ים והרים" , bg: "Морски и планински приключения" , cs: "Mořská a horská dobrodružství" },
  tile_fnd_d: { ru: "6 вопросов — идеальная экскурсия", en: "6 questions, your perfect trip", de: "6 Fragen zur perfekten Tour", pl: "6 pytań do idealnej wycieczki", he: "6 שאלות לסיור המושלם" , bg: "6 въпроса — идеалната екскурзия" , cs: "6 otázek — ideální výlet" },
  tile_car_d: { ru: "От эконома до минивэна, без залога", en: "Economy to minivan, no deposit", de: "Vom Kleinwagen bis Van, ohne Kaution", pl: "Od auta po vana, bez kaucji", he: "מאקונומי ועד ואן, ללא פיקדון" , bg: "От икономичен до ван, без депозит" , cs: "Od malého auta po van, bez kauce" },
  tile_con_d: { ru: "5 офисов на побережье", en: "5 offices on the coast", de: "5 Büros an der Küste", pl: "5 biur na wybrzeżu", he: "5 משרדים לאורך החוף" , bg: "5 офиса на крайбрежието" , cs: "5 kanceláří na pobřeží" },

  cat_label:  { ru: "КАТАЛОГ · ЭКСКУРСИИ", en: "CATALOGUE · EXCURSIONS", de: "KATALOG · TOUREN", pl: "KATALOG · WYCIECZKI", he: "קטלוג · סיורים" , bg: "КАТАЛОГ · ЕКСКУРЗИИ" , cs: "KATALOG · VÝLETY" },
  exc_h1:     { ru: "Все направления", en: "Every direction", de: "Alle Ziele", pl: "Wszystkie kierunki", he: "כל היעדים" , bg: "Всички посоки" , cs: "Všechny směry" },
  exc_intro:  { ru: "Выбери несколько фильтров — например «Актив» + «С детьми» — и каталог отсортируется по релевантности.", en: "Pick several filters — e.g. Active + Kids — and the catalogue ranks by relevance.", de: "Wähle mehrere Filter — z. B. Aktiv + Kinder — der Katalog sortiert nach Relevanz.", pl: "Wybierz kilka filtrów — np. Aktyw + Z dziećmi — katalog ułoży się według trafności.", he: "בחרו כמה מסננים — למשל אקטיב + עם ילדים — והקטלוג יסודר לפי רלוונטיות." , bg: "Изберете няколко филтъра — например «Актив» + «С деца» — и каталогът се подрежда по релевантност." , cs: "Vyberte několik filtrů — například «Aktivní» + «S dětmi» — a katalog se seřadí podle relevance." },
  selected:   { ru: "Выбрано:", en: "Selected:", de: "Gewählt:", pl: "Wybrano:", he: "נבחר:" , bg: "Избрано:" , cs: "Vybráno:" },
  no_match:   { ru: "Нет экскурсий под выбранные фильтры.", en: "No excursions match those filters.", de: "Keine Touren für diese Filter.", pl: "Brak wycieczek dla tych filtrów.", he: "אין סיורים למסננים אלה." , bg: "Няма екскурзии за избраните филтри." , cs: "Žádné výlety pro zvolené filtry." },

  finder_label:{ ru: "AI-ПОДБОР · 06 ВОПРОСОВ", en: "AI FINDER · 06 QUESTIONS", de: "AI-FINDER · 06 FRAGEN", pl: "DOBÓR AI · 06 PYTAŃ", he: "בורר AI · 06 שאלות" , bg: "AI-ПОДБОР · 06 ВЪПРОСА" , cs: "AI-VÝBĚR · 06 OTÁZEK" },
  finder_t1:  { ru: "Найдём твою", en: "Find your", de: "Finde deine", pl: "Znajdź swoją", he: "מצא את" , bg: "Намерете вашата" , cs: "Najděte svůj" },
  finder_t2:  { ru: "идеальную экскурсию", en: "perfect excursion", de: "perfekte Tour", pl: "idealną wycieczkę", he: "הסיור המושלם" , bg: "идеална екскурзия" , cs: "ideální výlet" },
  finder_intro:{ ru: "Ответь на 6 коротких вопросов — алгоритм сопоставит твой настрой, бюджет и компанию с каталогом и выдаст лучший матч.", en: "Answer 6 quick questions — the engine matches your vibe, budget and party to the catalogue and returns the best fit.", de: "Beantworte 6 kurze Fragen — der Algorithmus gleicht Stimmung, Budget und Gruppe mit dem Katalog ab.", pl: "Odpowiedz na 6 pytań — algorytm dopasuje nastrój, budżet i towarzystwo do katalogu.", he: "ענו על 6 שאלות קצרות — האלגוריתם יתאים את האווירה, התקציב והחברה לקטלוג." , bg: "Отговорете на 6 кратки въпроса — алгоритъмът съпоставя настроението, бюджета и компанията ви с каталога и връща най-доброто съвпадение." , cs: "Odpovězte na 6 krátkých otázek — algoritmus porovná vaši náladu, rozpočet a společnost s katalogem a vrátí nejlepší shodu." },
  finder_start:{ ru: "Начать подбор", en: "Start", de: "Starten", pl: "Zacznij", he: "התחל" , bg: "Започни" , cs: "Začít" },
  step_answer:{ ru: "Ответь на вопросы", en: "Answer", de: "Antworten", pl: "Odpowiedz", he: "ענה" , bg: "Отговори" , cs: "Odpovězte" },
  step_score: { ru: "Алгоритм считает матч", en: "Engine scores", de: "Auswertung", pl: "Algorytm liczy", he: "חישוב התאמה" , bg: "Алгоритъмът оценява" , cs: "Algoritmus počítá" },
  step_pick:  { ru: "Получи рекомендацию", en: "Get your pick", de: "Empfehlung", pl: "Rekomendacja", he: "קבל המלצה" , bg: "Получи препоръка" , cs: "Získejte doporučení" },
  calc_text:  { ru: "Анализируем 38 экскурсий…", en: "Analysing 38 excursions…", de: "Analysiere 38 Touren…", pl: "Analiza 38 wycieczek…", he: "מנתח 38 סיורים…" , bg: "Анализираме 38 екскурзии…" , cs: "Analyzujeme 38 výletů…" },
  result_label:{ ru: "РЕЗУЛЬТАТ · ЛУЧШИЙ МАТЧ", en: "RESULT · BEST MATCH", de: "ERGEBNIS · BESTE WAHL", pl: "WYNIK · NAJLEPSZE", he: "תוצאה · ההתאמה הטובה" , bg: "РЕЗУЛТАТ · НАЙ-ДОБРО СЪВПАДЕНИЕ" , cs: "VÝSLEDEK · NEJLEPŠÍ SHODA" },
  why:        { ru: "Почему это", en: "Why this", de: "Warum das", pl: "Dlaczego to", he: "למה זה" , bg: "Защо това" , cs: "Proč právě tohle" },
  alternatives:{ ru: "Альтернативы", en: "Alternatives", de: "Alternativen", pl: "Alternatywy", he: "חלופות" , bg: "Алтернативи" , cs: "Alternativy" },
  restart:    { ru: "Заново", en: "Restart", de: "Neu", pl: "Od nowa", he: "התחל מחדש" , bg: "Отначало" , cs: "Znovu" },
  match:      { ru: "МАТЧ", en: "MATCH", de: "TREFFER", pl: "DOPASOWANIE", he: "התאמה" , bg: "СЪВПАДЕНИЕ" , cs: "SHODA" },
  back:       { ru: "Назад", en: "Back", de: "Zurück", pl: "Wstecz", he: "חזרה" , bg: "Назад" , cs: "Zpět" },

  reason_party:{ ru: "Идеально для вашей компании", en: "Perfect for your party", de: "Ideal für eure Gruppe", pl: "Idealne dla waszej grupy", he: "מושלם לקבוצה שלכם" , bg: "Идеално за вашата компания" , cs: "Ideální pro vaši společnost" },
  reason_time:{ ru: "Совпадает по длительности", en: "Matches your time", de: "Passt zur Dauer", pl: "Pasuje czasowo", he: "מתאים למשך הזמן" , bg: "Съвпада по продължителност" , cs: "Odpovídá délce" },
  reason_budget:{ ru: "В рамках бюджета", en: "Within budget", de: "Im Budget", pl: "W budżecie", he: "בתקציב" , bg: "В рамките на бюджета" , cs: "V rámci rozpočtu" },
  reason_drinks:{ ru: "Напитки и атмосфера включены", en: "Drinks & atmosphere included", de: "Getränke & Stimmung inklusive", pl: "Drinki i atmosfera w cenie", he: "משקאות ואווירה כלולים" , bg: "Напитки и атмосфера включени" , cs: "Nápoje a atmosféra v ceně" },
  reason_kids:{ ru: "Подходит для детей", en: "Kid-friendly", de: "Kinderfreundlich", pl: "Przyjazne dzieciom", he: "ידידותי לילדים" , bg: "Подходящо за деца" , cs: "Vhodné pro děti" },
  reason_relax:{ ru: "Спокойный, восстанавливающий формат", en: "Calm, restorative format", de: "Ruhig und erholsam", pl: "Spokojny, regenerujący", he: "רגוע ומשקם" , bg: "Спокоен, възстановяващ формат" , cs: "Klidný, regenerační formát" },
  reason_culture:{ ru: "Глубокое культурное погружение", en: "Rich cultural immersion", de: "Tiefe Kultur", pl: "Głębokie zanurzenie w kulturę", he: "חוויה תרבותית עשירה" , bg: "Богато културно потапяне" , cs: "Hluboké kulturní ponoření" },
  reason_rated:{ ru: "Высокий рейтинг у гостей", en: "Highly rated by guests", de: "Top bewertet", pl: "Wysoko oceniane", he: "מדורג גבוה" , bg: "Високо оценено от гостите" , cs: "Vysoce hodnoceno hosty" },

  rental_label:{ ru: "СЕРВИС · АРЕНДА АВТО", en: "SERVICE · CAR RENTAL", de: "SERVICE · MIETWAGEN", pl: "USŁUGA · WYNAJEM", he: "שירות · השכרת רכב" , bg: "УСЛУГА · КОЛИ ПОД НАЕМ" , cs: "SLUŽBA · PŮJČOVNA AUT" },
  rental_h1:  { ru: "Свобода на колёсах", en: "Freedom on wheels", de: "Freiheit auf Rädern", pl: "Wolność na kołach", he: "חופש על גלגלים" , bg: "Свобода на колела" , cs: "Svoboda na kolech" },
  rental_intro:{ ru: "Машина к отелю за 2 часа. Без залога, полная страховка, цены за сутки.", en: "Car to your hotel in 2 hours. No deposit, full insurance, daily rates.", de: "Auto ans Hotel in 2 Std. Ohne Kaution, Vollkasko, Tagespreise.", pl: "Auto pod hotel w 2 h. Bez kaucji, pełne ubezpieczenie, ceny za dobę.", he: "רכב למלון תוך שעתיים. ללא פיקדון, ביטוח מלא, מחיר ליום." , bg: "Кола до хотела за 2 часа. Без депозит, пълна застраховка, цени на ден." , cs: "Auto k hotelu za 2 hodiny. Bez kauce, plné pojištění, ceny za den." },
  sp_seats:   { ru: "Мест", en: "Seats", de: "Sitze", pl: "Miejsca", he: "מושבים" , bg: "Места" , cs: "Místa" },
  sp_gear:    { ru: "КПП", en: "Gear", de: "Getriebe", pl: "Skrzynia", he: "תיבה" , bg: "Скорости" , cs: "Převodovka" },
  sp_ac:      { ru: "Климат", en: "AC", de: "Klima", pl: "Klima", he: "מיזוג" , bg: "Климатик" , cs: "Klima" },
  sp_fuel:    { ru: "Топливо", en: "Fuel", de: "Kraftstoff", pl: "Paliwo", he: "דלק" , bg: "Гориво" , cs: "Palivo" },
  rent:       { ru: "Арендовать", en: "Rent", de: "Mieten", pl: "Wynajmij", he: "השכר" , bg: "Наеми" , cs: "Pronajmout" },
  how_works:  { ru: "КАК ЭТО РАБОТАЕТ", en: "HOW IT WORKS", de: "SO GEHT'S", pl: "JAK TO DZIAŁA", he: "איך זה עובד" , bg: "КАК РАБОТИ" , cs: "JAK TO FUNGUJE" },
  hw1:        { ru: "Выбери авто и даты", en: "Pick car & dates", de: "Auto & Termine wählen", pl: "Wybierz auto i daty", he: "בחר רכב ותאריכים" , bg: "Избери кола и дати" , cs: "Vyberte auto a termíny" },
  hw2:        { ru: "Подтверди по телефону", en: "Confirm by phone", de: "Per Telefon bestätigen", pl: "Potwierdź telefonicznie", he: "אישור בטלפון" , bg: "Потвърди по телефона" , cs: "Potvrďte telefonicky" },
  hw3:        { ru: "Получи у отеля", en: "Get it at your hotel", de: "Am Hotel erhalten", pl: "Odbierz pod hotelem", he: "קבל ליד המלון" , bg: "Вземи от хотела" , cs: "Vyzvedněte u hotelu" },

  contacts_label:{ ru: "КОНТАКТЫ · 05 ОФИСОВ", en: "CONTACTS · 05 OFFICES", de: "KONTAKT · 05 BÜROS", pl: "KONTAKT · 05 BIUR", he: "צור קשר · 05 משרדים" , bg: "КОНТАКТИ · 05 ОФИСА" , cs: "KONTAKTY · 05 KANCELÁŘÍ" },
  contacts_h1:{ ru: "Найди нас на побережье", en: "Find us on the coast", de: "Finde uns an der Küste", pl: "Znajdź nas na wybrzeżu", he: "מצאו אותנו בחוף" , bg: "Намерете ни на крайбрежието" , cs: "Najděte nás na pobřeží" },
  write_us:   { ru: "Напишите нам", en: "Write to us", de: "Schreib uns", pl: "Napisz do nas", he: "כתבו לנו" , bg: "Пишете ни" , cs: "Napište nám" },
  guest:      { ru: "Турист", en: "Guest", de: "Gast", pl: "Turysta", he: "תייר" , bg: "Турист" , cs: "Turista" },
  agent:      { ru: "Агент", en: "Agent", de: "Agentur", pl: "Agent", he: "סוכן" , bg: "Агент" , cs: "Agent" },
  ph_name:    { ru: "Имя*", en: "Name*", de: "Name*", pl: "Imię*", he: "שם*" , bg: "Име*" , cs: "Jméno*" },
  ph_phone:   { ru: "Телефон / мессенджер*", en: "Phone / messenger*", de: "Telefon / Messenger*", pl: "Telefon / komunikator*", he: "טלפון / מסנג'ר*" , bg: "Телефон / месинджър*" , cs: "Telefon / messenger*" },
  ph_msg:     { ru: "Сообщение", en: "Message", de: "Nachricht", pl: "Wiadomość", he: "הודעה" , bg: "Съобщение" , cs: "Zpráva" },
  send_req:   { ru: "Отправить заявку", en: "Send request", de: "Anfrage senden", pl: "Wyślij", he: "שלח בקשה" , bg: "Изпрати заявка" , cs: "Odeslat žádost" },
  form_note:  { ru: "Заявка уходит менеджеру в Telegram. Ответим в течение 15 минут в рабочее время.", en: "Your request goes to a manager via Telegram. We reply within 15 min during hours.", de: "Anfrage geht per Telegram an einen Manager. Antwort in 15 Min. zu Geschäftszeiten.", pl: "Zgłoszenie trafia do menedżera na Telegramie. Odpowiadamy w 15 min w godzinach pracy.", he: "הבקשה נשלחת למנהל בטלגרם. נגיב תוך 15 דק' בשעות הפעילות." , bg: "Заявката отива при мениджър в Telegram. Отговаряме до 15 минути в работно време." , cs: "Žádost jde manažerovi na Telegram. Odpovídáme do 15 minut v pracovní době." },
  sent_title: { ru: "Заявка отправлена", en: "Request sent", de: "Anfrage gesendet", pl: "Wysłano", he: "הבקשה נשלחה" , bg: "Заявката е изпратена" , cs: "Žádost odeslána" },
  send_err:   { ru: "Не удалось отправить. Позвоните нам или попробуйте ещё раз.", en: "Couldn't send. Please call us or try again.", de: "Senden fehlgeschlagen. Bitte rufen Sie an oder versuchen Sie es erneut.", pl: "Nie udało się wysłać. Zadzwoń lub spróbuj ponownie.", he: "השליחה נכשלה. התקשרו אלינו או נסו שוב.", bg: "Неуспешно изпращане. Обадете се или опитайте отново." , cs: "Nepodařilo se odeslat. Zavolejte nám nebo zkuste znovu." },
  sent_msg:   { ru: "мы свяжемся с вами очень скоро.", en: "we'll be in touch shortly.", de: "wir melden uns in Kürze.", pl: "wkrótce się odezwiemy.", he: "ניצור קשר בקרוב." , bg: "ще се свържем с вас съвсем скоро." , cs: "brzy se vám ozveme." },
  map_label:  { ru: "На карте", en: "Map", de: "Karte", pl: "Mapa", he: "מפה" , bg: "На картата" , cs: "Na mapě" },
  price_check: { ru: "Цена по запросу", en: "Price on request", de: "Preis auf Anfrage", pl: "Cena na zapytanie", he: "מחיר לפי בקשה", bg: "Цена при запитване", cs: "Cena na vyžádání" },
  until_label: { ru: "до", en: "until", de: "bis", pl: "do", he: "עד", bg: "до", cs: "do" },

  foot_about: { ru: "Экскурсии, аренда авто и сервис на болгарском побережье Чёрного моря. Солнечный берег · Несебр · Бургас.", en: "Excursions, car rental and service on Bulgaria's Black Sea coast.", de: "Touren, Mietwagen und Service an Bulgariens Schwarzmeerküste.", pl: "Wycieczki, wynajem aut i obsługa na bułgarskim wybrzeżu Morza Czarnego.", he: "סיורים, השכרת רכב ושירות בחוף הים השחור בבולגריה." , bg: "Екскурзии, коли под наем и обслужване по българското Черноморие. Слънчев бряг · Несебър · Бургас." , cs: "Výlety, půjčovna aut a servis na bulharském pobřeží Černého moře. Slunečné pobřeží · Nesebar · Burgas." },
  sec_sections:{ ru: "Разделы", en: "Sections", de: "Bereiche", pl: "Sekcje", he: "מדורים" , bg: "Раздели" , cs: "Sekce" },
  sec_contact:{ ru: "Связь", en: "Contact", de: "Kontakt", pl: "Kontakt", he: "יצירת קשר" , bg: "Връзка" , cs: "Spojení" },
  foot_proto: { ru: "ПРОТОТИП · ДИЗАЙН-КОНЦЕПТ", en: "PROTOTYPE · DESIGN CONCEPT", de: "PROTOTYP · DESIGNKONZEPT", pl: "PROTOTYP · KONCEPT", he: "אב-טיפוס · קונספט" , bg: "ПРОТОТИП · ДИЗАЙН-КОНЦЕПЦИЯ" , cs: "PROTOTYP · DESIGN-KONCEPT" },
  theme_label:{ ru: "Тема", en: "Theme", de: "Thema", pl: "Motyw", he: "ערכה" , bg: "Тема" , cs: "Téma" },
};
function t(lang, k) { const e = TX[k]; if (!e) return k; return e[lang] || e.en || e.ru || k; }

// ── CURRENCY (Bulgarian lev is fixed-pegged to the euro) ──────────────────
const EURBGN = 1.95583;
const toEur = (bgn) => Math.round(bgn / EURBGN);

// ── TELEGRAM LEAD DELIVERY (production: via serverless proxy) ──────────────
// SECURITY: the bot token NEVER ships to the browser. It lives only as a
// server-side secret (Cloudflare Pages env var TG_BOT_TOKEN). The client just
// POSTs the message text to /api/lead and the Function forwards it to Telegram.
// Local note: without the Function running (plain static server) sends will
// return ok:false — that is expected; deploy to Cloudflare Pages to go live.
const TG = {
  endpoint: "/api/lead", // serverless proxy (see functions/api/lead.js)
};
async function sendLeadToTelegram(text) {
  try {
    const r = await fetch(TG.endpoint, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ text }),
    });
    const d = await r.json().catch(() => ({}));
    return { ok: !!(r.ok && d.ok !== false), raw: d };
  } catch (e) { return { ok: false, reason: String(e) }; }
}

// ── DAYS OF WEEK (Mon=0 … Sun=6) ──────────────────────────────────
const DOW = {
  bg: ["Пн","Вт","Ср","Чт","Пт","Сб","Нд"],
  ru: ["Пн","Вт","Ср","Чт","Пт","Сб","Вс"],
  en: ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"],
  de: ["Mo","Di","Mi","Do","Fr","Sa","So"],
  pl: ["Pn","Wt","Śr","Cz","Pt","So","Nd"],
  he: ["ב'","ג'","ד'","ה'","ו'","ש'","א'"],
  cs: ["Po","Út","St","Čt","Pá","So","Ne"],
};
function dayNames(lang, arr) { const d = DOW[lang] || DOW.en; return (arr || []).map((i) => d[i]); }

// ── EXCURSIONS ───────────────────────────────────────────────────────────
const VEXC = [
  { id: 1, code: "EX-01", cat: "ADVENTURE", dur: "full", time: "10:00–15:00", price: 111, priceChild: 76, days: [0,1,2,3,4,5,6], seats: 6,
    tags: ["kids","active","nature"], party: ["family","friends"],
    title: { ru: "Джип-сафари", en: "Jeep Safari", de: "Jeep-Safari", pl: "Jeep Safari", he: "ספארי ג'יפים", bg: "Джип сафари" , cs: "Jeep safari" },
    place: { ru: "Болгарская природа · бездорожье", en: "Bulgarian nature · off-road", de: "Bulgarische Natur · Offroad", pl: "Bułgarska natura · off-road", he: "טבע בולגרי · שטח", bg: "Българска природа · офроуд" , cs: "Bulharská příroda · offroad" },
    pitch: { ru: "Настоящее внедорожное приключение по болгарской природе: горные маршруты, лесные дороги, панорамы и фотосессии с опытными гидами. Для семей, пар и друзей.", en: "A real off-road adventure through Bulgarian nature: mountain trails, forest roads, panoramas and photo stops with expert guides. For families, couples and friends.", de: "Ein echtes Offroad-Abenteuer durch Bulgariens Natur: Bergpfade, Waldwege, Panoramen und Fotostopps mit erfahrenen Guides. Für Familien, Paare und Freunde.", pl: "Prawdziwa przygoda off-road przez bułgarską naturę: górskie szlaki, leśne drogi, panoramy i sesje zdjęciowe z doświadczonymi przewodnikami. Dla rodzin, par i przyjaciół.", he: "הרפתקת שטח אמיתית בטבע הבולגרי: שבילי הרים, דרכי יער, נופים ועצירות צילום עם מדריכים מנוסים. למשפחות, זוגות וחברים.", bg: "Истинско офроуд приключение сред българската природа: планински маршрути, горски пътища, панорами и фотопаузи с опитни водачи. За семейства, двойки и приятели." , cs: "Skutečné offroad dobrodružství bulharskou přírodou: horské trasy, lesní cesty, panoramata a foto-pauzy se zkušenými průvodci. Pro rodiny, páry i přátele." } },
  { id: 2, code: "EX-02", cat: "CRUISE", dur: "full", time: "09:00–15:15", price: 108, priceChild: 68, seats: 12,
    tags: ["kids","party","active"], party: ["family","friends","couple"],
    title: { ru: "Дикие Пираты", en: "Wild Pirates", de: "Wilde Piraten", pl: "Dzicy Piraci", he: "פיראטים פראים", bg: "Диви пирати" , cs: "Divocí piráti" },
    place: { ru: "Остров Св. Анастасии", en: "St. Anastasia Island", de: "Insel St. Anastasia", pl: "Wyspa Św. Anastazji", he: "אי סנטה אנסטסיה", bg: "Остров Св. Анастасия" , cs: "Ostrov sv. Anastasie" },
    pitch: { ru: "Морское путешествие с капитаном Хуком из Поморья: пиратские игры, весёлая анимация и волшебная атмосфера острова Святой Анастасии. Незабываемо для детей и взрослых.", en: "A sea voyage with Captain Hook from Pomorie: pirate games, lively animation and the magical St. Anastasia Island. Unforgettable for kids and grown-ups alike.", de: "Eine Seereise mit Kapitän Hook ab Pomorie: Piratenspiele, fröhliche Animation und die magische Insel St. Anastasia. Unvergesslich für Groß und Klein.", pl: "Morska wyprawa z kapitanem Hakiem z Pomorie: zabawy piratów, animacje i magiczna wyspa Św. Anastazji. Niezapomniane dla dzieci i dorosłych.", he: "הפלגה עם קפטן הוק מפומורייה: משחקי פיראטים, אנימציה עליזה והאי הקסום סנטה אנסטסיה. חוויה בלתי נשכחת לילדים ולמבוגרים.", bg: "Морско пътешествие с капитан Хук от Поморие: пиратски игри, забавна анимация и вълшебната атмосфера на остров Света Анастасия. Незабравимо за деца и възрастни." , cs: "Mořská plavba s kapitánem Hookem z Pomorie: pirátské hry, zábavná animace a kouzelná atmosféra ostrova svaté Anastasie. Nezapomenutelné pro děti i dospělé." } },
  { id: 3, code: "EX-03", cat: "CULTURE", dur: "evening", time: "18:00–23:00", price: 106, priceChild: 84, days: [2,3,5,6], seats: 4,
    tags: ["party","romance","culture"], party: ["couple","friends"],
    title: { ru: "Болгарский вечер", en: "Bulgarian Evening", de: "Bulgarischer Abend", pl: "Bułgarski Wieczór", he: "ערב בולגרי", bg: "Българска вечер" , cs: "Bulharský večer" },
    place: { ru: "Комплекс «Горная хижина»", en: "'Mountain House' complex", de: "Komplex „Berghaus“", pl: "Kompleks „Górska Chata”", he: "מתחם 'בית ההר'", bg: "Комплекс «Планинска хижа»" , cs: "Komplex «Horská chata»" },
    pitch: { ru: "Вечер в комплексе «Горная хижина»: древний болгарский быт, богатое меню, вино из бочек без лимита, детская анимация и фольклор с танцами на углях.", en: "An evening at the 'Mountain House': old Bulgarian life, a rich menu, unlimited barrel wine, kids' animation and folklore with fire-dancing.", de: "Ein Abend im „Berghaus“: altes bulgarisches Leben, reichhaltiges Menü, Fasswein ohne Limit, Kinderanimation und Folklore mit Feuertanz.", pl: "Wieczór w „Górskiej Chacie”: dawne bułgarskie życie, bogate menu, wino z beczki bez limitu, animacje dla dzieci i folklor z tańcem na ogniu.", he: "ערב ב'בית ההר': אורח חיים בולגרי עתיק, תפריט עשיר, יין חבית ללא הגבלה, אנימציה לילדים ופולקלור עם ריקוד אש.", bg: "Вечер в комплекс «Планинска хижа»: древен български бит, богато меню, вино от бъчва без лимит, детска анимация и фолклор с танци върху жар." , cs: "Večer v komplexu «Horská chata»: starobylý bulharský život, bohaté menu, sudové víno bez limitu, dětská animace a folklor s tancem na žhavém uhlí." } },
  { id: 4, code: "EX-04", cat: "WELLNESS", dur: "half", time: "09:00–12:00", price: 78, priceChild: 65, days: [2,5], seats: 8,
    tags: ["relax","nature"], party: ["couple","solo","family"],
    title: { ru: "Соляный SPA · Солницы", en: "Saltworks Spa", de: "Salz-Spa", pl: "Spa Solne", he: "ספא מלח", bg: "Солен SPA · Солницата" , cs: "Solné SPA · Solnitsata" },
    place: { ru: "Пляж Солницы · Поморье", en: "Solnitsi beach · Pomorie", de: "Strand Solnitsi · Pomorie", pl: "Plaża Solnitsi · Pomorie", he: "חוף סולניצי · פומורייה", bg: "Плаж Солницата · Поморие" , cs: "Pláž Solnitsata · Pomorie" },
    pitch: { ru: "Лечебный комплекс под открытым небом на пляже Солницы у Поморья: бассейны с чёрной грязью, красной щёлочью и белой солью, грязевые ванны и купание в море.", en: "An open-air healing complex at Solnitsi beach near Pomorie: pools of black mud, red lye and white salt, mud baths and a swim in the sea.", de: "Ein Heilkomplex unter freiem Himmel am Strand Solnitsi bei Pomorie: Becken mit schwarzem Schlamm, roter Lauge und weißem Salz, Schlammbäder und Meerbad.", pl: "Leczniczy kompleks pod gołym niebem na plaży Solnitsi koło Pomorie: baseny z czarnym błotem, czerwonym ługiem i białą solą, kąpiele błotne i morskie.", he: "מתחם מרפא תחת כיפת השמיים בחוף סולניצי ליד פומורייה: בריכות בוץ שחור, בורית אדומה ומלח לבן, אמבטי בוץ ורחצה בים.", bg: "Лечебен комплекс на открито на плаж Солницата край Поморие: басейни с черна кал, червена луга и бяла сол, кални бани и къпане в морето." , cs: "Léčebný komplex pod širým nebem na pláži Solnitsata u Pomorie: bazény s černým bahnem, červenou solankou a bílou solí, bahenní koupele a koupání v moři." } },
  { id: 5, code: "EX-05", cat: "SEA", dur: "half", time: "13:30–18:30", price: 96, priceChild: 70, days: [4,6], seats: 5,
    tags: ["romance","culture","sea"], party: ["couple","friends"],
    title: { ru: "Несебр с яхты", en: "Nessebar by Yacht", de: "Nessebar per Yacht", pl: "Nesebyr jachtem", he: "נסבר ביאכטה", bg: "Несебър с яхта" , cs: "Nesebar jachtou" },
    place: { ru: "Старый Несебр · ЮНЕСКО", en: "Old Nessebar · UNESCO", de: "Altstadt Nessebar · UNESCO", pl: "Stary Nesebyr · UNESCO", he: "נסבר העתיקה · אונסקו", bg: "Стар Несебър · ЮНЕСКО" , cs: "Starý Nesebar · UNESCO" },
    pitch: { ru: "Прогулка на яхте от Солнечного Берега в 15:00, затем пешеходная экскурсия по Старому Несебру — городу ЮНЕСКО — и свободное время. Возвращение в 18:30.", en: "A 15:00 yacht cruise from Sunny Beach, then a walking tour of UNESCO Old Nessebar and free time. Back by 18:30.", de: "Eine Yachtfahrt um 15:00 ab Sonnenstrand, dann ein Rundgang durch die UNESCO-Altstadt Nessebar und Freizeit. Rückkehr um 18:30.", pl: "Rejs jachtem o 15:00 ze Słonecznego Brzegu, potem spacer po starym Nesebyrze z listy UNESCO i czas wolny. Powrót o 18:30.", he: "שיט יאכטה ב-15:00 מסאני ביץ', לאחר מכן סיור רגלי בנסבר העתיקה (אונסקו) וזמן חופשי. חזרה ב-18:30.", bg: "Разходка с яхта от Слънчев бряг в 15:00, след което пешеходна обиколка на Стария Несебър — град на ЮНЕСКО — и свободно време. Връщане в 18:30." , cs: "Plavba jachtou ze Slunečného pobřeží v 15:00, poté pěší prohlídka Starého Nesebaru — města UNESCO — a volný čas. Návrat v 18:30." } },
  { id: 6, code: "EX-06", cat: "HERITAGE", dur: "full", time: "08:00–16:30", price: 151, priceChild: 102, days: [2,5], seats: 15,
    tags: ["romance","culture"], party: ["couple","family","solo"],
    title: { ru: "Созополь и Замок", en: "Sozopol & Castle", de: "Sosopol & Schloss", pl: "Sozopol i Zamek", he: "סוזופול וטירה", bg: "Созопол и Замъка" , cs: "Sozopol a Zámek" },
    place: { ru: "Замок Равадиново", en: "Ravadinovo Castle", de: "Schloss Ravadinovo", pl: "Zamek Ravadinovo", he: "טירת רבדינובו", bg: "Замък Равадиново" , cs: "Zámek Ravadinovo" },
    pitch: { ru: "Старый Созополь и сказочный замок «Влюблённый в ветер».", en: "Old Sozopol and the fairy-tale castle 'In Love with the Wind'.", de: "Das alte Sosopol und das Märchenschloss „Verliebt in den Wind“.", pl: "Stary Sozopol i baśniowy zamek „Zakochany w wietrze”.", he: "סוזופול העתיקה וטירת האגדה 'מאוהב ברוח'.", bg: "Старият Созопол и приказният замък «Влюбен във вятъра»." , cs: "Starý Sozopol a pohádkový zámek «Zamilovaný do větru»." } },
  { id: 7, code: "EX-07", cat: "FAMILY", dur: "full", time: "10:00–18:00", price: 59, priceChild: 35, days: [0,1,2,3,4,5,6], valid_until: "06-15", seats: 4,
    tags: ["kids","active"], party: ["family","friends"],
    title: { ru: "Аквапарк Action", en: "Aquapark Action", de: "Aquapark Action", pl: "Aquapark Action", he: "אקווה פארק", bg: "Аквапарк Action" , cs: "Aquapark Action" },
    place: { ru: "Аквапарк Несебр", en: "Nessebar Aquapark", de: "Aquapark Nessebar", pl: "Aquapark Nesebyr", he: "אקווה פארק נסבר", bg: "Аквапарк Несебър" , cs: "Aquapark Nesebar" },
    pitch: { ru: "Аквапарк Несебра: водные аттракционы, семейные бассейны и тихие зоны отдыха. Идеальный летний день с детьми, друзьями или вдвоём.", en: "Nessebar Aquapark: water rides, family pools and quiet lounging zones. A perfect summer day with kids, friends or your other half.", de: "Aquapark Nessebar: Wasserrutschen, Familienbecken und ruhige Liegezonen. Ein perfekter Sommertag mit Kindern, Freunden oder zu zweit.", pl: "Aquapark Nesebyr: zjeżdżalnie wodne, baseny rodzinne i ciche strefy relaksu. Idealny letni dzień z dziećmi, znajomymi lub we dwoje.", he: "אקווה פארק נסבר: מתקני מים, בריכות משפחתיות ופינות מנוחה שקטות. יום קיץ מושלם עם ילדים, חברים או בני זוג.", bg: "Аквапарк Несебър: водни атракции, семейни басейни и тихи зони за отдих. Идеален летен ден с деца, приятели или на двойка." , cs: "Aquapark Nesebar: vodní atrakce, rodinné bazény a klidné zóny pro odpočinek. Ideální letní den s dětmi, přáteli nebo ve dvou." } },
  { id: 8, code: "EX-08", cat: "ABROAD", dur: "multi", time: "21:30 · +2D", price: 254, priceChild: 156, days: [2,6], seats: 10,
    tags: ["culture","city"], party: ["couple","friends","solo"],
    title: { ru: "Стамбул — 2 дня", en: "Istanbul — 2 days", de: "Istanbul — 2 Tage", pl: "Stambuł — 2 dni", he: "איסטנבול — יומיים", bg: "Истанбул — 2 дни" , cs: "Istanbul — 2 dny" },
    place: { ru: "Турция · 2 дня", en: "Turkey · 2 days", de: "Türkei · 2 Tage", pl: "Turcja · 2 dni", he: "טורקיה · יומיים", bg: "Турция · 2 дни" , cs: "Turecko · 2 dny" },
    pitch: { ru: "Два дня в городе на двух континентах. Панорамная экскурсия: Ипподром, Голубая мечеть и переправа через Босфор из Европы в Азию. Ночь в отеле и круиз по Босфору.", en: "Two days across two continents. Panoramic tour: the Hippodrome, Blue Mosque and a Bosphorus crossing from Europe to Asia. A hotel night and a Bosphorus cruise.", de: "Zwei Tage auf zwei Kontinenten. Panoramatour: Hippodrom, Blaue Moschee und Bosporus-Überfahrt von Europa nach Asien. Hotelnacht und Bosporus-Kreuzfahrt.", pl: "Dwa dni na dwóch kontynentach. Panoramiczna trasa: Hipodrom, Błękitny Meczet i przeprawa przez Bosfor z Europy do Azji. Nocleg i rejs po Bosforze.", he: "יומיים בשני יבשות. סיור פנורמי: ההיפודרום, המסגד הכחול ומעבר הבוספור מאירופה לאסיה. לינה במלון ושיט בבוספור.", bg: "Два дни в град на два континента. Панорамна обиколка: Хиподрумът, Синята джамия и преминаване през Босфора от Европа в Азия. Нощувка в хотел и круиз по Босфора." , cs: "Dva dny ve městě na dvou kontinentech. Panoramatická prohlídka: Hipodrom, Modrá mešita a přejezd přes Bospor z Evropy do Asie. Nocleh v hotelu a plavba po Bosporu." } },
  { id: 9, code: "EX-09", cat: "ABROAD", dur: "full", time: "21:30–17:30", price: 196, priceChild: 135, days: [0,4], seats: 12, pricing_note: "100/69 · 90/62",
    tags: ["culture","city"], party: ["couple","friends","solo"],
    title: { ru: "Стамбул — 1 день", en: "Istanbul — 1 day" },
    place: { ru: "Турция · 1 день", en: "Turkey · 1 day" },
    pitch: { ru: "Ранний завтрак, Голубая мечеть и Святая София, панорама города. Доп. прогулка по Босфору — 35 €.", en: "Early breakfast, the Blue Mosque and Hagia Sophia, a city panorama. Optional Bosphorus boat trip — €35." } },
  { id: 10, code: "EX-10", cat: "HERITAGE", dur: "full", time: "08:00–18:00", price: 180, priceChild: 117, days: [3,6], seats: 20,
    tags: ["culture"], party: ["couple","family","solo"],
    title: { ru: "Велико Тырново — Арбанаси", en: "Veliko Tarnovo — Arbanasi" },
    place: { ru: "Старая столица · Арбанаси", en: "Old capital · Arbanasi" },
    pitch: { ru: "Древняя столица Болгарии: крепость Царевец, старинные улицы и село Арбанаси. Обед и свободное время.", en: "Bulgaria's ancient capital: Tsarevets fortress, old streets and the village of Arbanasi. Lunch and free time." } },
  { id: 11, code: "EX-11", cat: "FAMILY", dur: "full", time: "08:00–17:00", price: 155, priceChild: 115, days: [4], seats: 30,
    tags: ["kids","family","city"], party: ["family","friends"],
    title: { ru: "Варна — Дельфинарий", en: "Varna — Dolphinarium" },
    place: { ru: "Варна · дельфинарий", en: "Varna · Dolphinarium" },
    pitch: { ru: "Поездка в морскую столицу Болгарии: кафедральный собор, шоу в единственном дельфинарии страны, обед и шопинг.", en: "A trip to Bulgaria's sea capital: the cathedral, a show at the country's only dolphinarium, lunch and shopping." } },
  { id: 12, code: "EX-12", cat: "CITY", dur: "half", time: "08:00–13:00", price: 68, priceChild: 49, days: [1,4], seats: 30,
    tags: ["city"], party: ["solo","friends","couple"],
    title: { ru: "Варна — шопинг", en: "Varna — Shopping" },
    place: { ru: "Варна · шопинг", en: "Varna · shopping" },
    pitch: { ru: "Шопинг-поездка в Варну дважды в неделю. Крупные торговые центры и центр города, свободное время.", en: "A twice-weekly shopping trip to Varna. Big malls and the city centre, with free time." } },
  { id: 13, code: "EX-13", cat: "NATURE", dur: "half", time: "09:00–14:00", price: 113, priceChild: 84, days: [2,5], seats: 20,
    tags: ["nature","culture"], party: ["couple","family","solo"],
    title: { ru: "Созополь — монастырь + Ропотамо", en: "Sozopol — Monastery + Ropotamo" },
    place: { ru: "Монастырь Св. Георгия · Ропотамо", en: "St. George Monastery · Ropotamo" },
    pitch: { ru: "Монастырь Святого Георгия и прогулка на лодке по заповедной реке Ропотамо. Старый Созополь и обед.", en: "St. George Monastery and a boat ride on the protected Ropotamo river. Old Sozopol and lunch." } },
  { id: 14, code: "EX-14", cat: "HERITAGE", dur: "half", time: "09:00–14:00", price: 57, priceChild: 37, days: [2,5], seats: 25,
    tags: ["culture","romance"], party: ["couple","solo","family"],
    title: { ru: "Панорама Несебра", en: "Panorama Nessebar" },
    place: { ru: "Старый Несебр · пешком", en: "Old Nessebar · walking" },
    pitch: { ru: "Пешеходная экскурсия по историческим улочкам древнего Несебра — города ЮНЕСКО.", en: "A walking tour of the historic lanes of ancient Nessebar — a UNESCO town." } },
  { id: 15, code: "EX-15", cat: "NATURE", dur: "full", time: "08:00–18:00", price: 155, priceChild: 111, days: [3,6], seats: 20, pricing_note: "79/57 · 57/47",
    tags: ["nature","culture","romance"], party: ["couple","family"],
    title: { ru: "Калиакра — Балчик", en: "Kaliakra — Balchik" },
    place: { ru: "Мыс Калиакра · Балчик", en: "Cape Kaliakra · Balchik" },
    pitch: { ru: "Ботанический сад и дворец королевы Марии в Балчике, мыс Калиакра и дегустация вин. Обед.", en: "The botanical garden and Queen Marie's palace in Balchik, Cape Kaliakra and a wine tasting. Lunch." } },
  { id: 16, code: "EX-16", cat: "NATURE", dur: "full", time: "08:00–18:00", price: 155, priceChild: 135, days: [3,6], seats: 20, pricing_note: "79/69 · 57/47",
    tags: ["nature","active"], party: ["couple","family","solo"],
    title: { ru: "Балчик — Каменный лес", en: "Balchik — Stone Forest" },
    place: { ru: "Побити Камани · Балчик", en: "Pobiti Kamani · Balchik" },
    pitch: { ru: "Балчик, мыс Калиакра и природный феномен «Побити Камани» — каменный лес из песчаных колонн.", en: "Balchik, Cape Kaliakra and the 'Pobiti Kamani' phenomenon — a desert forest of stone columns." } },
  { id: 17, code: "EX-17", cat: "HERITAGE", dur: "full", time: "06:00–18:00", price: 174, priceChild: 115, days: [5], seats: 20,
    tags: ["culture","city"], party: ["couple","solo","family"],
    title: { ru: "Пловдив — Бачково", en: "Plovdiv — Bachkovo" },
    place: { ru: "Пловдив · Бачковский монастырь", en: "Plovdiv · Bachkovo Monastery" },
    pitch: { ru: "Старый Пловдив — один из древнейших городов Европы — и Бачковский монастырь. Целый день истории.", en: "Old Plovdiv — one of Europe's oldest cities — and the Bachkovo Monastery. A full day of history." } },
  { id: 18, code: "EX-18", cat: "HERITAGE", dur: "half", time: "08:00–14:00", price: 90, priceChild: 57, days: [2,5], seats: 20,
    tags: ["culture","nature"], party: ["couple","solo","family"],
    title: { ru: "Варна — Аладжа монастырь", en: "Varna — Aladzha Monastery" },
    place: { ru: "Варна · скальный монастырь", en: "Varna · rock monastery" },
    pitch: { ru: "Скальный монастырь Аладжа близ Варны — пещерная обитель в отвесной скале. История и природа.", en: "The Aladzha rock monastery near Varna — a cave cloister carved into a sheer cliff. History and nature." } },
  { id: 19, code: "EX-19", cat: "HERITAGE", dur: "full", time: "07:00–18:00", price: 350, priceChild: 213, days: [3], seats: 25,
    tags: ["culture","nature"], party: ["couple","solo","friends"],
    title: { ru: "София — Рила — Ванга — Мелник", en: "Sofia — Rila — Vanga — Melnik" },
    place: { ru: "Рильский монастырь · Мелник", en: "Rila Monastery · Melnik" },
    pitch: { ru: "Большое путешествие: Рильский монастырь, дом Ванги в Рупите и самый маленький город Мелник.", en: "A grand journey: Rila Monastery, Vanga's house in Rupite and Melnik, Bulgaria's smallest town." } },
  { id: 20, code: "EX-20", cat: "HERITAGE", dur: "full", time: "06:30–19:00", price: null, priceChild: null, requires_price_check: true, days: [6], seats: 20,
    tags: ["culture","nature"], party: ["couple","family","solo"],
    title: { ru: "Сливен — Жеравна", en: "Sliven — Zheravna" },
    place: { ru: "Сливен · село Жеравна", en: "Sliven · Zheravna village" },
    pitch: { ru: "Сливен и архитектурный заповедник Жеравна — село с деревянными домами эпохи Возрождения.", en: "Sliven and the Zheravna architectural reserve — a village of Revival-era wooden houses." } },
  { id: 21, code: "EX-21", cat: "CRUISE", dur: "half", time: "Day / Evening", price: 117, days: [], seats: 12, pricing_note: "День 85 € · Вечер 60 €",
    tags: ["sea","romance","relax","party"], party: ["couple","friends","family"],
    title: { ru: "VIP-круиз на катамаране", en: "VIP Catamaran Cruise" },
    place: { ru: "Катамаран · открытое море", en: "Catamaran · open sea" },
    pitch: { ru: "Морская прогулка на просторном VIP-катамаране: купание в открытом море, угощение на борту включено. Дневная программа — 85 €, вечерняя — 60 € с видом на закат.", en: "A cruise on a spacious VIP catamaran: swimming in the open sea, food on board included. Day programme €85, evening shift €60 with a sunset view." } },
  { id: 22, code: "EX-22", cat: "CULTURE", dur: "evening", time: "19:30–23:30", price: 113, priceChild: null, days: [0,1,2,3,4,5,6], seats: 30,
    tags: ["party","culture","romance"], party: ["couple","friends","family"],
    title: { ru: "Ханская Шатра", en: "Khan's Tent" },
    place: { ru: "Khan's Tent · шоу-кабаре", en: "Khan's Tent · show-cabaret" },
    pitch: { ru: "Трансфер в обе стороны, живая музыка и интернациональное шоу-кабаре. Включён ужин из 4 блюд и напитки (включая бутылку вина).", en: "Return transfer, live music and an international show-cabaret. Includes a 4-course dinner and drinks (a bottle of wine included)." } },
  { id: 23, code: "EX-23", cat: "CRUISE", dur: "half", time: "09:00–16:30", price: 110, priceChild: 78, days: [2,5], seats: 25,
    tags: ["sea","culture","party"], party: ["couple","family","friends"],
    title: { ru: "Созополь — монастырь + корабль", en: "Sozopol — Monastery + Ship" },
    place: { ru: "Аполлония · остров Св. Ивана", en: "Apollonia · St. Ivan island" },
    pitch: { ru: "Монастырь Св. Георгия в Поморье и древняя Аполлония. Пиратская прогулка на корабле вокруг Созополя и острова Святого Ивана с обедом на борту.", en: "St. George Monastery in Pomorie and ancient Apollonia. A pirate boat trip around Sozopol and St. Ivan island with lunch on board." } },
  { id: 24, code: "EX-24", cat: "CULTURE", dur: "evening", time: "13:30–23:00", price: null, priceChild: null, requires_price_check: true, days: [2], seats: 30,
    tags: ["culture","party","romance"], party: ["couple","friends","family"],
    title: { ru: "Панорама Несебр + Болгарское село", en: "Panorama Nessebar + Bulgarian Village" },
    place: { ru: "Яхта · Старый Несебр · «Горный дом»", en: "Yacht · Old Nessebar · 'Mountain House'" },
    pitch: { ru: "Прогулка на яхте в 15:00 и пешая экскурсия по Старому Несебру, затем вечер в комплексе «Горный дом»: богатый ужин, вино без лимита, фольклор и танцы с фейерверками. Возвращение в 23:00.", en: "A 15:00 yacht cruise and a walk through Old Nessebar, then an evening at the 'Mountain House': a rich dinner, unlimited wine, folklore and fire-dancing. Back at 23:00." } },
  { id: 25, code: "EX-25", cat: "FAMILY", dur: "half", time: "13:30–17:00", price: null, priceChild: null, requires_price_check: true, days: [0,2,4,6], seats: 30,
    tags: ["kids","family","culture"], party: ["family","friends"],
    title: { ru: "Варна — Дельфинарий + Аладжа", en: "Varna — Dolphinarium + Aladzha" },
    place: { ru: "Варна · дельфинарий · скальный монастырь", en: "Varna · dolphinarium · rock monastery" },
    pitch: { ru: "Шоу в дельфинарии Варны и посещение скального монастыря Аладжа — пещерной обители в отвесной скале.", en: "A show at the Varna dolphinarium and a visit to the Aladzha rock monastery — a cave cloister in a sheer cliff." } },
  // ── NEW from BRD-2026 price list ─────────────────────────────────────────
  { id: 26, code: "EX-26", cat: "SEA", dur: "half", time: "09:00 / 13:00", price: 133, priceChild: null, days: [0,1,2,3,4,5,6], seats: 8,
    tags: ["active","sea"], party: ["friends","couple","solo"],
    title: { ru: "Дайвинг", en: "Diving", de: "Tauchen", pl: "Nurkowanie", he: "צלילה", bg: "Гмуркане", cs: "Potápění" },
    place: { ru: "Чёрное море · Солнечный берег", en: "Black Sea · Sunny Beach", de: "Schwarzes Meer · Sonnenstrand", pl: "Morze Czarne · Słoneczny Brzeg", he: "הים השחור · סאני ביץ'", bg: "Черно море · Слънчев бряг", cs: "Černé moře · Slunečné pobřeží" },
    pitch: { ru: "Погружения с инструктором в тёплых водах Чёрного моря. Два сеанса — утро и полдень. Подходит для начинающих и опытных дайверов.", en: "Instructor-led dives in the warm Black Sea. Two daily slots — morning and midday. Suitable for all levels." } },
  { id: 27, code: "EX-27", cat: "ADVENTURE", dur: "full", time: "09:00 / 13:00", price: 154, priceChild: 123, days: [0,1,2,3,4,5,6], seats: 8,
    tags: ["active","nature","kids"], party: ["family","friends","couple"],
    title: { ru: "Мега джип-сафари", en: "Mega Jeep Safari", de: "Mega-Jeep-Safari", pl: "Mega Jeep Safari", he: "מגה ספארי ג'יפים", bg: "Мега джип сафари", cs: "Mega Jeep safari" },
    place: { ru: "Болгарская природа · внедорожье", en: "Bulgarian nature · off-road", de: "Bulgarische Natur · Offroad", pl: "Bułgarska natura · off-road", he: "טבע בולגרי · שטח", bg: "Българска природа · офроуд", cs: "Bulharská příroda · offroad" },
    pitch: { ru: "Расширенная версия джип-сафари на мощных машинах — длинный маршрут, экстремальные препятствия и водные переправы. Для настоящих любителей адреналина.", en: "The big version of jeep safari on powerful vehicles — a longer route, extreme obstacles and river crossings. For real thrill-seekers." } },
  { id: 28, code: "EX-28", cat: "NATURE", dur: "half", time: "по запросу", price: 88, priceChild: 88, days: [0,1,2,3,4,5,6], seats: 10,
    tags: ["active","nature","kids"], party: ["family","couple","friends"],
    title: { ru: "Конные прогулки", en: "Horse Riding", de: "Reiten", pl: "Jazda konna", he: "רכיבה על סוסים", bg: "Конна езда", cs: "Jízda na koni" },
    place: { ru: "Конная ферма · Солнечный берег", en: "Horse farm · Sunny Beach", de: "Pferdehof · Sonnenstrand", pl: "Stadnina · Słoneczny Brzeg", he: "חווה לרכיבה · סאני ביץ'", bg: "Конна ферма · Слънчев бряг", cs: "Jezdecký statek · Slunečné pobřeží" },
    pitch: { ru: "Верховая прогулка по живописным окрестностям Солнечного берега. Программы 1–2 часа, подходит для детей от 3 лет. Инструктор сопровождает на всём маршруте.", en: "Horseback riding through Sunny Beach's scenic surroundings. 1–2 hour programmes, suitable for children from age 3. An instructor accompanies the whole route." } },
  { id: 29, code: "EX-29", cat: "WELLNESS", dur: "half", time: "2 ч.", price: 195, priceChild: null, days: [0,1,2,3,4,5,6], seats: 12,
    tags: ["relax"], party: ["couple","solo","friends"],
    title: { ru: "Турецкая баня", en: "Turkish Bath", de: "Türkisches Bad", pl: "Łaźnia turecka", he: "חמאם טורקי", bg: "Турска баня", cs: "Turecká lázeň" },
    place: { ru: "Хамам · Солнечный берег", en: "Hammam · Sunny Beach", de: "Hamam · Sonnenstrand", pl: "Hamam · Słoneczny Brzeg", he: "חמאם · סאני ביץ'", bg: "Хамам · Слънчев бряг", cs: "Hamam · Slunečné pobřeží" },
    pitch: { ru: "Полное расслабление в традиционном хамаме: сауна, паровая баня, пилинг лица, рефлексология и полный аромамассаж тела. Сеанс — 2 часа.", en: "Full relaxation in a traditional hammam: sauna, steam bath, face peel, reflexology and full body aroma massage. Session — 2 hours." } },
  { id: 30, code: "EX-30", cat: "ADVENTURE", dur: "half", time: "по запросу", price: 96, priceChild: null, days: [0,1,2,3,4,5,6], seats: 6, pricing_note: "SINGLE · DOUBLE €69",
    tags: ["active","nature"], party: ["friends","couple","solo"],
    title: { ru: "Квадроциклы", en: "Quad Bikes", de: "Quad-Bikes", pl: "Quady", he: "אופנועי שטח", bg: "Четириколки", cs: "Čtyřkolky" },
    place: { ru: "Трасса · Солнечный берег", en: "Track · Sunny Beach", de: "Strecke · Sonnenstrand", pl: "Trasa · Słoneczny Brzeg", he: "מסלול · סאני ביץ'", bg: "Писта · Слънчев бряг", cs: "Trasa · Slunečné pobřeží" },
    pitch: { ru: "Приключение на квадроцикле по живописной трассе. Одиночные и двухместные байки. Инструктаж, шлемы и снаряжение включены.", en: "Quad-bike adventure on a scenic track. Single and double bikes available. Briefing, helmets and gear included." } },
  { id: 31, code: "EX-31", cat: "FAMILY", dur: "half", time: "по запросу", price: 94, priceChild: null, days: [0,1,2,3,4,5,6], seats: 10,
    tags: ["active","kids"], party: ["family","friends","couple"],
    title: { ru: "Картинг GO-GO", en: "GO-GO Karting", de: "GO-GO Kartbahn", pl: "Gokart GO-GO", he: "GO-GO קארטינג", bg: "GO-GO Картинг", cs: "GO-GO Karting" },
    place: { ru: "Картодром · Солнечный берег", en: "Karting track · Sunny Beach", de: "Kartbahn · Sonnenstrand", pl: "Kartodrom · Słoneczny Brzeg", he: "מסלול קארטינג · סאני ביץ'", bg: "Картодром · Слънчев бряг", cs: "Kartodrom · Slunečné pobřeží" },
    pitch: { ru: "Гонки на картах на современном картодроме Солнечного берега. Подходит для взрослых и детей. Заряд адреналина и честная борьба на трассе.", en: "Kart racing at Sunny Beach's modern circuit. Suitable for adults and kids. A burst of adrenaline and a fair fight on the track." } },
  { id: 32, code: "EX-32", cat: "SEA", dur: "full", time: "09:00 / 10:00", price: 98, priceChild: 74, days: [0,1,2,3,4,5,6], seats: 12,
    tags: ["sea","party","relax","kids"], party: ["couple","friends","family"],
    title: { ru: "Яхтенный пикник", en: "Yacht Picnic", de: "Yacht-Picknick", pl: "Piknik na jachcie", he: "פיקניק ביאכטה", bg: "Яхтен пикник", cs: "Jachtový piknik" },
    place: { ru: "Яхта · открытое море", en: "Yacht · open sea", de: "Yacht · offenes Meer", pl: "Jacht · otwarte morze", he: "יאכטה · ים פתוח", bg: "Яхта · открито море", cs: "Jachta · otevřené moře" },
    pitch: { ru: "Морская прогулка на яхте с обедом: пиво, белое и красное вино, безалкогольные напитки включены. Купание в открытом море. Ежедневно в 09:00 или 10:00.", en: "Yacht cruise with lunch on board: beer, white and red wine, soft drinks included. Swimming in the open sea. Daily at 09:00 or 10:00." } },
  { id: 33, code: "EX-33", cat: "SEA", dur: "full", time: "09:00", price: 117, priceChild: 88, days: [0,1,2,3,4,5,6], seats: 10,
    tags: ["sea","active","relax"], party: ["friends","couple","solo"],
    title: { ru: "Яхта + рыбалка", en: "Yacht + Fishing", de: "Yacht + Angeln", pl: "Jacht + wędkarstwo", he: "יאכטה + דיג", bg: "Яхта + риболов", cs: "Jachta + rybolov" },
    place: { ru: "Яхта Glory · Gergana · море", en: "Yacht Glory · Gergana · open sea", de: "Yacht Glory · Gergana · Meer", pl: "Jacht Glory · Gergana · morze", he: "יאכטה גלורי · גרגנה · ים", bg: "Яхта Glory · Gergana · море", cs: "Jachta Glory · Gergana · moře" },
    pitch: { ru: "Яхтенный пикник с настоящей морской рыбалкой. Обед, пиво, вино включены. До 10 человек, 5 часов в море.", en: "Yacht picnic with real sea fishing. Lunch, beer and wine included. Up to 10 people, 5 hours at sea." } },
  { id: 34, code: "EX-34", cat: "SEA", dur: "half", time: "06:30", price: 88, priceChild: 59, days: [0,1,2,3,4,5,6], seats: 12,
    tags: ["sea","active","relax"], party: ["friends","solo","couple"],
    title: { ru: "Морская рыбалка", en: "Sea Fishing", de: "Meeresangeln", pl: "Rybołówstwo morskie", he: "דיג בים", bg: "Морски риболов", cs: "Mořský rybolov" },
    place: { ru: "Черноморское побережье · на рассвете", en: "Black Sea coast · at dawn", de: "Schwarzmeerküste · bei Sonnenaufgang", pl: "Wybrzeże Morza Czarnego · o świcie", he: "חוף הים השחור · בשחר", bg: "Черноморско крайбрежие · на разсъмване", cs: "Pobřeží Černého moře · za úsvitu" },
    pitch: { ru: "Раннее утро на рыбацком боте в открытом море. Снасти и наживка включены. Свежий рассветный воздух, тишина и шанс на крупный улов.", en: "Early morning on a fishing boat in the open sea. Tackle and bait included. Fresh dawn air, silence and a chance at a big catch." } },
  { id: 35, code: "EX-35", cat: "CRUISE", dur: "evening", time: "18:30", price: 76, priceChild: 55, days: [1,3,5], seats: 15,
    tags: ["sea","romance","relax"], party: ["couple","friends","family"],
    title: { ru: "Закатный круиз", en: "Sunset Cruise", de: "Sonnenuntergangs-Kreuzfahrt", pl: "Rejs o zachodzie słońca", he: "שיט שקיעה", bg: "Круиз при залез", cs: "Plavba při západu slunce" },
    place: { ru: "Яхта Blue Sky · открытое море", en: "Blue Sky yacht · open sea", de: "Yacht Blue Sky · offenes Meer", pl: "Jacht Blue Sky · otwarte morze", he: "יאכטה בלו סקיי · ים פתוח", bg: "Яхта Blue Sky · открито море", cs: "Jachta Blue Sky · otevřené moře" },
    pitch: { ru: "Романтический вечерний круиз на яхте Blue Sky: закат над Чёрным морем, прохладные напитки и морской бриз. По вторникам, четвергам и субботам в 18:30.", en: "A romantic evening cruise on the Blue Sky: Black Sea sunset, cool drinks and a sea breeze. Tue, Thu and Sat at 18:30." } },
  { id: 36, code: "EX-36", cat: "FAMILY", dur: "full", time: "10:00–18:00", price: 65, priceChild: 49, days: [0,1,2,3,4,5,6], seats: 30,
    tags: ["kids","active","family"], party: ["family","friends"],
    title: { ru: "Аквапарк Солнечный берег", en: "Aquapark Sunny Beach", de: "Aquapark Sonnenstrand", pl: "Aquapark Słoneczny Brzeg", he: "אקווה פארק סאני ביץ'", bg: "Аквапарк Слънчев бряг", cs: "Aquapark Slunečné pobřeží" },
    place: { ru: "Аквапарк · Солнечный берег", en: "Aquapark · Sunny Beach", de: "Aquapark · Sonnenstrand", pl: "Aquapark · Słoneczny Brzeg", he: "אקווה פארק · סאני ביץ'", bg: "Аквапарк · Слънчев бряг", cs: "Aquapark · Slunečné pobřeží" },
    pitch: { ru: "Аквапарк прямо на Солнечном берегу: горки, волновые бассейны и семейные зоны. Два сеанса: 10:00–18:00 и 15:00–18:00.", en: "Aquapark right on Sunny Beach: water slides, wave pools and family zones. Two sessions: 10:00–18:00 and 15:00–18:00." } },
  { id: 37, code: "EX-37", cat: "SEA", dur: "half", time: "по запросу", price: null, priceChild: null, requires_price_check: true, days: [0,1,2,3,4,5,6], seats: 4,
    tags: ["active","sea"], party: ["friends","couple","solo"],
    title: { ru: "Гидроцикл · Джетски", en: "Jet Ski", de: "Jet-Ski", pl: "Skuter wodny", he: "ג'ט סקי", bg: "Джет-ски", cs: "Vodní skútr" },
    place: { ru: "Пляж Солнечного берега", en: "Sunny Beach shore", de: "Strand Sonnenstrand", pl: "Plaża Słonecznego Brzegu", he: "חוף סאני ביץ'", bg: "Плаж Слънчев бряг", cs: "Pláž Slunečného pobřeží" },
    pitch: { ru: "Заряженное приключение на гидроцикле вдоль побережья. Скорость и мощь прямо у берега. Инструктаж и спасательный жилет включены.", en: "A charged jet-ski adventure along the shoreline. Speed and power right by the beach. Briefing and life jacket included." } },
  { id: 38, code: "EX-38", cat: "SEA", dur: "half", time: "по запросу", price: null, priceChild: null, requires_price_check: true, days: [0,1,2,3,4,5,6], seats: 4,
    tags: ["active","sea"], party: ["friends","couple","solo"],
    title: { ru: "Парасейлинг", en: "Parasailing", de: "Parasailing", pl: "Parasailing", he: "פאראסיילינג", bg: "Парасейлинг", cs: "Parasailing" },
    place: { ru: "Солнечный берег · в воздухе", en: "Sunny Beach · in the air", de: "Sonnenstrand · in der Luft", pl: "Słoneczny Brzeg · w powietrzu", he: "סאני ביץ' · באוויר", bg: "Слънчев бряг · във въздуха", cs: "Slunečné pobřeží · ve vzduchu" },
    pitch: { ru: "Полёт над Чёрным морем на парашюте за катером: панорамный вид с высоты птичьего полёта. Мягкий старт с берега и мягкая посадка.", en: "A flight over the Black Sea on a parachute towed by a speedboat: bird's-eye panorama of the coast. Gentle beach take-off and soft landing." } },
];
// normalize: ensure every multilang field has all 5 langs (fallback en)
VEXC.forEach((e) => { ["title","place","pitch"].forEach((f) => { const o = e[f]; ["de","pl","he","bg","cs"].forEach((lg) => { if (!o[lg]) o[lg] = o.en; }); }); });

// default relevant photos (user can drag-drop to override; clearing reveals these again)
const U = (id) => `https://images.unsplash.com/photo-${id}?auto=format&fit=crop&w=800&q=75`;
const EXC_IMG = {
  1: U("1533473359331-0135ef1b58bf"), // jeep / off-road SUV
  2: U("1605281317010-fe5ffe798166"), // boat on open sea
  3: U("1475483768296-6163e08872a1"), // bonfire at night
  4: U("1600334129128-685c5582fd35"), // spa / hot stones
  5: U("1601581875309-fafbf2d3ed3a"), // seaside old town
  6: U("1533154683836-84ea7a0bc310"), // castle
  7: U("1530549387789-4c1017266635"), // pool / swimming
  8: U("1541432901042-2d8bd64b4a9b"), // Istanbul · Blue Mosque
  9: U("1524231757912-21f4fe3a7200"), // Istanbul cityscape
  10: U("1558642084-fd07fae5282e"), // hilltop castle (Tsarevets)
  11: U("1607153333879-c174d265f1d2"), // dolphins
  12: U("1481437156560-3205f6a55735"), // shopping arcade
  13: U("1505228395891-9a51e7e86bf6"), // river / coast nature
  14: U("1601581875309-fafbf2d3ed3a"), // old seaside town (Nessebar)
  15: U("1507525428034-b723cf961d3e"), // sea cliffs / coast
  16: U("1547234935-80c7145ec969"), // rock formations (stone forest)
  17: U("1467269204594-9661b134dd2b"), // old town (Plovdiv)
  18: U("1533154683836-84ea7a0bc310"), // stone monastery / cliff
  19: U("1551632811-561732d1e306"), // mountains (Rila)
  20: U("1500382017468-9049fed747ef"), // rural village (Zheravna)
  21: U("1567899378494-47b22a2ae96a"), // luxury yacht / catamaran
  22: U("1503095396549-807759245b35"), // cabaret stage / show
  23: U("1605281317010-fe5ffe798166"), // pirate boat on sea
  24: U("1475483768296-6163e08872a1"), // folk evening / bonfire
  25: U("1607153333879-c174d265f1d2"), // dolphins
  26: U("1559825481124-4a57d2e86b7a"), // diving / underwater
  27: U("1469854523086-cc702fe5d3e3"), // mega jeep off-road
  28: U("1551698317060-96a23bb58f0a"), // horse riding
  29: U("1544161515430-4be31277aec5"), // turkish bath / spa
  30: U("1558618666012-fcd25c85cd64"), // quad bikes
  31: U("1555361658374-74eca0e5ccd8"), // karting
  32: U("1520250497591-112f2f40a3f4"), // yacht picnic
  33: U("1544552284502-5de30fba8dd7"), // yacht + fishing
  34: U("1502680390441-8ea0b098d76f"), // sea fishing
  35: U("1504280390367-361c6d9f38f4"), // sunset cruise
  36: U("1523906834012-a69e1e9be9aa"), // aquapark sunny beach
  37: U("1564767615061-66cff6f3d098"), // jet ski
  38: U("1506905925346-21bda4d32df4"), // parasailing
};
VEXC.forEach((e) => { e.img = EXC_IMG[e.id]; });

// ── CARS ─────────────────────────────────────────────────────────────────
const VCARS = [
  { id: 1, code: "CAR-A", name: "Renault Clio", cls: "ECONOMY", seats: 5, trans: "MT", ac: true, fuel: "Petrol", price: 35 },
  { id: 2, code: "CAR-B", name: "VW Golf", cls: "COMPACT", seats: 5, trans: "AT", ac: true, fuel: "Diesel", price: 45 },
  { id: 3, code: "CAR-C", name: "Dacia Duster", cls: "SUV", seats: 5, trans: "MT", ac: true, fuel: "Petrol", price: 55 },
  { id: 4, code: "CAR-D", name: "Toyota RAV4", cls: "SUV", seats: 5, trans: "AT", ac: true, fuel: "Hybrid", price: 75 },
  { id: 5, code: "CAR-E", name: "Mercedes E-Class", cls: "PREMIUM", seats: 5, trans: "AT", ac: true, fuel: "Diesel", price: 120 },
  { id: 6, code: "CAR-F", name: "VW Caravelle", cls: "MINIVAN", seats: 8, trans: "AT", ac: true, fuel: "Diesel", price: 95 },
];
const CAR_IMG = {
  1: U("1549317661-bd32c8ce0db2"), // small city car
  2: U("1471444928139-48c5bf5173f8"), // hatchback
  3: U("1519641471654-76ce0107ad1b"), // SUV outdoors
  4: U("1568605117036-5fe5e7bab0b7"), // SUV on road
  5: U("1618843479313-40f8afb4b4d8"), // premium sedan/coupe
  6: U("1527786356703-4b100091cd2c"), // van / camper
};
VCARS.forEach((c) => { c.img = CAR_IMG[c.id]; });

// ── SHOPS / OFFICES ──────────────────────────────────────────────────────
const VSHOPS = [
  { id: 1, code: "PT-01", area: "Sunny Beach", name: "Central Office · Hub", addr: "Sunny Beach blvd, by Hotel Kuban", hours: "09:00 – 21:00", phone: "+359 88 100 0001", q: "Sunny Beach Kuban Hotel" },
  { id: 2, code: "PT-02", area: "Sunny Beach", name: "North · Cacao Beach", addr: "Promenade, opposite Cacao Beach", hours: "09:00 – 22:00", phone: "+359 88 100 0002", q: "Cacao Beach Sunny Beach" },
  { id: 3, code: "PT-03", area: "Nessebar", name: "Old Town", addr: "Mesambria st, by the bus station", hours: "09:00 – 20:00", phone: "+359 88 100 0003", q: "Nessebar bus station old town" },
  { id: 4, code: "PT-04", area: "Sveti Vlas", name: "Marina Dinevi", addr: "Marina Dinevi, pier B", hours: "10:00 – 20:00", phone: "+359 88 100 0004", q: "Marina Dinevi Sveti Vlas" },
  { id: 5, code: "PT-05", area: "Burgas", name: "Sea Station", addr: "Morska Gara, Knyaz Al. Batenberg st", hours: "09:00 – 19:00", phone: "+359 88 100 0005", q: "Burgas Sea Station" },
];

// ── AI FINDER MODEL ──────────────────────────────────────────────────────
const FINDER_Q = [
  { id: "party", q: { ru: "С кем едешь?", en: "Who's coming?", de: "Wer kommt mit?", pl: "Z kim jedziesz?", he: "עם מי אתם?", cs: "S kým cestujete?", bg: "С кого пътувате?" },
    opts: [
      { v: "family", l: { ru: "Семья с детьми", en: "Family w/ kids", de: "Familie mit Kindern", pl: "Rodzina z dziećmi", he: "משפחה עם ילדים", cs: "Rodina s dětmi", bg: "Семейство с деца" } },
      { v: "couple", l: { ru: "Вдвоём", en: "A couple", de: "Zu zweit", pl: "We dwoje", he: "זוג", cs: "Pár", bg: "Двойка" } },
      { v: "friends", l: { ru: "Компания друзей", en: "Friends", de: "Freunde", pl: "Znajomi", he: "חברים", cs: "Parta přátel", bg: "Компания приятели" } },
      { v: "solo", l: { ru: "Один / одна", en: "Solo", de: "Allein", pl: "Solo", he: "לבד", cs: "Sám/sama", bg: "Сам/сама" } },
    ] },
  { id: "vibe", q: { ru: "Какой настрой?", en: "What's the vibe?", de: "Welche Stimmung?", pl: "Jaki klimat?", he: "איזו אווירה?", cs: "Jaká nálada?", bg: "Какво настроение?" },
    opts: [
      { v: "active", l: { ru: "Адреналин и движ", en: "Adrenaline", de: "Adrenalin", pl: "Adrenalina", he: "אדרנלין", cs: "Adrenalin", bg: "Адреналин" } },
      { v: "culture", l: { ru: "История и культура", en: "Culture", de: "Kultur", pl: "Kultura", he: "תרבות", cs: "Kultura", bg: "Култура" } },
      { v: "relax", l: { ru: "Релакс и спа", en: "Relax", de: "Entspannung", pl: "Relaks", he: "רגיעה", cs: "Relax", bg: "Релакс" } },
      { v: "sea", l: { ru: "Море и пляж", en: "Sea & beach", de: "Meer & Strand", pl: "Morze i plaża", he: "ים וחוף", cs: "Moře a pláž", bg: "Море и плаж" } },
    ] },
  { id: "budget", q: { ru: "Бюджет на человека?", en: "Budget per person?", de: "Budget pro Person?", pl: "Budżet na osobę?", he: "תקציב לאדם?", cs: "Rozpočet na osobu?", bg: "Бюджет на човек?" },
    opts: [
      { v: "lo", l: { ru: "≤ €26", en: "≤ €26", de: "≤ €26", pl: "≤ €26", he: "≤ €26", cs: "≤ €26", bg: "≤ €26" } },
      { v: "mid", l: { ru: "€26–41", en: "€26–41", de: "€26–41", pl: "€26–41", he: "€26–41", cs: "€26–41", bg: "€26–41" } },
      { v: "hi", l: { ru: "€41+", en: "€41+", de: "€41+", pl: "€41+", he: "€41+", cs: "€41+", bg: "€41+" } },
    ] },
  { id: "dur", q: { ru: "Сколько времени?", en: "How long?", de: "Wie lange?", pl: "Ile czasu?", he: "כמה זמן?", cs: "Kolik času?", bg: "Колко време?" },
    opts: [
      { v: "half", l: { ru: "Полдня", en: "Half-day", de: "Halbtags", pl: "Pół dnia", he: "חצי יום", cs: "Půl dne", bg: "Половин ден" } },
      { v: "full", l: { ru: "Целый день", en: "Full day", de: "Ganztags", pl: "Cały dzień", he: "יום שלם", cs: "Celý den", bg: "Цял ден" } },
      { v: "multi", l: { ru: "С ночёвкой", en: "Multi-day", de: "Mehrtägig", pl: "Z noclegiem", he: "עם לינה", cs: "S noclehem", bg: "С нощувка" } },
    ] },
  { id: "party_ok", q: { ru: "Напитки и веселье?", en: "Drinks & party?", de: "Drinks & Party?", pl: "Drinki i zabawa?", he: "משקאות ובילוי?", cs: "Nápoje a zábava?", bg: "Напитки и веселба?" },
    opts: [
      { v: "yes", l: { ru: "Да, конечно", en: "Yes please", de: "Ja, gern", pl: "Tak", he: "כן", cs: "Ano, jistě", bg: "Да, разбира се" } },
      { v: "no", l: { ru: "Лучше спокойно", en: "Keep it calm", de: "Lieber ruhig", pl: "Spokojnie", he: "רגוע יותר", cs: "Raději v klidu", bg: "По-спокойно" } },
    ] },
  { id: "kids_ok", q: { ru: "Едут дети?", en: "Any children?", de: "Kinder dabei?", pl: "Czy będą dzieci?", he: "ילדים מגיעים?", cs: "Jedou děti?", bg: "Идват ли деца?" },
    opts: [
      { v: "yes", l: { ru: "Да, с детьми", en: "Yes, with kids", de: "Ja, mit Kindern", pl: "Tak, z dziećmi", he: "כן, עם ילדים", cs: "Ano, s dětmi", bg: "Да, с деца" } },
      { v: "no", l: { ru: "Без детей", en: "No kids", de: "Ohne Kinder", pl: "Bez dzieci", he: "בלי ילדים", cs: "Bez dětí", bg: "Без деца" } },
    ] },
];

function scoreExcursions(ans) {
  return VEXC.map((e) => {
    let s = 0;
    if (ans.party && e.party.includes(ans.party)) s += 3;
    if (ans.vibe) {
      const map = { active: ["active","kids"], culture: ["culture","city"], relax: ["relax","nature"], sea: ["sea","romance","nature"] };
      (map[ans.vibe] || []).forEach((tag) => { if (e.tags.includes(tag)) s += 2; });
    }
    if (ans.budget) {
      const ok = ans.budget === "lo" ? e.price <= 50 : ans.budget === "mid" ? e.price > 50 && e.price <= 80 : e.price > 80;
      if (ok) s += 2; else s -= 1;
    }
    if (ans.dur) { if (e.dur === ans.dur) s += 3; else if (ans.dur === "full" && e.dur === "evening") s += 1; }
    if (ans.party_ok === "yes" && e.tags.includes("party")) s += 2;
    if (ans.party_ok === "no" && e.tags.includes("party")) s -= 2;
    if (ans.kids_ok === "yes" && e.tags.includes("kids")) s += 2;
    if (ans.kids_ok === "no" && e.tags.includes("kids")) s -= 1;
    return { e, s };
  }).sort((a, b) => b.s - a.s);
}

// ── LIVE WEATHER (Sunny Beach: 42.69, 27.71) ─────────────────────────────
function wmoToCond(code) {
  if (code == null) return "clear";
  if ([0, 1].includes(code)) return "clear";
  if ([2, 3, 45, 48].includes(code)) return "clouds";
  if (code >= 95) return "storm";
  if ((code >= 51 && code <= 67) || (code >= 80 && code <= 82)) return "rain";
  if (code >= 71 && code <= 86) return "snow";
  return "clouds";
}
const COND_LABEL = {
  clear:  { ru: "Ясно", en: "Clear", de: "Klar", pl: "Bezchmurnie", he: "בהיר", bg: "Ясно", cs: "Jasno" },
  clouds: { ru: "Облачно", en: "Cloudy", de: "Bewölkt", pl: "Pochmurno", he: "מעונן", bg: "Облачно", cs: "Zataženo" },
  rain:   { ru: "Дождь", en: "Rain", de: "Regen", pl: "Deszcz", he: "גשם", bg: "Дъжд", cs: "Déšť" },
  storm:  { ru: "Гроза", en: "Storm", de: "Gewitter", pl: "Burza", he: "סופה", bg: "Буря", cs: "Bouřka" },
  snow:   { ru: "Снег", en: "Snow", de: "Schnee", pl: "Śnieg", he: "שלג", bg: "Сняг", cs: "Sníh" },
};
function useSunnyWeather() {
  const [w, setW] = uS({ loading: true, cond: "clear", temp: null, wind: null, error: false });
  // demo override: ?weather=rain|storm|clouds|snow|clear in URL, or localStorage dt_demo_weather
  const demo = (() => {
    try {
      const q = new URLSearchParams(location.search).get("weather");
      const h = (location.hash.match(/weather=(\w+)/) || [])[1];
      return q || h || localStorage.getItem("dt_demo_weather") || "";
    } catch (e) { return ""; }
  })();
  uE(() => {
    if (demo && ["clear", "clouds", "rain", "storm", "snow"].includes(demo)) {
      const t = { clear: 27, clouds: 22, rain: 18, storm: 17, snow: 1 }[demo];
      setW({ loading: false, cond: demo, temp: t, wind: 14, error: false, demo: true });
      return;
    }
    let alive = true;
    const url = "https://api.open-meteo.com/v1/forecast?latitude=42.6917&longitude=27.7142&current=temperature_2m,weather_code,wind_speed_10m&timezone=Europe%2FSofia";
    fetch(url).then((r) => r.json()).then((d) => {
      if (!alive) return;
      const c = d && d.current;
      if (!c) throw new Error("no data");
      setW({ loading: false, cond: wmoToCond(c.weather_code), temp: Math.round(c.temperature_2m),
        wind: Math.round(c.wind_speed_10m), code: c.weather_code, error: false });
    }).catch(() => { if (alive) setW({ loading: false, cond: "clear", temp: 24, wind: 12, error: true }); });
    return () => { alive = false; };
  }, []);
  return w;
}

// ── PRIMITIVES ───────────────────────────────────────────────────────────
function Brackets({ color = VK.line, size = 26, inset = 0, sw = 1.5 }) {
  const c = (pos) => {
    const base = { position: "absolute", width: size, height: size, pointerEvents: "none" };
    const b = `${sw}px solid ${color}`;
    if (pos === "tl") return { ...base, top: inset, left: inset, borderTop: b, borderLeft: b };
    if (pos === "tr") return { ...base, top: inset, right: inset, borderTop: b, borderRight: b };
    if (pos === "bl") return { ...base, bottom: inset, left: inset, borderBottom: b, borderLeft: b };
    return { ...base, bottom: inset, right: inset, borderBottom: b, borderRight: b };
  };
  return <>{["tl","tr","bl","br"].map((p) => <span key={p} style={c(p)} />)}</>;
}

function MonoTag({ children, accent = false, solid = false, style }) {
  const mk = accent || solid ? (solid ? VK.void : VK.coral) : VK.faint;
  return (
    <span style={{
      display: "inline-flex", alignItems: "center", gap: 9, padding: "7px 12px", whiteSpace: "nowrap",
      border: `1px solid ${accent ? VK.coral : VK.line}`,
      background: solid ? VK.coral : "transparent",
      fontFamily: VK.MONO, fontSize: 11, letterSpacing: "0.14em", textTransform: "uppercase",
      color: solid ? VK.void : (accent ? VK.coral : VK.sub), ...style,
    }}>
      <svg width="11" height="11" viewBox="0 0 12 12" style={{ flexShrink: 0 }}>
        <rect x="1" y="1" width="10" height="10" fill="none" stroke={mk} strokeWidth="1.2" />
        <path d="M2 2 L10 10 M10 2 L2 10" stroke={mk} strokeWidth="1.2" />
      </svg>
      {children}
    </span>
  );
}

const ANGULAR_CLIP = "polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px)";
function Angular({ children, onClick, variant = "solid", size = "md", style }) {
  const pad = size === "lg" ? "16px 30px" : size === "sm" ? "9px 16px" : "12px 22px";
  const map = {
    solid:   { background: VK.ink, color: VK.void, border: "none" },
    coral:   { background: VK.coral, color: "#0A0A0B", border: "none" },
    ghost:   { background: "transparent", color: VK.ink, border: `1px solid ${VK.line}` },
  };
  return (
    <button onClick={onClick} style={{
      clipPath: ANGULAR_CLIP, padding: pad, cursor: "pointer",
      fontFamily: VK.HEAD, fontWeight: 700, fontSize: size === "lg" ? 15 : 13.5,
      letterSpacing: "0.02em", display: "inline-flex", alignItems: "center", gap: 10,
      transition: "transform .15s, filter .15s", ...map[variant], ...style,
    }}
      onMouseEnter={(ev) => { ev.currentTarget.style.filter = "brightness(1.08)"; ev.currentTarget.style.transform = "translateY(-1px)"; }}
      onMouseLeave={(ev) => { ev.currentTarget.style.filter = "none"; ev.currentTarget.style.transform = "none"; }}>
      {variant !== "ghost" && <span style={{ width: 7, height: 7, background: variant === "solid" ? VK.coral : "#0A0A0B", flexShrink: 0 }} />}
      {children}
    </button>
  );
}

function ArrowBullet({ color = VK.coral, size = 16 }) {
  return <svg width={size} height={size} viewBox="0 0 16 16" fill="none" style={{ flexShrink: 0 }}>
    <path d="M4 4 L12 12 M12 12 V5 M12 12 H5" stroke={color} strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
  </svg>;
}

function Wordmark({ size = 26, onClick }) {
  return (
    <div onClick={onClick} style={{ display: "flex", alignItems: "baseline", gap: "0.48em", direction: "ltr", cursor: onClick ? "pointer" : "default", userSelect: "none", whiteSpace: "nowrap" }}>
      <span style={{ fontFamily: VK.WORD, fontWeight: 700, fontSize: size, letterSpacing: "0.08em", color: VK.ink, lineHeight: 1 }}>DREAM</span>
      <span style={{ fontFamily: VK.WORD, fontWeight: 600, fontSize: size, letterSpacing: "0.08em", color: VK.sub, lineHeight: 1 }}>TEAM</span>
      <span style={{ width: 6, height: 6, background: VK.coral, transform: "translateY(-2px)", marginLeft: "0.1em", flexShrink: 0 }} />
    </div>
  );
}

Object.assign(window, {
  VK, THEMES, applyTheme, LANGS, RTL_LANGS, TX, t, VEXC, VCARS, VSHOPS, FINDER_Q, scoreExcursions,
  useSunnyWeather, COND_LABEL, Brackets, MonoTag, Angular, ANGULAR_CLIP,
  ArrowBullet, Wordmark, uS, uE, uM, uR, uC, DOW, dayNames, toEur, EURBGN, TG, sendLeadToTelegram,
});
