{"id":3113,"date":"2026-08-17T13:37:59","date_gmt":"2026-08-17T12:37:59","guid":{"rendered":"https:\/\/ls2026.aau.dk\/?page_id=3113"},"modified":"2026-08-21T13:58:39","modified_gmt":"2026-08-21T12:58:39","slug":"program-search","status":"publish","type":"page","link":"https:\/\/ls2026.aau.dk\/?page_id=3113","title":{"rendered":"Program Search"},"content":{"rendered":"\n<style>\n  .symp {\n    --symp-red: #b02525; --symp-red-light: #ef9797; --symp-border: #ffb2bf;\n    --symp-text: #9f0000; --symp-muted: #6b7280; --symp-panel: #ffe0e5;\n    font-family: 'DM Sans', sans-serif;\n    color: #1a1d23;\n    max-width: 1000px;\n    margin: 0 auto;\n    padding: 0 0 64px;\n  }\n  .symp *, .symp *::before, .symp *::after { box-sizing: border-box; }\n\n  \/* ---- Sticky search header ---- *\/\n  .symp .pp-head { position: sticky; top: 0; z-index: 20; background: #fff; padding: 20px 0 14px; border-bottom: 2px solid var(--symp-border); margin-bottom: 4px; }\n  .symp .pp-searchrow { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }\n  .symp .pp-search { flex: 1; min-width: 220px; font-family: 'DM Sans', sans-serif; font-size: 0.95rem; color: #1a1d23; background: #fff; border: 2px solid var(--symp-border); border-radius: 999px; padding: 12px 20px; outline: none; transition: border-color 0.15s; }\n  .symp .pp-search:focus { border-color: var(--symp-red); }\n  .symp .pp-search::placeholder { color: var(--symp-muted); }\n  .symp .pp-btn { font-family: 'DM Sans', sans-serif; font-size: 0.82rem; font-weight: 600; background: #fff; color: var(--symp-red); border: 2px solid var(--symp-border); border-radius: 999px; padding: 11px 20px; cursor: pointer; transition: background 0.15s, border-color 0.15s, color 0.15s; white-space: nowrap; }\n  .symp .pp-btn:hover { border-color: var(--symp-red); }\n  .symp .pp-btn.on { background: var(--symp-red); color: #fff; border-color: var(--symp-red); }\n  .symp .pp-status { font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; font-weight: 600; color: var(--symp-muted); margin: 12px 0 0; }\n\n  \/* ---- Author rows ---- *\/\n  .symp .pp-person { display: flex; gap: 16px; padding: 18px 0; border-bottom: 1px solid var(--symp-border); }\n  .symp .pp-avatar { width: 46px; height: 46px; border-radius: 50%; background: var(--symp-red-light); display: flex; align-items: center; justify-content: center; font-size: 0.8rem; font-weight: 700; color: var(--symp-red); flex-shrink: 0; }\n  .symp .pp-body { flex: 1; min-width: 0; }\n  .symp .pp-name { font-size: 1rem; font-weight: 600; color: var(--symp-text); margin: 0; line-height: 1.35; overflow-wrap: break-word; }\n  .symp .pp-papers { display: flex; flex-direction: column; gap: 12px; margin-top: 9px; }\n  .symp .pp-paper { font-size: 0.88rem; color: #1a1d23; line-height: 1.5; overflow-wrap: break-word; word-break: break-word; }\n  .symp .pp-co { font-size: 0.76rem; font-style: italic; color: var(--symp-muted); margin: 3px 0 0; line-height: 1.5; overflow-wrap: break-word; }\n  .symp .pp-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }\n  .symp .pp-tag { display: inline-block; font-size: 0.68rem; font-weight: 600; letter-spacing: 0.04em; background: var(--symp-panel); color: var(--symp-red); border-radius: 4px; padding: 3px 8px; white-space: nowrap; }\n  .symp .pp-tag.theme { background: var(--symp-red); color: #fff; white-space: normal; }\n  .symp mark { background: #ffd24d; color: #1a1d23; border-radius: 2px; padding: 0 1px; }\n\n  \/* ---- Session groups ---- *\/\n  .symp .pp-group { padding: 20px 0; border-bottom: 1px solid var(--symp-border); }\n  .symp .pp-group-title { font-size: 1rem; font-weight: 600; color: var(--symp-text); margin: 0 0 7px; line-height: 1.35; }\n  .symp .pp-group-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }\n  .symp .pp-group-sub { font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--symp-muted); margin: 8px 0 4px; font-weight: 600; }\n  .symp .pp-group .pp-paper { padding: 9px 0 0; }\n\n  \/* ---- States ---- *\/\n  .symp .pp-msg { font-size: 0.9rem; color: var(--symp-muted); line-height: 1.7; padding: 48px 20px; text-align: center; }\n  .symp .pp-msg strong { color: var(--symp-text); display: block; font-size: 0.98rem; margin-bottom: 6px; }\n\n  @media (max-width: 768px) {\n    .symp { padding: 0 0 48px; }\n    .symp .pp-head { padding: 14px 0 12px; }\n    .symp .pp-search { min-width: 0; width: 100%; font-size: 16px; padding: 11px 18px; }\n    .symp .pp-btn { flex: 1; padding: 10px 14px; font-size: 0.78rem; }\n    .symp .pp-status { margin-top: 10px; font-size: 0.7rem; }\n    .symp .pp-person { gap: 12px; padding: 15px 0; }\n    .symp .pp-avatar { width: 38px; height: 38px; font-size: 0.72rem; }\n    .symp .pp-name { font-size: 0.92rem; }\n    .symp .pp-paper { font-size: 0.83rem; }\n    .symp .pp-group { padding: 16px 0; }\n    .symp .pp-group-title { font-size: 0.92rem; }\n  }\n<\/style>\n\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=DM+Sans:ital,wght@0,300;0,400;0,500;0,600;1,300&amp;display=swap\" rel=\"stylesheet\">\n\n<!-- ============================================================\n     AUTHORS AND PAPERS - standalone page\n     Put your Media Library CSV address in data-csv-url below.\n     Nothing else needs editing.\n\n     Columns used (any order, extra columns are ignored):\n       Paper Session, Session Theme, Title, Authors (Full Names), Day, Time\n     Ignored: Abstract Id, Abstract, Authors (short form), Assosiation, Notes\n\n     Rows with no author name are skipped, so placeholder rows for\n     keynotes stay hidden until they are filled in.\n     ============================================================ -->\n<div class=\"symp\" id=\"pp-root\" data-csv-url=\"https:\/\/ls2026.aau.dk\/wp-content\/uploads\/2026\/08\/abstractSubmissionsReport_with_sessions.csv\">\n\n  <div class=\"pp-head\">\n    <div class=\"pp-searchrow\">\n      <input type=\"text\" class=\"pp-search\" id=\"pp-search\" placeholder=\"Search author, paper title or theme...\" autocomplete=\"off\" disabled>\n      <button class=\"pp-btn on\" id=\"pp-view-people\" type=\"button\">By author<\/button>\n      <button class=\"pp-btn\" id=\"pp-view-theme\" type=\"button\">By session<\/button>\n    <\/div>\n    <p class=\"pp-status\" id=\"pp-status\">Loading&#8230;<\/p>\n  <\/div>\n\n  <div id=\"pp-list\">\n    <p class=\"pp-msg\">Loading the paper list&#8230;<\/p>\n  <\/div>\n\n<\/div>\n\n<script>\n(function () {\n  var root = document.getElementById('pp-root');\n  if (!root) { return; }\n\n  var listEl = document.getElementById('pp-list');\n  var searchEl = document.getElementById('pp-search');\n  var btnPeople = document.getElementById('pp-view-people');\n  var btnTheme = document.getElementById('pp-view-theme');\n  var statusEl = document.getElementById('pp-status');\n\n  var papers = [];\n  var people = [];\n  var groups = [];\n  var view = 'people';\n\n  \/* ---------- helpers ---------- *\/\n\n  function esc(s) {\n    return String(s === undefined || s === null ? '' : s)\n      .replace(\/&\/g, '&amp;')\n      .replace(\/\\u003C\/g, '&lt;')\n      .replace(\/\\u003E\/g, '&gt;')\n      .replace(\/\"\/g, '&quot;');\n  }\n\n  function initials(name) {\n    var parts = String(name).trim().split(\/\\s+\/).filter(Boolean);\n    if (!parts.length) { return '?'; }\n    if (parts.length === 1) { return parts[0].substring(0, 2).toUpperCase(); }\n    return (parts[0].charAt(0) + parts[parts.length - 1].charAt(0)).toUpperCase();\n  }\n\n  function surname(name) {\n    var parts = String(name).trim().split(\/\\s+\/).filter(Boolean);\n    return parts.length ? parts[parts.length - 1] : name;\n  }\n\n  var DAY_ORDER = {\n    monday: 1, tuesday: 2, wednesday: 3, thursday: 4, friday: 5, saturday: 6, sunday: 7,\n    mandag: 1, tirsdag: 2, onsdag: 3, torsdag: 4, fredag: 5, lordag: 6, sondag: 7\n  };\n\n  function dayRank(day) {\n    var key = String(day).toLowerCase().trim();\n    return DAY_ORDER[key] || 99;\n  }\n\n  \/* ---------- text decoding (UTF-8, Windows-1252, mojibake repair) ---------- *\/\n\n  var CP1252 = {\n    '\\u20AC': 0x80, '\\u201A': 0x82, '\\u0192': 0x83, '\\u201E': 0x84,\n    '\\u2026': 0x85, '\\u2020': 0x86, '\\u2021': 0x87, '\\u02C6': 0x88,\n    '\\u2030': 0x89, '\\u0160': 0x8A, '\\u2039': 0x8B, '\\u0152': 0x8C,\n    '\\u017D': 0x8E, '\\u2018': 0x91, '\\u2019': 0x92, '\\u201C': 0x93,\n    '\\u201D': 0x94, '\\u2022': 0x95, '\\u2013': 0x96, '\\u2014': 0x97,\n    '\\u02DC': 0x98, '\\u2122': 0x99, '\\u0161': 0x9A, '\\u203A': 0x9B,\n    '\\u0153': 0x9C, '\\u017E': 0x9E, '\\u0178': 0x9F\n  };\n\n  function repairMojibake(text) {\n    if (!\/[\\u00C2-\\u00C3][\\u0080-\\u00BF]\/.test(text)) { return text; }\n    var bytes = new Uint8Array(text.length);\n    var i = 0;\n    while (i !== text.length) {\n      var ch = text.charAt(i);\n      var code = ch.charCodeAt(0);\n      if (code > 0xFF) {\n        if (CP1252[ch] === undefined) { return text; }\n        bytes[i] = CP1252[ch];\n      } else {\n        bytes[i] = code;\n      }\n      i = i + 1;\n    }\n    try {\n      return new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n    } catch (e) {\n      return text;\n    }\n  }\n\n  function decodeBuffer(buffer) {\n    var bytes = new Uint8Array(buffer);\n    if (typeof TextDecoder === 'undefined') {\n      return String.fromCharCode.apply(null, bytes);\n    }\n    var text;\n    try {\n      text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);\n    } catch (e) {\n      try {\n        text = new TextDecoder('windows-1252').decode(bytes);\n      } catch (e2) {\n        text = new TextDecoder('utf-8').decode(bytes);\n      }\n    }\n    return repairMojibake(text);\n  }\n\n  \/* ---------- CSV parsing ---------- *\/\n\n  function detectDelimiter(text) {\n    var head = text.split(\/\\r?\\n\/)[0] || '';\n    var counts = { ',': 0, ';': 0, '\\t': 0 };\n    var inQuotes = false;\n    var i = 0;\n    while (i !== head.length) {\n      var ch = head.charAt(i);\n      if (ch === '\"') { inQuotes = !inQuotes; }\n      else if (!inQuotes && counts[ch] !== undefined) { counts[ch] = counts[ch] + 1; }\n      i = i + 1;\n    }\n    var best = ',';\n    if (counts[';'] > counts[best]) { best = ';'; }\n    if (counts['\\t'] > counts[best]) { best = '\\t'; }\n    return best;\n  }\n\n  function parseCSV(text) {\n    text = text.replace(\/^\\uFEFF\/, '');\n    var delim = detectDelimiter(text);\n    var rows = [];\n    var row = [];\n    var field = '';\n    var inQuotes = false;\n    var i = 0;\n    var n = text.length;\n\n    while (i !== n) {\n      var ch = text.charAt(i);\n      if (inQuotes) {\n        if (ch === '\"') {\n          if (text.charAt(i + 1) === '\"') { field = field + '\"'; i = i + 2; continue; }\n          inQuotes = false; i = i + 1; continue;\n        }\n        field = field + ch; i = i + 1; continue;\n      }\n      if (ch === '\"') { inQuotes = true; i = i + 1; continue; }\n      if (ch === delim) { row.push(field); field = ''; i = i + 1; continue; }\n      if (ch === '\\r') { i = i + 1; continue; }\n      if (ch === '\\n') { row.push(field); rows.push(row); row = []; field = ''; i = i + 1; continue; }\n      field = field + ch;\n      i = i + 1;\n    }\n    row.push(field);\n    rows.push(row);\n\n    return rows.filter(function (r) {\n      return r.some(function (c) { return String(c).trim() !== ''; });\n    });\n  }\n\n  \/* ---------- column detection (priority order, no reuse) ---------- *\/\n\n  function pickColumn(headers, used, patterns) {\n    var found = -1;\n    patterns.forEach(function (p) {\n      if (found !== -1) { return; }\n      headers.forEach(function (h, idx) {\n        if (found !== -1 || used[idx]) { return; }\n        if (String(h).toLowerCase().trim().indexOf(p) !== -1) { found = idx; }\n      });\n    });\n    if (found !== -1) { used[found] = true; }\n    return found;\n  }\n\n  \/* ---------- author splitting ---------- *\/\n\n  function splitAuthors(cell) {\n    var s = String(cell || '').trim();\n    if (s === '') { return []; }\n    s = s.replace(\/\\band\\b\/gi, ',').replace(\/&\/g, ',').replace(\/;\/g, ',');\n    return s.split(',')\n      .map(function (a) { return a.replace(\/\\s+\/g, ' ').trim(); })\n      .filter(function (a) {\n        if (a === '') { return false; }\n        if (\/^et\\.?\\s*al\\.?$\/i.test(a)) { return false; }\n        return true;\n      });\n  }\n\n  \/* ---------- build model ---------- *\/\n\n  function build(rows) {\n    papers = [];\n    people = [];\n    groups = [];\n    if (rows.length === 0) { return; }\n\n    var headers = rows[0].map(function (h) { return String(h).trim(); });\n    var used = {};\n\n    \/* \"full name\" is matched first so the long author column wins\n       over the short \"Kantola, E., ...\" citation column. *\/\n    var cAuthors = pickColumn(headers, used, ['full name', 'author', 'presenter', 'speaker', 'navn']);\n    var cTitle = pickColumn(headers, used, ['title', 'titel']);\n    var cTheme = pickColumn(headers, used, ['theme', 'track', 'topic', 'emne']);\n    var cRoom = pickColumn(headers, used, ['room', 'lokale', 'venue', 'location']);\n    var cTime = pickColumn(headers, used, ['time', 'tid', 'slot']);\n    var cDay = pickColumn(headers, used, ['day', 'dag', 'date', 'dato']);\n    var cSession = pickColumn(headers, used, ['session']);\n    \/* Claimed so they cannot be mistaken for anything else. Never displayed. *\/\n    pickColumn(headers, used, ['abstract id']);\n    pickColumn(headers, used, ['abstract']);\n\n    if (cAuthors === -1) { return; }\n\n    var body = rows.slice(1);\n    var peopleMap = {};\n    var groupMap = {};\n    var groupOrder = [];\n\n    body.forEach(function (r) {\n      var get = function (idx) {\n        if (idx === -1 || idx >= r.length) { return ''; }\n        return String(r[idx]).replace(\/\\s+\/g, ' ').trim();\n      };\n\n      \/* Skip placeholder rows that have no author yet *\/\n      var authors = splitAuthors(get(cAuthors));\n      if (authors.length === 0) { return; }\n\n      var session = get(cSession);\n      var theme = get(cTheme);\n      var day = get(cDay);\n      var time = get(cTime);\n\n      \/* Entries with no day whose theme is only the generic words\n         \"Paper session\" or \"Poster session\" are not scheduled yet.\n         Their number belongs to a separate list, so it is ignored. *\/\n      if (day === '' && \/^(paper|poster)\\s*session$\/i.test(theme)) {\n        session = '';\n        theme = \/poster\/i.test(theme) ? 'Poster session' : 'Not scheduled yet';\n      } else {\n        theme = theme.replace(\/:?\\s*special session\\s*$\/i, '').trim();\n      }\n\n      var paper = {\n        title: get(cTitle),\n        theme: theme,\n        session: session,\n        room: get(cRoom),\n        time: time,\n        day: day,\n        authors: authors\n      };\n      paper.sortKey = dayRank(paper.day) * 1000000\n        + (parseInt(String(paper.time).replace(\/[^0-9]\/g, '').substring(0, 4), 10) || 0) * 100\n        + (parseInt(paper.session, 10) || 99);\n      papers.push(paper);\n\n      authors.forEach(function (a) {\n        var key = a.toLowerCase();\n        if (!peopleMap[key]) {\n          peopleMap[key] = { name: a, papers: [] };\n        }\n        peopleMap[key].papers.push(paper);\n      });\n\n      \/* One group per session slot, so a theme that runs twice stays separate *\/\n      var gkey = [paper.theme, paper.session, paper.day, paper.time].join('|').toLowerCase();\n      if (!groupMap[gkey]) {\n        groupMap[gkey] = {\n          name: paper.theme || 'Other',\n          session: paper.session,\n          day: paper.day,\n          time: paper.time,\n          room: paper.room,\n          sortKey: paper.sortKey,\n          papers: []\n        };\n        groupOrder.push(gkey);\n      }\n      groupMap[gkey].papers.push(paper);\n    });\n\n    people = Object.keys(peopleMap).map(function (k) {\n      var p = peopleMap[k];\n      p.papers.sort(function (a, b) { return a.sortKey - b.sortKey; });\n      var hay = [p.name];\n      p.papers.forEach(function (pp) {\n        hay.push(pp.title, pp.theme, pp.session, pp.room, pp.time, pp.day);\n      });\n      p.haystack = hay.join(' ').toLowerCase();\n      return p;\n    });\n    people.sort(function (a, b) {\n      return surname(a.name).localeCompare(surname(b.name), 'da');\n    });\n\n    groups = groupOrder.map(function (k) {\n      var g = groupMap[k];\n      var hay = [g.name, g.session, g.day, g.time];\n      g.papers.forEach(function (pp) {\n        hay.push(pp.title, pp.authors.join(' '));\n      });\n      g.haystack = hay.join(' ').toLowerCase();\n      return g;\n    });\n    groups.sort(function (a, b) { return a.sortKey - b.sortKey; });\n  }\n\n  \/* ---------- rendering ---------- *\/\n\n  function highlight(text, term) {\n    var safe = esc(text);\n    if (term === '') { return safe; }\n    var pattern = term.replace(\/[.*+?^${}()|[\\]\\\\]\/g, '\\\\$&');\n    return safe.replace(new RegExp('(' + pattern + ')', 'gi'), '<mark>$1<\/mark>');\n  }\n\n  \/* Abstract id is never shown. The session tag appears only when the\n     row actually carries a real session number. *\/\n  function tagsHtml(item, withTheme) {\n    var tags = '';\n    if (withTheme && item.theme !== undefined && item.theme !== '') {\n      tags = tags + '<span class=\"pp-tag theme\">' + esc(item.theme) + '<\/span>';\n    }\n    if (item.day !== '') { tags = tags + '<span class=\"pp-tag\">' + esc(item.day) + '<\/span>'; }\n    if (item.time !== '') { tags = tags + '<span class=\"pp-tag\">' + esc(item.time) + '<\/span>'; }\n    if (item.room !== '') { tags = tags + '<span class=\"pp-tag\">' + esc(item.room) + '<\/span>'; }\n    if (item.session !== '') { tags = tags + '<span class=\"pp-tag\">Session ' + esc(item.session) + '<\/span>'; }\n    return tags;\n  }\n\n  function renderPeople(term, low) {\n    var shown = people;\n    if (low !== '') {\n      shown = people.filter(function (p) { return p.haystack.indexOf(low) !== -1; });\n    }\n    if (shown.length === 0) {\n      listEl.innerHTML = '<p class=\"pp-msg\"><strong>Nothing found<\/strong>No author or paper matches &ldquo;' + esc(term) + '&rdquo;.<\/p>';\n      statusEl.textContent = '0 of ' + people.length + ' authors';\n      return;\n    }\n\n    var html = '';\n    shown.forEach(function (p) {\n      html = html + '<div class=\"pp-person\">';\n      html = html + '<div class=\"pp-avatar\">' + esc(initials(p.name)) + '<\/div>';\n      html = html + '<div class=\"pp-body\">';\n      html = html + '<p class=\"pp-name\">' + highlight(p.name, term) + '<\/p>';\n      html = html + '<div class=\"pp-papers\">';\n      p.papers.forEach(function (pp) {\n        html = html + '<div class=\"pp-paper\">';\n        html = html + highlight(pp.title, term);\n        var co = pp.authors.filter(function (a) { return a !== p.name; });\n        if (co.length !== 0) {\n          html = html + '<p class=\"pp-co\">with ' + esc(co.join(', ')) + '<\/p>';\n        }\n        var tags = tagsHtml(pp, true);\n        if (tags !== '') { html = html + '<div class=\"pp-meta\">' + tags + '<\/div>'; }\n        html = html + '<\/div>';\n      });\n      html = html + '<\/div><\/div><\/div>';\n    });\n\n    listEl.innerHTML = html;\n    statusEl.textContent = (low === '' ? people.length + ' authors \\u00b7 ' + papers.length + ' papers' : shown.length + ' of ' + people.length + ' authors');\n  }\n\n  function renderGroups(term, low) {\n    var shown = groups;\n    if (low !== '') {\n      shown = groups.filter(function (g) { return g.haystack.indexOf(low) !== -1; });\n    }\n    if (shown.length === 0) {\n      listEl.innerHTML = '<p class=\"pp-msg\"><strong>Nothing found<\/strong>No session matches &ldquo;' + esc(term) + '&rdquo;.<\/p>';\n      statusEl.textContent = '0 of ' + groups.length + ' sessions';\n      return;\n    }\n\n    var html = '';\n    shown.forEach(function (g) {\n      html = html + '<div class=\"pp-group\">';\n      html = html + '<p class=\"pp-group-title\">' + highlight(g.name, term) + '<\/p>';\n      var tags = tagsHtml(g, false);\n      if (tags !== '') { html = html + '<div class=\"pp-group-meta\">' + tags + '<\/div>'; }\n      html = html + '<p class=\"pp-group-sub\">' + g.papers.length + ' presentations<\/p>';\n      g.papers.forEach(function (pp) {\n        html = html + '<div class=\"pp-paper\">';\n        html = html + highlight(pp.title, term);\n        html = html + '<p class=\"pp-co\">' + highlight(pp.authors.join(', '), term) + '<\/p>';\n        html = html + '<\/div>';\n      });\n      html = html + '<\/div>';\n    });\n\n    listEl.innerHTML = html;\n    statusEl.textContent = (low === '' ? groups.length + ' sessions \\u00b7 ' + papers.length + ' papers' : shown.length + ' of ' + groups.length + ' sessions');\n  }\n\n  function render() {\n    var term = String(searchEl.value || '').trim();\n    var low = term.toLowerCase();\n    if (view === 'people') { renderPeople(term, low); } else { renderGroups(term, low); }\n  }\n\n  function fail(msg) {\n    listEl.innerHTML = '<p class=\"pp-msg\"><strong>The paper list is unavailable<\/strong>' + msg + '<\/p>';\n    statusEl.textContent = '';\n  }\n\n  \/* ---------- events ---------- *\/\n\n  btnPeople.addEventListener('click', function () {\n    view = 'people';\n    btnPeople.classList.add('on');\n    btnTheme.classList.remove('on');\n    render();\n  });\n  btnTheme.addEventListener('click', function () {\n    view = 'theme';\n    btnTheme.classList.add('on');\n    btnPeople.classList.remove('on');\n    render();\n  });\n\n  searchEl.addEventListener('input', render);\n  searchEl.addEventListener('keydown', function (e) {\n    if (e.key === 'Escape') { searchEl.value = ''; render(); }\n  });\n\n  \/* ---------- load ---------- *\/\n\n  var url = (root.getAttribute('data-csv-url') || '').trim();\n  if (url === '') {\n    fail('No file address has been set for this page.');\n    return;\n  }\n\n  window.fetch(url)\n    .then(function (r) {\n      if (!r.ok) { throw new Error('HTTP ' + r.status); }\n      return r.arrayBuffer();\n    })\n    .then(function (buffer) {\n      build(parseCSV(decodeBuffer(buffer)));\n      if (people.length === 0) {\n        fail('The file was found but no entries could be read from it.');\n        return;\n      }\n      searchEl.disabled = false;\n      render();\n    })\n    .catch(function () {\n      fail('Please try reloading the page in a moment.');\n    });\n})();\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>By author By session Loading&#8230; Loading the paper list&#8230;<\/p>\n","protected":false},"author":6,"featured_media":0,"parent":93,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-3113","page","type-page","status-publish","hentry"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.9 - aioseo.com -->\n\t<meta name=\"description\" content=\"By author By session Loading... Loading the paper list...\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"google-site-verification\" content=\"PvQSSsTgcXK2bJPXsvwwdXDo1mU-oqaBts6wQwgiKPw\" \/>\n\t<meta name=\"msvalidate.01\" content=\"596BE547CB9B43F182217AC58FFA33DC\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/ls2026.aau.dk\/?page_id=3113\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.9\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Light Symposium 2026 - Sensing light\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Program Search - Light Symposium 2026\" \/>\n\t\t<meta property=\"og:description\" content=\"By author By session Loading... Loading the paper list...\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/ls2026.aau.dk\/?page_id=3113\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/ls2026.aau.dk\/wp-content\/uploads\/2025\/12\/cropped-cropped-Logo2026.png\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/ls2026.aau.dk\/wp-content\/uploads\/2025\/12\/cropped-cropped-Logo2026.png\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-08-17T12:37:59+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-08-21T12:58:39+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Program Search - Light Symposium 2026\" \/>\n\t\t<meta name=\"twitter:description\" content=\"By author By session Loading... Loading the paper list...\" \/>\n\t\t<meta name=\"twitter:image\" content=\"https:\/\/ls2026.aau.dk\/wp-content\/uploads\/2025\/12\/cropped-cropped-Logo2026.png\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=3113#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/ls2026.aau.dk\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=93#listItem\",\"name\":\"Program\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=93#listItem\",\"position\":2,\"name\":\"Program\",\"item\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=93\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=3113#listItem\",\"name\":\"Program Search\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=3113#listItem\",\"position\":3,\"name\":\"Program Search\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=93#listItem\",\"name\":\"Program\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/#organization\",\"name\":\"Light Symposium 2026\",\"description\":\"Sensing light Light Symposium 2026\",\"url\":\"https:\\\/\\\/ls2026.aau.dk\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https:\\\/\\\/ls2026.aau.dk\\\/wp-content\\\/uploads\\\/2025\\\/12\\\/cropped-cropped-Logo2026.png\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=3113\\\/#organizationLogo\"},\"image\":{\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=3113\\\/#organizationLogo\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=3113#webpage\",\"url\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=3113\",\"name\":\"Program Search - Light Symposium 2026\",\"description\":\"By author By session Loading... Loading the paper list...\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/?page_id=3113#breadcrumblist\"},\"datePublished\":\"2026-08-17T13:37:59+01:00\",\"dateModified\":\"2026-08-21T13:58:39+01:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/#website\",\"url\":\"https:\\\/\\\/ls2026.aau.dk\\\/\",\"name\":\"Light Symposium 2022\",\"description\":\"Sensing light\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/ls2026.aau.dk\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Program Search - Light Symposium 2026","description":"By author By session Loading... Loading the paper list...","canonical_url":"https:\/\/ls2026.aau.dk\/?page_id=3113","robots":"max-image-preview:large","keywords":"","webmasterTools":{"google-site-verification":"PvQSSsTgcXK2bJPXsvwwdXDo1mU-oqaBts6wQwgiKPw","msvalidate.01":"596BE547CB9B43F182217AC58FFA33DC","miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BreadcrumbList","@id":"https:\/\/ls2026.aau.dk\/?page_id=3113#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/ls2026.aau.dk#listItem","position":1,"name":"Home","item":"https:\/\/ls2026.aau.dk","nextItem":{"@type":"ListItem","@id":"https:\/\/ls2026.aau.dk\/?page_id=93#listItem","name":"Program"}},{"@type":"ListItem","@id":"https:\/\/ls2026.aau.dk\/?page_id=93#listItem","position":2,"name":"Program","item":"https:\/\/ls2026.aau.dk\/?page_id=93","nextItem":{"@type":"ListItem","@id":"https:\/\/ls2026.aau.dk\/?page_id=3113#listItem","name":"Program Search"},"previousItem":{"@type":"ListItem","@id":"https:\/\/ls2026.aau.dk#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/ls2026.aau.dk\/?page_id=3113#listItem","position":3,"name":"Program Search","previousItem":{"@type":"ListItem","@id":"https:\/\/ls2026.aau.dk\/?page_id=93#listItem","name":"Program"}}]},{"@type":"Organization","@id":"https:\/\/ls2026.aau.dk\/#organization","name":"Light Symposium 2026","description":"Sensing light Light Symposium 2026","url":"https:\/\/ls2026.aau.dk\/","logo":{"@type":"ImageObject","url":"https:\/\/ls2026.aau.dk\/wp-content\/uploads\/2025\/12\/cropped-cropped-Logo2026.png","@id":"https:\/\/ls2026.aau.dk\/?page_id=3113\/#organizationLogo"},"image":{"@id":"https:\/\/ls2026.aau.dk\/?page_id=3113\/#organizationLogo"}},{"@type":"WebPage","@id":"https:\/\/ls2026.aau.dk\/?page_id=3113#webpage","url":"https:\/\/ls2026.aau.dk\/?page_id=3113","name":"Program Search - Light Symposium 2026","description":"By author By session Loading... Loading the paper list...","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/ls2026.aau.dk\/#website"},"breadcrumb":{"@id":"https:\/\/ls2026.aau.dk\/?page_id=3113#breadcrumblist"},"datePublished":"2026-08-17T13:37:59+01:00","dateModified":"2026-08-21T13:58:39+01:00"},{"@type":"WebSite","@id":"https:\/\/ls2026.aau.dk\/#website","url":"https:\/\/ls2026.aau.dk\/","name":"Light Symposium 2022","description":"Sensing light","inLanguage":"en-US","publisher":{"@id":"https:\/\/ls2026.aau.dk\/#organization"}}]},"og:locale":"en_US","og:site_name":"Light Symposium 2026 - Sensing light","og:type":"article","og:title":"Program Search - Light Symposium 2026","og:description":"By author By session Loading... Loading the paper list...","og:url":"https:\/\/ls2026.aau.dk\/?page_id=3113","og:image":"https:\/\/ls2026.aau.dk\/wp-content\/uploads\/2025\/12\/cropped-cropped-Logo2026.png","og:image:secure_url":"https:\/\/ls2026.aau.dk\/wp-content\/uploads\/2025\/12\/cropped-cropped-Logo2026.png","article:published_time":"2026-08-17T12:37:59+00:00","article:modified_time":"2026-08-21T12:58:39+00:00","twitter:card":"summary","twitter:title":"Program Search - Light Symposium 2026","twitter:description":"By author By session Loading... Loading the paper list...","twitter:image":"https:\/\/ls2026.aau.dk\/wp-content\/uploads\/2025\/12\/cropped-cropped-Logo2026.png"},"aioseo_meta_data":{"post_id":"3113","title":"#post_title #separator_sa #site_title","description":"#post_content","keywords":null,"keyphrases":{"focus":{"keyphrase":"","score":0,"analysis":{"keyphraseInTitle":{"score":0,"maxScore":9,"error":1}}},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"WebPage","isEnabled":true},"graphs":[]},"schema_type":"default","schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"created":"2026-08-17 12:38:00","updated":"2026-08-21 12:58:49","seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/ls2026.aau.dk\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/ls2026.aau.dk\/?page_id=93\" title=\"Program\">Program<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tProgram Search\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/ls2026.aau.dk"},{"label":"Program","link":"https:\/\/ls2026.aau.dk\/?page_id=93"},{"label":"Program Search","link":"https:\/\/ls2026.aau.dk\/?page_id=3113"}],"_links":{"self":[{"href":"https:\/\/ls2026.aau.dk\/index.php?rest_route=\/wp\/v2\/pages\/3113","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ls2026.aau.dk\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ls2026.aau.dk\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ls2026.aau.dk\/index.php?rest_route=\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/ls2026.aau.dk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3113"}],"version-history":[{"count":3,"href":"https:\/\/ls2026.aau.dk\/index.php?rest_route=\/wp\/v2\/pages\/3113\/revisions"}],"predecessor-version":[{"id":3135,"href":"https:\/\/ls2026.aau.dk\/index.php?rest_route=\/wp\/v2\/pages\/3113\/revisions\/3135"}],"up":[{"embeddable":true,"href":"https:\/\/ls2026.aau.dk\/index.php?rest_route=\/wp\/v2\/pages\/93"}],"wp:attachment":[{"href":"https:\/\/ls2026.aau.dk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}