Index: src/views/partials/post-card.ejs
===================================================================
--- src/views/partials/post-card.ejs	(revision 2165b6d3d57ceaa8b5d1f70491868482149470cf)
+++ src/views/partials/post-card.ejs	(revision 7bc636b391c66ac399c33e54f7173a022c6a3cbd)
@@ -11,39 +11,8 @@
 //   Hover state on cover. Tap-target stays large.
 
-const _base      = (typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : '';
-const _external  = post.external_url || null;
-const _href      = _external || (_base + '/' + post.slug);
-const _ext       = !!_external;
-const _src       = post.source_name || '';
-const _realCover = !!post.cover_image_url || !!post.cover_video_url;
-// Content-derived fallback (see post-tile.ejs): a C2S post's media lives in
-// its content, and the card fronts it from there.
-let _cVideo = null, _cPoster = null, _cImg = null, _cAudio = false, _cWave = null;
-if (!_realCover && post.content) {
-  const vm = String(post.content).match(/<video[^>]*\ssrc="([^"]+)"[^>]*>/i);
-  if (vm) { _cVideo = vm[1]; const pm = vm[0].match(/poster="([^"]+)"/i); if (pm) _cPoster = pm[1]; }
-  else {
-    const im = String(post.content).match(/<img[^>]*\ssrc="([^"]+)"/i);
-    if (im) _cImg = im[1];
-    else {
-      // An audio post (Robins vraag, 30-7): the upload leg drew a waveform
-      // (data-poster on the tag); the card fronts it like a cover.
-      const am = String(post.content).match(/<audio[^>]*>/i);
-      if (am) { _cAudio = true; const wm = am[0].match(/data-poster="([^"]+)"/i); if (wm) _cWave = wm[1]; }
-    }
-  }
-}
-const _hasCover  = _realCover || !!_cVideo || !!_cImg || !!_cWave;
-// A C2S post has no title: fall back to the post's own words, then to a
-// friendly type label instead of "(zonder titel)".
-let _title = post.title || '';
-if (!_title && post.content) {
-  const _txt = String(post.content).replace(/<[^>]*>/g, ' ').replace(/&[a-zA-Z#0-9]+;/g, ' ').replace(/\s+/g, ' ').trim();
-  if (_txt) _title = _txt.length > 64 ? _txt.slice(0, 63).replace(/\s+\S*$/, '') + '…' : _txt;
-}
-if (!_title) _title = _cAudio ? '♪ audio' : _cVideo ? '▶ video' : '(zonder titel)';
+const _href      = '/' + post.slug;
+const _hasCover  = !!post.cover_image_url;
 const _typeLabel = (post.type && post.type !== 'overig' && post.type !== 'post') ? post.type : '';
 const _isPinned  = !!post.pinned;
-const _isBoost   = !!post.isBoost;
 const _isDraft   = post.status && post.status !== 'published';
 
@@ -69,22 +38,12 @@
 }
 %>
-<li class="post-list-item<%= (_hasCover || post.nsfw) ? ' has-cover' : '' %><%= (_isPinned || _isBoost) ? ' is-pinned' : '' %>">
+<li class="post-list-item<%= _hasCover ? ' has-cover' : '' %><%= _isPinned ? ' is-pinned' : '' %>">
 
   <% if (_hasCover) { %>
-    <a class="post-list-cover<%= post.nsfw ? ' nsfw-media' : '' %>" href="<%= _href %>"
-       <% if (_ext) { %>target="_blank" rel="noopener"<% } else { %>hx-get="<%= _href %>?partial=1" hx-target="#pcms-main" hx-swap="innerHTML" hx-push-url="<%= _href %>" hx-indicator="#pcms-loading"<% } %>
-       aria-label="<%= _title %>" tabindex="-1">
-      <% if (post.cover_image_url) { %><img src="<%= thumb(post.cover_image_url, 480) %>"
-           srcset="<%= thumb(post.cover_image_url, 320) %> 320w, <%= thumb(post.cover_image_url, 640) %> 640w, <%= thumb(post.cover_image_url, 1280) %> 1280w"
-           sizes="(min-width: 768px) 120px, 100vw"
-           alt="" loading="lazy" decoding="async"<% if (post.cover_video_url) { %> data-ios-mp4="<%= post.cover_video_url %>"<% } %>>
-      <% } else if (post.cover_video_url) { %><video src="<%= post.cover_video_url %>" poster="<%= thumb(post.cover_video_url, 480) %>" autoplay loop muted playsinline></video><% } else if (_cVideo) { %><video src="<%= _cVideo %>"<% if (_cPoster) { %> poster="<%= _cPoster %>"<% } %> autoplay loop muted playsinline preload="metadata"></video><% } else if (_cImg) { %><img src="<%= _cImg %>" alt="" loading="lazy" decoding="async"><% } else if (_cWave) { %><img class="post-cover-wave" src="<%= _cWave %>" alt="" loading="lazy" decoding="async"><% } %>
-      <% if (post.nsfw) { %><span class="nsfw-veil"><%- include('nsfw-veil', { cw: post.content_warning }) %></span><% } %>
-    </a>
-  <% } else if (post.nsfw) { %>
-    <a class="post-list-cover nsfw-media" href="<%= _href %>"
-       <% if (_ext) { %>target="_blank" rel="noopener"<% } else { %>hx-get="<%= _href %>?partial=1" hx-target="#pcms-main" hx-swap="innerHTML" hx-push-url="<%= _href %>" hx-indicator="#pcms-loading"<% } %>
-       aria-label="<%= _title %>" tabindex="-1">
-      <span class="nsfw-veil"><%- include('nsfw-veil', { cw: post.content_warning }) %></span>
+    <a class="post-list-cover" href="<%= _href %>"
+       hx-get="<%= _href %>?partial=1" hx-target="#pcms-main" hx-swap="innerHTML"
+       hx-push-url="<%= _href %>" hx-indicator="#pcms-loading"
+       aria-label="<%= post.title || '(zonder titel)' %>" tabindex="-1">
+      <img src="<%= post.cover_image_url %>" alt="" loading="lazy" decoding="async">
     </a>
   <% } %>
@@ -92,7 +51,6 @@
   <div class="post-list-body">
     <div class="post-list-meta mono">
-      <% if (_isBoost) { %><span class="post-list-pin post-list-boost" aria-label="Boost"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg></span><% } else if (_isPinned) { %><span class="post-list-pin" aria-label="Vastgepind"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="12" y1="17" x2="12" y2="22"/><path d="M5 17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V6h1a2 2 0 0 0 0-4H8a2 2 0 0 0 0 4h1v4.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24z"/></svg></span><% } %>
+      <% if (_isPinned) { %><span class="post-list-pin" aria-label="Vastgepind">★</span><% } %>
       <time datetime="<%= post.published_at || post.created_at %>"><%= _ddmmyyyy(post.published_at || post.created_at) %></time>
-      <% if (_src) { %><span class="post-list-type">&middot; via <%= _src %></span><% } %>
       <% if (_typeLabel) { %>
         <span class="post-list-type">· <%= _typeLabel.charAt(0).toUpperCase() + _typeLabel.slice(1) %></span>
@@ -105,6 +63,7 @@
     <h3 class="post-list-title">
       <a href="<%= _href %>"
-         <% if (_ext) { %>target="_blank" rel="noopener"<% } else { %>hx-get="<%= _href %>?partial=1" hx-target="#pcms-main" hx-swap="innerHTML" hx-push-url="<%= _href %>" hx-indicator="#pcms-loading"<% } %>>
-        <%= _title %>
+         hx-get="<%= _href %>?partial=1" hx-target="#pcms-main" hx-swap="innerHTML"
+         hx-push-url="<%= _href %>" hx-indicator="#pcms-loading">
+        <%= post.title || '(zonder titel)' %>
       </a>
     </h3>
@@ -117,7 +76,7 @@
       <div class="post-list-tags">
         <% _tags.forEach(function(t) { %>
-          <a href="<%= _base %>/tag/<%= encodeURIComponent(t) %>" class="tag-chip"
-             hx-get="<%= _base %>/tag/<%= encodeURIComponent(t) %>?partial=1" hx-target="#pcms-main"
-             hx-swap="innerHTML" hx-push-url="<%= _base %>/tag/<%= encodeURIComponent(t) %>"
+          <a href="/tag/<%= encodeURIComponent(t) %>" class="tag-chip"
+             hx-get="/tag/<%= encodeURIComponent(t) %>?partial=1" hx-target="#pcms-main"
+             hx-swap="innerHTML" hx-push-url="/tag/<%= encodeURIComponent(t) %>"
              hx-indicator="#pcms-loading">#<%= t %></a>
         <% }); %>
@@ -168,16 +127,11 @@
     margin-right: calc(-1 * clamp(1.25rem, 4vw, 2rem));
     width: calc(100% + 2 * clamp(1.25rem, 4vw, 2rem)) !important;
-    /* Accent-gradient placeholder shown while the cover loads (the image fades in over it). */
-    background-image: linear-gradient(135deg,
-        color-mix(in srgb, var(--accent, #888) 22%, var(--paper-2)) 0%,
-        color-mix(in srgb, var(--accent, #888) 6%, var(--paper-2)) 100%);
-  }
-  .post-list-cover img, .post-list-cover video {
+    background: var(--paper-2);
+  }
+  .post-list-cover img {
     width: 100%; height: 100%;
     object-fit: cover;
     display: block;
-    transition: opacity .4s ease;
-  }
-  .post-list-cover img.is-loading { opacity: 0; }
+  }
 
   /* Re-apply rounded corners on slightly larger phones */
@@ -206,7 +160,4 @@
   }
 
-  /* Audio cover (Shaer): white-on-transparent waveform on its own accent
-     gradient, contained so the shape reads at 120px and full-bleed alike. */
-  /* (see also .grid-tile-wave in style.css for the grid tiles) */
   /* Pinned indicator */
   .post-list-item.is-pinned .post-list-title a {
@@ -253,18 +204,4 @@
 
 /* ============================================================
-   AUDIO COVER (shared) — Shaer audio post (Robins vraag, 30-7):
-   the waveform PNG is white on transparent; give it its own accent
-   gradient and contain it so the shape reads at 120px and full-bleed.
-   ============================================================ */
-.post-list-cover .post-cover-wave {
-  width: 100%; height: 100%;
-  object-fit: contain !important;
-  padding: 14% 8%;
-  background-image: linear-gradient(135deg,
-      color-mix(in srgb, var(--accent, #888) 26%, var(--paper-2, var(--paper))) 0%,
-      color-mix(in srgb, var(--accent, #888) 8%, var(--paper-2, var(--paper))) 100%);
-}
-
-/* ============================================================
    PIN + DRAFT INDICATORS (shared)
    ============================================================ */
@@ -272,10 +209,6 @@
   color: var(--accent);
   margin-right: .35rem;
-  display: inline-flex;
-  align-items: center;
-  vertical-align: middle;
-}
-.post-list-pin svg { width: 13px; height: 13px; display: block; }
-.post-list-boost { color: #2fa85a; }
+  font-size: .9rem;
+}
 .post-list-draft {
   color: var(--accent);
