{"id":88,"date":"2026-09-14T21:50:54","date_gmt":"2026-09-14T19:50:54","guid":{"rendered":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/"},"modified":"2026-09-14T21:50:54","modified_gmt":"2026-09-14T19:50:54","slug":"rozklad-rejsow","status":"publish","type":"page","link":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/","title":{"rendered":"Rozk\u0142ad rejs\u00f3w Dunkierka Dover"},"content":{"rendered":"\n<div class=\"dd-hero dd-hero--page\"><img src=\"https:\/\/dover-dunkirk.com\/pl\/wp-content\/uploads\/sites\/5\/2026\/09\/delft-seaways-bow-loading-ramp.webp\" alt=\"Delft Seaways przy nabrze\u017cu w Loon-Plage z opuszczon\u0105 ramp\u0105\" width=\"1400\" height=\"1050\" fetchpriority=\"high\" decoding=\"async\"><\/div><div class=\"dd-wrap\">\n\t<div class=\"dd-page-head dd-page-head--card\">\n\t\t<h1>Rozk\u0142ad rejs\u00f3w Dunkierka Dover<\/h1>\n\t\t<p class=\"dd-lede\">DFDS p\u0142ywa co dwie godziny, dzie\u0144 i noc, w obu kierunkach. Poni\u017cej dzisiejsze rejsy, rozk\u0142ad na najbli\u017cszy tydzie\u0144 i godziny, o kt\u00f3rych zamyka si\u0119 odprawa. Godziny odjazd\u00f3w podano w czasie lokalnym portu wyj\u015bcia.<\/p>\n\t\t<div class=\"dd-meta\"><span class=\"dd-updated\"><svg class=\"dd-ic\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9\"\/><path d=\"M12 7v5l3 2\"\/><\/svg>Aktualizacja 14 September 2026<\/span><span class=\"dd-small dd-muted\">\u0179r\u00f3d\u0142o: rozk\u0142ad DFDS przez DirectFerries, od\u015bwie\u017cany co minut\u0119<\/span><\/div>\n\t<\/div>\n\n\t<div class=\"dd-page\">\n\t\t<div class=\"dd-main\">\n\t\t\t<section id=\"dzis\">\n\t\t\t\t<h2>Rejsy dzisiaj<\/h2>\n\t\t\t\t<p>Oba kierunki, z godzin\u0105 zamkni\u0119cia odprawy. Dunkierka i Dover le\u017c\u0105 w r\u00f3\u017cnych strefach czasowych; dlatego dwugodzinny rejs wygl\u0105da na bilecie na godzin\u0119 (do Anglii) albo na trzy godziny (do Francji).<\/p>\n\t\t\t\t<section class=\"dd-board dd-board--full\" aria-label=\"Rejsy dzisiaj\"><div class=\"dd-board__head\"><p class=\"dd-board__title\">Rejsy dzisiaj<\/p><span class=\"dd-board__live\"><i><\/i>Na \u017cywo <span class=\"dd-board__upd\">\u00b7 aktualizacja 11:15<\/span><\/span><\/div><div class=\"dd-board__clocks\"><div class=\"dd-board__clock\" data-tz=\"Europe\/Paris\"><span class=\"dd-board__port\">Dunkierka<\/span><span class=\"dd-board__time dd-num\" data-dd-clock>12:15<\/span><span class=\"dd-board__zone\" data-dd-zone>CEST<\/span><\/div><div class=\"dd-board__mid\">2 godz. rejsu<br>Francja +1 godz.<\/div><div class=\"dd-board__clock is-right\" data-tz=\"Europe\/London\"><span class=\"dd-board__port\">Dover<\/span><span class=\"dd-board__time dd-num\" data-dd-clock>11:15<\/span><span class=\"dd-board__zone\" data-dd-zone>BST<\/span><\/div><\/div><div class=\"dd-board__pane is-on\" id=\"dd-pane-99\" role=\"tabpanel\" aria-labelledby=\"dd-tab-99\"><h3 class=\"dd-board__pane-title\">Dunkierka \u2192 Dover<\/h3><table class=\"dd-board__table\"><thead><tr><th>Odjazd<\/th><th>Przyjazd<\/th><th>Odprawa do<\/th><th><\/th><\/tr><\/thead><tbody><tr><td class=\"dd-board__dep dd-num\">12:00<\/td><td class=\"dd-board__arr dd-num\">13:00<\/td><td class=\"dd-board__chk dd-num\">11:00<\/td><td class=\"dd-board__st\"><span class=\"dd-pill dd-pill--sailed\">Odp\u0142yn\u0105\u0142<\/span><\/td><\/tr><tr class=\"is-next\"><td class=\"dd-board__dep dd-num\">14:00<\/td><td class=\"dd-board__arr dd-num\">15:00<\/td><td class=\"dd-board__chk dd-num\">13:00<\/td><td class=\"dd-board__st\"><span class=\"dd-pill dd-pill--next\"><i><\/i>Nast\u0119pny<\/span><\/td><\/tr><tr><td class=\"dd-board__dep dd-num\">16:00<\/td><td class=\"dd-board__arr dd-num\">17:00<\/td><td class=\"dd-board__chk dd-num\">15:00<\/td><td class=\"dd-board__st\"><\/td><\/tr><tr><td class=\"dd-board__dep dd-num\">18:00<\/td><td class=\"dd-board__arr dd-num\">19:00<\/td><td class=\"dd-board__chk dd-num\">17:00<\/td><td class=\"dd-board__st\"><\/td><\/tr><tr><td class=\"dd-board__dep dd-num\">20:00<\/td><td class=\"dd-board__arr dd-num\">21:00<\/td><td class=\"dd-board__chk dd-num\">19:00<\/td><td class=\"dd-board__st\"><\/td><\/tr><tr><td class=\"dd-board__dep dd-num\">23:59<\/td><td class=\"dd-board__arr dd-num\">00:59<\/td><td class=\"dd-board__chk dd-num\">22:59<\/td><td class=\"dd-board__st\"><\/td><\/tr><\/tbody><\/table><\/div><div class=\"dd-board__pane\" id=\"dd-pane-100\" role=\"tabpanel\" aria-labelledby=\"dd-tab-100\"><h3 class=\"dd-board__pane-title\">Dover \u2192 Dunkierka<\/h3><table class=\"dd-board__table\"><thead><tr><th>Odjazd<\/th><th>Przyjazd<\/th><th>Odprawa do<\/th><th><\/th><\/tr><\/thead><tbody><tr><td class=\"dd-board__dep dd-num\">12:00<\/td><td class=\"dd-board__arr dd-num\">15:00<\/td><td class=\"dd-board__chk dd-num\">11:00<\/td><td class=\"dd-board__st\"><span class=\"dd-pill dd-pill--boarding\">Wej\u015bcie<\/span><\/td><\/tr><tr class=\"is-next\"><td class=\"dd-board__dep dd-num\">14:00<\/td><td class=\"dd-board__arr dd-num\">17:00<\/td><td class=\"dd-board__chk dd-num\">13:00<\/td><td class=\"dd-board__st\"><span class=\"dd-pill dd-pill--next\"><i><\/i>Nast\u0119pny<\/span><\/td><\/tr><tr><td class=\"dd-board__dep dd-num\">16:00<\/td><td class=\"dd-board__arr dd-num\">19:00<\/td><td class=\"dd-board__chk dd-num\">15:00<\/td><td class=\"dd-board__st\"><\/td><\/tr><tr><td class=\"dd-board__dep dd-num\">18:00<\/td><td class=\"dd-board__arr dd-num\">21:00<\/td><td class=\"dd-board__chk dd-num\">17:00<\/td><td class=\"dd-board__st\"><\/td><\/tr><tr><td class=\"dd-board__dep dd-num\">20:00<\/td><td class=\"dd-board__arr dd-num\">23:00<\/td><td class=\"dd-board__chk dd-num\">19:00<\/td><td class=\"dd-board__st\"><\/td><\/tr><tr><td class=\"dd-board__dep dd-num\">22:00<\/td><td class=\"dd-board__arr dd-num\">01:00<\/td><td class=\"dd-board__chk dd-num\">21:00<\/td><td class=\"dd-board__st\"><\/td><\/tr><\/tbody><\/table><\/div><div class=\"dd-board__foot\"><span>Odjazd w czasie lokalnym portu wyj\u015bcia, przyjazd w czasie lokalnym portu docelowego.<\/span><\/div><\/section>\n\t\t\t<\/section>\n\n\t\t\t<section id=\"tydzien\">\n\t\t\t\t<h2>Rozk\u0142ad na najbli\u017cszy tydzie\u0144: Dunkierka do Dover<\/h2>\n\t\t\t\t<p>Dla ka\u017cdego dnia liczba rejs\u00f3w i godziny odjazd\u00f3w w czasie francuskim, czyli takim samym jak w Polsce. W dni robocze zwykle dziesi\u0119\u0107 rejs\u00f3w, w weekend mniej; nocny rejs o 23:59 nie p\u0142ywa codziennie.<\/p>\n\t\t\t\t<div class=\"dd-panel dd-tw\"><table class=\"dd-table dd-week\"><thead><tr><th>Dzie\u0144<\/th><th>Rejsy<\/th><th>Godziny odjazdu, czas lokalny<\/th><\/tr><\/thead><tbody><tr class=\"is-today\"><th scope=\"row\">wt 15-9<\/th><td><span class=\"dd-week__n dd-num\">10<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">04:00<\/span><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><span class=\"dd-week__t dd-num\">23:59<\/span><\/td><\/tr><tr><th scope=\"row\">\u015br 16-9<\/th><td><span class=\"dd-week__n dd-num\">10<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">04:00<\/span><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><span class=\"dd-week__t dd-num\">23:59<\/span><\/td><\/tr><tr><th scope=\"row\">czw 17-9<\/th><td><span class=\"dd-week__n dd-num\">10<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">04:00<\/span><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><span class=\"dd-week__t dd-num\">23:59<\/span><\/td><\/tr><tr><th scope=\"row\">pt 18-9<\/th><td><span class=\"dd-week__n dd-num\">9<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">04:00<\/span><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><\/td><\/tr><tr><th scope=\"row\">sob 19-9<\/th><td><span class=\"dd-week__n dd-num\">8<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">04:00<\/span><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><\/td><\/tr><tr><th scope=\"row\">niedz 20-9<\/th><td><span class=\"dd-week__n dd-num\">7<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><\/td><\/tr><tr><th scope=\"row\">pon 21-9<\/th><td><span class=\"dd-week__n dd-num\">10<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">04:00<\/span><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><span class=\"dd-week__t dd-num\">23:59<\/span><\/td><\/tr><\/tbody><\/table><\/div>\n\t\t\t<\/section>\n\n\t\t\t<section id=\"tydzien-powrot\">\n\t\t\t\t<h2>Rozk\u0142ad na najbli\u017cszy tydzie\u0144: Dover do Dunkierki<\/h2>\n\t\t\t\t<p>Godziny odjazd\u00f3w w czasie angielskim. Dodaj godzin\u0119, \u017ceby uzyska\u0107 czas przyjazdu do Dunkierki.<\/p>\n\t\t\t\t<div class=\"dd-panel dd-tw\"><table class=\"dd-table dd-week\"><thead><tr><th>Dzie\u0144<\/th><th>Rejsy<\/th><th>Godziny odjazdu, czas lokalny<\/th><\/tr><\/thead><tbody><tr class=\"is-today\"><th scope=\"row\">wt 15-9<\/th><td><span class=\"dd-week__n dd-num\">10<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">02:00<\/span><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><span class=\"dd-week__t dd-num\">22:00<\/span><\/td><\/tr><tr><th scope=\"row\">\u015br 16-9<\/th><td><span class=\"dd-week__n dd-num\">10<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">02:00<\/span><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><span class=\"dd-week__t dd-num\">22:00<\/span><\/td><\/tr><tr><th scope=\"row\">czw 17-9<\/th><td><span class=\"dd-week__n dd-num\">10<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">02:00<\/span><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><span class=\"dd-week__t dd-num\">22:00<\/span><\/td><\/tr><tr><th scope=\"row\">pt 18-9<\/th><td><span class=\"dd-week__n dd-num\">10<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">02:00<\/span><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><span class=\"dd-week__t dd-num\">22:00<\/span><\/td><\/tr><tr><th scope=\"row\">sob 19-9<\/th><td><span class=\"dd-week__n dd-num\">8<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">22:00<\/span><\/td><\/tr><tr><th scope=\"row\">niedz 20-9<\/th><td><span class=\"dd-week__n dd-num\">7<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><span class=\"dd-week__t dd-num\">22:00<\/span><\/td><\/tr><tr><th scope=\"row\">pon 21-9<\/th><td><span class=\"dd-week__n dd-num\">9<\/span><\/td><td class=\"dd-week__times\"><span class=\"dd-week__t dd-num\">06:00<\/span><span class=\"dd-week__t dd-num\">08:00<\/span><span class=\"dd-week__t dd-num\">10:00<\/span><span class=\"dd-week__t dd-num\">12:00<\/span><span class=\"dd-week__t dd-num\">14:00<\/span><span class=\"dd-week__t dd-num\">16:00<\/span><span class=\"dd-week__t dd-num\">18:00<\/span><span class=\"dd-week__t dd-num\">20:00<\/span><span class=\"dd-week__t dd-num\">22:00<\/span><\/td><\/tr><\/tbody><\/table><\/div>\n\t\t\t<\/section>\n\n\t\t\t<section id=\"data\">\n\t\t\t\t<h2>Wybierz inn\u0105 dat\u0119<\/h2>\n\t\t\t\t<p>Wybierz dat\u0119 i liczb\u0119 dni; godziny pochodz\u0105 wprost z rozk\u0142adu. Cen\u0119 na ten dzie\u0144 znajdziesz w <a href=\"https:\/\/dover-dunkirk.com\/pl\/ceny-i-bilety\/\">cenach i biletach<\/a>.<\/p>\n\t\t\t\t<h3>Dunkierka do Dover<\/h3>\n\t\t\t\t<div class=\"tp-wrap tp-theme-extended_cards tp-day-setup-modern\" data-config=\"{&quot;rest&quot;:&quot;https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/wp-json\\\/timetables-pro\\\/v1\\\/timetables&quot;,&quot;routes&quot;:[99],&quot;days&quot;:1,&quot;autoload&quot;:true,&quot;theme&quot;:&quot;extended_cards&quot;,&quot;daySetup&quot;:&quot;modern&quot;,&quot;limit10&quot;:false,&quot;routeLabels&quot;:{&quot;99&quot;:&quot;Dunkierka-Dover&quot;},&quot;opFilter&quot;:[&quot;6&quot;],&quot;labels&quot;:{&quot;ui_date&quot;:&quot;Date&quot;,&quot;ui_days&quot;:&quot;Days&quot;,&quot;ui_button&quot;:&quot;Show sailings&quot;,&quot;status_idle&quot;:&quot;Pick a date and click Show sailings&quot;,&quot;status_loading&quot;:&quot;Retrieving schedule data...&quot;,&quot;status_empty&quot;:&quot;No sailings found&quot;,&quot;status_found&quot;:&quot;%d sailings found&quot;,&quot;th_date&quot;:&quot;Date&quot;,&quot;th_dep&quot;:&quot;Departure&quot;,&quot;th_arr&quot;:&quot;Arrival&quot;,&quot;th_dur&quot;:&quot;Duration&quot;,&quot;th_ship&quot;:&quot;Ship&quot;,&quot;th_op&quot;:&quot;Operator&quot;,&quot;th_route&quot;:&quot;Route&quot;,&quot;wd_sun&quot;:&quot;SUN&quot;,&quot;wd_mon&quot;:&quot;MON&quot;,&quot;wd_tue&quot;:&quot;TUE&quot;,&quot;wd_wed&quot;:&quot;WED&quot;,&quot;wd_thu&quot;:&quot;THU&quot;,&quot;wd_fri&quot;:&quot;FRI&quot;,&quot;wd_sat&quot;:&quot;SAT&quot;,&quot;summary_footer_one&quot;:&quot;\\u00bb Check all %s departures on our timetable&quot;,&quot;summary_footer_two&quot;:&quot;\\u00bb Check more %1$s and %2$s departures on our timetable&quot;,&quot;summary_footer_generic&quot;:&quot;Check our timetable for more sailings&quot;,&quot;summary_header&quot;:&quot;The next two departures:&quot;,&quot;summary_no_upcoming&quot;:&quot;No upcoming departures found&quot;,&quot;more_link&quot;:&quot;More sailings&quot;,&quot;more_departures_button&quot;:&quot;Show more departures&quot;,&quot;day_nav_previous&quot;:&quot;Show previous day&quot;,&quot;day_nav_next&quot;:&quot;Show next day&quot;,&quot;day_nav_today&quot;:&quot;Show today&quot;,&quot;day_nav_tomorrow&quot;:&quot;Show tomorrow&quot;,&quot;local_time_pair&quot;:&quot;Departure Port Local Time: %1$s \\\/ Arrival Port Local Time: %2$s&quot;,&quot;local_time_combined&quot;:&quot;Departure &amp; Arrival Port Local Time: %s&quot;,&quot;tag_often_booked&quot;:&quot;\\u2b50 Often booked&quot;,&quot;tag_leaving_soon&quot;:&quot;\\ud83d\\udd34 Leaving soon&quot;,&quot;tag_currently_sailing&quot;:&quot;\\ud83d\\udfe2 Currently sailing&quot;,&quot;tag_arrived&quot;:&quot;\\u26ab Arrived&quot;,&quot;tag_overnight&quot;:&quot;Overnight&quot;},&quot;showLogo&quot;:true,&quot;activityBoosters&quot;:true,&quot;title&quot;:&quot;&quot;,&quot;shipMap&quot;:[],&quot;shipLinks&quot;:[],&quot;showShip&quot;:false,&quot;departurePort&quot;:&quot;Dunkirk&quot;,&quot;arrivalPort&quot;:&quot;Dover&quot;,&quot;departureTimezone&quot;:&quot;Europe\\\/Paris&quot;,&quot;arrivalTimezone&quot;:&quot;Europe\\\/London&quot;}\">\n  <div class=\"tp-controls\" role=\"group\" aria-label=\"Timetable controls\">\n    <div>\n      <label for=\"tp-date-ops\">Date<\/label><br>\n      <input id=\"tp-date-ops\" class=\"tp-date\" type=\"date\" aria-label=\"Date\">\n    <\/div>\n    <div class=\"tp-day-field\">\n      <label for=\"tp-range-ops\">Days<\/label><br>\n      <select id=\"tp-range-ops\" class=\"tp-range\" aria-label=\"Days\">\n        <option value=\"1\">1<\/option><option value=\"3\">3<\/option><option value=\"7\">7<\/option><option value=\"14\">14<\/option>\n      <\/select>\n    <\/div>\n    <div><button id=\"tp-load-ops\" class=\"tp-btn\">Show sailings<\/button><\/div>\n  <\/div>\n\n  <div class=\"tp-local-nav-row\">\n    <div class=\"tp-local-times\" id=\"tp-local-times-ops\" aria-live=\"polite\"><\/div>\n    <div class=\"tp-day-nav-host\"><\/div>\n  <\/div>\n\n  \n  <div id=\"tp-status-ops\" class=\"tp-muted\" aria-live=\"polite\">Pick a date and click Show sailings<\/div>\n\n  <div id=\"tp-ops-results\"><\/div>\n\n  <div class=\"tp-loader\" aria-hidden=\"true\">\n    <div class=\"tp-loader-card\">\n      <div class=\"tp-spinner\" aria-hidden=\"true\"><\/div>\n      <div class=\"tp-loader-text\">Retrieving schedule data...<\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<script>\n(function(){\n  const wrap   = document.currentScript.previousElementSibling;\n  const cfg    = JSON.parse(wrap.getAttribute('data-config')||'{}');\n  const L      = cfg.labels||{};\n  const dateEl = wrap.querySelector('#tp-date-ops');\n  const daysEl = wrap.querySelector('#tp-range-ops');\n  const btn    = wrap.querySelector('#tp-load-ops');\n  const status = wrap.querySelector('#tp-status-ops');\n  const out    = wrap.querySelector('#tp-ops-results');\n  const loader = wrap.querySelector('.tp-loader');\n  const navHost = wrap.querySelector('.tp-day-nav-host');\n  const localTimesEl = wrap.querySelector('#tp-local-times-ops');\n\n  const showShip = (cfg.showShip !== false && cfg.showShip !== 0 && cfg.showShip !== '0');\n  const activityBoosters = !!cfg.activityBoosters;\n  const daySetup = (cfg.daySetup === 'modern') ? 'modern' : 'classic';\n  const limit10 = !!cfg.limit10;\n  let featuredKey = '';\n  let soonKey = '';\n  let revealAll = false;\n\n  if (daySetup === 'modern') {\n    const dayField = wrap.querySelector('.tp-day-field');\n    if (dayField) dayField.style.display = 'none';\n  }\n\n  dateEl.valueAsDate = new Date();\n  dateEl.min = new Date().toISOString().split('T')[0];\n  Array.from(daysEl.options).forEach(o=>{ if(parseInt(o.value,10)===parseInt(cfg.days||7,10)) o.selected=true; });\n\n  function pad(n){ return String(n).padStart(2,'0'); }\n  function iso(d){ return d.getFullYear()+'-'+pad(d.getMonth()+1)+'-'+pad(d.getDate()); }\n  function toLocal(s){ return new Date(s); }\n  function hhmm(d){ return d.toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}); }\n  function dShort(d){ return d.toLocaleDateString([], {day:'numeric', month:'short'}); }\n  function dur(m){ const h=Math.floor(m\/60), r=m%60; return r? (h+'h '+r+'m') : (h+'h'); }\n\n  const WD = [\n    L.wd_sun || 'SUN',\n    L.wd_mon || 'MON',\n    L.wd_tue || 'TUE',\n    L.wd_wed || 'WED',\n    L.wd_thu || 'THU',\n    L.wd_fri || 'FRI',\n    L.wd_sat || 'SAT'\n  ];\n\n  function setLoader(v){ loader.classList.toggle('show', !!v); loader.setAttribute('aria-hidden', v?'false':'true'); }\n\n  function formatZoneTime(tz){\n    if (!tz) return '--:--';\n    try {\n      return new Intl.DateTimeFormat([], {hour:'2-digit', minute:'2-digit', hour12:false, timeZone: tz}).format(new Date());\n    } catch (e) {\n      return '--:--';\n    }\n  }\n\n  function renderLocalTimes(){\n    if (!localTimesEl) return;\n    if (!cfg.departureTimezone || !cfg.arrivalTimezone) {\n      localTimesEl.textContent = '';\n      return;\n    }\n    const depTime = formatZoneTime(cfg.departureTimezone);\n    const arrTime = formatZoneTime(cfg.arrivalTimezone);\n    const pairTpl = L.local_time_pair || 'Departure Port Local Time: %1$s \/ Arrival Port Local Time: %2$s';\n    const combinedTpl = L.local_time_combined || 'Departure & Arrival Port Local Time: %s';\n    if (depTime === arrTime) {\n      localTimesEl.textContent = combinedTpl.replace('%s', depTime);\n      return;\n    }\n    localTimesEl.textContent = pairTpl.replace('%1$s', depTime).replace('%2$s', arrTime);\n  }\n\n  function setStatusInline(html){\n    let box = wrap.querySelector('.tp-controls-status');\n    if (!box) {\n      box = document.createElement('div');\n      box.className = 'tp-controls-status';\n      wrap.querySelector('.tp-controls').appendChild(box);\n    }\n    box.innerHTML = html || '';\n  }\n\n  function clearStatusInline(){\n    const box = wrap.querySelector('.tp-controls-status');\n    if (box) box.innerHTML = '';\n  }\n\n  function navHtml(){\n    if (daySetup !== 'modern') return '';\n    const base = new Date(dateEl.value || new Date());\n    const today = new Date();\n    const tomorrow = new Date(today);\n    tomorrow.setDate(today.getDate() + 1);\n    const isToday = base.toDateString() === today.toDateString();\nlet prevLabel = L.day_nav_previous || 'Show previous day';\nlet nextLabel = L.day_nav_next || 'Show next day';\nif (isToday) nextLabel = L.day_nav_tomorrow || 'Show tomorrow';\nif (base.toDateString() === tomorrow.toDateString()) prevLabel = L.day_nav_today || 'Show today';\n    return '<div class=\"tp-day-nav\">'\n      + (isToday ? '' : '<a href=\"#\" data-shift=\"-1\">'+prevLabel+'<\/a>')\n      + '<a href=\"#\" data-shift=\"1\">'+nextLabel+'<\/a>'\n      + '<\/div>';\n  }\n\n  function shiftDate(delta){\n    const base = new Date(dateEl.value || new Date());\n    base.setDate(base.getDate() + delta);\n    dateEl.value = iso(base);\n    load();\n  }\n\n  function moreButtonHtml(hiddenCount){\n    if (!limit10 || revealAll || hiddenCount <= 0) return '';\n    return '<div style=\"margin-top:12px;text-align:center\">'\n      + '<button type=\"button\" class=\"tp-btn tp-more-btn\">'+(L.more_departures_button || 'Show more departures')+' ('+hiddenCount+')<\/button>'\n      + '<\/div>';\n  }\n\n  function opCell(r){\n    const name = r.opName || ('Operator '+(r.opId||''));\n    const logo = (cfg.showLogo && r.opLogo) ? '<img decoding=\"async\" src=\"'+r.opLogo+'\" alt=\"'+name+'\"> ' : '';\n    const label = logo + '<span>'+name+'<\/span>';\n    return r.opLink ? '<a class=\"tp-op\" href=\"'+r.opLink+'\" target=\"_blank\" rel=\"nofollow noopener\">'+label+'<\/a>' : '<span class=\"tp-op\">'+label+'<\/span>';\n  }\n\n  function shipInfo(original){\n    const key = (original||'').toLowerCase().trim();\n    const label = (cfg.shipMap && cfg.shipMap[key]) || original || '';\n    const href  = (cfg.shipLinks && cfg.shipLinks[key]) || '';\n    return {label, href};\n  }\n\n  function shipBadge(original){\n    const s = shipInfo(original);\n    const badge = '<span class=\"tp-badge\">'+(s.label||'')+'<\/span>';\n    return s.href ? ('<a href=\"'+s.href+'\" target=\"_blank\" rel=\"nofollow noopener\">'+badge+'<\/a>') : badge;\n  }\n\n  function rowKey(r){\n    return [String(r.routeId||''), String(r.opId||''), String(+r.dep||0), String(+r.arr||0)].join('|');\n  }\n\n  function pickFeaturedKey(rows, avoidKey){\n    if (!activityBoosters || !rows.length) return '';\n    const routesSum = Array.isArray(cfg.routes) ? cfg.routes.reduce((acc, n)=>acc + (parseInt(n,10)||0), 0) : 0;\n    const dateSeed = parseInt(String(dateEl.value || '').replace(\/-\/g,''), 10) || 0;\n\n    let pool = rows;\n    if (avoidKey) {\n      const soonIdx = rows.findIndex(r => rowKey(r) === avoidKey);\n      if (soonIdx >= 0) {\n        const later = rows.slice(soonIdx + 1).filter(r => rowKey(r) !== avoidKey);\n        pool = later.length ? later : rows.filter(r => rowKey(r) !== avoidKey);\n      } else {\n        pool = rows.filter(r => rowKey(r) !== avoidKey);\n      }\n    }\n\n    if (!pool.length) return '';\n    const idx = Math.abs((routesSum + dateSeed + rows.length) % pool.length);\n    return rowKey(pool[idx]);\n  }\n\n  function pickSoonKey(rows){\n    if (!activityBoosters || !rows.length) return '';\n    const now = Date.now();\n    const todayStr = new Date(now).toDateString();\n    const firstUpcoming = rows.find(r => (r.dep instanceof Date) && r.dep.getTime() > now && r.dep.toDateString() === todayStr);\n    return firstUpcoming ? rowKey(firstUpcoming) : '';\n  }\n\n  function boostersFor(r){\n    if (!activityBoosters) return [];\n    const now = Date.now();\n    const depMs = (r.dep instanceof Date) ? r.dep.getTime() : 0;\n    const arrMs = (r.arr instanceof Date) ? r.arr.getTime() : 0;\n    const depIsToday = (r.dep instanceof Date) && (new Date(now).toDateString() === r.dep.toDateString());\n\n    if (depMs > 0 && arrMs > 0 && depMs <= now && arrMs > now) {\n      return [{cls:'tp-booster-sailing', text:(L.tag_currently_sailing || '\ud83d\udfe2 Currently sailing')}];\n    }\n    if (depIsToday && arrMs > 0 && arrMs <= now) {\n      return [{cls:'tp-booster-arrived', text:(L.tag_arrived || '\u26ab Arrived')}];\n    }\n    if (rowKey(r) === soonKey) return [{cls:'tp-booster-soon', text:(L.tag_leaving_soon || '\ud83d\udd34 Leaving soon')}];\n    if (r.dep && r.arr && r.dep.toDateString() !== r.arr.toDateString()) return [{cls:'tp-booster-overnight', text:(L.tag_overnight || 'Overnight')}];\n\n    return [];\n  }\n\n  function boostersHtml(r, floating){\n    const tags = boostersFor(r);\n    if (!tags.length) return '';\n    const cls = floating ? 'tp-boosters tp-boosters-float' : 'tp-boosters';\n    return '<div class=\"'+cls+'\">' + tags.map(t => '<span class=\"tp-booster '+t.cls+'\">'+boosterLabelHtml(t.text)+'<\/span>').join('') + '<\/div>';\n  }\n\n  function boosterLabelHtml(text){\n    return String(text || '').replace(\/^(\ud83d\udd34|\ud83d\udfe2|\u26ab|\u2b50)\\s*\/, '<span class=\"tp-booster-emoji\">$1<\/span>');\n  }\n\n  function routeTicketHtml(label){\n    const raw = String(label || '').trim();\n    if (!raw) return '';\n    if (cfg.theme !== 'small_cards') return escAttr(raw);\n    const parts = raw.split(\/\\s*[\\-\u2013]\\s*\/, 2);\n    if (parts.length < 2) return escAttr(raw);\n    return escAttr(parts[0]) + '<br>' + escAttr(parts[1]);\n  }\n\n  function escAttr(v){\n    return String(v||'').replace(\/[&<>\"']\/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#39;'}[m]));\n  }\n\n  function bindRowLinks(){\n    if (cfg.theme !== 'max_clickouts') return;\n    out.querySelectorAll('tr.tp-row-link').forEach((row)=>{\n      row.setAttribute('role','link');\n      row.setAttribute('tabindex','0');\n      row.addEventListener('click', (e)=>{\n        if (e.target && e.target.closest('a')) return;\n        const href = row.getAttribute('data-row-link');\n        if (!href) return;\n        window.open(href, '_blank', 'noopener,noreferrer');\n      });\n      row.addEventListener('keydown', (e)=>{\n        if (e.key !== 'Enter' && e.key !== ' ') return;\n        e.preventDefault();\n        row.click();\n      });\n    });\n  }\n\n  function routeLabel(rid){\n    return (cfg.routeLabels && (cfg.routeLabels[String(rid)] || cfg.routeLabels[rid])) || String(rid);\n  }\n\n  function renderTable(rows){\n    const th = {date:L.th_date,dep:L.th_dep,arr:L.th_arr,dur:L.th_dur,ship:L.th_ship,route:L.th_route,op:L.th_op};\n\n    const headCells = [\n      '<th>'+th.date+'<\/th>',\n      '<th>'+th.dep+'<\/th>',\n      '<th>'+th.arr+'<\/th>',\n      '<th>'+th.dur+'<\/th>'\n    ];\n    if (showShip) {\n      headCells.push('<th>'+th.ship+'<\/th>');\n    }\n    headCells.push('<th>'+th.route+'<\/th>');\n    headCells.push('<th>'+th.op+'<\/th>');\n\n    let html = '<table class=\"tp-table\"><thead><tr>'+headCells.join('')+'<\/tr><\/thead><tbody>';\n    rows.forEach(r=>{\n      const dow = WD[r.dep.getDay()] || '';\n      const clickable = (cfg.theme === 'max_clickouts' && r.opLink);\n      const rowAttr = clickable ? (' class=\"tp-row-link\" data-row-link=\"'+escAttr(r.opLink)+'\"') : '';\n      const dateBoosters = (cfg.theme === 'max_clickouts') ? '' : boostersHtml(r, false);\n      const routeBoosters = (cfg.theme === 'max_clickouts') ? boostersHtml(r, false) : '';\n      const cells = [\n        '<td>'+dShort(r.dep)+' <span class=\"tp-day\">'+dow+'<\/span>'+dateBoosters+'<\/td>',\n        '<td>'+hhmm(r.dep)+'<\/td>',\n        '<td>'+hhmm(r.arr)+'<\/td>',\n        '<td>'+dur(r.min)+'<\/td>'\n      ];\n      if (showShip) {\n        cells.push('<td>'+shipBadge(r.ship)+'<\/td>');\n      }\n      cells.push('<td>'+routeBoosters+'<div>'+routeLabel(r.routeId)+'<\/div><\/td>');\n      cells.push('<td>'+opCell(r)+'<\/td>');\n      html += '<tr'+rowAttr+'>'+cells.join('')+'<\/tr>';\n    });\n    html += '<\/tbody><\/table>';\n    return html;\n  }\n\n  function renderCards(rows){\n    if (cfg.theme === 'extended_cards') {\n      return renderExtendedCards(rows);\n    }\n\n    let html = '<div class=\"tp-cardlist\">';\n    rows.forEach(r=>{\n      const dow   = WD[r.dep.getDay()] || '';\n      const times = hhmm(r.dep) + ' <span class=\"tp-arrow\">\u2192<\/span> ' + hhmm(r.arr);\n      html += '<div class=\"tp-card\">'+boostersHtml(r, true)+\n        \/\/ Row 1: Date + weekday + times\n        '<div class=\"tp-mrow\">'+\n          '<div class=\"lhs\"><span class=\"tp-sub\">'+dShort(r.dep)+'<\/span><span class=\"tp-day\">'+dow+'<\/span><\/div>'+\n          '<div class=\"rhs\"><span class=\"tp-time\">'+times+'<\/span><\/div>'+\n        '<\/div>';\n\n      if (showShip) {\n        html +=\n        \/\/ Row 2: Ship\n        '<div class=\"tp-mrow\">'+\n          '<div class=\"lhs\">'+shipBadge(r.ship)+'<\/div>'+\n          '<div class=\"rhs\"><\/div>'+\n        '<\/div>';\n      }\n\n      html +=\n        \/\/ Row 3: Operator + route label\n        '<div class=\"tp-mrow\">'+\n          '<div class=\"lhs\">'+opCell(r)+'<\/div>'+\n          '<div class=\"rhs\"><span class=\"tp-route-ticket\">'+routeTicketHtml(routeLabel(r.routeId))+'<\/span><\/div>'+\n        '<\/div>'+\n      '<\/div>';\n    });\n    html += '<\/div>';\n    return html;\n  }\n\n  function renderExtendedCards(rows){\n    const ctaText = L.more_link || 'More sailings';\n    let html = '<div class=\"tp-cardlist\">';\n    rows.forEach(r=>{\n      const dow = WD[r.dep.getDay()] || '';\n      const link = r.opLink ? ('<a class=\"tp-ext-cta\" href=\"'+r.opLink+'\" target=\"_blank\" rel=\"nofollow noopener\">'+ctaText+' <span class=\"tp-ext-cta-arrow\">\u00bb<\/span><\/a>') : '<span class=\"tp-ext-cta\">'+ctaText+' <span class=\"tp-ext-cta-arrow\">\u00bb<\/span><\/span>';\n      html += '<div class=\"tp-ext-card\">'\n        + boostersHtml(r, true)\n        + '<div class=\"tp-ext-left\">'\n        +   '<div>'+opCell(r)+'<\/div>'\n        +   (showShip ? ('<div>'+shipBadge(r.ship)+'<\/div>') : '')\n        + '<\/div>'\n        + '<div class=\"tp-ext-mid\">'\n        +   '<div class=\"tp-ext-top\"><span class=\"tp-sub\">'+dShort(r.dep)+' <span class=\"tp-day\">'+dow+'<\/span><\/span><span class=\"tp-ext-dur\">'+dur(r.min)+'<\/span><\/div>'\n        +   '<div class=\"tp-ext-times\"><span class=\"tp-ext-time\">'+hhmm(r.dep)+'<\/span><span class=\"tp-ext-line\"><\/span><span class=\"tp-ext-dur\">'+dur(r.min)+'<\/span><span class=\"tp-ext-line\"><\/span><span class=\"tp-ext-time\">'+hhmm(r.arr)+'<\/span><\/div>'\n        +   '<div class=\"tp-ext-route\">'+routeLabel(r.routeId)+'<\/div>'\n        + '<\/div>'\n        + '<div class=\"tp-ext-right\">'+link+'<\/div>'\n        + '<\/div>';\n    });\n    html += '<\/div>';\n    return html;\n  }\n\n  \/\/ Safe fetch helper\n  async function fetchOne(routeId, from, to){\n    try{\n      const url = new URL(cfg.rest);\n      url.searchParams.set('route', String(routeId));\n      url.searchParams.set('from', from);\n      url.searchParams.set('to', to);\n      const res = await fetch(url.toString(), {credentials:'same-origin'});\n      if(!res.ok) return { rid: routeId, error: 'HTTP '+res.status };\n      const json = await res.json();\n      const list = (json && json.data && Array.isArray(json.data.rows)) ? json.data.rows : [];\n      return { rid: routeId, rows: list };\n    }catch(e){\n      return { rid: routeId, error: String(e && e.message ? e.message : e) };\n    }\n  }\n\n  async function load(){\n    btn.disabled = true; setLoader(true); status.textContent = L.status_loading;\n\n    const start = new Date(dateEl.value || new Date());\n    const days  = (daySetup === 'modern') ? 1 : Math.max(1, parseInt(daysEl.value,10)||1);\n    const end   = new Date(start); end.setDate(start.getDate()+days-1);\n    const fromIso = iso(start), toIso = iso(end);\n\n    try{\n      const results  = await Promise.all((cfg.routes||[]).map(rid=>fetchOne(rid, fromIso, toIso)));\n      const oks  = results.filter(r => !r.error);\n      const errs = results.filter(r =>  r.error);\n\n      const all = [];\n      oks.forEach(({rid, rows})=>{\n        rows.forEach(t=>{\n          all.push({\n            routeId: rid,\n            opId: t.operatorId || null,\n            opName: t.operatorName || '',\n            opLogo: t.operatorLogo || '',\n            opLink: t.operatorLink || '',\n            dep: toLocal(t.departureTime),\n            arr: toLocal(t.arrivalTime),\n            min: t.durationInMinutes || 0,\n            ship: t.shipName || ''\n          });\n        });\n      });\n\n      let rows = all;\n      if (Array.isArray(cfg.opFilter) && cfg.opFilter.length>0) {\n        rows = all.filter(r => r.opId && cfg.opFilter.includes(String(r.opId)));\n      }\n\n      rows.sort((a,b)=> a.dep - b.dep);\n\n      const todayStr = new Date().toDateString();\n      const nowMs = Date.now();\n      const arrivedToday = rows\n        .filter(r => (r.dep instanceof Date) && (r.arr instanceof Date) && r.dep.toDateString() === todayStr && r.arr.getTime() <= nowMs)\n        .sort((a,b) => b.arr - a.arr);\n      if (arrivedToday.length > 2) {\n        const keep = new Set(arrivedToday.slice(0,2).map(rowKey));\n        rows = rows.filter(r => {\n          const isArrivedToday = (r.dep instanceof Date) && (r.arr instanceof Date) && r.dep.toDateString() === todayStr && r.arr.getTime() <= nowMs;\n          return !isArrivedToday || keep.has(rowKey(r));\n        });\n      }\n\n      const total = rows.length;\n      if (total===0){\n        status.textContent = L.status_empty + (errs.length ? ' (some routes returned no data or errors)' : '');\n        clearStatusInline();\n        out.innerHTML='';\n        setLoader(false); btn.disabled=false; return;\n      }\n\n      const visibleRows = (limit10 && !revealAll && rows.length > 10) ? rows.slice(0,10) : rows;\n      const hiddenCount = rows.length - visibleRows.length;\n      soonKey = pickSoonKey(visibleRows);\n      featuredKey = pickFeaturedKey(visibleRows, soonKey);\n\n      status.textContent = errs.length ? ('Skipped '+errs.length+' route'+(errs.length>1?'s':'')) : '';\n      setStatusInline(\n  (L.status_found || '%d sailings found').replace('%d', '<strong>'+total+'<\/strong>')\n);\n      out.innerHTML = renderTable(visibleRows) + renderCards(visibleRows) + moreButtonHtml(hiddenCount);\n      bindRowLinks();\n      if (navHost) navHost.innerHTML = navHtml();\n\n    } catch(e){\n      status.textContent = 'Failed to load data';\n      out.innerHTML = '<pre>'+String(e.message||e)+'<\/pre>';\n    } finally {\n      setLoader(false);\n      btn.disabled = false;\n    }\n  }\n\n  wrap.addEventListener('click', function(e){\n    const nav = e.target.closest('.tp-day-nav a[data-shift]');\n    if (nav) {\n      e.preventDefault();\n      shiftDate(parseInt(nav.getAttribute('data-shift'),10) || 0);\n      return;\n    }\n    const more = e.target.closest('.tp-more-btn');\n    if (more) {\n      e.preventDefault();\n      revealAll = true;\n      load();\n    }\n  });\n\n  btn.addEventListener('click', load);\n  if (navHost) navHost.innerHTML = navHtml();\n  renderLocalTimes();\n  setInterval(renderLocalTimes, 30000);\n  if (cfg.autoload) load();\n})();\n<\/script>\n\n\t\t\t\t<h3>Dover do Dunkierki<\/h3>\n\t\t\t\t<div class=\"tp-wrap tp-theme-extended_cards tp-day-setup-modern\" data-config=\"{&quot;rest&quot;:&quot;https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/wp-json\\\/timetables-pro\\\/v1\\\/timetables&quot;,&quot;routes&quot;:[100],&quot;days&quot;:1,&quot;autoload&quot;:true,&quot;theme&quot;:&quot;extended_cards&quot;,&quot;daySetup&quot;:&quot;modern&quot;,&quot;limit10&quot;:false,&quot;routeLabels&quot;:{&quot;100&quot;:&quot;Dover-Dunkierka&quot;},&quot;opFilter&quot;:[&quot;6&quot;],&quot;labels&quot;:{&quot;ui_date&quot;:&quot;Date&quot;,&quot;ui_days&quot;:&quot;Days&quot;,&quot;ui_button&quot;:&quot;Show sailings&quot;,&quot;status_idle&quot;:&quot;Pick a date and click Show sailings&quot;,&quot;status_loading&quot;:&quot;Retrieving schedule data...&quot;,&quot;status_empty&quot;:&quot;No sailings found&quot;,&quot;status_found&quot;:&quot;%d sailings found&quot;,&quot;th_date&quot;:&quot;Date&quot;,&quot;th_dep&quot;:&quot;Departure&quot;,&quot;th_arr&quot;:&quot;Arrival&quot;,&quot;th_dur&quot;:&quot;Duration&quot;,&quot;th_ship&quot;:&quot;Ship&quot;,&quot;th_op&quot;:&quot;Operator&quot;,&quot;th_route&quot;:&quot;Route&quot;,&quot;wd_sun&quot;:&quot;SUN&quot;,&quot;wd_mon&quot;:&quot;MON&quot;,&quot;wd_tue&quot;:&quot;TUE&quot;,&quot;wd_wed&quot;:&quot;WED&quot;,&quot;wd_thu&quot;:&quot;THU&quot;,&quot;wd_fri&quot;:&quot;FRI&quot;,&quot;wd_sat&quot;:&quot;SAT&quot;,&quot;summary_footer_one&quot;:&quot;\\u00bb Check all %s departures on our timetable&quot;,&quot;summary_footer_two&quot;:&quot;\\u00bb Check more %1$s and %2$s departures on our timetable&quot;,&quot;summary_footer_generic&quot;:&quot;Check our timetable for more sailings&quot;,&quot;summary_header&quot;:&quot;The next two departures:&quot;,&quot;summary_no_upcoming&quot;:&quot;No upcoming departures found&quot;,&quot;more_link&quot;:&quot;More sailings&quot;,&quot;more_departures_button&quot;:&quot;Show more departures&quot;,&quot;day_nav_previous&quot;:&quot;Show previous day&quot;,&quot;day_nav_next&quot;:&quot;Show next day&quot;,&quot;day_nav_today&quot;:&quot;Show today&quot;,&quot;day_nav_tomorrow&quot;:&quot;Show tomorrow&quot;,&quot;local_time_pair&quot;:&quot;Departure Port Local Time: %1$s \\\/ Arrival Port Local Time: %2$s&quot;,&quot;local_time_combined&quot;:&quot;Departure &amp; Arrival Port Local Time: %s&quot;,&quot;tag_often_booked&quot;:&quot;\\u2b50 Often booked&quot;,&quot;tag_leaving_soon&quot;:&quot;\\ud83d\\udd34 Leaving soon&quot;,&quot;tag_currently_sailing&quot;:&quot;\\ud83d\\udfe2 Currently sailing&quot;,&quot;tag_arrived&quot;:&quot;\\u26ab Arrived&quot;,&quot;tag_overnight&quot;:&quot;Overnight&quot;},&quot;showLogo&quot;:true,&quot;activityBoosters&quot;:true,&quot;title&quot;:&quot;&quot;,&quot;shipMap&quot;:[],&quot;shipLinks&quot;:[],&quot;showShip&quot;:false,&quot;departurePort&quot;:&quot;Dover&quot;,&quot;arrivalPort&quot;:&quot;Dunkirk&quot;,&quot;departureTimezone&quot;:&quot;Europe\\\/London&quot;,&quot;arrivalTimezone&quot;:&quot;Europe\\\/Paris&quot;}\">\n  <div class=\"tp-controls\" role=\"group\" aria-label=\"Timetable controls\">\n    <div>\n      <label for=\"tp-date-ops\">Date<\/label><br>\n      <input id=\"tp-date-ops\" class=\"tp-date\" type=\"date\" aria-label=\"Date\">\n    <\/div>\n    <div class=\"tp-day-field\">\n      <label for=\"tp-range-ops\">Days<\/label><br>\n      <select id=\"tp-range-ops\" class=\"tp-range\" aria-label=\"Days\">\n        <option value=\"1\">1<\/option><option value=\"3\">3<\/option><option value=\"7\">7<\/option><option value=\"14\">14<\/option>\n      <\/select>\n    <\/div>\n    <div><button id=\"tp-load-ops\" class=\"tp-btn\">Show sailings<\/button><\/div>\n  <\/div>\n\n  <div class=\"tp-local-nav-row\">\n    <div class=\"tp-local-times\" id=\"tp-local-times-ops\" aria-live=\"polite\"><\/div>\n    <div class=\"tp-day-nav-host\"><\/div>\n  <\/div>\n\n  \n  <div id=\"tp-status-ops\" class=\"tp-muted\" aria-live=\"polite\">Pick a date and click Show sailings<\/div>\n\n  <div id=\"tp-ops-results\"><\/div>\n\n  <div class=\"tp-loader\" aria-hidden=\"true\">\n    <div class=\"tp-loader-card\">\n      <div class=\"tp-spinner\" aria-hidden=\"true\"><\/div>\n      <div class=\"tp-loader-text\">Retrieving schedule data...<\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<script>\n(function(){\n  const wrap   = document.currentScript.previousElementSibling;\n  const cfg    = JSON.parse(wrap.getAttribute('data-config')||'{}');\n  const L      = cfg.labels||{};\n  const dateEl = wrap.querySelector('#tp-date-ops');\n  const daysEl = wrap.querySelector('#tp-range-ops');\n  const btn    = wrap.querySelector('#tp-load-ops');\n  const status = wrap.querySelector('#tp-status-ops');\n  const out    = wrap.querySelector('#tp-ops-results');\n  const loader = wrap.querySelector('.tp-loader');\n  const navHost = wrap.querySelector('.tp-day-nav-host');\n  const localTimesEl = wrap.querySelector('#tp-local-times-ops');\n\n  const showShip = (cfg.showShip !== false && cfg.showShip !== 0 && cfg.showShip !== '0');\n  const activityBoosters = !!cfg.activityBoosters;\n  const daySetup = (cfg.daySetup === 'modern') ? 'modern' : 'classic';\n  const limit10 = !!cfg.limit10;\n  let featuredKey = '';\n  let soonKey = '';\n  let revealAll = false;\n\n  if (daySetup === 'modern') {\n    const dayField = wrap.querySelector('.tp-day-field');\n    if (dayField) dayField.style.display = 'none';\n  }\n\n  dateEl.valueAsDate = new Date();\n  dateEl.min = new Date().toISOString().split('T')[0];\n  Array.from(daysEl.options).forEach(o=>{ if(parseInt(o.value,10)===parseInt(cfg.days||7,10)) o.selected=true; });\n\n  function pad(n){ return String(n).padStart(2,'0'); }\n  function iso(d){ return d.getFullYear()+'-'+pad(d.getMonth()+1)+'-'+pad(d.getDate()); }\n  function toLocal(s){ return new Date(s); }\n  function hhmm(d){ return d.toLocaleTimeString([], {hour:'2-digit', minute:'2-digit'}); }\n  function dShort(d){ return d.toLocaleDateString([], {day:'numeric', month:'short'}); }\n  function dur(m){ const h=Math.floor(m\/60), r=m%60; return r? (h+'h '+r+'m') : (h+'h'); }\n\n  const WD = [\n    L.wd_sun || 'SUN',\n    L.wd_mon || 'MON',\n    L.wd_tue || 'TUE',\n    L.wd_wed || 'WED',\n    L.wd_thu || 'THU',\n    L.wd_fri || 'FRI',\n    L.wd_sat || 'SAT'\n  ];\n\n  function setLoader(v){ loader.classList.toggle('show', !!v); loader.setAttribute('aria-hidden', v?'false':'true'); }\n\n  function formatZoneTime(tz){\n    if (!tz) return '--:--';\n    try {\n      return new Intl.DateTimeFormat([], {hour:'2-digit', minute:'2-digit', hour12:false, timeZone: tz}).format(new Date());\n    } catch (e) {\n      return '--:--';\n    }\n  }\n\n  function renderLocalTimes(){\n    if (!localTimesEl) return;\n    if (!cfg.departureTimezone || !cfg.arrivalTimezone) {\n      localTimesEl.textContent = '';\n      return;\n    }\n    const depTime = formatZoneTime(cfg.departureTimezone);\n    const arrTime = formatZoneTime(cfg.arrivalTimezone);\n    const pairTpl = L.local_time_pair || 'Departure Port Local Time: %1$s \/ Arrival Port Local Time: %2$s';\n    const combinedTpl = L.local_time_combined || 'Departure & Arrival Port Local Time: %s';\n    if (depTime === arrTime) {\n      localTimesEl.textContent = combinedTpl.replace('%s', depTime);\n      return;\n    }\n    localTimesEl.textContent = pairTpl.replace('%1$s', depTime).replace('%2$s', arrTime);\n  }\n\n  function setStatusInline(html){\n    let box = wrap.querySelector('.tp-controls-status');\n    if (!box) {\n      box = document.createElement('div');\n      box.className = 'tp-controls-status';\n      wrap.querySelector('.tp-controls').appendChild(box);\n    }\n    box.innerHTML = html || '';\n  }\n\n  function clearStatusInline(){\n    const box = wrap.querySelector('.tp-controls-status');\n    if (box) box.innerHTML = '';\n  }\n\n  function navHtml(){\n    if (daySetup !== 'modern') return '';\n    const base = new Date(dateEl.value || new Date());\n    const today = new Date();\n    const tomorrow = new Date(today);\n    tomorrow.setDate(today.getDate() + 1);\n    const isToday = base.toDateString() === today.toDateString();\nlet prevLabel = L.day_nav_previous || 'Show previous day';\nlet nextLabel = L.day_nav_next || 'Show next day';\nif (isToday) nextLabel = L.day_nav_tomorrow || 'Show tomorrow';\nif (base.toDateString() === tomorrow.toDateString()) prevLabel = L.day_nav_today || 'Show today';\n    return '<div class=\"tp-day-nav\">'\n      + (isToday ? '' : '<a href=\"#\" data-shift=\"-1\">'+prevLabel+'<\/a>')\n      + '<a href=\"#\" data-shift=\"1\">'+nextLabel+'<\/a>'\n      + '<\/div>';\n  }\n\n  function shiftDate(delta){\n    const base = new Date(dateEl.value || new Date());\n    base.setDate(base.getDate() + delta);\n    dateEl.value = iso(base);\n    load();\n  }\n\n  function moreButtonHtml(hiddenCount){\n    if (!limit10 || revealAll || hiddenCount <= 0) return '';\n    return '<div style=\"margin-top:12px;text-align:center\">'\n      + '<button type=\"button\" class=\"tp-btn tp-more-btn\">'+(L.more_departures_button || 'Show more departures')+' ('+hiddenCount+')<\/button>'\n      + '<\/div>';\n  }\n\n  function opCell(r){\n    const name = r.opName || ('Operator '+(r.opId||''));\n    const logo = (cfg.showLogo && r.opLogo) ? '<img decoding=\"async\" src=\"'+r.opLogo+'\" alt=\"'+name+'\"> ' : '';\n    const label = logo + '<span>'+name+'<\/span>';\n    return r.opLink ? '<a class=\"tp-op\" href=\"'+r.opLink+'\" target=\"_blank\" rel=\"nofollow noopener\">'+label+'<\/a>' : '<span class=\"tp-op\">'+label+'<\/span>';\n  }\n\n  function shipInfo(original){\n    const key = (original||'').toLowerCase().trim();\n    const label = (cfg.shipMap && cfg.shipMap[key]) || original || '';\n    const href  = (cfg.shipLinks && cfg.shipLinks[key]) || '';\n    return {label, href};\n  }\n\n  function shipBadge(original){\n    const s = shipInfo(original);\n    const badge = '<span class=\"tp-badge\">'+(s.label||'')+'<\/span>';\n    return s.href ? ('<a href=\"'+s.href+'\" target=\"_blank\" rel=\"nofollow noopener\">'+badge+'<\/a>') : badge;\n  }\n\n  function rowKey(r){\n    return [String(r.routeId||''), String(r.opId||''), String(+r.dep||0), String(+r.arr||0)].join('|');\n  }\n\n  function pickFeaturedKey(rows, avoidKey){\n    if (!activityBoosters || !rows.length) return '';\n    const routesSum = Array.isArray(cfg.routes) ? cfg.routes.reduce((acc, n)=>acc + (parseInt(n,10)||0), 0) : 0;\n    const dateSeed = parseInt(String(dateEl.value || '').replace(\/-\/g,''), 10) || 0;\n\n    let pool = rows;\n    if (avoidKey) {\n      const soonIdx = rows.findIndex(r => rowKey(r) === avoidKey);\n      if (soonIdx >= 0) {\n        const later = rows.slice(soonIdx + 1).filter(r => rowKey(r) !== avoidKey);\n        pool = later.length ? later : rows.filter(r => rowKey(r) !== avoidKey);\n      } else {\n        pool = rows.filter(r => rowKey(r) !== avoidKey);\n      }\n    }\n\n    if (!pool.length) return '';\n    const idx = Math.abs((routesSum + dateSeed + rows.length) % pool.length);\n    return rowKey(pool[idx]);\n  }\n\n  function pickSoonKey(rows){\n    if (!activityBoosters || !rows.length) return '';\n    const now = Date.now();\n    const todayStr = new Date(now).toDateString();\n    const firstUpcoming = rows.find(r => (r.dep instanceof Date) && r.dep.getTime() > now && r.dep.toDateString() === todayStr);\n    return firstUpcoming ? rowKey(firstUpcoming) : '';\n  }\n\n  function boostersFor(r){\n    if (!activityBoosters) return [];\n    const now = Date.now();\n    const depMs = (r.dep instanceof Date) ? r.dep.getTime() : 0;\n    const arrMs = (r.arr instanceof Date) ? r.arr.getTime() : 0;\n    const depIsToday = (r.dep instanceof Date) && (new Date(now).toDateString() === r.dep.toDateString());\n\n    if (depMs > 0 && arrMs > 0 && depMs <= now && arrMs > now) {\n      return [{cls:'tp-booster-sailing', text:(L.tag_currently_sailing || '\ud83d\udfe2 Currently sailing')}];\n    }\n    if (depIsToday && arrMs > 0 && arrMs <= now) {\n      return [{cls:'tp-booster-arrived', text:(L.tag_arrived || '\u26ab Arrived')}];\n    }\n    if (rowKey(r) === soonKey) return [{cls:'tp-booster-soon', text:(L.tag_leaving_soon || '\ud83d\udd34 Leaving soon')}];\n    if (r.dep && r.arr && r.dep.toDateString() !== r.arr.toDateString()) return [{cls:'tp-booster-overnight', text:(L.tag_overnight || 'Overnight')}];\n\n    return [];\n  }\n\n  function boostersHtml(r, floating){\n    const tags = boostersFor(r);\n    if (!tags.length) return '';\n    const cls = floating ? 'tp-boosters tp-boosters-float' : 'tp-boosters';\n    return '<div class=\"'+cls+'\">' + tags.map(t => '<span class=\"tp-booster '+t.cls+'\">'+boosterLabelHtml(t.text)+'<\/span>').join('') + '<\/div>';\n  }\n\n  function boosterLabelHtml(text){\n    return String(text || '').replace(\/^(\ud83d\udd34|\ud83d\udfe2|\u26ab|\u2b50)\\s*\/, '<span class=\"tp-booster-emoji\">$1<\/span>');\n  }\n\n  function routeTicketHtml(label){\n    const raw = String(label || '').trim();\n    if (!raw) return '';\n    if (cfg.theme !== 'small_cards') return escAttr(raw);\n    const parts = raw.split(\/\\s*[\\-\u2013]\\s*\/, 2);\n    if (parts.length < 2) return escAttr(raw);\n    return escAttr(parts[0]) + '<br>' + escAttr(parts[1]);\n  }\n\n  function escAttr(v){\n    return String(v||'').replace(\/[&<>\"']\/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','\"':'&quot;',\"'\":'&#39;'}[m]));\n  }\n\n  function bindRowLinks(){\n    if (cfg.theme !== 'max_clickouts') return;\n    out.querySelectorAll('tr.tp-row-link').forEach((row)=>{\n      row.setAttribute('role','link');\n      row.setAttribute('tabindex','0');\n      row.addEventListener('click', (e)=>{\n        if (e.target && e.target.closest('a')) return;\n        const href = row.getAttribute('data-row-link');\n        if (!href) return;\n        window.open(href, '_blank', 'noopener,noreferrer');\n      });\n      row.addEventListener('keydown', (e)=>{\n        if (e.key !== 'Enter' && e.key !== ' ') return;\n        e.preventDefault();\n        row.click();\n      });\n    });\n  }\n\n  function routeLabel(rid){\n    return (cfg.routeLabels && (cfg.routeLabels[String(rid)] || cfg.routeLabels[rid])) || String(rid);\n  }\n\n  function renderTable(rows){\n    const th = {date:L.th_date,dep:L.th_dep,arr:L.th_arr,dur:L.th_dur,ship:L.th_ship,route:L.th_route,op:L.th_op};\n\n    const headCells = [\n      '<th>'+th.date+'<\/th>',\n      '<th>'+th.dep+'<\/th>',\n      '<th>'+th.arr+'<\/th>',\n      '<th>'+th.dur+'<\/th>'\n    ];\n    if (showShip) {\n      headCells.push('<th>'+th.ship+'<\/th>');\n    }\n    headCells.push('<th>'+th.route+'<\/th>');\n    headCells.push('<th>'+th.op+'<\/th>');\n\n    let html = '<table class=\"tp-table\"><thead><tr>'+headCells.join('')+'<\/tr><\/thead><tbody>';\n    rows.forEach(r=>{\n      const dow = WD[r.dep.getDay()] || '';\n      const clickable = (cfg.theme === 'max_clickouts' && r.opLink);\n      const rowAttr = clickable ? (' class=\"tp-row-link\" data-row-link=\"'+escAttr(r.opLink)+'\"') : '';\n      const dateBoosters = (cfg.theme === 'max_clickouts') ? '' : boostersHtml(r, false);\n      const routeBoosters = (cfg.theme === 'max_clickouts') ? boostersHtml(r, false) : '';\n      const cells = [\n        '<td>'+dShort(r.dep)+' <span class=\"tp-day\">'+dow+'<\/span>'+dateBoosters+'<\/td>',\n        '<td>'+hhmm(r.dep)+'<\/td>',\n        '<td>'+hhmm(r.arr)+'<\/td>',\n        '<td>'+dur(r.min)+'<\/td>'\n      ];\n      if (showShip) {\n        cells.push('<td>'+shipBadge(r.ship)+'<\/td>');\n      }\n      cells.push('<td>'+routeBoosters+'<div>'+routeLabel(r.routeId)+'<\/div><\/td>');\n      cells.push('<td>'+opCell(r)+'<\/td>');\n      html += '<tr'+rowAttr+'>'+cells.join('')+'<\/tr>';\n    });\n    html += '<\/tbody><\/table>';\n    return html;\n  }\n\n  function renderCards(rows){\n    if (cfg.theme === 'extended_cards') {\n      return renderExtendedCards(rows);\n    }\n\n    let html = '<div class=\"tp-cardlist\">';\n    rows.forEach(r=>{\n      const dow   = WD[r.dep.getDay()] || '';\n      const times = hhmm(r.dep) + ' <span class=\"tp-arrow\">\u2192<\/span> ' + hhmm(r.arr);\n      html += '<div class=\"tp-card\">'+boostersHtml(r, true)+\n        \/\/ Row 1: Date + weekday + times\n        '<div class=\"tp-mrow\">'+\n          '<div class=\"lhs\"><span class=\"tp-sub\">'+dShort(r.dep)+'<\/span><span class=\"tp-day\">'+dow+'<\/span><\/div>'+\n          '<div class=\"rhs\"><span class=\"tp-time\">'+times+'<\/span><\/div>'+\n        '<\/div>';\n\n      if (showShip) {\n        html +=\n        \/\/ Row 2: Ship\n        '<div class=\"tp-mrow\">'+\n          '<div class=\"lhs\">'+shipBadge(r.ship)+'<\/div>'+\n          '<div class=\"rhs\"><\/div>'+\n        '<\/div>';\n      }\n\n      html +=\n        \/\/ Row 3: Operator + route label\n        '<div class=\"tp-mrow\">'+\n          '<div class=\"lhs\">'+opCell(r)+'<\/div>'+\n          '<div class=\"rhs\"><span class=\"tp-route-ticket\">'+routeTicketHtml(routeLabel(r.routeId))+'<\/span><\/div>'+\n        '<\/div>'+\n      '<\/div>';\n    });\n    html += '<\/div>';\n    return html;\n  }\n\n  function renderExtendedCards(rows){\n    const ctaText = L.more_link || 'More sailings';\n    let html = '<div class=\"tp-cardlist\">';\n    rows.forEach(r=>{\n      const dow = WD[r.dep.getDay()] || '';\n      const link = r.opLink ? ('<a class=\"tp-ext-cta\" href=\"'+r.opLink+'\" target=\"_blank\" rel=\"nofollow noopener\">'+ctaText+' <span class=\"tp-ext-cta-arrow\">\u00bb<\/span><\/a>') : '<span class=\"tp-ext-cta\">'+ctaText+' <span class=\"tp-ext-cta-arrow\">\u00bb<\/span><\/span>';\n      html += '<div class=\"tp-ext-card\">'\n        + boostersHtml(r, true)\n        + '<div class=\"tp-ext-left\">'\n        +   '<div>'+opCell(r)+'<\/div>'\n        +   (showShip ? ('<div>'+shipBadge(r.ship)+'<\/div>') : '')\n        + '<\/div>'\n        + '<div class=\"tp-ext-mid\">'\n        +   '<div class=\"tp-ext-top\"><span class=\"tp-sub\">'+dShort(r.dep)+' <span class=\"tp-day\">'+dow+'<\/span><\/span><span class=\"tp-ext-dur\">'+dur(r.min)+'<\/span><\/div>'\n        +   '<div class=\"tp-ext-times\"><span class=\"tp-ext-time\">'+hhmm(r.dep)+'<\/span><span class=\"tp-ext-line\"><\/span><span class=\"tp-ext-dur\">'+dur(r.min)+'<\/span><span class=\"tp-ext-line\"><\/span><span class=\"tp-ext-time\">'+hhmm(r.arr)+'<\/span><\/div>'\n        +   '<div class=\"tp-ext-route\">'+routeLabel(r.routeId)+'<\/div>'\n        + '<\/div>'\n        + '<div class=\"tp-ext-right\">'+link+'<\/div>'\n        + '<\/div>';\n    });\n    html += '<\/div>';\n    return html;\n  }\n\n  \/\/ Safe fetch helper\n  async function fetchOne(routeId, from, to){\n    try{\n      const url = new URL(cfg.rest);\n      url.searchParams.set('route', String(routeId));\n      url.searchParams.set('from', from);\n      url.searchParams.set('to', to);\n      const res = await fetch(url.toString(), {credentials:'same-origin'});\n      if(!res.ok) return { rid: routeId, error: 'HTTP '+res.status };\n      const json = await res.json();\n      const list = (json && json.data && Array.isArray(json.data.rows)) ? json.data.rows : [];\n      return { rid: routeId, rows: list };\n    }catch(e){\n      return { rid: routeId, error: String(e && e.message ? e.message : e) };\n    }\n  }\n\n  async function load(){\n    btn.disabled = true; setLoader(true); status.textContent = L.status_loading;\n\n    const start = new Date(dateEl.value || new Date());\n    const days  = (daySetup === 'modern') ? 1 : Math.max(1, parseInt(daysEl.value,10)||1);\n    const end   = new Date(start); end.setDate(start.getDate()+days-1);\n    const fromIso = iso(start), toIso = iso(end);\n\n    try{\n      const results  = await Promise.all((cfg.routes||[]).map(rid=>fetchOne(rid, fromIso, toIso)));\n      const oks  = results.filter(r => !r.error);\n      const errs = results.filter(r =>  r.error);\n\n      const all = [];\n      oks.forEach(({rid, rows})=>{\n        rows.forEach(t=>{\n          all.push({\n            routeId: rid,\n            opId: t.operatorId || null,\n            opName: t.operatorName || '',\n            opLogo: t.operatorLogo || '',\n            opLink: t.operatorLink || '',\n            dep: toLocal(t.departureTime),\n            arr: toLocal(t.arrivalTime),\n            min: t.durationInMinutes || 0,\n            ship: t.shipName || ''\n          });\n        });\n      });\n\n      let rows = all;\n      if (Array.isArray(cfg.opFilter) && cfg.opFilter.length>0) {\n        rows = all.filter(r => r.opId && cfg.opFilter.includes(String(r.opId)));\n      }\n\n      rows.sort((a,b)=> a.dep - b.dep);\n\n      const todayStr = new Date().toDateString();\n      const nowMs = Date.now();\n      const arrivedToday = rows\n        .filter(r => (r.dep instanceof Date) && (r.arr instanceof Date) && r.dep.toDateString() === todayStr && r.arr.getTime() <= nowMs)\n        .sort((a,b) => b.arr - a.arr);\n      if (arrivedToday.length > 2) {\n        const keep = new Set(arrivedToday.slice(0,2).map(rowKey));\n        rows = rows.filter(r => {\n          const isArrivedToday = (r.dep instanceof Date) && (r.arr instanceof Date) && r.dep.toDateString() === todayStr && r.arr.getTime() <= nowMs;\n          return !isArrivedToday || keep.has(rowKey(r));\n        });\n      }\n\n      const total = rows.length;\n      if (total===0){\n        status.textContent = L.status_empty + (errs.length ? ' (some routes returned no data or errors)' : '');\n        clearStatusInline();\n        out.innerHTML='';\n        setLoader(false); btn.disabled=false; return;\n      }\n\n      const visibleRows = (limit10 && !revealAll && rows.length > 10) ? rows.slice(0,10) : rows;\n      const hiddenCount = rows.length - visibleRows.length;\n      soonKey = pickSoonKey(visibleRows);\n      featuredKey = pickFeaturedKey(visibleRows, soonKey);\n\n      status.textContent = errs.length ? ('Skipped '+errs.length+' route'+(errs.length>1?'s':'')) : '';\n      setStatusInline(\n  (L.status_found || '%d sailings found').replace('%d', '<strong>'+total+'<\/strong>')\n);\n      out.innerHTML = renderTable(visibleRows) + renderCards(visibleRows) + moreButtonHtml(hiddenCount);\n      bindRowLinks();\n      if (navHost) navHost.innerHTML = navHtml();\n\n    } catch(e){\n      status.textContent = 'Failed to load data';\n      out.innerHTML = '<pre>'+String(e.message||e)+'<\/pre>';\n    } finally {\n      setLoader(false);\n      btn.disabled = false;\n    }\n  }\n\n  wrap.addEventListener('click', function(e){\n    const nav = e.target.closest('.tp-day-nav a[data-shift]');\n    if (nav) {\n      e.preventDefault();\n      shiftDate(parseInt(nav.getAttribute('data-shift'),10) || 0);\n      return;\n    }\n    const more = e.target.closest('.tp-more-btn');\n    if (more) {\n      e.preventDefault();\n      revealAll = true;\n      load();\n    }\n  });\n\n  btn.addEventListener('click', load);\n  if (navHost) navHost.innerHTML = navHtml();\n  renderLocalTimes();\n  setInterval(renderLocalTimes, 30000);\n  if (cfg.autoload) load();\n})();\n<\/script>\n\n\t\t\t<\/section>\n\n\t\t\t<section id=\"czas\">\n\t\t\t\t<h2>Ile trwa rejs z Dunkierki do Dover?<\/h2>\n\t\t\t\t<p>Rejs trwa dwie godziny, w obu kierunkach; prawdziwy czas na morzu to 2 godziny, cokolwiek m\u00f3wi bilet. Poniewa\u017c Anglia jest godzin\u0119 za Francj\u0105, na bilecie do Dover czas przyjazdu jest tylko godzin\u0119 po odje\u017adzie. Z powrotem do Dunkierki wygl\u0105da to na trzy godziny. Na pok\u0142adzie nic si\u0119 nie zmienia: zegarek cofasz o godzin\u0119 dopiero po przyje\u017adzie, a w drodze powrotnej przestawiasz o godzin\u0119 do przodu.<\/p>\n\t\t\t\t<div class=\"dd-panel dd-tw\"><table class=\"dd-table\">\n\t\t\t\t\t<thead><tr><th>Kierunek<\/th><th>Odjazd (czas lokalny)<\/th><th>Przyjazd (czas lokalny)<\/th><th>Rzeczywisty czas<\/th><\/tr><\/thead>\n\t\t\t\t\t<tbody>\n\t\t\t\t\t\t<tr><td>Dunkierka do Dover<\/td><td class=\"dd-num\">14:00 (CEST)<\/td><td class=\"dd-num\">15:00 (BST)<\/td><td class=\"dd-num\">2 godziny<\/td><\/tr>\n\t\t\t\t\t\t<tr><td>Dover do Dunkierki<\/td><td class=\"dd-num\">12:00 (BST)<\/td><td class=\"dd-num\">15:00 (CEST)<\/td><td class=\"dd-num\">2 godziny<\/td><\/tr>\n\t\t\t\t\t<\/tbody>\n\t\t\t\t<\/table><\/div>\n\t\t\t\t<p>Na ca\u0142o\u015b\u0107 licz oko\u0142o trzech godzin: godzina w porcie przed odjazdem, dwie godziny na morzu i kwadrans do p\u00f3\u0142 godziny na zjazd i wyjazd z portu.<\/p>\n\t\t\t\t<div class=\"dd-figs\"><figure class=\"dd-figure\"><img src=\"https:\/\/dover-dunkirk.com\/pl\/wp-content\/uploads\/sites\/5\/2026\/09\/wake-leaving-dunkirk.webp\" alt=\"Kilwater promu przy wyj\u015bciu z portu w Dunkierce\" width=\"1800\" height=\"1350\" loading=\"lazy\" decoding=\"async\"><figcaption>Wyj\u015bcie z Dunkierki: po kwadransie port zostaje za tob\u0105.<\/figcaption><\/figure><figure class=\"dd-figure\"><img src=\"https:\/\/dover-dunkirk.com\/pl\/wp-content\/uploads\/sites\/5\/2026\/09\/entering-dover-harbour.webp\" alt=\"Prom przep\u0142ywa mi\u0119dzy g\u0142\u00f3wkami portu w Dover\" width=\"1800\" height=\"1350\" loading=\"lazy\" decoding=\"async\"><figcaption>Dwie godziny p\u00f3\u017aniej: mi\u0119dzy g\u0142\u00f3wkami portu w Dover.<\/figcaption><\/figure><\/div>\t\t\t<\/section>\n\n\t\t\t<section id=\"odprawa\">\n\t\t\t\t<h2>Kiedy zamyka si\u0119 odprawa?<\/h2>\n\t\t\t\t<p>Odprawa zamyka si\u0119 60 minut przed odjazdem. W Dunkierce godzina wcze\u015bniej w zupe\u0142no\u015bci wystarcza: jeden przewo\u017anik i kr\u00f3tkie kolejki. W Dover francuska kontrola paszportowa odbywa si\u0119 przed wjazdem na prom, wi\u0119c w wakacje szkolne licz tam 90 do 120 minut. Je\u015bli si\u0119 sp\u00f3\u017anisz, DFDS zwykle wsadza ci\u0119 na nast\u0119pny rejs z wolnymi miejscami, po cenie obowi\u0105zuj\u0105cej w tym momencie.<\/p>\n\t\t\t\t<ol class=\"dd-steps\">\n\t\t\t\t\t<li><b>Terminal Loon-Plage, nie centrum Dunkierki<\/b><span>W nawigacji wpisz Loon-Plage albo Port 5625. Z A16 zjed\u017a na zje\u017adzie 53 i jed\u017a za znakami Car Ferry.<\/span><\/li>\n\t\t\t\t\t<li><b>Odprawa na stanowiskach<\/b><span>Pokazujesz numer rezerwacji albo e-mail. Dostajesz zawieszk\u0119 na lusterko z numerem pasa i godzin\u0105 rejsu.<\/span><\/li>\n\t\t\t\t\t<li><b>Kontrola graniczna i celna<\/b><span>Kontrola paszportowa Francji i Wielkiej Brytanii, potem czasem kontrola celna. Miej pod r\u0119k\u0105 paszporty i dow\u00f3d rejestracyjny.<\/span><\/li>\n\t\t\t\t\t<li><b>Czekanie na pasie<\/b><span>Jedziesz na pas z zawieszki. Wjazd na prom zaczyna si\u0119 oko\u0142o 30 minut przed odjazdem.<\/span><\/li>\n\t\t\t\t<\/ol>\n\t\t\t\t<div class=\"dd-tip\"><svg class=\"dd-ic\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9\"\/><path d=\"M12 11v5M12 8h.01\"\/><\/svg><span>Zwierz\u0119ta zostaj\u0105 w czasie rejsu w samochodzie. Wyprowad\u017a psa przed odpraw\u0105; obok parkingu przy terminalu jest wybieg.<\/span><\/div>\n\t\t\t<\/section>\n\n\t\t\t<section id=\"noc\">\n\t\t\t\t<h2>Rejsy nocne i weekend<\/h2>\n\t\t\t\t<p>Rejs o 23:59 z Dunkierki i ten o 04:00 nie p\u0142ywaj\u0105 codziennie; w weekend wypada kilka rejs\u00f3w. Przegl\u0105d powy\u017cej pokazuje dla ka\u017cdego dnia, co p\u0142ywa. Rezerwuj nocny rejs tylko wtedy, gdy widzisz go w rozk\u0142adzie, i pami\u0119taj, \u017ce w nocy terminal ma skromne zaplecze.<\/p>\n\t\t\t<\/section>\n\n\t\t\t<section id=\"pytania\">\n\t\t\t\t<h2>Cz\u0119ste pytania o rozk\u0142ad<\/h2>\n\t\t\t\t<div class=\"dd-faq\">\n\t\t\t\t\t<details open><summary>Jak cz\u0119sto p\u0142ywa prom z Dunkierki do Dover? <svg class=\"dd-ic\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M6 9l6 6 6-6\"\/><\/svg><\/summary><p>Do jedenastu razy dziennie, w dni robocze zwykle dziesi\u0119\u0107: o 04:00, 06:00, 08:00, 10:00, 12:00, 14:00, 16:00, 18:00, 20:00 i 23:59. W weekend wypada kilka rejs\u00f3w.<\/p><\/details>\n\t\t\t\t\t<details open><summary>Czy godziny s\u0105 podane w czasie polskim? <svg class=\"dd-ic\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M6 9l6 6 6-6\"\/><\/svg><\/summary><p>Odjazdy z Dunkierki s\u0105 w czasie francuskim, takim samym jak polski. Odjazdy z Dover s\u0105 w czasie angielskim, godzin\u0119 wcze\u015bniej.<\/p><\/details>\n\t\t\t\t\t<details open><summary>O kt\u00f3rej jest pierwszy i ostatni rejs? <svg class=\"dd-ic\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M6 9l6 6 6-6\"\/><\/svg><\/summary><p>Pierwszy rejs z Dunkierki jest o 04:00, ostatni o 23:59 w dni, w kt\u00f3re p\u0142ywa. Z Dover pierwszy o 02:00, ostatni o 22:00 czasu angielskiego.<\/p><\/details>\n\t\t\t\t\t<details open><summary>Co przy op\u00f3\u017anieniu albo odwo\u0142aniu? <svg class=\"dd-ic\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M6 9l6 6 6-6\"\/><\/svg><\/summary><p>Przy sztormie lub usterce technicznej DFDS czasem p\u0142ywa mniejsz\u0105 liczb\u0105 statk\u00f3w. Wtedy trafiasz na nast\u0119pny rejs. Aktualne komunikaty publikuje DFDS na stronie <a href=\"https:\/\/www.dfds.com\/en-gb\/passenger-ferries\/passenger-information\/travel-updates\" rel=\"noopener\" target=\"_blank\">travel updates<\/a> (po angielsku).<\/p><\/details>\n\t\t\t\t<\/div>\n\t\t\t<\/section>\n\t\t<\/div>\n\n\t\t<aside class=\"dd-aside\">\n\t\t\t<div class=\"dd-panel\"><h3>Rezerwacja na rejs<\/h3><p class=\"dd-small dd-muted\" style=\"margin:0 0 12px\">Ceny r\u00f3\u017cni\u0105 si\u0119 w zale\u017cno\u015bci od rejsu i dnia. Por\u00f3wnaj je dla wybranej godziny.<\/p><a class=\"dd-btn\" href=\"https:\/\/dover-dunkirk.com\/pl\/ceny-i-bilety\/\">Por\u00f3wnaj ceny<\/a><p class=\"dd-disc\">Rezerwujesz u naszego partnera DirectFerries.<\/p><\/div>\n\t\t\t<div class=\"dd-panel\"><h3>Trasa w liczbach<\/h3><div class=\"dd-panel dd-facts\"><dl><div><dt>Rejs<\/dt><dd class=\"dd-num\">2 godziny<\/dd><\/div><div><dt>Rejsy dziennie<\/dt><dd class=\"dd-num\">do 11 w ka\u017cd\u0105 stron\u0119<\/dd><\/div><div><dt>Odprawa zamyka si\u0119<\/dt><dd class=\"dd-num\">60 min przed<\/dd><\/div><div><dt>Auto + 5, w jedn\u0105 stron\u0119<\/dt><dd class=\"dd-num\">od 99 \u00a3<\/dd><\/div><div><dt>Pasa\u017cerowie piesi<\/dt><dd class=\"dd-num\">nieprzewo\u017ceni<\/dd><\/div><div><dt>Zwierz\u0119ta<\/dt><dd class=\"dd-num\">zostaj\u0105 w aucie<\/dd><\/div><\/dl><\/div><\/div>\n\t\t\t<div class=\"dd-panel\"><h3>Na tej stronie<\/h3><nav class=\"dd-toc\"><a href=\"#dzis\">Rejsy dzisiaj<\/a><a href=\"#tydzien\">Tydzie\u0144 do Dover<\/a><a href=\"#tydzien-powrot\">Tydzie\u0144 do Dunkierki<\/a><a href=\"#data\">Inna data<\/a><a href=\"#czas\">Czas rejsu<\/a><a href=\"#odprawa\">Odprawa<\/a><a href=\"#noc\">Noc i weekend<\/a><a href=\"#pytania\">Pytania<\/a><\/nav><\/div>\n\t\t<\/aside>\n\t<\/div>\n<\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>Rozk\u0142ad rejs\u00f3w Dunkierka Dover DFDS p\u0142ywa co dwie godziny, dzie\u0144 i noc, w obu kierunkach. Poni\u017cej dzisiejsze rejsy, rozk\u0142ad na najbli\u017cszy tydzie\u0144 i godziny, o kt\u00f3rych zamyka si\u0119 odprawa. Godziny odjazd\u00f3w podano w czasie lokalnym portu wyj\u015bcia. \u0179r\u00f3d\u0142o: rozk\u0142ad DFDS przez DirectFerries, od\u015bwie\u017cany co minut\u0119 Rejsy dzisiaj Oba kierunki, z godzin\u0105 zamkni\u0119cia odprawy. Dunkierka i&#8230;<\/p>\n","protected":false},"author":0,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_kad_post_transparent":"","_kad_post_title":"hide","_kad_post_layout":"fullwidth","_kad_post_sidebar_id":"","_kad_post_content_style":"unboxed","_kad_post_vertical_padding":"","_kad_post_feature":"hide","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"class_list":["post-88","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Rozk\u0142ad rejs\u00f3w Dunkierka Dover: dzisiejsze odjazdy i rozk\u0142ad tygodniowy<\/title>\n<meta name=\"description\" content=\"Rozk\u0142ad promu DFDS Dunkierka Dover: wszystkie dzisiejsze rejsy, rozk\u0142ad na najbli\u017cszy tydzie\u0144, wyja\u015bnienie dwugodzinnego rejsu i godzina zamkni\u0119cia odprawy.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Rozk\u0142ad rejs\u00f3w Dunkierka Dover: dzisiejsze odjazdy i rozk\u0142ad tygodniowy\" \/>\n<meta property=\"og:description\" content=\"Rozk\u0142ad promu DFDS Dunkierka Dover: wszystkie dzisiejsze rejsy, rozk\u0142ad na najbli\u017cszy tydzie\u0144, wyja\u015bnienie dwugodzinnego rejsu i godzina zamkni\u0119cia odprawy.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/\" \/>\n<meta property=\"og:site_name\" content=\"Prom Dunkierka Dover\" \/>\n<meta property=\"og:image\" content=\"https:\/\/dover-dunkirk.com\/pl\/wp-content\/uploads\/sites\/5\/2026\/09\/delft-seaways-bow-loading-ramp.webp\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/rozklad-rejsow\\\/\",\"url\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/rozklad-rejsow\\\/\",\"name\":\"Rozk\u0142ad rejs\u00f3w Dunkierka Dover: dzisiejsze odjazdy i rozk\u0142ad tygodniowy\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/rozklad-rejsow\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/rozklad-rejsow\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/09\\\/delft-seaways-bow-loading-ramp.webp\",\"datePublished\":\"2026-09-14T19:50:54+00:00\",\"description\":\"Rozk\u0142ad promu DFDS Dunkierka Dover: wszystkie dzisiejsze rejsy, rozk\u0142ad na najbli\u017cszy tydzie\u0144, wyja\u015bnienie dwugodzinnego rejsu i godzina zamkni\u0119cia odprawy.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/rozklad-rejsow\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/rozklad-rejsow\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/rozklad-rejsow\\\/#primaryimage\",\"url\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/09\\\/delft-seaways-bow-loading-ramp.webp\",\"contentUrl\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/wp-content\\\/uploads\\\/sites\\\/5\\\/2026\\\/09\\\/delft-seaways-bow-loading-ramp.webp\",\"width\":1400,\"height\":1050,\"caption\":\"Delft Seaways przy nabrze\u017cu w Dunkierce z opuszczon\u0105 ramp\u0105\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/rozklad-rejsow\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Rozk\u0142ad rejs\u00f3w Dunkierka Dover\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/#website\",\"url\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/\",\"name\":\"Prom Dunkierka Dover\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/dover-dunkirk.com\\\/pl\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Rozk\u0142ad rejs\u00f3w Dunkierka Dover: dzisiejsze odjazdy i rozk\u0142ad tygodniowy","description":"Rozk\u0142ad promu DFDS Dunkierka Dover: wszystkie dzisiejsze rejsy, rozk\u0142ad na najbli\u017cszy tydzie\u0144, wyja\u015bnienie dwugodzinnego rejsu i godzina zamkni\u0119cia odprawy.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/","og_locale":"en_US","og_type":"article","og_title":"Rozk\u0142ad rejs\u00f3w Dunkierka Dover: dzisiejsze odjazdy i rozk\u0142ad tygodniowy","og_description":"Rozk\u0142ad promu DFDS Dunkierka Dover: wszystkie dzisiejsze rejsy, rozk\u0142ad na najbli\u017cszy tydzie\u0144, wyja\u015bnienie dwugodzinnego rejsu i godzina zamkni\u0119cia odprawy.","og_url":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/","og_site_name":"Prom Dunkierka Dover","og_image":[{"url":"https:\/\/dover-dunkirk.com\/pl\/wp-content\/uploads\/sites\/5\/2026\/09\/delft-seaways-bow-loading-ramp.webp","type":"","width":"","height":""}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/","url":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/","name":"Rozk\u0142ad rejs\u00f3w Dunkierka Dover: dzisiejsze odjazdy i rozk\u0142ad tygodniowy","isPartOf":{"@id":"https:\/\/dover-dunkirk.com\/pl\/#website"},"primaryImageOfPage":{"@id":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/#primaryimage"},"image":{"@id":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/#primaryimage"},"thumbnailUrl":"https:\/\/dover-dunkirk.com\/pl\/wp-content\/uploads\/sites\/5\/2026\/09\/delft-seaways-bow-loading-ramp.webp","datePublished":"2026-09-14T19:50:54+00:00","description":"Rozk\u0142ad promu DFDS Dunkierka Dover: wszystkie dzisiejsze rejsy, rozk\u0142ad na najbli\u017cszy tydzie\u0144, wyja\u015bnienie dwugodzinnego rejsu i godzina zamkni\u0119cia odprawy.","breadcrumb":{"@id":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/#primaryimage","url":"https:\/\/dover-dunkirk.com\/pl\/wp-content\/uploads\/sites\/5\/2026\/09\/delft-seaways-bow-loading-ramp.webp","contentUrl":"https:\/\/dover-dunkirk.com\/pl\/wp-content\/uploads\/sites\/5\/2026\/09\/delft-seaways-bow-loading-ramp.webp","width":1400,"height":1050,"caption":"Delft Seaways przy nabrze\u017cu w Dunkierce z opuszczon\u0105 ramp\u0105"},{"@type":"BreadcrumbList","@id":"https:\/\/dover-dunkirk.com\/pl\/rozklad-rejsow\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/dover-dunkirk.com\/pl\/"},{"@type":"ListItem","position":2,"name":"Rozk\u0142ad rejs\u00f3w Dunkierka Dover"}]},{"@type":"WebSite","@id":"https:\/\/dover-dunkirk.com\/pl\/#website","url":"https:\/\/dover-dunkirk.com\/pl\/","name":"Prom Dunkierka Dover","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/dover-dunkirk.com\/pl\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/dover-dunkirk.com\/pl\/wp-json\/wp\/v2\/pages\/88","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dover-dunkirk.com\/pl\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/dover-dunkirk.com\/pl\/wp-json\/wp\/v2\/types\/page"}],"replies":[{"embeddable":true,"href":"https:\/\/dover-dunkirk.com\/pl\/wp-json\/wp\/v2\/comments?post=88"}],"version-history":[{"count":1,"href":"https:\/\/dover-dunkirk.com\/pl\/wp-json\/wp\/v2\/pages\/88\/revisions"}],"predecessor-version":[{"id":89,"href":"https:\/\/dover-dunkirk.com\/pl\/wp-json\/wp\/v2\/pages\/88\/revisions\/89"}],"wp:attachment":[{"href":"https:\/\/dover-dunkirk.com\/pl\/wp-json\/wp\/v2\/media?parent=88"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}