{"id":63,"date":"2024-03-07T09:39:14","date_gmt":"2024-03-07T09:39:14","guid":{"rendered":"https:\/\/hirtshals-kristiansand.com\/de\/?page_id=63"},"modified":"2026-06-10T14:25:18","modified_gmt":"2026-06-10T14:25:18","slug":"fahrplan","status":"publish","type":"page","link":"https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/","title":{"rendered":"F\u00e4hre Fahrplan Hirtshals Kristiansand"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Sehen Sie sich den aktuellen Fahrplan f\u00fcr die F\u00e4hrverbindung Hirtshals Kristiansand (betrieben von Fjord Line und Color Line) an.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">F\u00e4hre Hirtshals Kristiansand fahrplan<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Abfahrts- und Ankunftszeiten vom <a href=\"https:\/\/hirtshals-kristiansand.com\/de\/hirsthals-hafen\/\">Hafen Hirtshals<\/a> anzeigen.<\/p>\n\n\n<div class=\"tp-wrap tp-theme-extended_cards tp-day-setup-modern\" data-config=\"{&quot;rest&quot;:&quot;https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/wp-json\\\/timetables-pro\\\/v1\\\/timetables&quot;,&quot;routes&quot;:[171],&quot;days&quot;:6,&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;171&quot;:&quot;Hirtshals nach Kristiansand&quot;},&quot;opFilter&quot;:[&quot;8&quot;,&quot;27&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;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;Alle Abfahrtszeiten&quot;,&quot;shipMap&quot;:[],&quot;shipLinks&quot;:{&quot;bf&quot;:&quot;https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/ms-bergensfjord\\\/&quot;,&quot;superspeed 1&quot;:&quot;https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/color-line-superspeed-1\\\/&quot;},&quot;showShip&quot;:true,&quot;departurePort&quot;:&quot;Hirtshals&quot;,&quot;arrivalPort&quot;:&quot;Kristiansand&quot;,&quot;departureTimezone&quot;:&quot;Europe\\\/Copenhagen&quot;,&quot;arrivalTimezone&quot;:&quot;Europe\\\/Oslo&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      <h3 style=\"margin:8px 0 12px;color:#0f172a;\">Alle Abfahrtszeiten<\/h3>\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();\n    let prevLabel = 'Show previous day';\n    let nextLabel = 'Show next day';\n    if (isToday) nextLabel = 'Show tomorrow';\n    if (base.toDateString() === tomorrow.toDateString()) prevLabel = '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\">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('<strong>'+total+'<\/strong> sailings found');\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\n\n\n<p class=\"wp-block-paragraph\">    <div class=\"fh-drive-tool\">\r\n        <h3>Berechne deine Ankunftszeit im Hafen von Hirtshals aus Deutschland<\/h3>\r\n        <p class=\"fh-text\">\r\n            Dieses Tool hilft dir bei der Planung deiner Fahrt nach Hirtshals. W\u00e4hle einfach deinen Abfahrtsort, den Reisetag und die Uhrzeit aus. Danach siehst du, wann du voraussichtlich im Hafen von Hirtshals ankommst.\r\n        <\/p>\r\n\r\n        <div class=\"fh-field\">\r\n            <label for=\"fh_place\">Abfahrtsort<\/label>\r\n            <select id=\"fh_place\">\r\n                <option value=\"hamburg\" selected>Hamburg<\/option>\r\n                <option value=\"bremen\">Bremen<\/option>\r\n                <option value=\"hannover\">Hannover<\/option>\r\n                <option value=\"berlin\">Berlin<\/option>\r\n                <option value=\"dusseldorf\">D\u00fcsseldorf<\/option>\r\n                <option value=\"koln\">K\u00f6ln<\/option>\r\n                <option value=\"frankfurt\">Frankfurt am Main<\/option>\r\n                <option value=\"munchen\">M\u00fcnchen<\/option>\r\n            <\/select>\r\n        <\/div>\r\n\r\n        <div class=\"fh-row\">\r\n            <div class=\"fh-field\">\r\n                <label for=\"fh_day\">Abfahrtstag<\/label>\r\n                <select id=\"fh_day\">\r\n                    <option value=\"1\">Montag<\/option>\r\n                    <option value=\"2\">Dienstag<\/option>\r\n                    <option value=\"3\">Mittwoch<\/option>\r\n                    <option value=\"4\">Donnerstag<\/option>\r\n                    <option value=\"5\">Freitag<\/option>\r\n                    <option value=\"6\">Samstag<\/option>\r\n                    <option value=\"0\">Sonntag<\/option>\r\n                <\/select>\r\n            <\/div>\r\n\r\n            <div class=\"fh-field\">\r\n                <label for=\"fh_time\">Abfahrtszeit<\/label>\r\n                <input type=\"time\" id=\"fh_time\" value=\"06:30\">\r\n            <\/div>\r\n        <\/div>\r\n\r\n        <div class=\"fh-field\">\r\n            <button type=\"button\" id=\"fh_calc\">Ankunftszeit berechnen<\/button>\r\n        <\/div>\r\n\r\n        <div id=\"fh_result\"><\/div>\r\n    <\/div>\r\n\r\n    <style>\r\n    .fh-drive-tool {\r\n        background: #f0f5fa;\r\n        padding: 26px 28px;\r\n        border-radius: 10px;\r\n    }\r\n\r\n    .fh-drive-tool h3 {\r\n        margin-bottom: 10px;\r\n    }\r\n\r\n    .fh-drive-tool .fh-text {\r\n        font-size: 0.95em;\r\n        margin-bottom: 20px;\r\n        line-height: 1.6;\r\n    }\r\n\r\n    .fh-drive-tool .fh-field {\r\n        margin-bottom: 18px;\r\n    }\r\n\r\n    .fh-drive-tool .fh-row {\r\n        display: flex;\r\n        gap: 14px;\r\n        align-items: flex-end;\r\n    }\r\n\r\n    .fh-drive-tool .fh-row .fh-field {\r\n        width: 50%;\r\n        display: flex;\r\n        flex-direction: column;\r\n    }\r\n\r\n    .fh-drive-tool button {\r\n        width: 100%;\r\n        padding: 16px 0;\r\n    }\r\n\r\n    .fh-drive-tool #fh_result {\r\n        margin-top: 20px;\r\n        font-size: 0.95em;\r\n        line-height: 1.6;\r\n    }\r\n\r\n    .fh-drive-tool #fh_result strong {\r\n        font-size: 1.05em;\r\n    }\r\n\r\n    @media (max-width: 767px) {\r\n        .fh-drive-tool .fh-row {\r\n            display: block;\r\n        }\r\n\r\n        .fh-drive-tool .fh-row .fh-field {\r\n            width: 100%;\r\n        }\r\n    }\r\n    <\/style>\r\n\r\n    <script>\r\n    document.addEventListener('DOMContentLoaded', function () {\r\n        var placeEl = document.getElementById('fh_place');\r\n        var dayEl = document.getElementById('fh_day');\r\n        var timeEl = document.getElementById('fh_time');\r\n        var calcEl = document.getElementById('fh_calc');\r\n        var resultEl = document.getElementById('fh_result');\r\n\r\n        if (!placeEl) return;\r\n\r\n        var baseMinutes = {\r\n            hamburg: 310,\r\n            bremen: 395,\r\n            hannover: 445,\r\n            berlin: 520,\r\n            dusseldorf: 585,\r\n            koln: 610,\r\n            frankfurt: 650,\r\n            munchen: 820\r\n        };\r\n\r\n        function pad(n){ return String(n).padStart(2,'0'); }\r\n\r\n        function minutesToText(total){\r\n            var h = Math.floor(total \/ 60);\r\n            var m = total % 60;\r\n            return m === 0 ? h + ' Stunden' : h + ' Stunden und ' + m + ' Minuten';\r\n        }\r\n\r\n        function getTrafficExtra(day, minutes, place){\r\n            var extra = 0;\r\n            var isWeekday = day >= 1 && day <= 5;\r\n\r\n            if (isWeekday){\r\n                if (minutes >= 360 && minutes < 570) extra += 35;\r\n                if (minutes >= 930 && minutes < 1110) extra += 25;\r\n            }\r\n\r\n            if (['hamburg','berlin','dusseldorf','koln','frankfurt','munchen'].includes(place) && isWeekday && minutes < 600){\r\n                extra += 15;\r\n            }\r\n\r\n            return Math.max(0, extra);\r\n        }\r\n\r\n        function formatArrival(time, drive){\r\n            var parts = time.split(':');\r\n            var total = (parseInt(parts[0])*60 + parseInt(parts[1]) + drive) % 1440;\r\n            return pad(Math.floor(total\/60)) + ':' + pad(total%60);\r\n        }\r\n\r\n        calcEl.addEventListener('click', function(){\r\n            var place = placeEl.value;\r\n            var day = parseInt(dayEl.value,10);\r\n            var time = timeEl.value;\r\n\r\n            if (!time){\r\n                resultEl.innerHTML = 'W\u00e4hle zuerst eine Abfahrtszeit aus.';\r\n                return;\r\n            }\r\n\r\n            var minutes = (parseInt(time.split(':')[0])*60 + parseInt(time.split(':')[1]));\r\n            var total = baseMinutes[place] + getTrafficExtra(day, minutes, place);\r\n            var arrival = formatArrival(time, total);\r\n\r\n            resultEl.innerHTML =\r\n            '<p><strong>Voraussichtliche Ankunftszeit im Hafen von Hirtshals: ' + arrival + ' Uhr<\/strong><br>' +\r\n            'Die Fahrzeit betr\u00e4gt ungef\u00e4hr ' + minutesToText(total) + '. Diese Berechnung ber\u00fccksichtigt Verkehrsaufkommen, Sto\u00dfzeiten, Wochentage und m\u00f6gliche Verz\u00f6gerungen.<\/p>';\r\n        });\r\n    });\r\n    <\/script>\r\n    <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">F\u00e4hre Kristiansand Hirtshals fahrplan<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Reisen Sie auch von Kristiansand zur\u00fcck nach Hirtshals? Dann \u00fcberpr\u00fcfen Sie unten die Abfahrts- und Ankunftszeiten vom <a href=\"https:\/\/hirtshals-kristiansand.com\/de\/kristiansand-hafen\/\">Hafen Kristiansand<\/a>.<\/p>\n\n\n<div class=\"tp-wrap tp-theme-extended_cards tp-day-setup-modern\" data-config=\"{&quot;rest&quot;:&quot;https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/wp-json\\\/timetables-pro\\\/v1\\\/timetables&quot;,&quot;routes&quot;:[172],&quot;days&quot;:6,&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;172&quot;:&quot;Kristiansand nach Hirtshals&quot;},&quot;opFilter&quot;:[&quot;8&quot;,&quot;27&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;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;Alle Abfahrtszeiten&quot;,&quot;shipMap&quot;:[],&quot;shipLinks&quot;:{&quot;bf&quot;:&quot;https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/ms-bergensfjord\\\/&quot;,&quot;superspeed 1&quot;:&quot;https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/color-line-superspeed-1\\\/&quot;},&quot;showShip&quot;:true,&quot;departurePort&quot;:&quot;Kristiansand&quot;,&quot;arrivalPort&quot;:&quot;Hirtshals&quot;,&quot;departureTimezone&quot;:&quot;Europe\\\/Oslo&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      <h3 style=\"margin:8px 0 12px;color:#0f172a;\">Alle Abfahrtszeiten<\/h3>\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();\n    let prevLabel = 'Show previous day';\n    let nextLabel = 'Show next day';\n    if (isToday) nextLabel = 'Show tomorrow';\n    if (base.toDateString() === tomorrow.toDateString()) prevLabel = '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\">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('<strong>'+total+'<\/strong> sailings found');\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\n\n\n<p class=\"has-small-font-size wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Weitere Informationen zum Fahrplan<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">M\u00f6chten Sie mehr \u00fcber die Schiffe erfahren? Lesen Sie mehr \u00fcber die betreffende F\u00e4hre:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/hirtshals-kristiansand.com\/de\/ms-bergensfjord\/\">MS Bergensfjord<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/hirtshals-kristiansand.com\/de\/ms-stavangerfjord\/\">MS Stavangerfjord<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/hirtshals-kristiansand.com\/de\/fjord-fstr\/\">Fjord FSTR<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/hirtshals-kristiansand.com\/de\/color-line-superspeed-1\/\">Color Line SuperSpeed 1<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Color Line:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/hirtshals-kristiansand.com\/de\/hirsthals-hafen\/color-line-terminal\/\">Color Line Terminal Hirtshals<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/hirtshals-kristiansand.com\/de\/kristiansand-hafen\/color-line-terminal\/\">Color Line Terminal Kristiansand<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Fjord Line:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/hirtshals-kristiansand.com\/de\/hirsthals-hafen\/fjord-line-terminal\/\">Fjord Line Terminal Hirtshals<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/hirtshals-kristiansand.com\/de\/kristiansand-hafen\/fjord-line-terminal\/\">Fjord Line Terminal Kristiansand<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Sehen Sie sich den aktuellen Fahrplan f\u00fcr die F\u00e4hrverbindung Hirtshals Kristiansand (betrieben von Fjord Line und Color Line) an. F\u00e4hre [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":153,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"inline_featured_image":false,"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-63","page","type-page","status-publish","has-post-thumbnail","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 Fahrplan Hirtshals Kristiansand (Color Line &amp; Fjord Line)<\/title>\n<meta name=\"description\" content=\"Entdecken Sie hier den aktuellen Fahrplan der F\u00e4hre Hirtshals Kristiansand. Der Fahrplan von Color Line und Fjord Line.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/hirtshals-kristiansand.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 Fahrplan Hirtshals Kristiansand (Color Line &amp; Fjord Line)\" \/>\n<meta property=\"og:description\" content=\"Entdecken Sie hier den aktuellen Fahrplan der F\u00e4hre Hirtshals Kristiansand. Der Fahrplan von Color Line und Fjord Line.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/\" \/>\n<meta property=\"og:site_name\" content=\"Hirtshals Kristiansand F\u00e4hre Guide\" \/>\n<meta property=\"article:modified_time\" content=\"2026-06-10T14:25:18+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"800\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\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=\"1\u00a0Minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/fahrplan\\\/\",\"url\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/fahrplan\\\/\",\"name\":\"F\u00e4hre Fahrplan Hirtshals Kristiansand (Color Line & Fjord Line)\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/fahrplan\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/fahrplan\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/wp-content\\\/uploads\\\/sites\\\/3\\\/2024\\\/03\\\/hirtshals-kristiansand-ferry-2.jpg\",\"datePublished\":\"2024-03-07T09:39:14+00:00\",\"dateModified\":\"2026-06-10T14:25:18+00:00\",\"description\":\"Entdecken Sie hier den aktuellen Fahrplan der F\u00e4hre Hirtshals Kristiansand. Der Fahrplan von Color Line und Fjord Line.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/fahrplan\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/fahrplan\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/fahrplan\\\/#primaryimage\",\"url\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/wp-content\\\/uploads\\\/sites\\\/3\\\/2024\\\/03\\\/hirtshals-kristiansand-ferry-2.jpg\",\"contentUrl\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/wp-content\\\/uploads\\\/sites\\\/3\\\/2024\\\/03\\\/hirtshals-kristiansand-ferry-2.jpg\",\"width\":1200,\"height\":800,\"caption\":\"fahrplan\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/fahrplan\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Hirtshals Kristiansand\",\"item\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"F\u00e4hre Fahrplan Hirtshals Kristiansand\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/#website\",\"url\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/\",\"name\":\"Hirtshals Kristiansand F\u00e4hre Guide\",\"description\":\"Alles \u00fcber die Hirtshals Kristiansand F\u00e4hr\u00fcberfahrt\",\"publisher\":{\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/#organization\",\"name\":\"Hirtshals Kristiansand F\u00e4hre Guide\",\"url\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/wp-content\\\/uploads\\\/sites\\\/3\\\/2025\\\/05\\\/hirtshals-kristiansand.svg\",\"contentUrl\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/wp-content\\\/uploads\\\/sites\\\/3\\\/2025\\\/05\\\/hirtshals-kristiansand.svg\",\"width\":800,\"height\":256,\"caption\":\"Hirtshals Kristiansand F\u00e4hre Guide\"},\"image\":{\"@id\":\"https:\\\/\\\/hirtshals-kristiansand.com\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"F\u00e4hre Fahrplan Hirtshals Kristiansand (Color Line & Fjord Line)","description":"Entdecken Sie hier den aktuellen Fahrplan der F\u00e4hre Hirtshals Kristiansand. Der Fahrplan von Color Line und Fjord Line.","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:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/","og_locale":"de_DE","og_type":"article","og_title":"F\u00e4hre Fahrplan Hirtshals Kristiansand (Color Line & Fjord Line)","og_description":"Entdecken Sie hier den aktuellen Fahrplan der F\u00e4hre Hirtshals Kristiansand. Der Fahrplan von Color Line und Fjord Line.","og_url":"https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/","og_site_name":"Hirtshals Kristiansand F\u00e4hre Guide","article_modified_time":"2026-06-10T14:25:18+00:00","og_image":[{"width":1200,"height":800,"url":"https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Gesch\u00e4tzte Lesezeit":"1\u00a0Minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/","url":"https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/","name":"F\u00e4hre Fahrplan Hirtshals Kristiansand (Color Line & Fjord Line)","isPartOf":{"@id":"https:\/\/hirtshals-kristiansand.com\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/#primaryimage"},"image":{"@id":"https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/#primaryimage"},"thumbnailUrl":"https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2.jpg","datePublished":"2024-03-07T09:39:14+00:00","dateModified":"2026-06-10T14:25:18+00:00","description":"Entdecken Sie hier den aktuellen Fahrplan der F\u00e4hre Hirtshals Kristiansand. Der Fahrplan von Color Line und Fjord Line.","breadcrumb":{"@id":"https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/#primaryimage","url":"https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2.jpg","contentUrl":"https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2.jpg","width":1200,"height":800,"caption":"fahrplan"},{"@type":"BreadcrumbList","@id":"https:\/\/hirtshals-kristiansand.com\/de\/fahrplan\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Hirtshals Kristiansand","item":"https:\/\/hirtshals-kristiansand.com\/de\/"},{"@type":"ListItem","position":2,"name":"F\u00e4hre Fahrplan Hirtshals Kristiansand"}]},{"@type":"WebSite","@id":"https:\/\/hirtshals-kristiansand.com\/de\/#website","url":"https:\/\/hirtshals-kristiansand.com\/de\/","name":"Hirtshals Kristiansand F\u00e4hre Guide","description":"Alles \u00fcber die Hirtshals Kristiansand F\u00e4hr\u00fcberfahrt","publisher":{"@id":"https:\/\/hirtshals-kristiansand.com\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/hirtshals-kristiansand.com\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/hirtshals-kristiansand.com\/de\/#organization","name":"Hirtshals Kristiansand F\u00e4hre Guide","url":"https:\/\/hirtshals-kristiansand.com\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/hirtshals-kristiansand.com\/de\/#\/schema\/logo\/image\/","url":"https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2025\/05\/hirtshals-kristiansand.svg","contentUrl":"https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2025\/05\/hirtshals-kristiansand.svg","width":800,"height":256,"caption":"Hirtshals Kristiansand F\u00e4hre Guide"},"image":{"@id":"https:\/\/hirtshals-kristiansand.com\/de\/#\/schema\/logo\/image\/"}}]}},"uagb_featured_image_src":{"full":["https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2.jpg",1200,800,false],"thumbnail":["https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2-150x150.jpg",150,150,true],"medium":["https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2-300x200.jpg",300,200,true],"medium_large":["https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2-768x512.jpg",768,512,true],"large":["https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2-1024x683.jpg",1024,683,true],"1536x1536":["https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2.jpg",1200,800,false],"2048x2048":["https:\/\/hirtshals-kristiansand.com\/de\/wp-content\/uploads\/sites\/3\/2024\/03\/hirtshals-kristiansand-ferry-2.jpg",1200,800,false]},"uagb_author_info":{"display_name":"mail@robberttigchelaar.com","author_link":"https:\/\/hirtshals-kristiansand.com\/de\/author\/mailrobberttigchelaar-com\/"},"uagb_comment_info":0,"uagb_excerpt":"Sehen Sie sich den aktuellen Fahrplan f\u00fcr die F\u00e4hrverbindung Hirtshals Kristiansand (betrieben von Fjord Line und Color Line) an. F\u00e4hre [&hellip;]","_links":{"self":[{"href":"https:\/\/hirtshals-kristiansand.com\/de\/wp-json\/wp\/v2\/pages\/63","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hirtshals-kristiansand.com\/de\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/hirtshals-kristiansand.com\/de\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/hirtshals-kristiansand.com\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hirtshals-kristiansand.com\/de\/wp-json\/wp\/v2\/comments?post=63"}],"version-history":[{"count":11,"href":"https:\/\/hirtshals-kristiansand.com\/de\/wp-json\/wp\/v2\/pages\/63\/revisions"}],"predecessor-version":[{"id":412,"href":"https:\/\/hirtshals-kristiansand.com\/de\/wp-json\/wp\/v2\/pages\/63\/revisions\/412"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hirtshals-kristiansand.com\/de\/wp-json\/wp\/v2\/media\/153"}],"wp:attachment":[{"href":"https:\/\/hirtshals-kristiansand.com\/de\/wp-json\/wp\/v2\/media?parent=63"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}