'use strict';
// Lichte meertaligheid (NL/EN/DE) zonder dependencies.
// Gebruik in HTML:  <span data-i18n="key"></span>  of  data-i18n-ph (placeholder), data-i18n-title.
// In JS:  window.t('key')  en  window.setLang('en').
(function () {
  const DICT = {
    nl: {
      lang_name: 'Nederlands',
      tab_drive: '🎚 Rijden', tab_track: '🗺 Baan', tab_schema: '✏️ Schema',
      rails: '⏻ Rails', estop: '⛔ NOODSTOP',
      connecting: 'verbinden…', offline: 'offline', sim_live: 'simulator · live',
      connected_live: 'verbonden · live', waiting_central: 'wacht op centrale',
      locos: 'Locomotieven', forward: 'Vooruit ▶', reverse: '◀ Achteruit', stop: 'STOP',
      turnouts: 'Wissels', occupancy: 'Bezetmelding (blokken)',
      block_free: 'vrij', block_busy: 'BEZET', straight: 'RECHTDOOR', diverging: 'AFBUIGEND',
      schema_view: '👁 Bekijken', schema_edit: '✏️ Bewerken', schema_save: '💾 Opslaan',
      saved: '✓ Opgeslagen', save_failed: '✗ Mislukt',
      hold: '(hou vast)', log: 'Logboek (DCC-verkeer)',
      lic_free: '🔓 Gratis', lic_pro: '🔑 Pro', lic_locked: '🔒 Vergrendeld',
      lic_title: 'Licentie', lic_intro: 'Heb je een licentiesleutel? Plak \'m hieronder. Activatie werkt volledig offline.',
      lic_ph: 'Plak je licentiesleutel…', lic_close: 'Sluiten', lic_activate: 'Activeren',
      lic_getkey: 'Nog geen sleutel? Maak gratis een account → 30 dagen proef',
      lic_locked_banner: '🔒 Besturen is vergrendeld — een geldige licentie is vereist.',
      lic_enter: 'Licentie invoeren',
      update_avail: '⬆️ Nieuwe versie {latest} beschikbaar (je hebt {current})', download: 'Downloaden',
      baan_hint: 'In simulator-modus loopt er een "trein" door de blokken zodra je rijdt. Op je echte baan komt dit van de s88/LDT-terugmelding.',
      no_blocks: 'Geen blokken gedefinieerd.', address: 'adres',
      tab_manage: '⚙️ Beheer', routes: 'Rijwegen', mng_locos: 'Locomotieven', mng_turnouts: 'Wissels', mng_blocks: 'Blokken', mng_routes: 'Rijwegen', mng_add: '+ Toevoegen', mng_save: '💾 Alles opslaan', mng_del: 'Verwijderen', mng_name: 'Naam', mng_addr: 'Adres', mng_color: 'Kleur', mng_id: 'Nr', mng_sensor: 'Sensor', mng_funcs: 'Functies (komma: nr:label)', mng_photo: 'Foto-URL', mng_accel: 'Optrek', mng_decel: 'Afrem', mng_accel_hint: 'Optrekstappen per tik (1-28). Lager = trager/zwaarder optrekken.', mng_decel_hint: 'Afremstappen per tik (1-28). Lager = langer uitrollen.', route_set: 'Instellen', route_busy: 'bezet', route_free: 'vrij', route_reserved: 'gereserveerd', mng_route_turnouts: 'Wissels (nr:stand, bv 1:r,2:a)', mng_route_blocks: 'Blokken (nrs, bv 1,2)', saved: '✓ Opgeslagen', qr_connect: 'Telefoon koppelen', qr_title: 'Telefoon koppelen', qr_intro: 'Scan deze QR-code met je telefoon — of typ het adres in je browser. Telefoon en dit apparaat moeten op hetzelfde wifi-netwerk zitten.', qr_ios: 'richt de Camera-app op de code en tik op de melding. Open in Safari. Tik daarna op het deel-icoon → "Zet op beginscherm" voor een echte app.', qr_android: 'scan met de Camera of Google Lens en open de link in Chrome. Menu → "Toevoegen aan startscherm".', auto_runs: 'Automatisch rijden', learn_title: '🧭 Leer-modus — baan automatisch ontdekken', learn_intro: 'Tik op Start en rijd een loc rond. ModelRailPro herkent welke bezetmelders afgaan en bouwt daar automatisch blokken + rijwegen uit. Daarna: Toepassen.', learn_start: '▶ Start leren', learn_stop: '⏹ Stop leren', learn_apply: '✓ Toepassen', learn_clear: 'Wissen', learn_recording: 'aan het leren', learn_detected: 'Gedetecteerd', learn_steps: 'stappen', track_plan: 'Spoorplan (live)', check_updates: 'Controleer op updates', up_to_date: 'Je hebt de nieuwste versie', update_to: 'Bijwerken naar', upd_offline: 'Kon niet controleren (offline?)', no_runs: 'Nog geen ritten — maak er een in Beheer.', auto_running: 'rijdt', auto_step: 'stap', auto_start_lbl: 'Start', mng_runs: 'Ritten (automatisch)', mng_run_loco: 'Loc-adres', mng_run_loop: 'Herhalen', mng_consists: 'Tractie (loc\'s koppelen)', mng_consist_members: 'Leden (adres, bv 3,7r — r=omgekeerd)', conn_title: 'Verbinding (centrale)', conn_central: 'Centrale', conn_host: 'IP-adres centrale', conn_serial: 'Seriële poort (COM3 / /dev/ttyUSB0)', conn_save: '💾 Verbinding opslaan', conn_saved_restart: 'Opgeslagen — herstart ModelRailPro om te verbinden', conn_active: 'Nu actief', relay_prompt: 'Koppelcode (zie het agentje thuis):', conn_relay: 'Cloud-code', conn_relay_ph: 'Koppelcode voor van-overal bedienen (leeg=uit)', conn_relay_on: '☁️ Cloud aan — bedien van overal op', conn_relay_off: 'Leeg = alleen op je eigen netwerk. Vul een geheime code in voor van-overal bedienen.', conn_relay_gen: 'genereer', conn_relay_short: 'Code moet minstens 6 tekens zijn', conn_relay_live: 'Cloud aan — webversie kan nu verbinden', conn_saved: 'Opgeslagen', mng_run_steps: 'Stappen (route:snelheid:wacht, bv 1:55:3,2:55:3)',
      preset_choose: 'Preset…', preset_light: 'Alleen licht', preset_diesel: 'Diesel + geluid', preset_steam: 'Stoom + geluid', preset_electric: 'Elektrisch + geluid',
      fn_light: 'Licht', fn_sound: 'Geluid', fn_horn: 'Hoorn', fn_whistle: 'Fluit', fn_shunt: 'Rangeren', fn_bell: 'Bel', fn_smoke: 'Rook', fn_dynbrake: 'Dyn. rem', fn_announce: 'Omroep', fn_pantograph: 'Pantograaf',
      clock_title: '🕒 Dienstregeling (modelklok)', clock_intro: 'Een modelklok die sneller loopt dan de echte tijd. Ritten starten automatisch op hun tijd.', clk_next: 'Volgende', mng_tt: 'Dienstregeling', mng_tt_time: 'Tijd (uu:mm)', mng_tt_run: 'Rit-id', mng_clockfactor: 'Kloksnelheid (×)',
      mng_signals: 'Seinen', mng_sig_watch: 'Bewaakt blok', mng_sig_addr: 'Rood-adres (optie)', mng_sig_addr_hint: 'Accessory-adres voor de stop-lamp (rood).', mng_sig_addr2: 'Geel-adres', mng_sig_addr2_hint: 'Tweede accessory-adres voor de waarschuwing-lamp (geel).', mng_sig_next: 'Volgend blok', mng_sig_next_hint: 'Blok ná het bewaakte blok. Ingevuld = 3-begrippen ABS (groen/geel/rood); leeg = alleen rood/groen.', mng_sig_watch_hint: 'Blok dat dit sein dekt. Bezet = rood.', sig_sys_simple: 'Eenvoudig (2-beeld)', mng_tts: 'Draaischijven', mng_tt_addr: 'Basis-adres', mng_tt_pos: 'Aantal sporen',
      mng_webcam: 'Webcam-URL (snapshot/MJPEG)', mng_cv: 'Decoder / CV (PoM)', cv_addr: 'Loc-adres', cv_cv: 'CV-nr', cv_val: 'Waarde', cv_write: '✎ Schrijf (PoM)', cv_done: '✓ verstuurd',
      mng_maint: 'Onderhoud / draaiuren', maint_hours: 'u', maint_service: 'Service ✓', maint_none: 'Nog geen draaiuren.', signals_h: 'Seinen', tt_h: 'Draaischijf', cam_h: '📷 Camera',
      learn_autoschema: '📐 Auto-schema', measure_title: '📏 Snelheid meten', measure_intro: 'Rijd een loc tussen twee terugmelders met een bekende afstand; de echte snelheid (schaal-km/h) wordt berekend en bewaard per loc.', measure_from: 'van melder', measure_to: 'naar melder', measure_dist: 'afstand (cm)', measure_scale: 'schaal (bv. 87)', measure_step: 'stap', block_len: 'lengte',
      mng_shuttles: 'Pendeltreinen', mng_sh_from: 'van blok', mng_sh_to: 'naar blok', mng_sh_speed: 'snelheid', mng_sh_wait: 'wacht (s)', shuttles_h: 'Pendeltreinen', mng_staging: 'Schaduwstation / opstelsporen', mng_st_tracks: 'Sporen (blok-ids, komma)', staging_h: 'Schaduwstation', big_mode: 'Grote knoppen', sound_on: 'Geluid aan (aankondigingen + sfeer)', sound_off: 'Geluid uit', push_on: 'Meldingen aan — tik om af te melden', push_off: 'Meldingen aan zetten (anomalieën van je baan)', push_key_prompt: 'Je cloud-code (zelfde als op de thuis-baan):', push_key_short: 'Cloud-code van minstens 6 tekens nodig.', push_denied: 'Meldingen niet toegestaan in de browser.', push_subscribed: 'Aangemeld voor meldingen', push_unsubscribed: 'Meldingen uit', gamepad_connected: 'Handregelaar verbonden — stick = snelheid, A = stop, B = noodstop', gamepad_disconnected: 'Handregelaar losgekoppeld', anim_title: '🚂 Live-animatie & sessie-replay', anim_intro: 'Een live-weergave van je treinen over de blokken. Neem een sessie op en speel hem later terug.', anim_noblocks: 'Maak blokken aan om de animatie te zien.', anim_moving: 'rijdend', rec_start: '⏺ Opnemen', rec_stop: '⏺ Stop', rec_play: '▶ Replay', rec_none: 'Nog niets opgenomen.', club_you: 'Jij bent', role_host: 'host (volledige controle)', role_driver: 'machinist', role_guest: 'gast (kijken)', mng_club: 'Club / multi-operator', mng_integrations: 'Integraties (API · webhooks · Home Assistant · licht)', integ_api: 'Open API-sleutel (voor externe scripts/tools)', integ_apikey: 'API-sleutel (leeg = API uit)', integ_gen: 'genereer', integ_webhooks_hint: 'Webhook-URL\'s (één per regel) — krijgen een POST bij gebeurtenissen (blok in/uit, anomalie).', integ_anomaly: 'Anomaliedetectie + push', integ_anomaly_on: 'Aan', integ_stuck: 'Blok-bezet-grens (s)', integ_pushurl: 'Push-endpoint-URL (modelrailpro.com)', integ_pushkey: 'Push-sleutel', integ_ha: 'Home Assistant (MQTT)', integ_ha_on: 'Aan', integ_user: 'gebruiker (optie)', integ_pass: 'wachtwoord (optie)', integ_lights: 'Lichtscènes dag/nacht (WLED · Hue · Art-Net DMX)', integ_lights_hint: 'Apparaten als JSON, bv. [{"type":"wled","host":"192.168.0.50","day":{"bri":200},"night":{"bri":40}}]. Schakelt mee met de modelklok.', integ_day: 'Dag vanaf', integ_night: 'Nacht vanaf', integ_test_day: 'Test dag', integ_test_night: 'Test nacht', integ_save: '💾 Integraties opslaan', mng_library: 'Community-bibliotheek', lib_hint: 'Deel je baanplan of loc-profielen en haal die van anderen op.', lib_search: 'Zoeken…', lib_all: 'Alles', lib_roster: 'Baanplannen', lib_loco: 'Loc-profielen', lib_route: 'Rijwegen', lib_load: 'Laad lijst', lib_get: 'Haal op', lib_empty: 'Niets gevonden.', lib_offline: 'Bibliotheek niet bereikbaar.', lib_imported: 'Toegevoegd — vergeet niet op te slaan.', lib_pub_name: 'Naam van je inzending', lib_pub_author: 'Jouw naam (optie)', lib_pub_roster: 'Hele baanplan', lib_pub_loco: 'Eerste loc-profiel', lib_publish: 'Delen', lib_published: '✓ Gedeeld — bedankt!', lib_pub_needname: 'Geef een naam op.', lib_pub_noloco: 'Geen loc om te delen.', mng_export: 'Exporteren', export_hint: 'Download je baan als bestand of print een overzicht (→ Opslaan als PDF).', export_locos: 'Locs (CSV)', export_inventory: 'Inventaris (CSV)', export_config: 'Hele baan (JSON)', export_print: 'Baanoverzicht printen', export_layout: 'Baanoverzicht', export_type: 'Type', export_popup: 'Sta pop-ups toe om te kunnen printen.', club_enable: 'Club-modus aan (rollen + rechten)', club_hint: 'Alleen de host (deze computer) kan dit wijzigen. Machinist = mag toegewezen loc’s rijden; gast = alleen kijken. Noodstop mag altijd iedereen.', club_role: 'Rol', club_locos: 'Loc-adressen (komma)', club_none: 'Nog geen operators verbonden.', conn_reconnect: 'Opnieuw verbinden', mng_import: 'Importeer baanplan (Rocrail / JMRI)', mng_import_p: 'Upload een Rocrail plan.xml of JMRI roster.xml — locs, wissels en blokken worden overgenomen (daarna verfijn je ze hier).', mng_import_btn: 'Importeren', diag_connected: 'verbonden', diag_disconnected: 'niet verbonden', diag_lastrx: 'laatste ontvangst', diag_error: 'laatste fout',
      wiz_title: "Baan instellen", wiz_skip: "Overslaan", wiz_back: "Terug", wiz_next: "Volgende", wiz_finish: "Klaar", wiz_first: "Maak mijn eerste baan", wiz_first_p: "Nog geen baan? Zet met één tik een voorbeeldbaan in de simulator — meteen iets om mee te spelen.", wiz_first_done: "Voorbeeldbaan klaar! Ga naar Rijden en schuif de snelheid omhoog.", first_loco: "Mijn eerste loc", first_sw: "Wissel", first_station: "Station", first_track: "Spoor", wiz_reopen: "🧭 Setup-wizard", wiz_w1_h: "Welkom bij ModelRailPro", wiz_w1_p: "In een paar stappen rijd je. Kies eerst je taal.", wiz_w2_h: "Je centrale", wiz_w2_p: "Kies je centrale en vul het IP in — of klik op Zoeken om het netwerk af te zoeken.", wiz_scan: "Zoeken", wiz_scanning: "aan het zoeken…", wiz_scan_none: "Geen centrale gevonden — vul het IP handmatig in (of kies Simulator).", wiz_w3_h: "Rails aan", wiz_w3_p: "Zet de rijstroom aan, kies straks een loc en geef gas.", wiz_power: "Rails aan", wiz_w4_h: "Klaar!", wiz_w4_p: "Bedien je baan ook vanaf je telefoon — koppel via de QR-code.", wiz_phone: "Telefoon koppelen",
      help_connect: 'Hoe koppel ik de baan?', help_title: 'De baan koppelen', help_current: 'Huidige centrale', help_sim_on: 'simulator actief (geen baan nodig)', help_connected: 'verbonden ✓', help_notconn: 'nog niet verbonden',
      help_sim_1: 'Je draait nu de simulator — handig om alles te proberen zonder baan.', help_sim_2: 'Om je echte centrale te koppelen: open data/config.json en zet \'mode\' op je centrale (zie hieronder), sla op en herstart ModelRailPro.',
      help_net_1: 'Verbind je centrale met je netwerk (of wifi-router), zodat hij een IP-adres heeft.', help_net_2: 'Open data/config.json en zet \'mode\' op \'{mode}\'.', help_net_3: 'Vul bij \'host\' het IP-adres van je centrale in', help_net_4: 'Sla op en (her)start ModelRailPro.',
      help_ser_1: 'Sluit je centrale met de USB/seriële kabel aan op dit apparaat.', help_ser_2: 'Installeer eenmalig de seriële driver: open een terminal in de modelrailpro-map en typ: npm i serialport', help_ser_3: 'Open data/config.json, zet \'mode\' op \'{mode}\' en vul \'serialPort\' in (Windows: COM3 · Mac/Linux: /dev/ttyUSB0).', help_ser_4: 'Sla op en (her)start ModelRailPro.',
      help_check: 'Gelukt? Het bolletje rechtsboven wordt groen en gaat \'verbonden\' tonen. Zet de rails aan en kies een loc.', help_more: 'Volledige uitleg + per-centrale checklist:',
    },
    en: {
      lang_name: 'English',
      tab_drive: '🎚 Drive', tab_track: '🗺 Track', tab_schema: '✏️ Layout',
      rails: '⏻ Track', estop: '⛔ EMERGENCY STOP',
      connecting: 'connecting…', offline: 'offline', sim_live: 'simulator · live',
      connected_live: 'connected · live', waiting_central: 'waiting for command station',
      locos: 'Locomotives', forward: 'Forward ▶', reverse: '◀ Reverse', stop: 'STOP',
      turnouts: 'Turnouts', occupancy: 'Occupancy (blocks)',
      block_free: 'free', block_busy: 'OCCUPIED', straight: 'STRAIGHT', diverging: 'DIVERGING',
      schema_view: '👁 View', schema_edit: '✏️ Edit', schema_save: '💾 Save',
      saved: '✓ Saved', save_failed: '✗ Failed',
      hold: '(hold)', log: 'Log (DCC traffic)',
      lic_free: '🔓 Free', lic_pro: '🔑 Pro', lic_locked: '🔒 Locked',
      lic_title: 'License', lic_intro: 'Have a license key? Paste it below. Activation works fully offline.',
      lic_ph: 'Paste your license key…', lic_close: 'Close', lic_activate: 'Activate',
      lic_getkey: 'No key yet? Create a free account → 30-day trial',
      lic_locked_banner: '🔒 Control is locked — a valid license is required.',
      lic_enter: 'Enter license',
      update_avail: '⬆️ New version {latest} available (you have {current})', download: 'Download',
      baan_hint: 'In simulator mode a "train" runs through the blocks while you drive. On your real layout this comes from s88/LDT feedback.',
      no_blocks: 'No blocks defined.', address: 'address',
      tab_manage: '⚙️ Manage', routes: 'Routes', mng_locos: 'Locomotives', mng_turnouts: 'Turnouts', mng_blocks: 'Blocks', mng_routes: 'Routes', mng_add: '+ Add', mng_save: '💾 Save all', mng_del: 'Delete', mng_name: 'Name', mng_addr: 'Address', mng_color: 'Colour', mng_id: 'No.', mng_sensor: 'Sensor', mng_funcs: 'Functions (comma: no:label)', mng_photo: 'Photo URL', mng_accel: 'Accel', mng_decel: 'Brake', mng_accel_hint: 'Acceleration steps per tick (1-28). Lower = slower/heavier pull-away.', mng_decel_hint: 'Braking steps per tick (1-28). Lower = longer coasting.', route_set: 'Set', route_busy: 'busy', route_free: 'free', route_reserved: 'reserved', mng_route_turnouts: 'Turnouts (no:state, e.g. 1:s,2:d)', mng_route_blocks: 'Blocks (nos, e.g. 1,2)', saved: '✓ Saved', qr_connect: 'Connect phone', qr_title: 'Connect phone', qr_intro: 'Scan this QR code with your phone — or type the address in your browser. Phone and this device must be on the same Wi-Fi network.', qr_ios: 'point the Camera app at the code and tap the banner. Open in Safari. Then tap the share icon → "Add to Home Screen" for a real app.', qr_android: 'scan with the Camera or Google Lens and open the link in Chrome. Menu → "Add to Home screen".', auto_runs: 'Automatic running', learn_title: '🧭 Learn mode — auto-discover the layout', learn_intro: 'Tap Start and drive a loco around. ModelRailPro detects which occupancy sensors fire and builds blocks + routes automatically. Then: Apply.', learn_start: '▶ Start learning', learn_stop: '⏹ Stop learning', learn_apply: '✓ Apply', learn_clear: 'Clear', learn_recording: 'learning', learn_detected: 'Detected', learn_steps: 'steps', track_plan: 'Track plan (live)', check_updates: 'Check for updates', up_to_date: 'You have the latest version', update_to: 'Update to', upd_offline: 'Could not check (offline?)', no_runs: 'No runs yet — create one in Manage.', auto_running: 'running', auto_step: 'step', auto_start_lbl: 'Start', mng_runs: 'Runs (automatic)', mng_run_loco: 'Loco address', mng_run_loop: 'Loop', mng_consists: 'Consist (multi-unit)', mng_consist_members: 'Members (address, e.g. 3,7r — r=reversed)', conn_title: 'Connection (command station)', conn_central: 'Station', conn_host: 'Station IP address', conn_serial: 'Serial port (COM3 / /dev/ttyUSB0)', conn_save: '💾 Save connection', conn_saved_restart: 'Saved — restart ModelRailPro to connect', conn_active: 'Currently active', relay_prompt: 'Pairing code (from the agent at home):', conn_relay: 'Cloud code', conn_relay_ph: 'Pairing code for remote control (empty=off)', conn_relay_on: '☁️ Cloud on — control from anywhere at', conn_relay_off: 'Empty = local network only. Enter a secret code for remote control.', conn_relay_gen: 'generate', conn_relay_short: 'Code must be at least 6 characters', conn_relay_live: 'Cloud on — web version can now connect', conn_saved: 'Saved', mng_run_steps: 'Steps (route:speed:wait, e.g. 1:55:3,2:55:3)',
      preset_choose: 'Preset…', preset_light: 'Light only', preset_diesel: 'Diesel + sound', preset_steam: 'Steam + sound', preset_electric: 'Electric + sound',
      fn_light: 'Light', fn_sound: 'Sound', fn_horn: 'Horn', fn_whistle: 'Whistle', fn_shunt: 'Shunting', fn_bell: 'Bell', fn_smoke: 'Smoke', fn_dynbrake: 'Dyn. brake', fn_announce: 'Announcement', fn_pantograph: 'Pantograph',
      clock_title: '🕒 Timetable (fast clock)', clock_intro: 'A model clock that runs faster than real time. Runs start automatically at their time.', clk_next: 'Next', mng_tt: 'Timetable', mng_tt_time: 'Time (hh:mm)', mng_tt_run: 'Run id', mng_clockfactor: 'Clock speed (×)',
      mng_signals: 'Signals', mng_sig_watch: 'Watches block', mng_sig_addr: 'Red address (opt.)', mng_sig_addr_hint: 'Accessory address for the stop lamp (red).', mng_sig_addr2: 'Yellow address', mng_sig_addr2_hint: 'Second accessory address for the caution lamp (yellow).', mng_sig_next: 'Next block', mng_sig_next_hint: 'Block beyond the watched one. Filled = 3-aspect ABS (green/yellow/red); empty = red/green only.', mng_sig_watch_hint: 'Block this signal protects. Occupied = red.', sig_sys_simple: 'Simple (2-aspect)', mng_tts: 'Turntables', mng_tt_addr: 'Base address', mng_tt_pos: 'Tracks',
      mng_webcam: 'Webcam URL (snapshot/MJPEG)', mng_cv: 'Decoder / CV (PoM)', cv_addr: 'Loco address', cv_cv: 'CV no.', cv_val: 'Value', cv_write: '✎ Write (PoM)', cv_done: '✓ sent',
      mng_maint: 'Maintenance / run hours', maint_hours: 'h', maint_service: 'Serviced ✓', maint_none: 'No run hours yet.', signals_h: 'Signals', tt_h: 'Turntable', cam_h: '📷 Camera',
      learn_autoschema: '📐 Auto-plan', measure_title: '📏 Measure speed', measure_intro: 'Drive a loco between two feedback sensors a known distance apart; the real speed (scale km/h) is computed and stored per loco.', measure_from: 'from sensor', measure_to: 'to sensor', measure_dist: 'distance (cm)', measure_scale: 'scale (e.g. 87)', measure_step: 'step', block_len: 'length',
      mng_shuttles: 'Shuttles', mng_sh_from: 'from block', mng_sh_to: 'to block', mng_sh_speed: 'speed', mng_sh_wait: 'wait (s)', shuttles_h: 'Shuttle trains', mng_staging: 'Staging yard', mng_st_tracks: 'Tracks (block ids, comma)', staging_h: 'Staging yard', big_mode: 'Large buttons', sound_on: 'Sound on (announcements + ambience)', sound_off: 'Sound off', push_on: 'Notifications on — tap to unsubscribe', push_off: 'Enable notifications (anomalies from your layout)', push_key_prompt: 'Your cloud code (same as on the home layout):', push_key_short: 'Cloud code of at least 6 characters needed.', push_denied: 'Notifications not allowed in the browser.', push_subscribed: 'Subscribed to notifications', push_unsubscribed: 'Notifications off', gamepad_connected: 'Throttle connected — stick = speed, A = stop, B = emergency stop', gamepad_disconnected: 'Throttle disconnected', anim_title: '🚂 Live animation & session replay', anim_intro: 'A live view of your trains across the blocks. Record a session and play it back later.', anim_noblocks: 'Create blocks to see the animation.', anim_moving: 'moving', rec_start: '⏺ Record', rec_stop: '⏺ Stop', rec_play: '▶ Replay', rec_none: 'Nothing recorded yet.', club_you: 'You are', role_host: 'host (full control)', role_driver: 'driver', role_guest: 'guest (view)', mng_club: 'Club / multi-operator', mng_integrations: 'Integrations (API · webhooks · Home Assistant · light)', integ_api: 'Open API key (for external scripts/tools)', integ_apikey: 'API key (empty = API off)', integ_gen: 'generate', integ_webhooks_hint: 'Webhook URLs (one per line) — receive a POST on events (block enter/exit, anomaly).', integ_anomaly: 'Anomaly detection + push', integ_anomaly_on: 'On', integ_stuck: 'Block-busy limit (s)', integ_pushurl: 'Push endpoint URL (modelrailpro.com)', integ_pushkey: 'Push key', integ_ha: 'Home Assistant (MQTT)', integ_ha_on: 'On', integ_user: 'user (opt.)', integ_pass: 'password (opt.)', integ_lights: 'Day/night light scenes (WLED · Hue · Art-Net DMX)', integ_lights_hint: 'Devices as JSON, e.g. [{"type":"wled","host":"192.168.0.50","day":{"bri":200},"night":{"bri":40}}]. Follows the model clock.', integ_day: 'Day from', integ_night: 'Night from', integ_test_day: 'Test day', integ_test_night: 'Test night', integ_save: '💾 Save integrations', mng_library: 'Community library', lib_hint: 'Share your layout or loco profiles and grab others\'.', lib_search: 'Search…', lib_all: 'All', lib_roster: 'Layouts', lib_loco: 'Loco profiles', lib_route: 'Routes', lib_load: 'Load list', lib_get: 'Get', lib_empty: 'Nothing found.', lib_offline: 'Library unreachable.', lib_imported: 'Added — remember to save.', lib_pub_name: 'Name of your submission', lib_pub_author: 'Your name (opt.)', lib_pub_roster: 'Whole layout', lib_pub_loco: 'First loco profile', lib_publish: 'Share', lib_published: '✓ Shared — thanks!', lib_pub_needname: 'Please enter a name.', lib_pub_noloco: 'No loco to share.', mng_export: 'Export', export_hint: 'Download your layout as a file or print an overview (→ Save as PDF).', export_locos: 'Locos (CSV)', export_inventory: 'Inventory (CSV)', export_config: 'Whole layout (JSON)', export_print: 'Print layout overview', export_layout: 'Layout overview', export_type: 'Type', export_popup: 'Allow pop-ups to print.', club_enable: 'Club mode on (roles + rights)', club_hint: 'Only the host (this computer) can change this. Driver = may run assigned locos; guest = view only. Emergency stop is always allowed for everyone.', club_role: 'Role', club_locos: 'Loco addresses (comma)', club_none: 'No operators connected yet.', conn_reconnect: 'Reconnect', mng_import: 'Import layout (Rocrail / JMRI)', mng_import_p: 'Upload a Rocrail plan.xml or JMRI roster.xml — locos, turnouts and blocks are imported (refine them here afterwards).', mng_import_btn: 'Import', diag_connected: 'connected', diag_disconnected: 'not connected', diag_lastrx: 'last received', diag_error: 'last error',
      wiz_title: "Set up your layout", wiz_skip: "Skip", wiz_back: "Back", wiz_next: "Next", wiz_finish: "Done", wiz_first: "Create my first layout", wiz_first_p: "No layout yet? Set up an example layout in the simulator with one tap — something to play with right away.", wiz_first_done: "Example layout ready! Go to Drive and slide the speed up.", first_loco: "My first loco", first_sw: "Turnout", first_station: "Station", first_track: "Track", wiz_reopen: "🧭 Setup wizard", wiz_w1_h: "Welcome to ModelRailPro", wiz_w1_p: "A few steps and you are driving. First pick your language.", wiz_w2_h: "Your command station", wiz_w2_p: "Pick your command station and enter its IP — or click Scan to search the network.", wiz_scan: "Scan", wiz_scanning: "scanning…", wiz_scan_none: "No command station found — enter the IP manually (or pick Simulator).", wiz_w3_h: "Track power on", wiz_w3_p: "Turn on track power, then pick a loco and give it throttle.", wiz_power: "Track on", wiz_w4_h: "Done!", wiz_w4_p: "Control your layout from your phone too — pair it with the QR code.", wiz_phone: "Connect phone",
      help_connect: 'How do I connect the layout?', help_title: 'Connecting the layout', help_current: 'Current command station', help_sim_on: 'simulator active (no layout needed)', help_connected: 'connected ✓', help_notconn: 'not connected yet',
      help_sim_1: 'You are running the simulator — handy to try everything without a layout.', help_sim_2: 'To connect your real command station: open data/config.json, set \'mode\' to your station (see below), save and restart ModelRailPro.',
      help_net_1: 'Connect your command station to your network (or Wi-Fi router) so it has an IP address.', help_net_2: 'Open data/config.json and set \'mode\' to \'{mode}\'.', help_net_3: 'Set \'host\' to the IP address of your command station', help_net_4: 'Save and (re)start ModelRailPro.',
      help_ser_1: 'Connect your command station to this device with the USB/serial cable.', help_ser_2: 'Install the serial driver once: open a terminal in the modelrailpro folder and type: npm i serialport', help_ser_3: 'Open data/config.json, set \'mode\' to \'{mode}\' and fill in \'serialPort\' (Windows: COM3 · Mac/Linux: /dev/ttyUSB0).', help_ser_4: 'Save and (re)start ModelRailPro.',
      help_check: 'Done? The dot top-right turns green and shows \'connected\'. Turn on track power and pick a loco.', help_more: 'Full guide + per-station checklist:',
    },
    de: {
      lang_name: 'Deutsch',
      tab_drive: '🎚 Fahren', tab_track: '🗺 Anlage', tab_schema: '✏️ Gleisplan',
      rails: '⏻ Gleis', estop: '⛔ NOTHALT',
      connecting: 'verbinde…', offline: 'offline', sim_live: 'Simulator · live',
      connected_live: 'verbunden · live', waiting_central: 'warte auf Zentrale',
      locos: 'Lokomotiven', forward: 'Vorwärts ▶', reverse: '◀ Rückwärts', stop: 'STOPP',
      turnouts: 'Weichen', occupancy: 'Belegtmeldung (Blöcke)',
      block_free: 'frei', block_busy: 'BELEGT', straight: 'GERADE', diverging: 'ABZWEIG',
      schema_view: '👁 Ansehen', schema_edit: '✏️ Bearbeiten', schema_save: '💾 Speichern',
      saved: '✓ Gespeichert', save_failed: '✗ Fehlgeschlagen',
      hold: '(halten)', log: 'Protokoll (DCC-Verkehr)',
      lic_free: '🔓 Gratis', lic_pro: '🔑 Pro', lic_locked: '🔒 Gesperrt',
      lic_title: 'Lizenz', lic_intro: 'Haben Sie einen Lizenzschlüssel? Hier einfügen. Aktivierung funktioniert komplett offline.',
      lic_ph: 'Lizenzschlüssel einfügen…', lic_close: 'Schließen', lic_activate: 'Aktivieren',
      lic_getkey: 'Noch kein Schlüssel? Kostenloses Konto → 30 Tage Test',
      lic_locked_banner: '🔒 Steuerung gesperrt — eine gültige Lizenz ist erforderlich.',
      lic_enter: 'Lizenz eingeben',
      update_avail: '⬆️ Neue Version {latest} verfügbar (Sie haben {current})', download: 'Herunterladen',
      baan_hint: 'Im Simulator-Modus fährt ein "Zug" durch die Blöcke, sobald Sie fahren. Auf Ihrer echten Anlage kommt das von der s88/LDT-Rückmeldung.',
      no_blocks: 'Keine Blöcke definiert.', address: 'Adresse',
      tab_manage: '⚙️ Verwalten', routes: 'Fahrstraßen', mng_locos: 'Lokomotiven', mng_turnouts: 'Weichen', mng_blocks: 'Blöcke', mng_routes: 'Fahrstraßen', mng_add: '+ Hinzufügen', mng_save: '💾 Alles speichern', mng_del: 'Löschen', mng_name: 'Name', mng_addr: 'Adresse', mng_color: 'Farbe', mng_id: 'Nr', mng_sensor: 'Sensor', mng_funcs: 'Funktionen (Komma: nr:Label)', mng_photo: 'Foto-URL', mng_accel: 'Anfahr', mng_decel: 'Bremse', mng_accel_hint: 'Anfahrstufen pro Takt (1-28). Niedriger = langsameres/schwereres Anfahren.', mng_decel_hint: 'Bremsstufen pro Takt (1-28). Niedriger = längeres Ausrollen.', route_set: 'Stellen', route_busy: 'belegt', route_free: 'frei', route_reserved: 'reserviert', mng_route_turnouts: 'Weichen (nr:Stellung, z.B. 1:g,2:a)', mng_route_blocks: 'Blöcke (nrn, z.B. 1,2)', saved: '✓ Gespeichert', qr_connect: 'Telefon verbinden', qr_title: 'Telefon verbinden', qr_intro: 'Scannen Sie diesen QR-Code mit Ihrem Telefon — oder geben Sie die Adresse im Browser ein. Telefon und dieses Gerät müssen im selben WLAN sein.', qr_ios: 'richten Sie die Kamera-App auf den Code und tippen Sie auf die Einblendung. In Safari öffnen. Dann Teilen-Symbol → "Zum Home-Bildschirm" für eine echte App.', qr_android: 'mit der Kamera oder Google Lens scannen und in Chrome öffnen. Menü → "Zum Startbildschirm hinzufügen".', auto_runs: 'Automatikbetrieb', learn_title: '🧭 Lernmodus — Anlage automatisch erkennen', learn_intro: 'Auf Start tippen und eine Lok fahren. ModelRailPro erkennt, welche Belegtmelder auslösen, und baut daraus automatisch Blöcke + Fahrstraßen. Dann: Übernehmen.', learn_start: '▶ Lernen starten', learn_stop: '⏹ Lernen stoppen', learn_apply: '✓ Übernehmen', learn_clear: 'Löschen', learn_recording: 'lernt', learn_detected: 'Erkannt', learn_steps: 'Schritte', track_plan: 'Gleisplan (live)', check_updates: 'Nach Updates suchen', up_to_date: 'Sie haben die neueste Version', update_to: 'Aktualisieren auf', upd_offline: 'Prüfung fehlgeschlagen (offline?)', no_runs: 'Noch keine Fahrten — in Verwalten anlegen.', auto_running: 'fährt', auto_step: 'Schritt', auto_start_lbl: 'Start', mng_runs: 'Fahrten (automatisch)', mng_run_loco: 'Lok-Adresse', mng_run_loop: 'Wiederholen', mng_consists: 'Mehrfachtraktion', mng_consist_members: 'Mitglieder (Adresse, z.B. 3,7r — r=umgekehrt)', conn_title: 'Verbindung (Zentrale)', conn_central: 'Zentrale', conn_host: 'IP-Adresse Zentrale', conn_serial: 'Serieller Port (COM3 / /dev/ttyUSB0)', conn_save: '💾 Verbindung speichern', conn_saved_restart: 'Gespeichert — ModelRailPro neu starten zum Verbinden', conn_active: 'Aktuell aktiv', relay_prompt: 'Kopplungscode (vom Agent zu Hause):', conn_relay: 'Cloud-Code', conn_relay_ph: 'Kopplungscode für Fernsteuerung (leer=aus)', conn_relay_on: '☁️ Cloud an — von überall steuern auf', conn_relay_off: 'Leer = nur lokales Netzwerk. Code eingeben für Fernsteuerung.', conn_relay_gen: 'erzeugen', conn_relay_short: 'Code muss mindestens 6 Zeichen haben', conn_relay_live: 'Cloud an — Webversion kann jetzt verbinden', conn_saved: 'Gespeichert', mng_run_steps: 'Schritte (Route:Tempo:Warten, z.B. 1:55:3,2:55:3)',
      preset_choose: 'Vorlage…', preset_light: 'Nur Licht', preset_diesel: 'Diesel + Sound', preset_steam: 'Dampf + Sound', preset_electric: 'Elektro + Sound',
      fn_light: 'Licht', fn_sound: 'Sound', fn_horn: 'Horn', fn_whistle: 'Pfeife', fn_shunt: 'Rangieren', fn_bell: 'Glocke', fn_smoke: 'Rauch', fn_dynbrake: 'Dyn. Bremse', fn_announce: 'Ansage', fn_pantograph: 'Pantograph',
      clock_title: '🕒 Fahrplan (Modelluhr)', clock_intro: 'Eine Modelluhr, die schneller läuft als die Echtzeit. Fahrten starten automatisch zu ihrer Zeit.', clk_next: 'Nächste', mng_tt: 'Fahrplan', mng_tt_time: 'Zeit (hh:mm)', mng_tt_run: 'Fahrt-ID', mng_clockfactor: 'Uhr-Tempo (×)',
      mng_signals: 'Signale', mng_sig_watch: 'Überwachter Block', mng_sig_addr: 'Rot-Adresse (opt.)', mng_sig_addr_hint: 'Accessory-Adresse für die Halt-Lampe (rot).', mng_sig_addr2: 'Gelb-Adresse', mng_sig_addr2_hint: 'Zweite Accessory-Adresse für die Warnung-Lampe (gelb).', mng_sig_next: 'Nächster Block', mng_sig_next_hint: 'Block hinter dem überwachten. Gefüllt = 3-begriffiges ABS (grün/gelb/rot); leer = nur rot/grün.', mng_sig_watch_hint: 'Block, den dieses Signal deckt. Belegt = rot.', sig_sys_simple: 'Einfach (2-begriffig)', mng_tts: 'Drehscheiben', mng_tt_addr: 'Basis-Adresse', mng_tt_pos: 'Gleise',
      mng_webcam: 'Webcam-URL (Snapshot/MJPEG)', mng_cv: 'Decoder / CV (PoM)', cv_addr: 'Lok-Adresse', cv_cv: 'CV-Nr.', cv_val: 'Wert', cv_write: '✎ Schreiben (PoM)', cv_done: '✓ gesendet',
      mng_maint: 'Wartung / Betriebsstunden', maint_hours: 'h', maint_service: 'Gewartet ✓', maint_none: 'Noch keine Betriebsstunden.', signals_h: 'Signale', tt_h: 'Drehscheibe', cam_h: '📷 Kamera',
      learn_autoschema: '📐 Auto-Plan', measure_title: '📏 Geschwindigkeit messen', measure_intro: 'Fahren Sie eine Lok zwischen zwei Rückmeldern mit bekanntem Abstand; die echte Geschwindigkeit (Maßstab-km/h) wird berechnet und pro Lok gespeichert.', measure_from: 'von Melder', measure_to: 'zu Melder', measure_dist: 'Abstand (cm)', measure_scale: 'Maßstab (z. B. 87)', measure_step: 'Schritt', block_len: 'Länge',
      mng_shuttles: 'Pendelzüge', mng_sh_from: 'von Block', mng_sh_to: 'zu Block', mng_sh_speed: 'Tempo', mng_sh_wait: 'Warten (s)', shuttles_h: 'Pendelzüge', mng_staging: 'Schattenbahnhof', mng_st_tracks: 'Gleise (Block-IDs, Komma)', staging_h: 'Schattenbahnhof', big_mode: 'Große Tasten', sound_on: 'Ton an (Ansagen + Atmosphäre)', sound_off: 'Ton aus', push_on: 'Meldungen an — zum Abmelden tippen', push_off: 'Meldungen aktivieren (Anomalien deiner Anlage)', push_key_prompt: 'Dein Cloud-Code (gleich wie auf der Heim-Anlage):', push_key_short: 'Cloud-Code mit mindestens 6 Zeichen nötig.', push_denied: 'Meldungen im Browser nicht erlaubt.', push_subscribed: 'Für Meldungen angemeldet', push_unsubscribed: 'Meldungen aus', gamepad_connected: 'Handregler verbunden — Stick = Geschwindigkeit, A = Stopp, B = Nothalt', gamepad_disconnected: 'Handregler getrennt', anim_title: '🚂 Live-Animation & Sitzungs-Replay', anim_intro: 'Eine Live-Ansicht deiner Züge über die Blöcke. Nimm eine Sitzung auf und spiele sie später ab.', anim_noblocks: 'Blöcke anlegen, um die Animation zu sehen.', anim_moving: 'fahrend', rec_start: '⏺ Aufnehmen', rec_stop: '⏺ Stopp', rec_play: '▶ Replay', rec_none: 'Noch nichts aufgenommen.', club_you: 'Sie sind', role_host: 'Host (volle Kontrolle)', role_driver: 'Fahrer', role_guest: 'Gast (ansehen)', mng_club: 'Club / Multi-Operator', mng_integrations: 'Integrationen (API · Webhooks · Home Assistant · Licht)', integ_api: 'Offener API-Schlüssel (für externe Skripte/Tools)', integ_apikey: 'API-Schlüssel (leer = API aus)', integ_gen: 'erzeugen', integ_webhooks_hint: 'Webhook-URLs (eine pro Zeile) — erhalten ein POST bei Ereignissen (Block ein/aus, Anomalie).', integ_anomaly: 'Anomalieerkennung + Push', integ_anomaly_on: 'An', integ_stuck: 'Block-belegt-Grenze (s)', integ_pushurl: 'Push-Endpunkt-URL (modelrailpro.com)', integ_pushkey: 'Push-Schlüssel', integ_ha: 'Home Assistant (MQTT)', integ_ha_on: 'An', integ_user: 'Benutzer (opt.)', integ_pass: 'Passwort (opt.)', integ_lights: 'Tag/Nacht-Lichtszenen (WLED · Hue · Art-Net DMX)', integ_lights_hint: 'Geräte als JSON, z.B. [{"type":"wled","host":"192.168.0.50","day":{"bri":200},"night":{"bri":40}}]. Folgt der Modelluhr.', integ_day: 'Tag ab', integ_night: 'Nacht ab', integ_test_day: 'Tag testen', integ_test_night: 'Nacht testen', integ_save: '💾 Integrationen speichern', mng_library: 'Community-Bibliothek', lib_hint: 'Teile deinen Gleisplan oder Lok-Profile und hole dir die anderer.', lib_search: 'Suchen…', lib_all: 'Alles', lib_roster: 'Gleispläne', lib_loco: 'Lok-Profile', lib_route: 'Fahrstraßen', lib_load: 'Liste laden', lib_get: 'Holen', lib_empty: 'Nichts gefunden.', lib_offline: 'Bibliothek nicht erreichbar.', lib_imported: 'Hinzugefügt — nicht vergessen zu speichern.', lib_pub_name: 'Name deines Beitrags', lib_pub_author: 'Dein Name (opt.)', lib_pub_roster: 'Ganzer Gleisplan', lib_pub_loco: 'Erstes Lok-Profil', lib_publish: 'Teilen', lib_published: '✓ Geteilt — danke!', lib_pub_needname: 'Bitte einen Namen angeben.', lib_pub_noloco: 'Keine Lok zum Teilen.', mng_export: 'Exportieren', export_hint: 'Anlage als Datei herunterladen oder Übersicht drucken (→ Als PDF speichern).', export_locos: 'Loks (CSV)', export_inventory: 'Inventar (CSV)', export_config: 'Ganze Anlage (JSON)', export_print: 'Anlagenübersicht drucken', export_layout: 'Anlagenübersicht', export_type: 'Typ', export_popup: 'Pop-ups erlauben zum Drucken.', club_enable: 'Club-Modus an (Rollen + Rechte)', club_hint: 'Nur der Host (dieser Computer) kann das ändern. Fahrer = darf zugewiesene Loks fahren; Gast = nur ansehen. Nothalt ist immer für alle erlaubt.', club_role: 'Rolle', club_locos: 'Lok-Adressen (Komma)', club_none: 'Noch keine Operatoren verbunden.', conn_reconnect: 'Neu verbinden', mng_import: 'Gleisplan importieren (Rocrail / JMRI)', mng_import_p: 'Laden Sie eine Rocrail plan.xml oder JMRI roster.xml hoch — Loks, Weichen und Blöcke werden übernommen (danach hier verfeinern).', mng_import_btn: 'Importieren', diag_connected: 'verbunden', diag_disconnected: 'nicht verbunden', diag_lastrx: 'letzter Empfang', diag_error: 'letzter Fehler',
      wiz_title: "Anlage einrichten", wiz_skip: "Überspringen", wiz_back: "Zurück", wiz_next: "Weiter", wiz_finish: "Fertig", wiz_first: "Meine erste Anlage erstellen", wiz_first_p: "Noch keine Anlage? Mit einem Tipp eine Beispielanlage im Simulator anlegen — sofort etwas zum Ausprobieren.", wiz_first_done: "Beispielanlage fertig! Geh zu Fahren und schiebe die Geschwindigkeit hoch.", first_loco: "Meine erste Lok", first_sw: "Weiche", first_station: "Bahnhof", first_track: "Gleis", wiz_reopen: "🧭 Einrichtungsassistent", wiz_w1_h: "Willkommen bei ModelRailPro", wiz_w1_p: "In wenigen Schritten fahren Sie. Wählen Sie zuerst Ihre Sprache.", wiz_w2_h: "Ihre Zentrale", wiz_w2_p: "Wählen Sie Ihre Zentrale und geben Sie die IP ein — oder klicken Sie auf Suchen.", wiz_scan: "Suchen", wiz_scanning: "sucht…", wiz_scan_none: "Keine Zentrale gefunden — IP manuell eingeben (oder Simulator wählen).", wiz_w3_h: "Gleisspannung an", wiz_w3_p: "Schalten Sie die Gleisspannung ein, wählen Sie eine Lok und geben Sie Gas.", wiz_power: "Gleis an", wiz_w4_h: "Fertig!", wiz_w4_p: "Steuern Sie Ihre Anlage auch vom Handy — koppeln Sie es per QR-Code.", wiz_phone: "Telefon verbinden",
      help_connect: 'Wie verbinde ich die Anlage?', help_title: 'Anlage verbinden', help_current: 'Aktuelle Zentrale', help_sim_on: 'Simulator aktiv (keine Anlage nötig)', help_connected: 'verbunden ✓', help_notconn: 'noch nicht verbunden',
      help_sim_1: 'Sie nutzen den Simulator — ideal zum Ausprobieren ohne Anlage.', help_sim_2: 'Echte Zentrale verbinden: data/config.json öffnen, \'mode\' auf Ihre Zentrale setzen (siehe unten), speichern und ModelRailPro neu starten.',
      help_net_1: 'Verbinden Sie Ihre Zentrale mit dem Netzwerk (oder WLAN-Router), damit sie eine IP-Adresse hat.', help_net_2: 'data/config.json öffnen und \'mode\' auf \'{mode}\' setzen.', help_net_3: 'Bei \'host\' die IP-Adresse Ihrer Zentrale eintragen', help_net_4: 'Speichern und ModelRailPro (neu) starten.',
      help_ser_1: 'Verbinden Sie Ihre Zentrale per USB/seriellem Kabel mit diesem Gerät.', help_ser_2: 'Seriellen Treiber einmalig installieren: Terminal im modelrailpro-Ordner öffnen und eingeben: npm i serialport', help_ser_3: 'data/config.json öffnen, \'mode\' auf \'{mode}\' setzen und \'serialPort\' eintragen (Windows: COM3 · Mac/Linux: /dev/ttyUSB0).', help_ser_4: 'Speichern und ModelRailPro (neu) starten.',
      help_check: 'Geschafft? Der Punkt oben rechts wird grün und zeigt \'verbunden\'. Gleisspannung einschalten und Lok wählen.', help_more: 'Vollständige Anleitung + Checkliste je Zentrale:',
    },
  };

  function detect() {
    try {
      const saved = localStorage.getItem('bb-lang');
      if (saved && DICT[saved]) return saved;
    } catch (e) {}
    const n = (navigator.language || 'nl').slice(0, 2).toLowerCase();
    return DICT[n] ? n : 'nl';
  }

  let lang = detect();
  window.t = function (key, vars) {
    let s = (DICT[lang] && DICT[lang][key]) || (DICT.nl[key]) || key;
    if (vars) for (const k in vars) s = s.replace('{' + k + '}', vars[k]);
    return s;
  };
  window.getLang = () => lang;
  window.i18nLangs = () => Object.keys(DICT).map((k) => ({ code: k, name: DICT[k].lang_name }));

  window.applyI18n = function (root) {
    (root || document).querySelectorAll('[data-i18n]').forEach((el) => { el.textContent = window.t(el.getAttribute('data-i18n')); });
    (root || document).querySelectorAll('[data-i18n-ph]').forEach((el) => { el.placeholder = window.t(el.getAttribute('data-i18n-ph')); });
    (root || document).querySelectorAll('[data-i18n-title]').forEach((el) => { el.title = window.t(el.getAttribute('data-i18n-title')); });
    document.documentElement.lang = lang;
  };

  window.setLang = function (l) {
    if (!DICT[l]) return;
    lang = l;
    try { localStorage.setItem('bb-lang', l); } catch (e) {}
    window.applyI18n();
    document.dispatchEvent(new CustomEvent('langchange'));
  };
})();
