Index: src/assets/js/audio-player.js
===================================================================
--- src/assets/js/audio-player.js	(revision 230e44682e487f793fa625a807aea1d6616cf03a)
+++ src/assets/js/audio-player.js	(revision fa089819894c489333fe1d0f327dae1085a86987)
@@ -592,5 +592,16 @@
     const t = queue[currentIndex];
     const isDesktop = window.matchMedia && window.matchMedia('(min-width: 768px)').matches;
-    if (isDesktop && t && t.postUrl) { goToPost(t.postUrl, t.id); return; }
+    if (isDesktop && t) {
+      // 1) Track speelde vanuit een post → die URL kennen we al.
+      if (t.postUrl) { goToPost(t.postUrl, t.id); return; }
+      // 2) Site-brede track (geen postUrl) → zoek de post op via de track-id.
+      if (t.id) {
+        fetch('/audio/track/' + encodeURIComponent(t.id) + '/post')
+          .then((r) => (r.ok ? r.json() : null))
+          .then((d) => { if (d && d.url) goToPost(d.url, t.id); else openSheet(); })
+          .catch(() => openSheet());
+        return;
+      }
+    }
     openSheet();
   });
@@ -831,4 +842,5 @@
     if (Array.isArray(window.PCMS_SITE_TRACKS) && window.PCMS_SITE_TRACKS.length) {
       queue = window.PCMS_SITE_TRACKS.map(t => ({
+        id:     t.id || null,
         url:    t.media_url || t.url,
         title:  t.title  || 'Untitled',
Index: src/routes/audio.js
===================================================================
--- src/routes/audio.js	(revision 230e44682e487f793fa625a807aea1d6616cf03a)
+++ src/routes/audio.js	(revision fa089819894c489333fe1d0f327dae1085a86987)
@@ -141,3 +141,20 @@
 });
 
+// Welke post bevat deze track? (voor de mini-speler → "spring naar de post +
+// scroll naar de track".) Pakt de nieuwste gepubliceerde post met [[track:<id>]].
+router.get('/track/:id/post', (req, res) => {
+  const id = String(req.params.id || '');
+  if (!/^[A-Za-z0-9_-]+$/.test(id)) return res.status(400).json({ error: 'bad id' });
+  const isHub = res.locals.tenancy === 'hub';
+  const row = db.prepare(`
+    SELECT p.slug, s.slug AS site_slug
+    FROM posts p JOIN sites s ON s.id = p.site_id
+    WHERE p.status = 'published' AND p.content LIKE ?
+    ORDER BY p.published_at DESC LIMIT 1
+  `).get('%[[track:' + id + ']]%');
+  if (!row) return res.status(404).json({ error: 'not found' });
+  const url = isHub ? `/user/${row.site_slug}/${row.slug}` : `/${row.slug}`;
+  res.json({ url });
+});
+
 export default router;
Index: src/views/shell.ejs
===================================================================
--- src/views/shell.ejs	(revision 230e44682e487f793fa625a807aea1d6616cf03a)
+++ src/views/shell.ejs	(revision fa089819894c489333fe1d0f327dae1085a86987)
@@ -300,5 +300,5 @@
      ?v=N — cache-buster: bump bij elke audio-player.js wijziging zodat
      Cloudflare (max-age=1y) niet de oude versie blijft serveren. -->
-<script src="/assets/js/audio-player.js?v=17"></script>
+<script src="/assets/js/audio-player.js?v=18"></script>
 <!-- Eigen custom media-embeds (YouTube/SoundCloud/Spotify) via de echte
      player-API's + gedeelde mutual-exclusion registry met de site-speler. -->
