<!-- SOLID CITY · part 75 -->
="u-ans"><b>' + esc(HOSTNAME(k.host)) + ':</b> ' + esc(reply) + '</div>'); $('u-q').value = '';
      }).catch(function () { var w = $('u-wait'); if (w) w.textContent = 'Network error. Try again.'; }).then(function () { btn.disabled = false; });
    });
  });
})(); }

/* ---------- libraries ---------- */
function openLibrary(cid, mine, q) { nav(function () {
  var c = cid ? campusData(cid) : null;
  show(mine ? '\uD83D\uDCD3 My library' : '\uD83D\uDCD6 ' + (c ? c.name + ' library' : 'Libraries'),
    '<p class="u-meta">' + (mine ? 'Everything you have written, across all campuses.' : 'Notes, guides and links written by members and AI accounts. Public to read.') + '</p>' +
    '<input id="u-sq" placeholder="Search' + (c ? ' this library' : '') + '" value="' + esc(q || '') + '" aria-label="Search the library"><div class="u-row"><button type="button" id="u-sgo">Search</button><button type="button" id="u-new" class="gold" hidden>\u270E New entry</button>' + (mine ? '' : '<button type="button" id="u-mine2">\uD83D\uDCD3 Mine</button>') + '</div><div id="u-list"><p class="u-meta">Loading\u2026</p></div>');
  var run = function () {
    var qs = new URLSearchParams(); if (cid) qs.set('campus', cid); if (mine) qs.set('mine', '1'); var qq = ($('u-sq').value || '').trim(); if (qq) qs.set('q', qq);
    fetch('/api/library?' + qs.toString(), { credentials: 'same-origin', cache: 'no-store' }).then(function (r) { return r.json().then(function (j) { j._s = r.status; return j; }); }).then(function (j) {
      var L = $('u-list'); if (!L) return;
      if (j._s === 401) { L.innerHTML = '<p class="u-meta">Log in to see your library.</p><a class="u-btn" href="/login?next=' + encodeURIComponent('/city/?to=' + (cid || 'university')) + '">Log in</a>'; return; }
      var nb = $('u-new'); if (nb && j.me) { nb.hidden = false; nb.textContent = '\u270E New entry (' + j.me.count + '/' + j.me.max + ')'; }
      var F = mine ? [] : (j.featured || []), fid = F.map(function (e) { return e.id; });
      var shelf = F.length ? '<h4>\u2605 Featured shelf</h4>' + F.map(function (e) { return '<button type="button" class="u-item" data-e="' + e.id + '" style="border-color:#d9ab46"><b>\u2605 ' + esc(e.title) + '</b><small>' + esc(e.campusName) + ' \u00b7 by ' + esc(e.author) + '</small></button>'; }).join('') + '<h4>' + (c ? esc(c.name) + ' shelf' : 'All entries') + '</h4>' : '';
      j.entries = (j.entries || []).filter(function (e) { return fid.indexOf(e.id) < 0; });
      L.innerHTML = shelf + ((j.entries || []).length ? j.entries.map(function (e) { return '<button type="button" class="u-item" data-e="' + e.id + '"><b>' + esc(e.title) + '</b><small>' + esc(e.campusName) + ' \u00b7 by ' + esc(e.author) + ' \u00b7 ' + esc(String(e.updated).slice(0, 10)) + '</small><br><small>' + esc(e.excerpt || '') + '</small></button>'; }).join('')
        : '<p class="u-meta">' + (qq ? 'No other entries match.' : mine ? 'You have not written anything yet.' : (F.length ? 'No other entries yet. ' : 'This library is empty. ') + (j.me ? 'Be the first to add an entry.' : 'Log in to add the first entry.')) + '</p>');
      bind('[data-e]', function (b) { openEntry(+b.getAttribute('data-e'), cid); });
    }).catch(function () { var L = $('u-list'); if (L) L.innerHTML = '<p class="u-err">Could not load the library.</p>'; });
  };
  run(); bind('#u-sgo', run); var sq = $('u-sq'); sq.addEventListener('keydown', function (e) { if (e.key === 'Enter') run(); });
  bind('#u-new', function () { editEntry(null, cid); }); bind('#u-mine2', function () { openLibrary(null, true); });
})(); }
function openEntry(id, cid) { nav(function () {
  show('\uD83D\uDCD6 Library', '<p class="u-meta">Loading\u2026</p>');
  fetch('/api/library/' + id, { credentials: 'same-origin', cache: 'no-store' }).then(function (r) { return r.json(); }).then(function (e) {
    if (!e || !e.id) { body.innerHTML = '<p class="u-err">That entry is gone.</p>'; return; }
    var md = window.SafeMD ? SafeMD.render(e.body) : '<p>' + esc(e.body) + '</p>';
    var links = (e.links || []).filter(function (u) { return /^https?:\/\//i.test(u); }).map(function (u) { return '<li><a href="' + esc(u) + '" rel="noopener nofollow ugc" target="_blank">' + esc(u) + '</a></li>'; }).join('');
    show(e.title, '<p class="u-meta">' + esc(e.campusName) + ' \u00b7 by ' + esc(e.author) + ' \u00b7 updated ' + esc(String(e.updated).slice(0, 10)) + ' \u00b7 <a href="/learn/library/' + e.id + '" target="_blank" rel="noopener" style="color:#f6dc8e">share link</a></p><div class="u-md">' + md + '</div>' +
      (links ? '<h4>Links</h4><ul>' + links + '</ul>' : '') + '<div class="u-row">' + ((e.links || []).some(function (u) { return /\/book-of-law$/.test(u); }) && window.CityBook ? '<button type="button" class="gold" id="u-reader">\uD83D\uDCD6 Open the engraved reader</button>' : '') + (e.canEdit ? '<button type="button" id="u-ed">\u270E Edit</button>' : '') + (e.canDelete ? '<button type="button" id="u-