Index: src/routes/account.js
===================================================================
--- src/routes/account.js	(revision c80e78bc18fad68fd4deed4bd94cd0b89ca32b1d)
+++ src/routes/account.js	(revision 8b014efbf867f5c2687f4c1aed544e6e7ef34386)
@@ -17,4 +17,5 @@
 import fs from 'fs';
 import { fileURLToPath } from 'url';
+import bcrypt from 'bcryptjs';
 import multer from 'multer';
 import { v4 as uuid } from 'uuid';
@@ -56,7 +57,9 @@
 router.get('/', requireAuth, (req, res) => {
   const account = db.prepare(`
-    SELECT id, username, email, role, bio, avatar_url, created_at
+    SELECT id, username, email, role, bio, avatar_url, created_at, password_hash
     FROM users WHERE id = ?
   `).get(req.session.user.id);
+  const hasPassword = !!(account && account.password_hash && account.password_hash !== '!google-oauth');
+  if (account) delete account.password_hash; // niet naar de view lekken
 
   renderPage(req, res, 'pages/account', {
@@ -64,4 +67,5 @@
     bodyClass: 'on-special',
     account,
+    hasPassword,
     success: req.query.success || null,
     error: req.query.error || null,
@@ -83,6 +87,32 @@
 // longer read or written.
 
-// Wachtwoord-wijzigen is verwijderd: inloggen gaat sinds de Google-OAuth-migratie
-// volledig via Google, er is geen wachtwoord meer om te wijzigen.
+// ==================== CHANGE PASSWORD ====================
+router.post('/password', requireAuth, (req, res) => {
+  const { current, new_password, confirm } = req.body;
+  if (!current || !new_password || !confirm) {
+    return res.redirect('/account?error=' + encodeURIComponent('Alle wachtwoordvelden zijn verplicht'));
+  }
+  if (new_password.length < 8) {
+    return res.redirect('/account?error=' + encodeURIComponent('Nieuw wachtwoord moet minstens 8 tekens zijn'));
+  }
+  if (new_password !== confirm) {
+    return res.redirect('/account?error=' + encodeURIComponent('Nieuwe wachtwoorden komen niet overeen'));
+  }
+
+  const row = db.prepare('SELECT password_hash FROM users WHERE id = ?').get(req.session.user.id);
+  // Google-only accounts (luisteraars) hebben geen echt wachtwoord.
+  if (!row || !row.password_hash || row.password_hash === '!google-oauth') {
+    return res.redirect('/account?error=' + encodeURIComponent('Dit account heeft geen wachtwoord (Google-login)'));
+  }
+  if (!bcrypt.compareSync(current, row.password_hash)) {
+    return res.redirect('/account?error=' + encodeURIComponent('Huidig wachtwoord is onjuist'));
+  }
+
+  const newHash = bcrypt.hashSync(new_password, 10);
+  db.prepare('UPDATE users SET password_hash = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?')
+    .run(newHash, req.session.user.id);
+
+  res.redirect('/account?success=' + encodeURIComponent('Wachtwoord gewijzigd'));
+});
 
 // ==================== UPLOAD AVATAR ====================
