{"id":651,"date":"2023-05-11T11:56:09","date_gmt":"2023-05-11T11:56:09","guid":{"rendered":"https:\/\/puttgardenrodby.nl\/?page_id=651"},"modified":"2026-06-24T11:28:41","modified_gmt":"2026-06-24T11:28:41","slug":"fahrplan","status":"publish","type":"page","link":"https:\/\/puttgardenrodby.com\/de\/fahrplan\/","title":{"rendered":"Fahrplan"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"651\" class=\"elementor elementor-651\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-348d881 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"348d881\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t\t<div class=\"elementor-background-overlay\"><\/div>\n\t\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-top-column elementor-element elementor-element-2e117c7\" data-id=\"2e117c7\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-18585c6 elementor-widget elementor-widget-heading\" data-id=\"18585c6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">Puttgarden R\u00f8dby Fahrplan<\/h1>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-bf504aa elementor-widget elementor-widget-text-editor\" data-id=\"bf504aa\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Hier finden Sie den Fahrplan und die n\u00e4chsten Abfahrten der F\u00e4hre Puttgarden\u2013R\u00f8dby und R\u00f8dby\u2013Puttgarden. W\u00e4hlen Sie ein Datum und klicken Sie auf <strong>\u201eAbfahrten anzeigen\u201c<\/strong>, um die F\u00e4hrzeiten f\u00fcr diesen Tag zu pr\u00fcfen.<\/p>\n\n<div class=\"fg-route-facts\">\n  <div class=\"fg-route-fact\">\n    <span>Route<\/span>\n    <strong>Puttgarden \u21c4 R\u00f8dby<\/strong>\n  <\/div>\n\n  <div class=\"fg-route-fact\">\n    <span>Betreiber<\/span>\n    <strong>Scandlines<\/strong>\n  <\/div>\n\n  <div class=\"fg-route-fact\">\n    <span>\u00dcberfahrt<\/span>\n    <strong>circa 45 Minuten<\/strong>\n  <\/div>\n\n  <div class=\"fg-route-fact\">\n    <span>Abfahrten<\/span>\n    <strong>meist etwa alle 30 Minuten<\/strong>\n  <\/div>\n<\/div>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4c34fbd elementor-widget elementor-widget-text-editor\" data-id=\"4c34fbd\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default elementor-inline-editing pen\" contenteditable=\"true\" data-elementor-setting-key=\"title\" data-pen-placeholder=\"Type Here...\">Aktuelle Abfahrten Puttgarden R\u00f8dby<\/h2>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0a60307 elementor-widget elementor-widget-shortcode\" data-id=\"0a60307\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><div class=\"tp-wrap tp-theme-extended_cards tp-day-setup-modern\" data-config=\"{&quot;rest&quot;:&quot;https:\\\/\\\/puttgardenrodby.com\\\/de\\\/wp-json\\\/timetables-pro\\\/v1\\\/timetables&quot;,&quot;routes&quot;:[209],&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;209&quot;:&quot;Puttgarden-Rodby&quot;},&quot;opFilter&quot;:[&quot;32&quot;],&quot;labels&quot;:{&quot;ui_date&quot;:&quot;Datum&quot;,&quot;ui_days&quot;:&quot;Tage&quot;,&quot;ui_button&quot;:&quot;\\u00dcberfahrten anzeigen&quot;,&quot;status_idle&quot;:&quot;W\\u00e4hlen Sie ein Datum und klicken Sie auf \\u00dcberfahrten anzeigen&quot;,&quot;status_loading&quot;:&quot;Wird geladen...&quot;,&quot;status_empty&quot;:&quot;Keine \\u00dcberfahrten gefunden&quot;,&quot;status_found&quot;:&quot;%d \\u00dcberfahrten gefunden&quot;,&quot;th_date&quot;:&quot;Datum&quot;,&quot;th_dep&quot;:&quot;Abfahrt&quot;,&quot;th_arr&quot;:&quot;Ankunft&quot;,&quot;th_dur&quot;:&quot;Dauer&quot;,&quot;th_ship&quot;:&quot;Schiff&quot;,&quot;th_op&quot;:&quot;Betreiber&quot;,&quot;th_route&quot;:&quot;Route&quot;,&quot;wd_sun&quot;:&quot;SO&quot;,&quot;wd_mon&quot;:&quot;MO&quot;,&quot;wd_tue&quot;:&quot;DI&quot;,&quot;wd_wed&quot;:&quot;MI&quot;,&quot;wd_thu&quot;:&quot;DO&quot;,&quot;wd_fri&quot;:&quot;FR&quot;,&quot;wd_sat&quot;:&quot;SA&quot;,&quot;summary_footer_one&quot;:&quot;\\u00bb Alle %s Abfahrten im Fahrplan ansehen&quot;,&quot;summary_footer_two&quot;:&quot;\\u00bb Mehr Abfahrten von %1$s und %2$s im Fahrplan ansehen&quot;,&quot;summary_footer_generic&quot;:&quot;Weitere \\u00dcberfahrten im Fahrplan ansehen&quot;,&quot;summary_header&quot;:&quot;Die n\\u00e4chsten zwei Abfahrten:&quot;,&quot;summary_no_upcoming&quot;:&quot;Keine kommenden Abfahrten gefunden&quot;,&quot;more_link&quot;:&quot;Weitere \\u00dcberfahrten&quot;,&quot;more_departures_button&quot;:&quot;Weitere Abfahrten anzeigen&quot;,&quot;day_nav_previous&quot;:&quot;Vorherigen Tag anzeigen&quot;,&quot;day_nav_next&quot;:&quot;N\\u00e4chsten Tag anzeigen&quot;,&quot;day_nav_today&quot;:&quot;Heute anzeigen&quot;,&quot;day_nav_tomorrow&quot;:&quot;Morgen anzeigen&quot;,&quot;local_time_pair&quot;:&quot;Ortszeit Abfahrtshafen: %1$s \\\/ Ortszeit Ankunftshafen: %2$s&quot;,&quot;local_time_combined&quot;:&quot;Ortszeit Abfahrts- &amp; Ankunftshafen: %s&quot;,&quot;tag_often_booked&quot;:&quot;\\u2b50 Oft gebucht&quot;,&quot;tag_leaving_soon&quot;:&quot;\\ud83d\\udd34 Bald abfahrend&quot;,&quot;tag_currently_sailing&quot;:&quot;\\ud83d\\udfe2 Derzeit unterwegs&quot;,&quot;tag_arrived&quot;:&quot;\\u26ab Angekommen&quot;,&quot;tag_overnight&quot;:&quot;\\u00dcber Nacht&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;Puttgarden&quot;,&quot;arrivalPort&quot;:&quot;Rodby&quot;,&quot;departureTimezone&quot;:&quot;Europe\\\/Berlin&quot;,&quot;arrivalTimezone&quot;:&quot;Europe\\\/Copenhagen&quot;}\">\n  <div class=\"tp-controls\" role=\"group\" aria-label=\"Timetable controls\">\n    <div>\n      <label for=\"tp-date-ops\">Datum<\/label><br>\n      <input id=\"tp-date-ops\" class=\"tp-date\" type=\"date\" aria-label=\"Datum\">\n    <\/div>\n    <div class=\"tp-day-field\">\n      <label for=\"tp-range-ops\">Tage<\/label><br>\n      <select id=\"tp-range-ops\" class=\"tp-range\" aria-label=\"Tage\">\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\">\u00dcberfahrten anzeigen<\/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\">W\u00e4hlen Sie ein Datum und klicken Sie auf \u00dcberfahrten anzeigen<\/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\">Wird geladen...<\/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<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8759ece elementor-widget elementor-widget-text-editor\" data-id=\"8759ece\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default elementor-inline-editing pen\" contenteditable=\"true\" data-elementor-setting-key=\"title\" data-pen-placeholder=\"Type Here...\">Aktuelle Abfahrten R\u00f8dby Puttgarden<\/h2>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4322934 elementor-widget elementor-widget-shortcode\" data-id=\"4322934\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><div class=\"tp-wrap tp-theme-extended_cards tp-day-setup-modern\" data-config=\"{&quot;rest&quot;:&quot;https:\\\/\\\/puttgardenrodby.com\\\/de\\\/wp-json\\\/timetables-pro\\\/v1\\\/timetables&quot;,&quot;routes&quot;:[210],&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;210&quot;:&quot;Rodby Puttgarden&quot;},&quot;opFilter&quot;:[&quot;32&quot;],&quot;labels&quot;:{&quot;ui_date&quot;:&quot;Datum&quot;,&quot;ui_days&quot;:&quot;Tage&quot;,&quot;ui_button&quot;:&quot;\\u00dcberfahrten anzeigen&quot;,&quot;status_idle&quot;:&quot;W\\u00e4hlen Sie ein Datum und klicken Sie auf \\u00dcberfahrten anzeigen&quot;,&quot;status_loading&quot;:&quot;Wird geladen...&quot;,&quot;status_empty&quot;:&quot;Keine \\u00dcberfahrten gefunden&quot;,&quot;status_found&quot;:&quot;%d \\u00dcberfahrten gefunden&quot;,&quot;th_date&quot;:&quot;Datum&quot;,&quot;th_dep&quot;:&quot;Abfahrt&quot;,&quot;th_arr&quot;:&quot;Ankunft&quot;,&quot;th_dur&quot;:&quot;Dauer&quot;,&quot;th_ship&quot;:&quot;Schiff&quot;,&quot;th_op&quot;:&quot;Betreiber&quot;,&quot;th_route&quot;:&quot;Route&quot;,&quot;wd_sun&quot;:&quot;SO&quot;,&quot;wd_mon&quot;:&quot;MO&quot;,&quot;wd_tue&quot;:&quot;DI&quot;,&quot;wd_wed&quot;:&quot;MI&quot;,&quot;wd_thu&quot;:&quot;DO&quot;,&quot;wd_fri&quot;:&quot;FR&quot;,&quot;wd_sat&quot;:&quot;SA&quot;,&quot;summary_footer_one&quot;:&quot;\\u00bb Alle %s Abfahrten im Fahrplan ansehen&quot;,&quot;summary_footer_two&quot;:&quot;\\u00bb Mehr Abfahrten von %1$s und %2$s im Fahrplan ansehen&quot;,&quot;summary_footer_generic&quot;:&quot;Weitere \\u00dcberfahrten im Fahrplan ansehen&quot;,&quot;summary_header&quot;:&quot;Die n\\u00e4chsten zwei Abfahrten:&quot;,&quot;summary_no_upcoming&quot;:&quot;Keine kommenden Abfahrten gefunden&quot;,&quot;more_link&quot;:&quot;Weitere \\u00dcberfahrten&quot;,&quot;more_departures_button&quot;:&quot;Weitere Abfahrten anzeigen&quot;,&quot;day_nav_previous&quot;:&quot;Vorherigen Tag anzeigen&quot;,&quot;day_nav_next&quot;:&quot;N\\u00e4chsten Tag anzeigen&quot;,&quot;day_nav_today&quot;:&quot;Heute anzeigen&quot;,&quot;day_nav_tomorrow&quot;:&quot;Morgen anzeigen&quot;,&quot;local_time_pair&quot;:&quot;Ortszeit Abfahrtshafen: %1$s \\\/ Ortszeit Ankunftshafen: %2$s&quot;,&quot;local_time_combined&quot;:&quot;Ortszeit Abfahrts- &amp; Ankunftshafen: %s&quot;,&quot;tag_often_booked&quot;:&quot;\\u2b50 Oft gebucht&quot;,&quot;tag_leaving_soon&quot;:&quot;\\ud83d\\udd34 Bald abfahrend&quot;,&quot;tag_currently_sailing&quot;:&quot;\\ud83d\\udfe2 Derzeit unterwegs&quot;,&quot;tag_arrived&quot;:&quot;\\u26ab Angekommen&quot;,&quot;tag_overnight&quot;:&quot;\\u00dcber Nacht&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;Rodby&quot;,&quot;arrivalPort&quot;:&quot;Puttgarden&quot;,&quot;departureTimezone&quot;:&quot;Europe\\\/Copenhagen&quot;,&quot;arrivalTimezone&quot;:&quot;Europe\\\/Berlin&quot;}\">\n  <div class=\"tp-controls\" role=\"group\" aria-label=\"Timetable controls\">\n    <div>\n      <label for=\"tp-date-ops\">Datum<\/label><br>\n      <input id=\"tp-date-ops\" class=\"tp-date\" type=\"date\" aria-label=\"Datum\">\n    <\/div>\n    <div class=\"tp-day-field\">\n      <label for=\"tp-range-ops\">Tage<\/label><br>\n      <select id=\"tp-range-ops\" class=\"tp-range\" aria-label=\"Tage\">\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\">\u00dcberfahrten anzeigen<\/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\">W\u00e4hlen Sie ein Datum und klicken Sie auf \u00dcberfahrten anzeigen<\/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\">Wird geladen...<\/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<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5fe5d43 elementor-widget elementor-widget-text-editor\" data-id=\"5fe5d43\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h2>Bevor Sie eine Abfahrt w\u00e4hlen<\/h2>\n<div class=\"after-timetable-facts\">\n<div><strong>\u00dcberfahrtszeit<\/strong>\nDie F\u00e4hre zwischen Puttgarden und R\u00f8dby ben\u00f6tigt etwa 45 Minuten.<\/div>\n<div><strong>Check-in<\/strong>\nSeien Sie mindestens 15 Minuten vor der Abfahrt im Hafen.<\/div>\n<div><strong>Abfahrten<\/strong>\nDie Route wird rund um die Uhr bedient, h\u00e4ufig mit Abfahrten alle 30 Minuten.<\/div>\n<\/div>\n<h2>F\u00e4hrtickets Puttgarden R\u00f8dby<\/h2>\nWenn Sie eine passende Abfahrt gefunden haben, k\u00f6nnen Sie Ihr Ticket bei Scandlines buchen. Der Preis h\u00e4ngt vom Fahrzeug, der Ticketart, dem Reisetag und der gew\u00e4hlten Abfahrt ab.\n\n<a class=\"scandlines-booking-button\" href=\"https:\/\/puttgardenrodby.com\/de\/go\/ttout\" target=\"_blank\" rel=\"noopener\">\n<span class=\"scandlines-button-logo\">\n<img decoding=\"async\" src=\"https:\/\/puttgardenrodby.com\/de\/wp-content\/uploads\/sites\/4\/2026\/06\/scandlines-logo-e1781018366813.jpg\" alt=\"Scandlines\" \/>\n<\/span>\n<span class=\"scandlines-button-text\">\n<strong>F\u00e4hre bei Scandlines buchen<\/strong>\n<small>Puttgarden \u21c4 R\u00f8dby<\/small>\n<\/span>\n<span class=\"scandlines-button-arrow\">\u2b9e<\/span>\n<\/a>\n<p class=\"timetable-disclaimer\">Hinweis: Die Abfahrtszeiten werden \u00fcber eine API bereitgestellt und k\u00f6nnen sich \u00e4ndern. Ma\u00dfgeblich sind immer die aktuellen Informationen des F\u00e4hrbetreibers.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-top-column elementor-element elementor-element-9a29147\" data-id=\"9a29147\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-de19ae8 elementor-widget elementor-widget-text-editor\" data-id=\"de19ae8\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;sticky&quot;:&quot;top&quot;,&quot;sticky_parent&quot;:&quot;yes&quot;,&quot;sticky_offset&quot;:100,&quot;sticky_effects_offset&quot;:60,&quot;sticky_on&quot;:[&quot;desktop&quot;,&quot;tablet&quot;,&quot;mobile&quot;],&quot;sticky_anchor_link_offset&quot;:0}\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<aside class=\"timetable-sidebar\">\n<div class=\"sidebar-card sidebar-card-image\"><img fetchpriority=\"high\" decoding=\"async\" class=\"sidebar-image alignnone size-full\" src=\"https:\/\/puttgardenrodby.com\/de\/wp-content\/uploads\/sites\/4\/2023\/05\/Helsingborg.jpg\" alt=\"F\u00e4hre Puttgarden R\u00f8dby\" width=\"400\" height=\"300\" \/><\/div>\n<div class=\"sidebar-card\">\n<h3>Fahrplan-Hinweise<\/h3>\n<ul>\n \t<li><strong>Beide Richtungen:<\/strong> Puttgarden und R\u00f8dby<\/li>\n \t<li><strong>Heute:<\/strong> Datum w\u00e4hlen<\/li>\n \t<li><strong>Nacht:<\/strong> Zeiten pr\u00fcfen<\/li>\n \t<li><strong>Ferien:<\/strong> mehr Wartezeit m\u00f6glich<\/li>\n<\/ul>\n<\/div>\n<div class=\"sidebar-card\">\n<h3>Beliebt<\/h3>\n<ul>\n \t<li><a href=\"\/de\/preise\/\">F\u00e4hrpreise &amp; Tickets<\/a><\/li>\n \t<li><a href=\"\/de\/wetter\/\">Wetter an der F\u00e4hre<\/a><\/li>\n \t<li><a href=\"\/de\/webcams\/\">Webcams Puttgarden R\u00f8dby<\/a><\/li>\n \t<li><a href=\"\/de\/puttgarden\/\">Hafen Puttgarden<\/a><\/li>\n \t<li><a href=\"\/de\/rodby\/\">Hafen R\u00f8dby<\/a><\/li>\n<\/ul>\n<\/div>\n<div class=\"sidebar-card sidebar-cta\">\n<h3>F\u00e4hre buchen<\/h3>\nPr\u00fcfen Sie Abfahrten, Fahrzeiten und Tickets f\u00fcr die F\u00e4hre Puttgarden R\u00f8dby.\n\n<a href=\"\/go\/ttout\" target=\"_blank\" rel=\"noopener\">\u00dcberfahrt zusammenstellen \u2b9e<\/a>\n\n<\/div>\n<\/aside>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Puttgarden R\u00f8dby Fahrplan Hier finden Sie den Fahrplan und die n\u00e4chsten Abfahrten der F\u00e4hre Puttgarden\u2013R\u00f8dby und R\u00f8dby\u2013Puttgarden. W\u00e4hlen Sie ein Datum und klicken Sie auf \u201eAbfahrten anzeigen\u201c, um die F\u00e4hrzeiten f\u00fcr diesen Tag zu pr\u00fcfen. Route Puttgarden \u21c4 R\u00f8dby Betreiber Scandlines \u00dcberfahrt circa 45 Minuten Abfahrten meist etwa alle 30 Minuten Aktuelle Abfahrten Puttgarden R\u00f8dby [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-651","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>F\u00e4hre R\u00f6dby Puttgarden Fahrplan: Abfahrtszeiten heute<\/title>\n<meta name=\"description\" content=\"Aktueller Fahrplan der F\u00e4hre R\u00f6dby Puttgarden. Pr\u00fcfen Sie heutige Abfahrten, Fahrzeit, Check-in und Tickets.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/puttgardenrodby.com\/de\/fahrplan\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"F\u00e4hre R\u00f6dby Puttgarden Fahrplan: Abfahrtszeiten heute\" \/>\n<meta property=\"og:description\" content=\"Aktueller Fahrplan der F\u00e4hre R\u00f6dby Puttgarden. Pr\u00fcfen Sie heutige Abfahrten, Fahrzeit, Check-in und Tickets.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/puttgardenrodby.com\/de\/fahrplan\/\" \/>\n<meta property=\"og:site_name\" content=\"Puttgarden Rodby Deutsch\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-24T11:28:41+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/puttgardenrodby.com\/de\/wp-content\/uploads\/sites\/4\/2026\/06\/scandlines-logo-e1781018366813.jpg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data1\" content=\"2\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/fahrplan\\\/\",\"url\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/fahrplan\\\/\",\"name\":\"F\u00e4hre R\u00f6dby Puttgarden Fahrplan: Abfahrtszeiten heute\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/fahrplan\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/fahrplan\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/wp-content\\\/uploads\\\/sites\\\/4\\\/2026\\\/06\\\/scandlines-logo-e1781018366813.jpg\",\"datePublished\":\"2023-05-11T11:56:09+00:00\",\"dateModified\":\"2026-06-24T11:28:41+00:00\",\"description\":\"Aktueller Fahrplan der F\u00e4hre R\u00f6dby Puttgarden. Pr\u00fcfen Sie heutige Abfahrten, Fahrzeit, Check-in und Tickets.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/fahrplan\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/fahrplan\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/fahrplan\\\/#primaryimage\",\"url\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/wp-content\\\/uploads\\\/sites\\\/4\\\/2026\\\/06\\\/scandlines-logo-e1781018366813.jpg\",\"contentUrl\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/wp-content\\\/uploads\\\/sites\\\/4\\\/2026\\\/06\\\/scandlines-logo-e1781018366813.jpg\",\"width\":36,\"height\":36,\"caption\":\"scandlines logo\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/fahrplan\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Fahrplan\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/#website\",\"url\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/\",\"name\":\"Puttgarden Rodby Deutsch\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/#organization\",\"name\":\"Puttgarden Rodby Deutsch\",\"url\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/wp-content\\\/uploads\\\/sites\\\/4\\\/2023\\\/05\\\/Puttgarden-Rodby-logo.png\",\"contentUrl\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/wp-content\\\/uploads\\\/sites\\\/4\\\/2023\\\/05\\\/Puttgarden-Rodby-logo.png\",\"width\":1043,\"height\":347,\"caption\":\"Puttgarden Rodby Deutsch\"},\"image\":{\"@id\":\"https:\\\/\\\/puttgardenrodby.com\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"F\u00e4hre R\u00f6dby Puttgarden Fahrplan: Abfahrtszeiten heute","description":"Aktueller Fahrplan der F\u00e4hre R\u00f6dby Puttgarden. Pr\u00fcfen Sie heutige Abfahrten, Fahrzeit, Check-in und Tickets.","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:\/\/puttgardenrodby.com\/de\/fahrplan\/","og_locale":"de_DE","og_type":"article","og_title":"F\u00e4hre R\u00f6dby Puttgarden Fahrplan: Abfahrtszeiten heute","og_description":"Aktueller Fahrplan der F\u00e4hre R\u00f6dby Puttgarden. Pr\u00fcfen Sie heutige Abfahrten, Fahrzeit, Check-in und Tickets.","og_url":"https:\/\/puttgardenrodby.com\/de\/fahrplan\/","og_site_name":"Puttgarden Rodby Deutsch","article_modified_time":"2026-06-24T11:28:41+00:00","og_image":[{"url":"https:\/\/puttgardenrodby.com\/de\/wp-content\/uploads\/sites\/4\/2026\/06\/scandlines-logo-e1781018366813.jpg","type":"","width":"","height":""}],"twitter_card":"summary_large_image","twitter_misc":{"Gesch\u00e4tzte Lesezeit":"2\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/puttgardenrodby.com\/de\/fahrplan\/","url":"https:\/\/puttgardenrodby.com\/de\/fahrplan\/","name":"F\u00e4hre R\u00f6dby Puttgarden Fahrplan: Abfahrtszeiten heute","isPartOf":{"@id":"https:\/\/puttgardenrodby.com\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/puttgardenrodby.com\/de\/fahrplan\/#primaryimage"},"image":{"@id":"https:\/\/puttgardenrodby.com\/de\/fahrplan\/#primaryimage"},"thumbnailUrl":"https:\/\/puttgardenrodby.com\/de\/wp-content\/uploads\/sites\/4\/2026\/06\/scandlines-logo-e1781018366813.jpg","datePublished":"2023-05-11T11:56:09+00:00","dateModified":"2026-06-24T11:28:41+00:00","description":"Aktueller Fahrplan der F\u00e4hre R\u00f6dby Puttgarden. Pr\u00fcfen Sie heutige Abfahrten, Fahrzeit, Check-in und Tickets.","breadcrumb":{"@id":"https:\/\/puttgardenrodby.com\/de\/fahrplan\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/puttgardenrodby.com\/de\/fahrplan\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/puttgardenrodby.com\/de\/fahrplan\/#primaryimage","url":"https:\/\/puttgardenrodby.com\/de\/wp-content\/uploads\/sites\/4\/2026\/06\/scandlines-logo-e1781018366813.jpg","contentUrl":"https:\/\/puttgardenrodby.com\/de\/wp-content\/uploads\/sites\/4\/2026\/06\/scandlines-logo-e1781018366813.jpg","width":36,"height":36,"caption":"scandlines logo"},{"@type":"BreadcrumbList","@id":"https:\/\/puttgardenrodby.com\/de\/fahrplan\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/puttgardenrodby.com\/de\/"},{"@type":"ListItem","position":2,"name":"Fahrplan"}]},{"@type":"WebSite","@id":"https:\/\/puttgardenrodby.com\/de\/#website","url":"https:\/\/puttgardenrodby.com\/de\/","name":"Puttgarden Rodby Deutsch","description":"","publisher":{"@id":"https:\/\/puttgardenrodby.com\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/puttgardenrodby.com\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/puttgardenrodby.com\/de\/#organization","name":"Puttgarden Rodby Deutsch","url":"https:\/\/puttgardenrodby.com\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/puttgardenrodby.com\/de\/#\/schema\/logo\/image\/","url":"https:\/\/puttgardenrodby.com\/de\/wp-content\/uploads\/sites\/4\/2023\/05\/Puttgarden-Rodby-logo.png","contentUrl":"https:\/\/puttgardenrodby.com\/de\/wp-content\/uploads\/sites\/4\/2023\/05\/Puttgarden-Rodby-logo.png","width":1043,"height":347,"caption":"Puttgarden Rodby Deutsch"},"image":{"@id":"https:\/\/puttgardenrodby.com\/de\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/puttgardenrodby.com\/de\/wp-json\/wp\/v2\/pages\/651","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/puttgardenrodby.com\/de\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/puttgardenrodby.com\/de\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/puttgardenrodby.com\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/puttgardenrodby.com\/de\/wp-json\/wp\/v2\/comments?post=651"}],"version-history":[{"count":107,"href":"https:\/\/puttgardenrodby.com\/de\/wp-json\/wp\/v2\/pages\/651\/revisions"}],"predecessor-version":[{"id":1609,"href":"https:\/\/puttgardenrodby.com\/de\/wp-json\/wp\/v2\/pages\/651\/revisions\/1609"}],"wp:attachment":[{"href":"https:\/\/puttgardenrodby.com\/de\/wp-json\/wp\/v2\/media?parent=651"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}