1<!DOCTYPE html><html lang="nl"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><!-- Consent-gated analytics: GTM/GA worden pas geladen NA cookie-akkoord (AVG + 2 bespaart ±420 KB JS voor bezoekers zonder akkoord). Consent Mode v2 defaults 3 staan op denied; de cookiebanner roept __psLoadAnalytics() aan bij accepteren. 4 html.psc-done wordt VOOR de eerste render gezet zodat de banner nooit flitst. -->
4<script> 5 window.dataLayer = window.dataLayer || []; 6 function gtag(){dataLayer.push(arguments);} 7 gtag('consent', 'default', { 8 ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', 9 analytics_storage: 'denied', wait_for_update: 500, 10 }); 11 window.__psLoadAnalytics = function () { 12 if (window.__psGtmLoaded) return; 13 window.__psGtmLoaded = true; 14 gtag('consent', 'update', { ad_storage: 'granted', ad_user_data: 'granted', ad_personalization: 'granted', analytics_storage: 'granted' }); 15 gtag('js', new Date()); 16 gtag('config', 'G-6HYS9VKDWW'); 17 var g = document.createElement('script'); 18 g.async = true; 19 g.src = 'https://www.googletagmanager.com/gtag/js?id=G-6HYS9VKDWW'; 20 document.head.appendChild(g);
vendor: 358 bytes, lines 20-25
20 21 (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 22 new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 23 j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 24 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 25 })(window,document,'script','dataLayer','
25GTM-5KS746MG
vendor: 10 bytes, lines 25-26
25'); 26
26// HubSpot-paginabezoek-tracking (25-9-2026, "enkel voor inzicht"): alleen 27 // bekende/ingelogde gebruikers (server beslist dit via current_user(), 28 // dit script hoeft de inlogstatus niet vooraf te kennen), alleen na 29 // cookietoestemming (zelfde poort als GTM/GA hierboven). Stille no-op 30 // voor anonieme bezoekers en bij een netwerkfout. 31 try { 32 fetch('/api/account/pageview', { 33 method: 'POST', credentials: 'same-origin', keepalive: true, 34 headers: { 'Content-Type': 'application/json' }, 35 body: JSON.stringify({ path: location.pathname }), 36 }).catch(function () {}); 37 } catch (e) {} 38 }; 39 try { 40 var __c = localStorage.getItem('ps-consent'); 41 if (__c) document.documentElement.classList.add('psc-done'); 42 if (__c === 'granted') window.__psLoadAnalytics(); 43 } catch (e) {} 44 </script>
44<title>Occasion check: gratis AI-fotoscan en AankoopScore | PlateScout</title><meta name="description" content="Plak een Marktplaats- of AutoScout24-link voor een gratis AankoopScore: AI-fotoscan op schade, rode vlaggen uit RDW-data en een onderhandelingsscript."><meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1, max-video-preview:-1"><!-- Open Graph / Facebook --><meta property="og:type" content="website"><meta property="og:site_name" content="PlateScout"><meta property="og:title" content="Occasion check: gratis AI-fotoscan en AankoopScore | PlateScout"><meta property="og:description" content="Plak een Marktplaats- of AutoScout24-link voor een gratis AankoopScore: AI-fotoscan op schade, rode vlaggen uit RDW-data en een onderhandelingsscript."><meta property="og:image" content="https://platescout.nl/og-image.png"><meta property="og:url" content="https://platescout.nl/occasion-check"><!-- WebSite-structured data (29-9-2026, Stephan: Google toont "platescout.nl" 45 boven de titel in de zoekresultaten i.p.v. "PlateScout"). Google leidt de 46 getoonde sitenaam af uit (in volgorde van vertrouwen): WebSite-JSON-LD met 47 een "name"-veld, dan og:site_name (hierboven ook toegevoegd), en anders de 48 kale domeinnaam als terugval. Beide signalen nu aanwezig, sitebreed via 49 BaseLayout; geen garantie op een exacte tijdlijn (Google herindexeert/ 50 herevalueert dit op eigen tempo, kan enkele weken duren). -->
50<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","name":"PlateScout","url":"https://platescout.nl"}</script>
50<!-- Twitter --><meta property="twitter:card" content="summary_large_image"><meta property="twitter:title" content="Occasion check: gratis AI-fotoscan en AankoopScore | PlateScout"><meta property="twitter:description" content="Plak een Marktplaats- of AutoScout24-link voor een gratis AankoopScore: AI-fotoscan op schade, rode vlaggen uit RDW-data en een onderhandelingsscript."><link rel="canonical" href="https://platescout.nl/occasion-check"><!-- Preconnect naar de auto-render-CDN (24-9-2026, Stephan: "trage foto's"): de 51 hero-carrousel/kaarten op het kentekenrapport en dashboard halen foto's op bij 52 cdn.imagin.studio (scImage/carImageUrl), soms 1,7-2,6s bij een koude cache-miss 53 daar. Preconnect zet de TCP/TLS-verbinding alvast op, parallel aan de RDW-fetches, 54 scheelt zo'n 100-300ms op het kritieke pad. Sitewide (i.p.v. alleen op de 55 homepage): kost niets op pagina's zonder auto-render, browsers sluiten een 56 ongebruikte preconnect na ~10s vanzelf. --><link rel="preconnect" href="https://cdn.imagin.studio" crossorigin><!-- Echte, opvraagbare favicon-bestanden (Google indexeert geen inline data:-favicons). --><link rel="icon" href="/favicon.ico" sizes="48x48"><link rel="icon" type="image/svg+xml" href="/favicon.svg"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><!-- PWA (7-9-2026): installeerbaar als app, geen offline-caching (zie public/sw.js). --><link rel="manifest" href="/manifest.webmanifest"><meta name="theme-color" content="#4c8c2b"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="default"><meta name="apple-mobile-web-app-title" content="PlateScout"><!-- Bewust GEEN defer (wijkt af van de "scripts hebben defer"-conventie): 57 dit bestand raakt de DOM niet aan (registreert alleen de service worker 58 en definieert window.PSPush), maar moet WEL synchroon vóór paginaspecifieke 59 scripts staan, want sommige pagina's (bv. instellingen.astro) roepen 60 PSPush.* synchroon aan in hun eigen init()-script, dat zelf niet op 61 DOMContentLoaded wacht. Klein bestand, geen netwerkkosten van betekenis. -->
61<script src="/js/ps-push.js"></script>
61<!-- Self-hosted Inter (OFL): sneller (geen externe DNS/verbinding), AVG-vriendelijk. 62 De @font-face-regels staan inline (scheelt een renderblokkerend CSS-request); 63 /fonts/inter.css blijft bestaan voor park/ en tank/. --><link rel="preload" href="/fonts/inter-400-latin.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="/fonts/inter-700-latin.woff2" as="font" type="font/woff2" crossorigin><!-- 800 = het kopgewicht van elke hero/h1; preload voorkomt de zichtbare 64 font-swap op de titel (de enige CLS-bron die Lighthouse nog zag). --><link rel="preload" href="/fonts/inter-800-latin.woff2" as="font" type="font/woff2" crossorigin><style>/* Inter, self-hosted (OFL). Uit Google Fonts css2, latin + latin-ext. */ 65@font-face{font-family:'Inter';font-style:normal;font-weight:300;font-display:swap;src:url('/fonts/inter-300-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;} 66@font-face{font-family:'Inter';font-style:normal;font-weight:300;font-display:swap;src:url('/fonts/inter-300-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;} 67@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/inter-400-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;} 68@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('/fonts/inter-400-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;} 69@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url('/fonts/inter-500-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;} 70@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url('/fonts/inter-500-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;} 71@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/inter-600-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;} 72@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('/fonts/inter-600-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;} 73@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/inter-700-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;} 74@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url('/fonts/inter-700-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;} 75@font-face{font-family:'Inter';font-style:normal;font-weight:800;font-display:swap;src:url('/fonts/inter-800-latin-ext.woff2') format('woff2');
75unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;} 76@font-face{font-family:'Inter';font-style:normal;font-weight:800;font-display:swap;src:url('/fonts/inter-800-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;} 77@font-face{font-family:'Inter';font-style:normal;font-weight:900;font-display:swap;src:url('/fonts/inter-900-latin-ext.woff2') format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;} 78@font-face{font-family:'Inter';font-style:normal;font-weight:900;font-display:swap;src:url('/fonts/inter-900-latin.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;} 79</style><!-- Sitebrede standaard linkkleur: PlateScout-groen i.p.v. browserblauw. Via :where() 80 op specificiteit 0, zodat ELKE class-regel wint. Zonder :where() kaapte a:hover 81 (0,1,1) de kleur van knop-links waarvan de class (0,1,0) wel color zet maar de 82 :hover niet (bijv. "Lees artikel": donkergroene tekst op groene knop). -->
82<script type="application/ld+json">{"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"Wat is de AankoopScore?","acceptedAnswer":{"@type":"Answer","text":"Een score van 0 tot 100 die aangeeft hoeveel aandachtspunten wij zien bij een occasion, op basis van officiele RDW-gegevens zoals APK, tellerstandoordeel, terugroepacties, importstatus en de vraagprijs ten opzichte van een afschrijvingsindicatie. Het is een gratis indicatie, geen taxatie of aankoopkeuring."}},{"@type":"Question","name":"Is de occasion check echt gratis?","acceptedAnswer":{"@type":"Answer","text":"Ja, volledig gratis en zonder account. De analyse gebruikt uitsluitend openbare RDW-data en eigen rekenmodellen."}},{"@type":"Question","name":"Welke advertentielinks werken?","acceptedAnswer":{"@type":"Answer","text":"Links van Marktplaats, AutoScout24, Gaspedaal, AutoTrack en AutoWeek. Lukt het uitlezen niet (sommige sites blokkeren dit), dan vul je het kenteken en de vraagprijs gewoon handmatig in."}},{"@type":"Question","name":"Zijn de genoemde reparatiekosten bij \"Bekende gebreken\" exact?","acceptedA
82nswer":{"@type":"Answer","text":"Nee. Het zijn indicatieve bandbreedtes uit de Nederlandse garagepraktijk, gebaseerd op onze eigen redactionele problemen-gidsen per merk en model, geen offerte of taxatie. Ze zeggen ook niets over de staat van dit specifieke exemplaar; gebruik daarvoor de AankoopScore en Bevindingen."}},{"@type":"Question","name":"Kan ik het chassisnummer (VIN) van een auto opzoeken bij PlateScout?","acceptedAnswer":{"@type":"Answer","text":"Nee, de RDW publiceert het chassisnummer zelf nergens in open data, dus wij kunnen het niet tonen of opzoeken. Wel registreert de RDW per kenteken waar het chassisnummer op de auto is aangebracht; die locatie nemen we op in de proefrit-checklist, zodat je zelf ter plekke kunt controleren of het ingeslagen nummer overeenkomt met de kentekencard."}}]}</script>
82<style>:root{--bg: #f5f5f7;--card: #fff;--text: #1d1d1f;--text-secondary: #5f6368;--text-tertiary: #6e6e73;--border: rgba(0,0,0,.06);--green: #4c8c2b;--radius: 20px;--radius-sm: 12px;--shadow: 0 4px 24px rgba(0,0,0,.06)}*{margin:0;padding:0;box-sizing:border-box}html,body{overflow-x:clip}body{font-family:Inter,-apple-system,BlinkMacSystemFont,sans-serif;background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased}nav{position:sticky;top:0;z-index:100;background:#f5f5f7d9;backdrop-filter:blur(20px);border-bottom:.5px solid var(--border);padding:0 2rem}.nav-inner{max-width:980px;margin:0 auto;display:flex;align-items:center;height:52px;gap:1rem}.nav-back{display:flex;align-items:center;gap:.4rem;color:var(--text-secondary);text-decoration:none;font-size:.85rem;font-weight:500}.nav-back:hover{color:var(--text)}.nav-logo-link{display:flex;align-items:center;text-decoration:none}.container{max-width:760px;margin:0 auto;padding:3rem 1.5rem 5rem}h1{font-size:2.5rem;font-weight:800;letter-spacing:-.04em;line-height:1.1;margin-bottom:.5rem}.subtitle{font-size:1.1rem;color:var(--text-secondary);margin-bottom:2.5rem;line-height:1.5}h2{font-size:1.25rem;font-weight:700;margin:2.5rem 0 .75rem}h3{font-size:1rem;font-weight:700;margin:1.5rem 0 .5rem}p{font-size:.95rem;line-height:1.7;color:var(--text-secondary);margin-bottom:1rem}p strong{color:var(--text)}.card{background:var(--card);border-radius:var(--radius);padding:2rem;box-shadow:var(--shadow);margin-bottom:1.5rem}.card>h2:first-child{margin-top:0}.info-row{display:flex;gap:1rem;padding:.8rem 0;border-bottom:.5px solid var(--border);font-size:.9rem}.info-row:last-child{border-bottom:none}.info-row .lbl{color:var(--text-secondary);min-width:180px}.info-row .val{font-weight:600}.badge{display:inline-flex;align-items:center;gap:.4rem;padding:.35rem .85rem;border-radius:99px;font-size:.78rem;font-weight:600}.badge-green{background:#4c8c2b1a;color:#2d6b10}.badge-blue{background:#007aff1a;color:#0050d0}.badge-orange{background:#ff95001a;color:#9a4000}.cta-box{background:linear-gradient(135deg,#4c8c2b,#3a6e1f);border-radius:var(--radius);padding:2rem;text-align:center;margin:2rem 0;color:#fff}.cta-box h2{color:#fff;margin:0 0 .5rem;font-size:1.4rem}.cta-box p{color:#fffc;margin-bottom:0}.tip-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:1rem;margin:1.5rem 0}.tip-card{background:var(--card);border-radius:var(--radius-sm);padding:1.25rem;box-shadow:var(--shadow)}.tip-card .ti{display:flex;align-items:center;margin-bottom:.5rem}.tip-card .ti svg{stroke:var(--green);width:24px;height:24px}.tip-card h3{font-size:.9rem;font-weight:700;margin:0 0 .3rem;color:var(--text)}.tip-card p{font-size:.82rem;margin:0}footer{border-top:.5px solid var(--border);padding:2rem 1.5rem;margin-top:3rem}.footer-inner{max-width:760px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:1rem;font-size:.78rem;color:var(--text-tertiary)}.footer-inner a{color:var(--text-secondary);text-decoration:none}.footer-inner a:hover{text-decoration:underline}.footer-links{display:flex;gap:1.25rem}ul.content-list{padding-left:1.25rem;margin-bottom:1rem}ul.content-list li{font-size:.95rem;color:var(--text-secondary);line-height:1.7;margin-bottom:.25rem}ul.content-list li strong{color:var(--text)}.faq-item{border-bottom:.5px solid var(--border);padding:1rem 0}.faq-item:last-child{border-bottom:none}.faq-q{font-weight:700;font-size:.95rem;cursor:pointer;display:flex;justify-content:space-between;align-items:center}.faq-a{font-size:.9rem;color:var(--text-secondary);line-height:1.6;max-height:0;overflow:hidden;transition:max-height .3s ease,padding-top .3s ease;padding-top:0}.faq-item.open .faq-a{max-height:400px;padding-top:.6rem}.faq-arrow{transition:transform .3s}.faq-item.open .faq-arrow{transform:rotate(180deg)}@media(max-width:640px){h1{font-size:1.8rem}.container{padding:2rem 1.25rem 4rem}}.tool-hero{position:relative;overflow:hidden;margin:0 0 1.75rem;padding:2.6rem 2.2rem;border-radius:0;color:#fff;width:100vw;margin-left:calc(50% - 50vw);margin-right:calc(50% - 50vw);background:radial-gradient(120% 140% at 100% 0%,#5aa632,#4c8c2b 45%,#2f5e18)}.container>.tool-hero:first-child{margin-top:-2rem}.tool-hero-inner{max-width:1100px;margin:0 auto}.tool-hero h1{color:#fff;font-size:clamp(1.9rem,4.2vw,2.7rem);margin-bottom:.6rem}.tool-hero .subtitle{color:#ffffffeb;margin-bottom:1.5rem}.th-badge{display:inline-flex;align-items:center;gap:.4rem;background:#ffffff29;color:#fff;font-size:.78rem;font-weight:600;padding:.35rem .7rem;border-radius:999px;margin-bottom:1rem}.th-badge svg{flex-shrink:0}.tool-hero .cta-box{background:#ffffff1a;border:1px solid rgba(255,255,255,.18);box-shadow:none;margin:0;padding:1.4rem 1.5rem;border-radius:16px}.tool-hero .cta-box h2{font-size:1.05rem}.tool-hero .cta-box p{font-size:.88rem}.th-grid{display:flex;flex-direction:column;align-items:center;gap:1.8rem}.th-left{width:100%}.th-visual{width:100%;display:flex;flex-direction:column;align-items:center;gap:.8rem}
82@media(min-width:900px){.th-grid{flex-direction:row;align-items:center}.th-left{flex:1 1 420px;min-width:0}.th-visual{flex:0 0 320px}}.card{border:1px solid rgba(0,0,0,.07);box-shadow:0 4px 24px #0000000a}.tip-card{border:1px solid rgba(0,0,0,.07);box-shadow:none;transition:border-color .15s,transform .1s}.tip-card:hover{border-color:#4c8c2b66;transform:translateY(-2px)}.tip-card .ti{width:44px;height:44px;border-radius:12px;background:#eaf4e3;display:flex;align-items:center;justify-content:center;margin-bottom:.8rem}.tip-card .ti svg{width:22px;height:22px}.cta-box{background:radial-gradient(120% 160% at 0% 0%,#5aa632,#4c8c2b 55%,#2f5e18)}@media(max-width:640px){.tool-hero{padding:1.8rem 1.3rem}.container>.tool-hero:first-child{margin-top:-1.5rem}} 83:root{--plate-yellow: #f7d117;--plate-blue: #003399}.plate-wrapper{display:flex;align-items:stretch;max-width:480px;margin:0 auto;background:linear-gradient(170deg,#fad931 0%,var(--plate-yellow) 40%,#f0c800 100%);border-radius:16px;border:2px solid rgba(0,0,0,.15);overflow:hidden;box-shadow:0 2px 4px #0000000a,0 8px 32px #00000014,inset 0 1px #ffffff59;transition:all .3s cubic-bezier(.25,.46,.45,.94)}.plate-wrapper:focus-within{transform:translateY(-2px) scale(1.01);box-shadow:0 4px 8px #0000000f,0 16px 48px #0000001f,inset 0 1px #ffffff59,0 0 0 4px #f7d11733;border-color:#0003}.plate-nl{background:linear-gradient(180deg,#0044aa 0%,var(--plate-blue) 100%);color:#fff;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:0 1rem;gap:2px;min-width:48px}.plate-nl .eu-stars{display:flex;align-items:center;justify-content:center}.plate-nl .eu-stars svg{width:18px;height:18px}.plate-nl .nl-code{font-size:.95rem;font-weight:800}.plate-input{flex:1;border:none;background:transparent;font-size:2.2rem;font-weight:800;letter-spacing:4px;padding:.85rem .5rem;text-transform:uppercase;outline:none;text-align:center;font-family:Inter,sans-serif;color:#1a1a1a;min-width:0}.plate-input::placeholder{color:#0000002e;font-weight:600;letter-spacing:3px;font-size:1.6rem}.plate-btn{background:#1a1a1a;border:none;color:#fff;padding:0 1.5rem;cursor:pointer;display:flex;align-items:center;transition:all .2s}.plate-btn:hover{background:#333}.plate-btn:active{transform:scale(.95)}.plate-btn:disabled{opacity:.4;cursor:not-allowed}.plate-btn svg{transition:transform .2s}.plate-btn:hover svg{transform:scale(1.1)}.plate-search .hint{text-align:center;margin-top:1rem;font-size:.78rem;color:inherit}.plate-search .hint a{color:inherit;text-decoration:underline;text-underline-offset:2px;font-weight:700}@media(max-width:520px){.plate-input{font-size:1.6rem;letter-spacing:2px}.plate-input::placeholder{font-size:1.2rem}} 84:root{--bg:#f5f5f7;--card:#fff;--text:#1d1d1f;--text-secondary:#5f6368;--text-tertiary:#6e6e73;--border:rgba(0,0,0,.08);--green:#4c8c2b}nav{position:sticky;top:0;z-index:100;background:#f5f5f7b8;backdrop-filter:blur(20px);border-bottom:.5px solid var(--border);padding:0 2rem}.nav-inner{max-width:980px;margin:0 auto;display:flex;align-items:center;height:52px;gap:1rem}.nav-back{display:flex;align-items:center;gap:.4rem;color:var(--text-secondary);text-decoration:none;font-size:.85rem;font-weight:500}.nav-back:hover{color:var(--text)}.nav-logo-link{display:flex;align-items:center;text-decoration:none}footer{border-top:.5px solid var(--border);padding:2rem 1.5rem;margin-top:3rem}.footer-inner{max-width:760px;margin:0 auto;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:1rem;font-size:.78rem;color:var(--text-tertiary)}.footer-inner a{color:var(--text-secondary);text-decoration:none}.footer-inner a:hover{text-decoration:underline}.footer-links{display:flex;gap:1.25rem}.faq-item{border-bottom:.5px solid var(--border);padding:1rem 0}.faq-item:last-child{border-bottom:none}.faq-q{font-weight:700;font-size:.95rem;cursor:pointer;display:flex;justify-content:space-between;align-items:center}.faq-a{font-size:.9rem;color:var(--text-secondary);line-height:1.6;max-height:0;overflow:hidden;transition:max-height .3s ease,padding-top .3s ease;padding-top:0}.faq-item.open .faq-a{max-height:400px;padding-top:.6rem}.faq-arrow{transition:transform .3s}.faq-item.open .faq-arrow{transform:rotate(180deg)}.page-shell-root{display:flex;flex-direction:column;min-height:100vh;min-height:100dvh}.page-shell-content{flex:1 0 auto} 85.oc-hero-outer{margin:1rem 0 0;padding:0}@media(max-width:640px){.oc-hero-outer{margin-top:.5rem}}.tool-hero.oc-hero{border-radius:0}.oc-hero-inner{max-width:1100px;margin:0 auto;width:100%}.oc-hero-grid{display:flex;flex-direction:column;align-items:center;gap:1.8rem}.oc-hero-left{width:100%}.oc-hero-visual{width:100%;display:flex;flex-direction:column;align-items:center;gap:.8rem}.oc-mock{background:#fff;border-radius:18px;padding:1.3rem 1.4rem;width:100%;max-width:340px;box-shadow:0 18px 40px #00000038;transform:rotate(1.2deg)}.oc-mock-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:.9rem}.oc-mock-plate{display:flex;align-items:center;background:#ffd200;border:2px solid #1a1a1a;border-radius:6px;overflow:hidden}.oc-mock-nl{background:#1a3fbf;color:#fff;font-weight:800;font-size:.58rem;padding:.35rem .3rem;align-self:stretch;display:flex;align-items:center}.oc-mock-plate b{color:#111;font-weight:800;font-size:.85rem;letter-spacing:.04em;padding:0 .45rem}.oc-mock-tag{font-size:.65rem;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:#8a8a8e;background:#0000000d;padding:.2rem .5rem;border-radius:999px}.oc-mock-score{display:flex;align-items:center;gap:.9rem;margin-bottom:.9rem}.oc-mock-dial{width:68px;height:68px;flex-shrink:0}.oc-mock-dial span{font-size:1.4rem}.oc-mock-dial small{font-size:.62rem}.oc-mock-score b{display:block;font-size:.92rem;color:#1d1d1f}.oc-mock-price{display:block;font-size:.8rem;color:#6e6e73;margin-top:.15rem}.oc-mock-flags .oc-flag{padding:.5rem 0;font-size:.82rem;gap:.55rem}.oc-mock-flags .oc-flag p{font-size:.76rem}.oc-mock-ai-badge{margin:.5rem 0 .3rem}
85.oc-mock-demo{display:inline-flex;align-items:center;gap:.4rem;background:#ffffff24;border:1px solid rgba(255,255,255,.3);color:#fff;text-decoration:none;font-size:.85rem;font-weight:700;padding:.55rem 1rem;border-radius:11px;transition:background .15s}.oc-mock-demo:hover{background:#ffffff3d;color:#fff}.oc-ext-pill{display:flex;align-items:center;gap:.85rem;margin-top:1rem;background:#fff;border-radius:14px;padding:.75rem 1rem;text-decoration:none;box-shadow:0 6px 20px #0000001f;transition:transform .1s}.oc-ext-pill:hover{transform:translateY(-1px)}.oc-ext-pill-logos{display:flex;align-items:center;flex-shrink:0}.oc-ext-pill-logos img{display:block;border-radius:50%;background:#fff;box-shadow:0 0 0 2px #fff}.oc-ext-pill-logos img+img{margin-left:-6px}.oc-ext-pill-txt{flex:1;min-width:0;text-align:left;line-height:1.35}.oc-ext-pill-txt strong{display:block;font-size:.88rem;color:#1d1d1f}.oc-ext-pill-txt span{display:block;font-size:.78rem;color:#6e6e73;margin-top:.1rem}.oc-ext-pill-arrow{color:#3f7523;flex-shrink:0}@media(min-width:900px){.oc-hero-grid{flex-direction:row;align-items:center}.oc-hero-left{flex:1 1 420px;min-width:0}.oc-hero-visual{flex:0 0 320px}}.oc-url-row{display:flex;gap:.5rem;max-width:560px;margin:.75rem auto 0}.oc-url-row input{flex:1;min-width:0;font-family:inherit;font-size:.95rem;padding:.7rem .85rem;border:none;border-radius:11px;outline:none;color:#1d1d1f}.oc-url-row button{font-family:inherit;font-size:.92rem;font-weight:700;padding:.7rem 1.2rem;border:none;border-radius:11px;background:#fff;color:#2f5e18;cursor:pointer;transition:transform .05s}.oc-url-row button:active{transform:scale(.98)}.oc-url-row button:disabled{opacity:.6;cursor:default}.oc-alt{display:inline-flex;align-items:center;gap:.35rem;margin-top:.9rem!important;font-size:.92rem!important;font-weight:700;font-family:inherit;background:none;border:none;padding:.3rem .1rem;color:#fff;cursor:pointer;text-decoration:underline;text-underline-offset:3px;text-decoration-color:#ffffff80;transition:text-decoration-color .15s}.oc-alt:hover{text-decoration-color:#fff}.oc-alt svg{flex-shrink:0}.oc-plate-row{margin:.5rem 0 1rem}.oc-plate-row label{display:block;font-size:.8rem;font-weight:700;color:#1d1d1f;margin-bottom:.4rem}.oc-plate-wrapper{margin:0}.oc-fields{display:grid;grid-template-columns:repeat(2,1fr);gap:.8rem;margin:0 0 1rem}.oc-field label{display:block;font-size:.8rem;font-weight:700;color:#1d1d1f;margin-bottom:.3rem}.oc-field input{width:100%;box-sizing:border-box;font-family:inherit;font-size:.95rem;padding:.65rem .8rem;border:1.5px solid rgba(0,0,0,.12);border-radius:11px;background:#fafafa;outline:none}.oc-field input:focus{border-color:#4c8c2b;background:#fff}.oc-run{display:inline-flex;align-items:center;gap:.5rem;border:none;cursor:pointer;font-family:inherit;padding:.7rem 1.3rem;border-radius:12px;background:#4c8c2b;color:#fff;font-size:.95rem;font-weight:700;transition:background .15s}.oc-run:hover{background:#3f7523}.oc-run:disabled{opacity:.6;cursor:default}.oc-score-wrap{display:flex;align-items:center;gap:1.5rem}.oc-dial{width:110px;height:110px;border-radius:50%;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#fff;flex-shrink:0;background:#5f6368}.oc-dial span{font-size:2.2rem;font-weight:800;line-height:1}.oc-dial small{font-size:.72rem;opacity:.85}.oc-dial.g{background:radial-gradient(120% 120% at 30% 20%,#5aa632,#2f5e18)}.oc-dial.o{background:radial-gradient(120% 120% at 30% 20%,#f5a623,#c97b06)}.oc-dial.r{background:radial-gradient(120% 120% at 30% 20%,#e05252,#a12727)}.oc-vehicle{font-weight:700;color:#1d1d1f;margin:0 0 .3rem}.oc-verdict{margin:0}.oc-verdict-badge{display:inline-block;margin-bottom:.9rem;padding:.4rem .9rem;border-radius:8px;font-size:.85rem;font-weight:800;letter-spacing:.01em;text-transform:uppercase}.oc-verdict-badge.g{background:#eaf4e3;color:#2f5e18}.oc-verdict-badge.o{background:#fdf0dd;color:#c97b06}.oc-verdict-badge.r{background:#fbe7e7;color:#a12727}.oc-verdict-badge:empty{display:none}.oc-verdict-pct{display:inline-block;padding:.4rem .9rem;border-radius:8px;font-size:.85rem;font-weight:800}.oc-verdict-pct.red{background:#fbe7e7;color:#a12727}.oc-verdict-pct.green{background:#eaf4e3;color:#2f5e18}.oc-score-top{display:flex;align-items:center;justify-content:space-between;gap:.6rem;flex-wrap:wrap;margin-bottom:.3rem}.oc-score-top .oc-verdict-badge{margin-bottom:0}.oc-verdict-pct{margin-right:auto}.oc-cost-sliders{display:flex;flex-direction:column;gap:.9rem;margin:.8rem 0 1rem}.oc-cost-slider-row{display:flex;flex-direction:column;gap:.3rem}.oc-cost-slider-row label{font-size:.85rem;font-weight:700;color:#1d1d1f}.oc-cost-slider-row input[type=range]{width:100%;accent-color:#4c8c2b}.oc-cost-slider-val{font-size:.82rem;color:#5f6368}.oc-new-search{display:inline-flex;align-items:center;gap:.4rem;background:none;border:1px solid var(--border);border-radius:99px;padding:.4rem .9rem;font-size:.8rem;font-weight:600;font-family:inherit;color:var(--text-secondary);cursor:pointer;transition:background .15s}.oc-new-search:hover{background:#0000000a}.oc-sk-dial,.oc-sk-bar,.oc-sk-photo{background:linear-gradient(100deg,#0000000d 30%,#0000001c,#0000000d 70%);background-size:200% 100%;animation:oc-sk-shimmer 1.4s ease-in-out infinite}.oc-sk-bar{border-radius:6px;height:13px}
85.oc-sk-title{width:200px;max-width:100%;height:22px;margin-bottom:.5rem}.oc-sk-sub{width:140px;max-width:100%}.oc-sk-line{width:85%;margin-bottom:.4rem}.oc-sk-line-short{width:45%}.oc-sk-dot{background:#0000001a}.oc-sk-plate{width:100%;max-width:480px;height:76px;border-radius:16px;margin:0 auto .8rem}.oc-sk-photo{width:220px;max-width:78vw;height:150px;border-radius:14px}@keyframes oc-sk-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@media(prefers-reduced-motion:reduce){.oc-sk-dial,.oc-sk-bar,.oc-sk-photo{animation:none}}.oc-photo-hero{margin-bottom:1.2rem}.oc-result-plate{margin:0 auto .8rem}.oc-plate-readonly{cursor:default;user-select:text}.oc-photo-strip{display:flex;gap:.6rem;overflow-x:auto;scroll-snap-type:x mandatory;-webkit-overflow-scrolling:touch;scrollbar-width:none}.oc-photo-strip::-webkit-scrollbar{display:none}.oc-photo-strip img{scroll-snap-align:start;flex:0 0 auto;width:220px;max-width:78vw;height:150px;object-fit:cover;border-radius:14px;border:1px solid rgba(0,0,0,.08);box-shadow:0 4px 16px #00000014;cursor:zoom-in;transition:opacity .15s}.oc-photo-strip img:hover{opacity:.9}body.oc-report-mode .oc-hero-outer,body.oc-report-mode #oc-manual-card{display:none}.oc-report-brand{display:none;text-align:center;margin:0 0 1.4rem}body.oc-report-mode .oc-report-brand{display:block}.oc-report-logo{margin:0 auto .9rem}.oc-report-title{font-size:1.6rem;font-weight:800;color:#1d1d1f;margin:0}.oc-trust-bar{display:none;background:var(--card);padding:1rem 0;min-height:72px;font-size:.9rem;color:var(--text-secondary);border-bottom:1px solid var(--border)}body.oc-report-mode .oc-trust-bar{display:block}.oc-trust-bar-content{display:flex;align-items:center;justify-content:center;gap:2.5rem;flex-wrap:wrap;max-width:980px;margin:0 auto;padding:0 1.5rem}.oc-trust-item{display:flex;align-items:center;gap:.5rem;font-weight:500}.oc-trust-item svg{width:18px;height:18px;stroke:#4c8c2b}.oc-trust-stats{margin-top:1rem;font-weight:700;font-size:1.1rem;color:#1d1d1f;width:100%;text-align:center}@media(max-width:768px){.oc-trust-bar-content{gap:1rem;font-size:.75rem;flex-wrap:nowrap}.oc-trust-item{gap:.35rem;white-space:nowrap}.oc-trust-item svg{width:14px;height:14px}.oc-trust-stats{font-size:.9rem}}.oc-nav-plate{display:none;align-items:stretch;background:linear-gradient(170deg,#fad931 0%,var(--plate-yellow) 40%,#f0c800 100%);border-radius:8px;border:1.5px solid rgba(0,0,0,.15);overflow:hidden;box-shadow:0 1px 3px #00000014}body.oc-report-mode .oc-nav-plate{display:flex}.oc-nav-plate .oc-np-blue{background:linear-gradient(180deg,#0044aa 0%,var(--plate-blue) 100%);color:#fff;padding:.25rem .45rem;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1px}.oc-nav-plate .oc-np-stars{display:flex;align-items:center;justify-content:center}.oc-nav-plate .oc-np-stars svg{width:14px;height:14px}.oc-nav-plate .oc-np-nl{font-size:.55rem;font-weight:800;line-height:1}.oc-nav-plate .oc-np-text{padding:.25rem .5rem;font-size:.85rem;font-weight:800;letter-spacing:2px;color:#1a1a1a;text-transform:uppercase;font-family:Inter,sans-serif;display:flex;align-items:center}.oc-share-section{background:var(--card);border-radius:var(--radius-sm);padding:1.25rem 1.5rem;margin:0 0 1.5rem;box-shadow:var(--shadow)}.oc-share-section h3{font-size:1rem;font-weight:700;margin:0 0 1.1rem;color:#1d1d1f;display:flex;align-items:center;gap:.5rem}.oc-share-buttons{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:.65rem}.oc-share-btn{padding:.7rem 1rem;border:1px solid var(--border);border-radius:9px;font-weight:600;font-size:.85rem;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:.5rem;transition:all .2s;font-family:inherit;background:var(--card);color:#1d1d1f}.oc-share-btn svg{width:16px;height:16px;flex-shrink:0;stroke:#4c8c2b}.oc-share-btn:hover{transform:translateY(-1px);box-shadow:var(--shadow);background:#3f7523;border-color:#3f7523;color:#fff}.oc-share-btn:hover svg{stroke:#fff}.oc-share-btn.oc-sb-flash,.oc-share-btn.oc-sb-flash:hover{background:#2f5e18;border-color:#2f5e18;color:#fff}.oc-share-btn.oc-sb-flash svg{stroke:#fff}@media(max-width:520px){.oc-share-buttons{grid-template-columns:1fr}}.oc-explain-toggle{margin-top:1rem;background:none;border:none;font-size:.75rem;color:#5f6368;cursor:pointer;padding:0;font-family:inherit;text-decoration:underline;text-underline-offset:2px}.oc-explain-toggle:hover{color:#1d1d1f}.oc-save-btn{display:inline-flex;align-items:center;gap:.5rem;margin-top:1.2rem;border:none;cursor:pointer;font-family:inherit;padding:.7rem 1.3rem;border-radius:12px;background:#4c8c2b;color:#fff;font-size:.92rem;font-weight:700;transition:background .15s}.oc-save-btn:hover{background:#3f7523}.oc-save-btn:disabled{opacity:.7;cursor:default}.oc-save-btn[hidden]{display:none}.oc-save-login-hint{margin-top:1.2rem}.oc-feedback-block{display:flex;align-items:center;gap:.8rem;flex-wrap:wrap;margin-top:1.2rem;padding-top:1.1rem;border-top:1px solid rgba(0,0,0,.06)}.oc-feedback-block[hidden]{display:none}.oc-feedback-q{margin:0;font-size:.85rem;color:#5f6368}.oc-feedback-buttons{display:flex;gap:.5rem}.oc-feedback-btn{font-family:inherit;font-size:.85rem;font-weight:700;padding:.4rem 1rem;border-radius:8px;border:1.5px solid #4c8c2b;background:#fff;color:#4c8c2b;cursor:pointer}.oc-feedback-btn:hover{background:#f2f8ee}.oc-feedback-btn.oc-fb-picked{background:#4c8c2b;color:#fff}.oc-vblock{display:flex;gap:.8rem;align-items:flex-start;padding:.8rem 0;border-bottom:1px solid rgba(0,0,0,.06)}.oc-vblock:last-child{border-bottom:none}.oc-vblock-dot{width:11px;height:11px;border-radius:50%;margin-top:.35rem;flex-shrink:0}.oc-vblock-red .oc-vblock-dot{background:#d33}.oc-vblock-orange .oc-vblock-dot{background:#f5a623}.oc-vblock-green .oc-vblock-dot{background:#4c8c2b}.oc-vblock strong{display:block;margin-bottom:.2rem;font-size:.95rem}.oc-vblock p{margin:0;font-size:.87rem;color:#5f6368;line-height:1.5}.oc-score-explain{margin-top:.75rem;font-size:.85rem;color:#5f6368;background:#f5f5f7;border-radius:10px;padding:.85rem 1rem}.oc-explain-row{display:flex;justify-content:space-between;gap:1rem;padding:.35rem 0;border-bottom:1px solid rgba(0,0,0,.06)}.oc-explain-row:last-of-type{border-bottom:none}.oc-explain-impact{font-weight:700;color:#a12727;flex-shrink:0}.oc-explain-start{color:#1d1d1f;font-weight:700}.oc-explain-total{font-weight:800;color:#1d1d1f;border-top:1.5px solid rgba(0,0,0,.12);margin-top:.3rem;padding-top:.55rem}.oc-flag{display:flex;gap:.7rem;align-items:flex-start;padding:.7rem 0;border-bottom:1px solid rgba(0,0,0,.06);font-size:.92rem}.oc-flag:last-child{border-bottom:none}#oc-flags:has(+#oc-flags-ai:not(:empty)) .oc-flag:last-child{border-bottom:1px solid rgba(0,0,0,.06)}.oc-flag .fdot{width:10px;height:10px;border-radius:50%;margin-top:.4rem;flex-shrink:0}.oc-flag.red .fdot{background:#d33}.oc-flag.orange .fdot{background:#f5a623}.oc-flag.green .fdot{background:#4c8c2b}.oc-flag strong{color:#1d1d1f}.oc-flag p{margin:.1rem 0 0}.oc-flag-photos{display:flex;gap:.5rem;flex-wrap:wrap;margin-top:.55rem}.oc-flag-photo{display:block;width:160px;max-width:100%;height:110px;object-fit:cover;border-radius:10px;border:1.5px solid rgba(0,0,0,.08);cursor:zoom-in;transition:opacity .15s}.oc-flag-photo:hover{opacity:.85}.oc-info-btn{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;margin-left:.3rem;padding:0;border:none;border-radius:50%;background:#00000014;color:#5f6368;cursor:pointer;vertical-align:middle;transition:background .15s,color .15s}.oc-info-btn:hover,.oc-info-btn[aria-expanded=true]{background:#4c8c2b;color:#fff}.oc-photocheck-wrap{margin-top:.8rem;padding-top:.8rem;border-top:1px solid rgba(0,0,0,.06)}.oc-lightbox{position:fixed;inset:0;z-index:999;background:#0a0a0aeb;display:flex;align-items:center;justify-content:center;padding:3.2rem 1.2rem}.oc-lightbox[hidden]{display:none}.oc-lightbox-img{max-width:min(92vw,1100px);max-height:85vh;border-radius:14px;box-shadow:0 20px 60px #00000080;object-fit:contain}.oc-lightbox-close,.oc-lightbox-prev,.oc-lightbox-next{position:absolute;border:none;border-radius:50%;background:#ffffff24;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s}.oc-lightbox-close:hover,.oc-lightbox-prev:hover,.oc-lightbox-next:hover{background:#ffffff42}.oc-lightbox-close{top:1rem;right:1rem;width:42px;height:42px}.oc-lightbox-prev,.oc-lightbox-next{top:50%;transform:translateY(-50%);width:48px;height:48px}.oc-lightbox-prev{left:.6rem}.oc-lightbox-next{right:.6rem}@media(max-width:640px){.oc-lightbox-prev,.oc-lightbox-next{width:38px;height:38px}.oc-lightbox-prev{left:.3rem}.oc-lightbox-next{right:.3rem}}.oc-script{background:#fafafa;border:1px solid rgba(0,0,0,.08);border-radius:12px;padding:1rem 1.2rem}.oc-script ul{margin:0;padding-left:1.1rem}.oc-script li{margin:0 0 .55rem;font-size:.92rem;line-height:1.55;color:#333}.oc-copy{margin-top:.8rem;font-family:inherit;font-size:.88rem;font-weight:700;padding:.55rem 1rem;border-radius:10px;border:1.5px solid #4c8c2b;background:#fff;color:#4c8c2b;cursor:pointer}.oc-copy:hover{background:#f2f8ee}.oc-bid{background:#f2f8ee;border-radius:10px;padding:.55rem .7rem;margin:.4rem -.7rem 0}.oc-bid .val{color:#2f5e18;font-weight:800}.oc-links{display:flex;gap:.6rem;flex-wrap:wrap}.oc-links a{display:inline-flex;align-items:center;gap:.5rem;padding:.6rem 1rem;border-radius:10px;border:1.5px solid rgba(0,0,0,.12);background:#fff;color:#5f6368;font-size:.88rem;font-weight:700;text-decoration:none}.oc-links a:hover{border-color:#4c8c2b;color:#2f5e18;background:#f2f8ee}.oc-links img{height:20px;width:auto;display:block}.oc-gp{font-size:.95rem;font-weight:800;color:#1d1d1f;letter-spacing:-.01em}.oc-gp b{color:#ff6d00}.oc-checkgroup{font-size:.8rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#5f6368;margin:1rem 0 .25rem}.oc-checkgroup:first-child{margin-top:.25rem}.oc-check{display:flex;align-items:flex-start;gap:.6rem;padding:.45rem 0;border-bottom:1px solid rgba(0,0,0,.05);font-size:.92rem;cursor:pointer}.oc-check input{width:17px;height:17px;margin-top:2px;flex-shrink:0;accent-color:#4c8c2b;cursor:pointer}.oc-check input:checked+span{color:#5f6368;text-decoration:line-through}.oc-photo{display:flex;gap:.7rem;align-items:flex-start;padding:.55rem 0;border-bottom:1px solid rgba(0,0,0,.05);font-size:.92rem}.oc-photo:last-child,.oc-check:last-child{border-bottom:none}.oc-photo .pnum{width:22px;height:22px;border-radius:50%;background:#eaf4e3;color:#2f5e18;font-size:.75rem;font-weight:800;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;margin-top:.1rem}#oc-ai-photocheck:not(:empty){margin-bottom:1rem;padding-bottom:1rem;border-bottom:1.5px solid rgba(0,0,0,.08)}.oc-ai-badge{display:inline-block;margin:0 0 .6rem;padding:.3rem .65rem;border-radius:8px;background:#eaf4e3;color:#2f5e18;font-size:.72rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase}.th-badges{display:flex;flex-wrap:wrap;gap:.5rem;margin-bottom:.9rem}.th-badges .th-badge{margin-bottom:0}.th-badge-new{background:#f5a62338;color:#ffd48a}.oc-ai-skeleton{display:flex;flex-direction:column;gap:.9rem}.oc-ai-skeleton .sk-row{display:flex;gap:.7rem;align-items:flex-start}.oc-ai-skeleton .sk-dot{width:10px;height:10px;border-radius:50%;margin-top:.4rem;flex-shrink:0;background:#e2e5e2}.oc-ai-skeleton .sk-lines{flex:1;display:flex;flex-direction:column;gap:.5rem}.oc-ai-skeleton .sk-bar{height:12px;border-radius:6px;background:linear-gradient(90deg,#eef1ee 25%,#f7f9f7 37%,#eef1ee 63%);background-size:400% 100%;animation:oc-shimmer 1.4s ease infinite}.oc-ai-skeleton .sk-bar.w30{width:30%}.oc-ai-skeleton .sk-bar.w40{width:40%}.oc-ai-skeleton .sk-bar.w70{width:70%}.oc-ai-skeleton .sk-bar.w90{width:90%}@keyframes oc-shimmer{0%{background-position:100% 50%}to{background-position:0 50%}}@media(max-width:640px){.oc-fields{grid-template-columns:1fr}.oc-url-row{flex-direction:column}.oc-score-wrap{flex-direction:column;text-align:center}.oc-score-card{text-align:center}.oc-score-explain{text-align:left}} 86body{margin:0;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;-webkit-font-smoothing:antialiased}:where(a){color:#3f7523}:where(a:hover){color:#345f1d}.psc{position:fixed;left:16px;right:16px;bottom:16px;z-index:9999;max-width:400px;margin-right:auto;box-sizing:border-box;background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:16px;padding:18px 19px;box-shadow:0 18px 50px #0000002e;font-size:14px;line-height:1.5;color:#1d1d1f}.psc *,.pse *{box-sizing:border-box}html.psc-done .psc{display:none!important}.psc-head{display:flex;align-items:center;gap:8px;margin-bottom:7px;color:#1d1d1f;font-size:14px}.psc-ic{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:9px;background:#eaf4e3;color:#4c8c2b;flex-shrink:0}.psc p{margin:0 0 13px;color:#555;line-height:1.55;font-size:14px}.psc p strong{color:#1d1d1f}.psc-actions{display:flex;gap:8px;flex-wrap:wrap}.psc-btn{font-family:inherit;font-size:13.5px;line-height:1.2;font-weight:700;padding:9px 16px;border-radius:10px;cursor:pointer;transition:background .15s,transform .05s}.psc-btn:active{transform:scale(.98)}.psc-accept{border:none;background:#3f7523;color:#fff}.psc-accept:hover{background:#345f1d}.psc-decline{border:1.5px solid rgba(0,0,0,.15);background:#fff;color:#1d1d1f}.psc-decline:hover{border-color:#0000004d}@media(max-width:480px){.psc{left:10px;right:10px;bottom:10px;max-width:none}}.pse{display:none;position:fixed;left:16px;right:16px;bottom:16px;z-index:9998;max-width:400px;margin-left:auto;box-sizing:border-box;background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:16px;padding:18px 19px;box-shadow:0 18px 50px #0000002e;font-size:14px;line-height:1.5;color:#1d1d1f}.pse-head{display:flex;align-items:center;gap:8px;margin-bottom:7px;color:#1d1d1f;font-size:14px;padding-right:26px}
86.pse-ic{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:9px;background:#eaf4e3;color:#4c8c2b;flex-shrink:0}.pse p{margin:0 0 13px;color:#555;line-height:1.55;font-size:14px}.pse p strong{color:#1d1d1f}.pse-actions{display:flex;gap:8px;flex-wrap:wrap}.pse-btn{display:inline-block;font-family:inherit;font-size:13.5px;line-height:1.2;font-weight:700;padding:9px 16px;border-radius:10px;cursor:pointer;text-decoration:none;transition:background .15s,transform .05s}.pse-btn:active{transform:scale(.98)}.pse-primary{border:none;background:#3f7523;color:#fff}.pse-primary:hover{background:#345f1d;color:#fff}.pse-secondary{border:1.5px solid rgba(0,0,0,.15);background:#fff;color:#1d1d1f}.pse-secondary:hover{border-color:#0000004d;color:#1d1d1f}.pse-x{position:absolute;top:10px;right:10px;width:28px;height:28px;border:none;background:transparent;color:#8a8a8e;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center}.pse-x:hover{background:#f0f0f2;color:#1d1d1f}.psi{display:none;position:fixed;left:16px;right:16px;bottom:16px;z-index:9997;max-width:400px;margin-right:auto;box-sizing:border-box;background:#fff;border:1px solid rgba(0,0,0,.1);border-radius:16px;padding:18px 19px;box-shadow:0 18px 50px #0000002e;font-size:14px;line-height:1.5;color:#1d1d1f}.psi *{box-sizing:border-box}.psi-head{display:flex;align-items:center;gap:8px;margin-bottom:7px;color:#1d1d1f;font-size:14px;padding-right:26px}.psi-ic{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:9px;background:#eaf4e3;color:#4c8c2b;flex-shrink:0}.psi p{margin:0 0 13px;color:#555;line-height:1.55;font-size:14px}.psi-actions{display:flex;gap:8px;flex-wrap:wrap}.psi-btn{display:inline-block;font-family:inherit;font-size:13.5px;line-height:1.2;font-weight:700;padding:9px 16px;border-radius:10px;cursor:pointer;text-decoration:none;border:none;transition:background .15s,transform .05s}.psi-btn:active{transform:scale(.98)}.psi-primary{background:#3f7523;color:#fff}.psi-primary:hover{background:#345f1d}.psi-secondary{border:1.5px solid rgba(0,0,0,.15);background:#fff;color:#1d1d1f}.psi-secondary:hover{border-color:#0000004d}.psi-x{position:absolute;top:10px;right:10px;width:28px;height:28px;border:none;background:transparent;color:#8a8a8e;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center}.psi-x:hover{background:#f0f0f2;color:#1d1d1f}.psa{position:relative;z-index:500;display:flex;align-items:center;justify-content:center;gap:.9rem;flex-wrap:wrap;background:linear-gradient(120deg,#2f5c1a,#4c8c2b 60%,#6cbf3f);color:#fff;font-size:.82rem;font-weight:500;padding:.6rem 2.4rem;text-align:center}.psa[hidden]{display:none}.psa-cta{flex-shrink:0;background:#fff;color:#2f5c1a;font-weight:700;font-size:.76rem;padding:.3rem .8rem;border-radius:999px;text-decoration:none;white-space:nowrap}.psa-cta:hover{background:#eaf6dd;color:#2f5c1a}.psa-x{position:absolute;top:50%;right:.6rem;transform:translateY(-50%);width:26px;height:26px;border:none;background:transparent;color:#ffffffbf;border-radius:8px;cursor:pointer;display:flex;align-items:center;justify-content:center}.psa-x:hover{background:#ffffff26;color:#fff}@media(max-width:560px){.psa{padding:.6rem 2.2rem;font-size:.78rem}}.ps-impers-bar{position:relative;z-index:501;display:flex;align-items:center;justify-content:center;gap:.9rem;flex-wrap:wrap;background:#a85d00;color:#fff;font-size:.82rem;font-weight:600;padding:.55rem 1.2rem;text-align:center}.ps-impers-bar[hidden]{display:none}.ps-impers-btn{flex-shrink:0;background:#fff;color:#a85d00;font-weight:700;font-size:.76rem;padding:.3rem .8rem;border-radius:999px;border:none;cursor:pointer;white-space:nowrap}.ps-impers-btn:hover{background:#fff4e0} 87.ra-section[data-astro-cid-2zkmu4eg]{margin:2.5rem 0 0}.ra-title[data-astro-cid-2zkmu4eg]{font-size:1.35rem;font-weight:800;letter-spacing:-.02em;margin:0 0 1.1rem;color:#1d1d1f}.ra-grid[data-astro-cid-2zkmu4eg]{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}.ra-card[data-astro-cid-2zkmu4eg]{display:flex;flex-direction:column;background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:16px;padding:1.1rem 1.15rem;text-decoration:none;transition:border-color .15s,transform .1s,box-shadow .15s}.ra-card[data-astro-cid-2zkmu4eg]:hover{border-color:#4c8c2b73;transform:translateY(-2px);box-shadow:0 10px 26px #00000012}.ra-tag[data-astro-cid-2zkmu4eg]{display:inline-flex;align-items:center;gap:.3rem;align-self:flex-start;font-size:.66rem;font-weight:800;letter-spacing:.03em;text-transform:uppercase;padding:.24rem .55rem;border-radius:20px;margin-bottom:.6rem}.ra-card[data-astro-cid-2zkmu4eg] h3[data-astro-cid-2zkmu4eg]{font-size:1rem;font-weight:700;line-height:1.3;margin:0 0 .4rem;color:#1d1d1f}.ra-card[data-astro-cid-2zkmu4eg] p[data-astro-cid-2zkmu4eg]{font-size:.85rem;line-height:1.55;color:#5f6368;margin:0 0 .9rem;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.ra-more[data-astro-cid-2zkmu4eg]{margin-top:auto;display:inline-flex;align-items:center;gap:.3rem;font-size:.82rem;font-weight:700;color:#3f7523}.ra-tag-kopen[data-astro-cid-2zkmu4eg]{background:#fff3e0;color:#e65100}.ra-tag-apk[data-astro-cid-2zkmu4eg]{background:#e8f5e9;color:#2e7d32}.ra-tag-rdw[data-astro-cid-2zkmu4eg]{background:#e3f2fd;color:#1565c0}.ra-tag-nap[data-astro-cid-2zkmu4eg]{background:#fce4ec;color:#880e4f}.ra-tag-belasting[data-astro-cid-2zkmu4eg]{background:#f3e5f5;color:#6a1b9a}.ra-tag-regelgeving[data-astro-cid-2zkmu4eg]{background:#fff8e1;color:#f57f17}.ra-tag-ev[data-astro-cid-2zkmu4eg]{background:#e0f2f1;color:#00695c}.ra-tag-import[data-astro-cid-2zkmu4eg]{background:#e8eaf6;color:#283593}.ra-tag-verzekering[data-astro-cid-2zkmu4eg]{background:#e0f7fa;color:#00838f}.ra-tag-techniek[data-astro-cid-2zkmu4eg]{background:#eceff1;color:#455a64}.ra-tag-schade[data-astro-cid-2zkmu4eg]{background:#ffebee;color:#c62828}@media(max-width:760px){.ra-grid[data-astro-cid-2zkmu4eg]{grid-template-columns:1fr}} 88nav .nav-inner{justify-content:flex-start!important;gap:12px!important}nav:has(>.nav-inner){z-index:500}nav:not(:has(>.nav-inner)){position:static;top:auto;z-index:auto;background:transparent;border-bottom:0;padding:0;backdrop-filter:none;-webkit-backdrop-filter:none}.sn-burger{display:none;border:none;background:transparent;color:#1d1d1f;cursor:pointer;padding:6px;border-radius:8px}.sn-burger:hover{background:#0000000d}.sn-links{display:flex;align-items:center;gap:4px;margin-left:10px}.sn-item{position:relative}.sn-top{display:inline-flex;align-items:center;gap:5px;padding:7px 11px;border:none;background:transparent;border-radius:10px;font-family:inherit;font-size:14px;line-height:1.2;font-weight:600;color:#1d1d1f;text-decoration:none;cursor:pointer;white-space:nowrap;transition:background .15s,color .15s}.sn-top:hover{background:#0000000d;color:#1d1d1f}.sn-chev{transition:transform .18s}.sn-item.open .sn-chev{transform:rotate(180deg)}.sn-panel{position:absolute;top:calc(100% + 8px);left:0;background:#fff;border:1px solid rgba(0,0,0,.08);border-radius:16px;box-shadow:0 18px 50px #0000001f;padding:10px;opacity:0;visibility:hidden;transform:translateY(6px);transition:opacity .16s,transform .16s,visibility .16s;z-index:200}.sn-item.open>.sn-panel{opacity:1;visibility:visible;transform:translateY(0)}@media(hover:hover)and (pointer:fine){.sn-item:hover>.sn-panel{opacity:1;visibility:visible;transform:translateY(0)}}.sn-mega{display:flex;gap:10px;width:940px}.sn-list{display:grid;grid-template-columns:1fr 1fr 1fr;gap:2px 8px;align-content:start;width:660px}.sn-cat-head{grid-column:1 / -1;font-size:11px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#8a8f86;padding:10px 10px 2px}.sn-cat-head:first-child{padding-top:2px}.sn-tool{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:10px;font-size:14px;line-height:1.3;font-weight:600;color:#1d1d1f;text-decoration:none;transition:background .12s,color .12s}.sn-list .sn-tool.sn-mobile-only{display:none}.sn-tool:hover,.sn-tool.active{background:#f2f8ee;color:#2f5e18}
88.sn-tool-ic{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:8px;background:#eaf4e3;color:#4c8c2b;flex-shrink:0}.sn-tool-badge{display:inline-flex;align-items:center;margin-left:2px;padding:1px 6px;border-radius:999px;background:#fff4e0;color:#b26b00;font-size:10px;font-weight:800;letter-spacing:.03em;line-height:1.5}.sn-tool.active .sn-tool-badge,.sn-tool:hover .sn-tool-badge{background:#ffe6ba}.sn-all{grid-column:1 / -1;display:inline-flex;align-items:center;gap:6px;margin-top:6px;padding:9px 10px;border-top:1px solid rgba(0,0,0,.06);font-size:13px;font-weight:700;color:#4c8c2b;text-decoration:none}.sn-all:hover{color:#2f5e18}.sn-preview{flex:1;display:flex;flex-direction:column;gap:7px;padding:17px;border-radius:12px;text-decoration:none;background:radial-gradient(130% 130% at 100% 0%,#5aa632,#4c8c2b 55%,#2f5e18);color:#fff}.sn-prev-ic{display:inline-flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:12px;background:#ffffff29;color:#fff}.sn-prev-title{font-size:16px;font-weight:800;color:#fff}.sn-prev-desc{font-size:13px;line-height:1.5;color:#ffffffe0}.sn-prev-open{display:inline-flex;align-items:center;gap:5px;margin-top:auto;font-size:13px;font-weight:700;color:#fff}.sn-simple{min-width:250px;display:flex;flex-direction:column}.sn-login-m{display:none}.sn-actions{margin-left:auto;display:flex;align-items:center;gap:14px}.sn-login{font-size:14px;font-weight:600;color:#1d1d1f;text-decoration:none;white-space:nowrap}.sn-login:hover{color:#4c8c2b}.sn-cta{display:inline-flex;align-items:center;gap:7px;padding:8px 15px;border-radius:11px;background:#3f7523;color:#fff;font-size:13.5px;line-height:1.2;font-weight:700;text-decoration:none;white-space:nowrap;transition:background .15s,transform .05s}.sn-cta:hover{background:#345f1d;color:#fff}.sn-cta:active{transform:scale(.98)}.sn-cta-label-short{display:none}body.has-results nav .sn-cta{display:none}nav.sn-compact .sn-burger{display:inline-flex;order:3}nav.sn-compact .sn-actions{order:2;margin-left:auto;gap:10px}nav.sn-compact .sn-links{display:none}nav.sn-compact .sn-links.sn-open{display:block;position:absolute;top:52px;left:0;right:0;margin:0;padding:14px 16px 18px;background:#fff;border-bottom:1px solid rgba(0,0,0,.08);box-shadow:0 24px 40px #0000001f;max-height:calc(100vh - 52px);overflow:auto;z-index:300}nav.sn-compact .sn-links.sn-open .sn-item{position:static}nav.sn-compact .sn-links.sn-open .sn-top{width:100%;justify-content:flex-start;font-size:15px;padding:10px 6px}nav.sn-compact .sn-links.sn-open .sn-toggle{justify-content:space-between;color:#1d1d1f}nav.sn-compact .sn-links.sn-open .sn-panel{display:none;position:static;opacity:1;visibility:visible;transform:none;box-shadow:none;border:none;padding:0 0 6px}nav.sn-compact .sn-links.sn-open .sn-item.open>.sn-panel{display:block}nav.sn-compact .sn-links.sn-open .sn-mega{width:auto}nav.sn-compact .sn-links.sn-open .sn-list{display:flex;flex-direction:column;width:auto}nav.sn-compact .sn-links.sn-open .sn-tool.sn-sec{display:none}nav.sn-compact .sn-links.sn-open .sn-tool.sn-mobile-only{display:flex}nav.sn-compact .sn-links.sn-open .sn-tool.active{background:transparent;color:#1d1d1f}nav.sn-compact .sn-links.sn-open .sn-preview{display:none}nav.sn-compact .sn-links.sn-open .sn-login-m{display:flex;align-items:center;gap:10px;padding:11px 6px;margin-top:6px;border-top:1px solid rgba(0,0,0,.06);font-size:15px;font-weight:700;color:#4c8c2b;text-decoration:none}@media(max-width:700px){nav.sn-compact .sn-login{display:none}}@media(max-width:480px){#nav-logo svg,.nav-logo-link svg{width:128px!important}.sn-cta{padding:8px 12px}.sn-cta-label{display:none}.sn-cta-label-short{display:inline}} 89.site-footer[data-astro-cid-gcn2mc3v]{margin-top:2rem;padding:2.5rem 1.5rem;background:transparent;border-top:.5px solid var(--border, rgba(0,0,0,.08));text-align:center;color:var(--text-tertiary, #6e6e73);font-size:.78rem}.site-footer[data-astro-cid-gcn2mc3v] .sf-inner[data-astro-cid-gcn2mc3v]{max-width:980px;margin:0 auto}.site-footer[data-astro-cid-gcn2mc3v] .sf-grid[data-astro-cid-gcn2mc3v]{display:grid;grid-template-columns:1.6fr 1fr 1fr 1fr 1fr 1fr;gap:2rem;margin-bottom:2rem;text-align:left}
89@media(max-width:900px){.site-footer[data-astro-cid-gcn2mc3v] .sf-grid[data-astro-cid-gcn2mc3v]{grid-template-columns:1fr 1fr}.site-footer[data-astro-cid-gcn2mc3v] .sf-brand[data-astro-cid-gcn2mc3v]{grid-column:1 / -1}}.site-footer[data-astro-cid-gcn2mc3v] .sf-logo[data-astro-cid-gcn2mc3v]{display:inline-block;margin-bottom:.5rem}.site-footer[data-astro-cid-gcn2mc3v] .sf-brand[data-astro-cid-gcn2mc3v] p[data-astro-cid-gcn2mc3v]{font-size:.8rem;line-height:1.6;color:var(--text-secondary, #5f6368);max-width:280px;margin:0}.site-footer[data-astro-cid-gcn2mc3v] .sf-col[data-astro-cid-gcn2mc3v] .sf-h[data-astro-cid-gcn2mc3v]{font-size:.72rem;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--text, #1d1d1f);margin:0 0 .6rem}.site-footer[data-astro-cid-gcn2mc3v] .sf-col[data-astro-cid-gcn2mc3v] a[data-astro-cid-gcn2mc3v]{display:inline-block;padding:5px 0}.site-footer[data-astro-cid-gcn2mc3v] .sf-col[data-astro-cid-gcn2mc3v] ul[data-astro-cid-gcn2mc3v]{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.45rem}.site-footer[data-astro-cid-gcn2mc3v] .sf-col[data-astro-cid-gcn2mc3v] ul[data-astro-cid-gcn2mc3v] li[data-astro-cid-gcn2mc3v] a[data-astro-cid-gcn2mc3v]{color:var(--text-secondary, #5f6368);text-decoration:none;font-size:.82rem;transition:color .15s}.site-footer[data-astro-cid-gcn2mc3v] .sf-col[data-astro-cid-gcn2mc3v] ul[data-astro-cid-gcn2mc3v] li[data-astro-cid-gcn2mc3v] a[data-astro-cid-gcn2mc3v]:hover{color:var(--text, #1d1d1f)}.site-footer[data-astro-cid-gcn2mc3v] .sf-bottom[data-astro-cid-gcn2mc3v]{padding-top:1.25rem;border-top:.5px solid var(--border, rgba(0,0,0,.08));display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}.site-footer[data-astro-cid-gcn2mc3v] .sf-bottom[data-astro-cid-gcn2mc3v] p[data-astro-cid-gcn2mc3v]{font-size:.75rem;color:var(--text-tertiary, #6e6e73);margin:0}.site-footer[data-astro-cid-gcn2mc3v] .sf-legal[data-astro-cid-gcn2mc3v]{display:flex;gap:1.25rem;font-size:.75rem}.site-footer[data-astro-cid-gcn2mc3v] .sf-legal[data-astro-cid-gcn2mc3v] a[data-astro-cid-gcn2mc3v]{color:var(--text-secondary, #5f6368);text-decoration:none}.site-footer[data-astro-cid-gcn2mc3v] .sf-legal[data-astro-cid-gcn2mc3v] a[data-astro-cid-gcn2mc3v]:hover{text-decoration:underline}.site-footer[data-astro-cid-gcn2mc3v] .sf-social[data-astro-cid-gcn2mc3v]{display:flex;gap:.85rem;align-items:center}.site-footer[data-astro-cid-gcn2mc3v] .sf-social[data-astro-cid-gcn2mc3v] a[data-astro-cid-gcn2mc3v]{display:inline-flex;padding:4px;color:var(--text-secondary, #5f6368);transition:color .15s}.site-footer[data-astro-cid-gcn2mc3v] .sf-social[data-astro-cid-gcn2mc3v] a[data-astro-cid-gcn2mc3v]:hover{color:var(--text, #1d1d1f)}@media(max-width:640px){.site-footer[data-astro-cid-gcn2mc3v] .sf-grid[data-astro-cid-gcn2mc3v]{grid-template-columns:1fr 1fr;gap:1.25rem 1.5rem}.site-footer[data-astro-cid-gcn2mc3v] .sf-brand[data-astro-cid-gcn2mc3v]{grid-column:1 / -1}}@media(max-width:768px){.site-footer[data-astro-cid-gcn2mc3v]{font-size:.65rem}} 90</style></head> <body> <!-- Impersonatie-banner: zie .ps-impers-bar-stijl hierboven voor de afweging. --> <div id="ps-impersonate" class="ps-impers-bar" hidden> <span id="psi-text"></span> <button id="psi-stop" type="button" class="ps-impers-btn">Terug naar eigen account</button> </div>
90<script> 91 (function () { 92 var box = document.getElementById('ps-impersonate'); 93 if (!box) return; 94 fetch('/api/impersonation-status').then(function (r) { return r.json(); }).then(function (d) { 95 if (!d || !d.ok || !d.active) return; 96 document.getElementById('psi-text').textContent = 'Je bekijkt PlateScout als ' + d.target_email + ' (ingelogd als ' + d.admin_email + ')'; 97 box.hidden = false; 98 document.getElementById('psi-stop').addEventListener('click', function () { 99 fetch('/api/admin/user/stop-impersonate', { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': d.csrf } }) 100 .then(function () { location.href = '/admin'; }); 101 }); 102 }).catch(function () {}); 103 })(); 104 </script>
104 <!-- Aankondigingsbalk: sitebrede balk bovenaan, admin zet zelf tekst + CTA aan/uit 105 in het adminportaal (settings-tabel, direct live). Weggeklikt = weg tot de 106 tekst verandert (localStorage-sleutel is een hash van de tekst, dus een NIEUWE 107 aankondiging verschijnt vanzelf weer ook al had iemand een vorige weggeklikt). --> <div id="ps-announce" class="psa" hidden> <span id="psa-text"></span> <a id="psa-cta" class="psa-cta" href="#" hidden></a> <button id="psa-close" type="button" class="psa-x" aria-label="Sluiten"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> </button> </div>
107<script> 108 (function () { 109 var box = document.getElementById('ps-announce'); 110 if (!box) return; 111 function hash(s) { var h = 0; for (var i = 0; i < s.length; i++) { h = ((h << 5) - h + s.charCodeAt(i)) | 0; } return String(h); } 112 fetch('/api/announce').then(function (r) { return r.json(); }).then(function (d) { 113 if (!d || !d.ok || !d.active || !d.text) return; 114 var key = hash(d.text); 115 try { if (localStorage.getItem('ps-announce-dismissed') === key) return; } catch (e) {} 116 document.getElementById('psa-text').textContent = d.text; 117 if (d.cta_text && d.cta_url) { 118 var cta = document.getElementById('psa-cta'); 119 cta.textContent = d.cta_text; 120 cta.href = d.cta_url; 121 cta.hidden = false; 122 } 123 box.hidden = false; 124 document.getElementById('psa-close').addEventListener('click', function () { 125 try { localStorage.setItem('ps-announce-dismissed', key); } catch (e) {} 126 box.hidden = true; 127 }); 128 }).catch(function () {}); 129 })(); 130 </script>
130 <div class="page-shell-root"> <nav> <div class="nav-inner"> <a href="/" class="nav-logo-link" aria-label="PlateScout home"><svg style="width:150px;height:auto;display:block;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 440.07 60.91"> 131 <defs><style>.cls-pg{fill:#4c8c2b;fill-rule:evenodd;}</style></defs> 132 <g> 133 <g><g> 134 <path d="M66.47,57.2h4.1v-.9l-1.4-.3v-3.5h1.4l2.5,3.5-1.2.3v.9h4.1v-.9l-1.2-.3-3-4.2,2.2-3.7,1.4-.3v-.9h-2.4l-2.5,4.3h-1.3v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v1.1Z"/> 135 <path d="M89.67,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 136 <path d="M109.37,56v-6.8l4.8,8h1.8v-9l1.2-.3v-.9h-3.8v.9l1.2.3v6.9l-4.8-8.1h-3v.9l1.2.3v7.8l-1.2.3v.9h3.9v-.9l-1.4-.3h.1Z"/> 137 <path d="M130.07,57.2h4.4v-.9l-1.4-.3v-7.8h1.9l.4,1.4h.9v-2.6h-7.9v2.6h.9l.4-1.4h1.9v7.8l-1.4.3v.9h-.1Z"/> 138 <path d="M149.87,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 139 <path d="M166.97,57.2h4.1v-.9l-1.4-.3v-3.5h1.4l2.5,3.5-1.2.3v.9h4.1v-.9l-1.2-.3-3-4.2,2.2-3.7,1.4-.3v-.9h-2.4l-2.5,4.3h-1.3v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v1.1Z"/> 140 <path d="M190.07,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 141 <path d="M209.87,56v-6.8l4.8,8h1.8v-9l1.2-.3v-.9h-3.8v.9l1.2.3v6.9l-4.8-8.1h-3v.9l1.2.3v7.8l-1.2.3v.9h3.9v-.9l-1.4-.3h.1Z"/> 142 <path d="M247.67,50.1h1.1v-2.5s-1.6-.7-3.2-.7c-3,0-4.8,2.1-4.8,5.4s1.7,5,4.6,5,3.6-1.5,3.6-1.5l-.6-.9s-1.4,1.2-2.9,1.2-3.1-1.2-3.1-3.8,1.1-4.1,3-4.1,1.9.3,1.9.3l.4,1.7v-.1Z"/> 143 <path d="M261.27,57.2h4.1v-.9l-1.4-.3v-3.5h4.8v3.5l-1.4.3v.9h4.1v-.9l-1.2-.3v-7.8l1.2-.3v-.9h-4.1v.9l1.4.3v3.2h-4.8v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v.9Z"/> 144 <path d="M286.77,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 145 <path d="M310.77,50.1h1.1v-2.5s-1.6-.7-3.2-.7c-3,0-4.8,2.1-4.8,5.4s1.7,5,4.6,5,3.6-1.5,3.6-1.5l-.6-.9s-1.4,1.2-2.9,1.2-3.1-1.2-3.1-3.8,1.1-4.1,3-4.1,1.9.3,1.9.3l.4,1.7v-.1Z"/> 146 <path d="M324.27,57.2h4.1v-.9l-1.4-.3v-3.5h1.4l2.5,3.5-1.2.3v.9h4.1v-.9l-1.2-.3-3-4.2,2.2-3.7,1.4-.3v-.9h-2.4l-2.5,4.3h-1.3v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v1.1Z"/> 147 </g><g> 148 <path d="M66.47,36.81h14.1v-3.9l-3.5-1.4v-6h2.5c8.4,0,13.2-3.8,13.2-11.6s-4.2-9.7-11.2-9.7h-4.4l-10.6.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h-.1ZM77.17,20.11v-10.3h3.7c3.1,0,4.8,2.1,4.8,5.1s-2.2,5.2-6,5.2h-2.5Z"/> 149 <path d="M112.87,31.31h-7.1V9.81l3.5-1.4v-4.2l-14.1.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h23.1v-10.6h-4.4l-1,5.1h0Z"/> 150 <path d="M153.07,32.91l-3.2-1.3-10-27.4h-7.4c0,.1-10.2,27.4-10.2,27.4l-3.4,1.3v3.9h14v-3.9l-3.6-1.3,1.2-3.3h10.3l1.1,3.4-3.5,1.2v3.9h14.7v-3.9h0ZM139.17,23.31h-7.1l3.7-11,3.5,11h-.1Z"/> 151 <path d="M160.87,31.51l-4.4,1.4v3.9h16v-3.9l-4.4-1.4V9.71h4.4l1.2,4.4h4.3V4.11h-26.8v10h4.3l1.2-4.4h4.4v21.8h-.2Z"/> 152 <path d="M200.37,17.41h-9.3v-7.6h7.6l1.2,3.4h4.2V4.31h-13l-10.6.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h24.2v-9.3h-4.2l-1.1,3.8h-8.3v-8.8h9.3v-5.2Z"/> 153 <path d="M214.67,26.81h-4.7v8.9s5.1,1.8,10.3,1.8,12.5-3.8,12.5-10.7c0-10.9-15.6-8.7-15.6-14.1s1.6-3.3,4.9-3.3,4.1.7,4.1.7l1.2,3.9h4.3l.2-8.4s-5-1.9-10.2-1.9-11.8,3.4-11.8,9.8c0,11.4,15.6,9,15.6,14.4s-2.6,3.7-5.6,3.7-4.5-1-4.5-1l-.7-3.9v.1Z"/> 154 <path d="M259.27,14.61h4.5l.2-8.8s-5.2-2.2-10.8-2.2c-9.5,0-15.6,6.5-15.6,17.4s5.4,16.4,14.8,16.4,12.1-5,12.1-5l-2.5-4.2s-4.2,3.2-8.8,3.2-7.9-3.1-7.9-10.6,2.8-11.3,7.6-11.3,5.2.7,5.2.7l1.1,4.4h.1Z"/> 155 <path d="M283.77,3.61c-9.4,0-15.3,6.5-15.3,17.1s5.1,16.7,14.3,16.7,15.5-6.9,15.5-17.4-5.3-16.4-14.6-16.4h.1ZM283.57,9.41c4.6,0,6.9,3.2,6.9,10.9s-2.8,11.3-7.4,11.3-6.7-3.5-6.7-11.1,2.5-11.1,7.2-11.1h0Z"/> 156 <path d="M313.17,9.71l3.6-1.4v-4.2l-14.2.2v3.9l3.4,1.4v14.6c0,8.9,3.7,13.1,13,13.1s13.4-4.8,13.4-13.7v-13.9l3.5-1.4v-4.2l-14.3.2v3.9l3.6,1.4v13.9c0,5.5-1.1,8.1-6,8.1s-6.1-2.1-6.1-7.4v-14.6l.1.1Z"/> 157 <path d="M347.67,31.51l-4.4,1.4v3.9h16v-3.9l-4.4-1.4V9.71h4.4l1.2,4.4h4.3V4.11h-26.8v10h4.3l1.2-4.4h4.4v21.8h-.2Z"/> 158 <path d="M368.17,33.21c0,2.7,1.3,4.2,3.9,4.2s4-1.5,4-4.2-1.3-4.2-3.9-4.2-4,1.5-4,4.2Z"/> 159 <path d="M380.67,36.81h13.4v-3.9l-3.6-1.4v-15.6l12.4,21h7.7V9.81l3.5-1.4v-4.2l-13.2.2v3.9l3.4,1.4v15.8l-12.5-21.4-11.1.2v3.9l3.5,1.4v21.8l-3.5,1.4v4Z"/> 160 <path d="M434.67,31.31h-7.1V9.81l3.5-1.4v-4.2l-14.1.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h23.1v-10.6h-4.4l-1,5.1h0Z"/> 161 </g></g> 162 <path class="cls-pg" d="M16.34,3.61c2.52-.66,4.46-1.4,8.46-3.14.58-.27,1.16-.47,1.32-.47s1.05.39,2.06.85c2.06.97,4.7,1.98,6.75,2.6l1.44.43,7.3.08c5.51.04,7.38.12,7.61.23.12.04.19.08.27.16.47.35.43,1.36.43,13.12s-.04,13.04-.16,13.97c-.5,5.32-2.45,10.68-5.4,15.06-1.71,2.56-4.7,5.78-7.14,7.72-2.79,2.25-7.1,4.62-10.56,5.86-1.75.62-2.37.85-2.91.82-.31,0-.58-.12-1.09-.27-9.28-3.11-16.15-8.62-20.57-16.42-1.82-3.26-3.18-7.26-3.77-11.37-.12-.74-.23-2.68-.27-4.35l-.08-2.99.39-.47.39-.47h7.34l7.34-.08.66.31c1.71.82,8.58,4.08,12.34,5.86,2.29,1.09,5.16,2.45,6.41,3.03l2.25,1.05h4.5c2.56,0,4.54-.04,4.58-.12.12-.19.58-2.99.66-4.11l.08-1.01h-5.32l-5.32-.08-3.57-1.75c-7.38-3.57-7.34-3.57-7.84-4.58-.39-.78-.31-1.98.23-2.72.43-.62.66-.74,7.65-4.35l3.57-1.82h10.56v-5.28h-5.36c-5.32,0-5.36,0-6.6-.35-1.55-.43-3.65-1.13-5.2-1.79l-1.2-.5-.08,2.91c-.08,3.14-.08,3.22-.85,3.92-.19.16-2.87,1.59-6.02,3.14l-5.67,2.83h-7.38c-6.44.08-7.41.04-7.76-.12-.12-.08-.23-.12-.35-.19-.47-.39-.47-1.32-.47-7.26s0-6.52.23-6.83c.08-.12.12-.23.19-.31.43-.47,1.36-.47,7.69-.47s6.83,0,8.07-.31h.16ZM17.27,8.54c1.4-.39,4.19-1.36,5.51-1.94.31-.16.62-.19.7-.16.
16204.04.08.85.08,1.79v1.71l-8.42,4.23h-5.01l-5.01.08v-5.28h10.68l1.48-.43h0ZM32.61,21.66c.31-.16,1.48-.78,2.6-1.36l2.06-1.05h9.7v5.28h-9.59l-2.37-1.13c-1.28-.62-2.48-1.2-2.68-1.24q-.31-.12.23-.43h0l.04-.08ZM5.71,34.04c-.19-.85-.54-3.34-.54-4.04v-.5h9.78l9.32,4.5c5.12,2.48,9.94,4.77,10.71,5.12l1.4.62h8.19l-.62,1.2c-.89,1.79-3.07,5.01-3.77,5.59-.16.16-1.28-.35-6.91-3.14-5.32-2.64-6.79-3.34-7.22-3.34s-1.71.58-7.14,3.38l-6.64,3.38-.39-.43c-.62-.66-2.1-2.68-2.72-3.73-.5-.85-1.48-2.72-1.48-2.91s1.75-.08,3.92-.08c3.57,0,3.96,0,4.39-.23,1.55-.82,1.75-3.22.31-4.31l-.5-.39-4.93-.08-4.93-.08-.16-.66-.08.12ZM28.65,54.77s-.08-1.82-.08-4.08v-4.08l3.77,1.86c2.06,1.05,3.73,1.94,3.73,2.02-.08.19-2.1,1.55-3.65,2.45-1.28.74-3.57,1.86-3.73,1.86h0l-.04-.04ZM15.88,50.54l3.73-1.94c2.06-1.09,3.8-1.94,3.84-1.98s.12,1.82.12,4.08-.04,4.08-.08,4.08-.97-.43-2.06-.97c-1.98-.97-3.77-1.98-4.89-2.83l-.62-.43h-.04Z"/> 163 </g> 164</svg></a> <button class="sn-burger" id="sn-burger" aria-label="Menu openen" aria-expanded="false"> <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg> </button> <div class="sn-links" id="sn-links"> <div class="sn-item"> <button class="sn-top sn-toggle" aria-expanded="false" aria-haspopup="true"> 165Tools 166<svg class="sn-chev" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg> </button> <div class="sn-panel sn-mega" role="menu"> <div class="sn-list"> <span class="sn-cat-head">Kenteken-checks</span> <a class="sn-tool active" href="/occasion-check" data-title="Occasion check" data-desc="Plak een advertentielink en krijg een AankoopScore, AI-fotoscan, rode vlaggen en onderhandeltips." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M5 17H3v-4l2-5h11l2 5v4h-2"/><path d="M5 8h14"/><circle cx="7.5" cy="17" r="1.5"/><circle cx="16.5" cy="17" r="1.5"/></svg></span> <span>Occasion check</span> <span class="sn-tool-badge">AI</span> </a><a class="sn-tool sn-sec" href="/proefrit-checklist" data-title="Proefrit-checklist" data-desc="Afvinkbare controlepunten voor de bezichtiging en proefrit van een occasion." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg></span> <span>Proefrit-checklist</span> </a><a class="sn-tool" href="/apk-check" data-title="APK check" data-desc="APK-vervaldatum, keuringshistorie en of de APK nog geldig is." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg></span> <span>APK check</span> </a><a class="sn-tool" href="/nap-tellerstand" data-title="NAP tellerstand" data-desc="Kilometerstandoordeel: is de teller logisch verklaarbaar?" role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg></span> <span>NAP tellerstand</span> </a><a class="sn-tool sn-sec" href="/terugroepactie-check" data-title="Terugroepacties" data-desc="Openstaande en afgeronde recalls met defectomschrijving." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/></svg></span> <span>Terugroepacties</span> </a><a class="sn-tool" href="/scan" data-title="Kenteken scannen" data-desc="Scan een kenteken met je camera, direct in de browser (beta)." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg></span> <span>Kenteken scannen</span> </a> <span class="sn-cat-head">Rekentools</span> <a class="sn-tool sn-sec" href="/wegenbelasting" data-title="Wegenbelasting" data-desc="Motorrijtuigenbelasting per provincie, inclusief vrijstellingen." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M4 10h11"/><path d="M4 14h9"/><path d="M19 5.5A7 7 0 0 0 8 12a7 7 0 0 0 11 6.5"/></svg></span> <span>Wegenbelasting</span> </a><a class="sn-tool" href="/autokosten" data-title="Autokosten per maand" data-desc="Maandlasten van een occasion: brandstof, wegenbelasting, verzekering, onderhoud en meer." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><rect x="4" y="2" width="16" height="20" rx="2"/><line x1="8" y1="6" x2="16" y2="6"/><line x1="8" y1="12" x2="8" y2="12.01"/><line x1="12" y1="12" x2="12" y2="12.01"/>
166<line x1="16" y1="12" x2="16" y2="12.01"/><line x1="8" y1="16" x2="8" y2="16.01"/><line x1="12" y1="16" x2="12" y2="16.01"/><line x1="16" y1="16" x2="16" y2="16.01"/></svg></span> <span>Autokosten per maand</span> </a><a class="sn-tool" href="/autowaarde-berekenen" data-title="Autowaarde berekenen" data-desc="Dagwaarde van je auto op kenteken: inruilwaarde, particuliere prijs en dealerprijs." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/></svg></span> <span>Autowaarde berekenen</span> </a><a class="sn-tool sn-sec" href="/financiering-berekenen" data-title="Autofinanciering berekenen" data-desc="Maandbedrag, totale rente en aflossingsschema van een autolening, met aanpasbare rente en looptijd." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><line x1="19" y1="5" x2="5" y2="19"/><circle cx="6.5" cy="6.5" r="2.5"/><circle cx="17.5" cy="17.5" r="2.5"/></svg></span> <span>Autofinanciering berekenen</span> </a><a class="sn-tool sn-sec" href="/bpm-berekenen" data-title="BPM berekenen" data-desc="Rest-BPM op kenteken of handmatig, volgens de forfaitaire tabel." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><rect x="4" y="2" width="16" height="20" rx="2"/><line x1="8" y1="6" x2="16" y2="6"/><line x1="8" y1="12" x2="8" y2="12.01"/><line x1="12" y1="12" x2="12" y2="12.01"/><line x1="16" y1="12" x2="16" y2="12.01"/><line x1="8" y1="16" x2="8" y2="16.01"/><line x1="12" y1="16" x2="12" y2="16.01"/><line x1="16" y1="16" x2="16" y2="16.01"/></svg></span> <span>BPM berekenen</span> </a><a class="sn-tool sn-sec" href="/kw-naar-pk" data-title="Van kW naar pk" data-desc="Reken vermogen om tussen kW en pk, of vul een kenteken in voor het echte vermogen." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg></span> <span>Van kW naar pk</span> </a><a class="sn-tool sn-sec" href="/auto-repareren-of-verkopen" data-title="Repareren of verkopen" data-desc="Zet je reparatie-offerte af tegen de geschatte dagwaarde van je auto." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg></span> <span>Repareren of verkopen</span> </a><a class="sn-tool sn-sec" href="/auto-schorsen-of-verkopen" data-title="Schorsen of verkopen" data-desc="Vergelijk de kosten van aanhouden, schorsen bij de RDW of nu verkopen." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/><path d="M11 18H8a2 2 0 0 1-2-2V9"/></svg></span> <span>Schorsen of verkopen</span> </a><a class="sn-tool sn-sec" href="/auto-particulier-of-opkoper-verkopen" data-title="Particulier of opkoper" data-desc="Bereken je break-even bod: vanaf welk bedrag een snelle verkoop net zo goed is als zelf verkopen." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"/></svg></span> <span>Particulier of opkoper</span> </a><a class="sn-tool sn-sec" href="/casco-calculator" data-title="Casco-calculator" data-desc="Zet je cascopremie af tegen de dagwaarde van je auto en zie of de verzekering nog in verhouding staat." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/></svg></span> <span>Casco-calculator</span> </a><a class="sn-tool sn-sec" href="/youngtimer-bijtelling-berekenen" data-title="Youngtimer-bijtelling" data-desc="Bereken de 35%-bijtelling over de dagwaarde van je youngtimer en vergelijk met de standaardbijtelling." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><rect x="4" y="2" width="16" height="20" rx="2"/><line x1="8" y1="6" x2="16" y2="6"/><line x1="8" y1="12" x2="8" y2="12.01"/><line x1="12" y1="12" x2="12" y2="12.01"/>
166<line x1="16" y1="12" x2="16" y2="12.01"/><line x1="8" y1="16" x2="8" y2="16.01"/><line x1="12" y1="16" x2="12" y2="16.01"/><line x1="16" y1="16" x2="16" y2="16.01"/></svg></span> <span>Youngtimer-bijtelling</span> </a> <span class="sn-cat-head">Cijfers & trends</span> <a class="sn-tool sn-sec" href="/kentekenvoorspeller" data-title="Kentekenvoorspeller" data-desc="Kies een datum en bekijk een schatting van het kenteken dat rond die dag wordt uitgegeven." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"/><line x1="1" y1="10" x2="23" y2="10"/></svg></span> <span>Kentekenvoorspeller</span> </a><a class="sn-tool sn-sec" href="/laatste-kentekens" data-title="Laatste kentekens" data-desc="De nieuwste kentekens die de RDW heeft uitgegeven, live bijgewerkt." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"/><line x1="1" y1="10" x2="23" y2="10"/></svg></span> <span>Laatste kentekens</span> </a><a class="sn-tool sn-sec" href="/apk-kalender" data-title="APK-kalender" data-desc="Hoeveel personenauto's moeten de komende 12 maanden APK-gekeurd worden." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"/><line x1="1" y1="10" x2="23" y2="10"/></svg></span> <span>APK-kalender</span> </a><a class="sn-tool sn-sec" href="/elektrische-autos-per-gemeente" data-title="Elektrische auto's per gemeente" data-desc="EV-aandeel en brandstofverdeling van personenauto's in elke Nederlandse gemeente." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M17 8C8 10 5.9 16.17 3.82 21.34l1.89.66.95-2.3c.48.17.98.3 1.34.3C19 20 22 3 22 3c-1 2-8 2.25-13 3.25S2 11.5 2 13.5s1.75 3.75 1.75 3.75"/></svg></span> <span>Elektrische auto's per gemeente</span> </a><a class="sn-tool sn-sec" href="/autostatistieken" data-title="Autoregistraties Nederland" data-desc="De meest geregistreerde automodellen per maand, dagelijks automatisch bijgewerkt." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"/><line x1="1" y1="10" x2="23" y2="10"/></svg></span> <span>Autoregistraties Nederland</span> </a> <span class="sn-cat-head">Zoeken & vergelijken</span> <a class="sn-tool sn-sec" href="/apk-station-vinder" data-title="APK-station vinden" data-desc="Zoek een RDW-erkend APK-keuringsstation op plaatsnaam of postcode." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg></span> <span>APK-station vinden</span> </a><a class="sn-tool sn-sec" href="/kenteken-zoeken" data-title="Kenteken zoeken op onderdeel" data-desc="Nog niet het hele kenteken? Zoek op een gedeeltelijk kenteken met wildcards en een optioneel merkfilter." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg></span> <span>Kenteken zoeken op onderdeel</span> </a><a class="sn-tool sn-sec" href="/auto-herkenning" data-title="AI auto-herkenning" data-desc="Upload of maak een foto van een auto en laat AI het merk, model, kleur en type herkennen." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg></span> <span>AI auto-herkenning</span> </a><a class="sn-tool sn-sec" href="/vergelijken" data-title="Kentekens vergelijken" data-desc="Twee voertuigen naast elkaar in een volledige vergelijkingstabel, met een AI-conclusie welke auto voordeliger is. Vereist een gratis account." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/><path d="M11 18H8a2 2 0 0 1-2-2V9"/></svg></span> <span>Kentekens vergelijken</span> </a> <span class="sn-cat-head">Kennis & extra</span> <a class="sn-tool sn-sec" href="/extensie" data-title="Browserextensie" data-desc="Voor Chrome, Edge en Firefox: kentekencheck direct vanaf occasions op Mar
166ktplaats, AutoTrack en meer." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M4 7h4V6a2 2 0 0 1 4 0v1h4a1 1 0 0 1 1 1v4h1a2 2 0 0 1 0 4h-1v4a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1z"/></svg></span> <span>Browserextensie</span> </a><a class="sn-tool sn-mobile-only" href="/app" data-title="PlateScout-app" data-desc="Installeer PlateScout op je startscherm voor razendsnelle kentekenchecks, gratis en zonder download." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg></span> <span>PlateScout-app</span> </a><a class="sn-tool sn-sec" href="/auto-chat" data-title="AI Autoadviseur" data-desc="Krijg advies over kopen, kosten en onderhoud, met berekeningen op basis van echte RDW-gegevens." role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg></span> <span>AI Autoadviseur</span> <span class="sn-tool-badge">AI</span> </a> <a class="sn-all" href="/functies">Alle functies 167<svg width="13" height="13" viewBox="0 0 16 16" fill="none"><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"></path></svg> </a> </div> <a class="sn-preview" id="sn-preview" href="/occasion-check" aria-hidden="true"> <span class="sn-prev-ic" id="sn-prev-ic"><svg xmlns="http://www.w3.org/2000/svg" width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M5 17H3v-4l2-5h11l2 5v4h-2"/><path d="M5 8h14"/><circle cx="7.5" cy="17" r="1.5"/><circle cx="16.5" cy="17" r="1.5"/></svg></span> <span class="sn-prev-title" id="sn-prev-title">Occasion check</span> <span class="sn-prev-desc" id="sn-prev-desc">Plak een advertentielink en krijg een AankoopScore, AI-fotoscan, rode vlaggen en onderhandeltips.</span> <span class="sn-prev-open">Open tool 168<svg width="13" height="13" viewBox="0 0 16 16" fill="none"><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"></path></svg> </span> </a> </div> </div> <div class="sn-item"> <button class="sn-top sn-toggle" aria-expanded="false" aria-haspopup="true"> 169Gidsen 170<svg class="sn-chev" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg> </button> <div class="sn-panel sn-simple" role="menu"> <a class="sn-tool" href="/gids/elektrisch-rijden" role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M17 8C8 10 5.9 16.17 3.82 21.34l1.89.66.95-2.3c.48.17.98.3 1.34.3C19 20 22 3 22 3c-1 2-8 2.25-13 3.25S2 11.5 2 13.5s1.75 3.75 1.75 3.75"/></svg></span> <span>Elektrisch rijden</span> </a><a class="sn-tool" href="/gids/auto-importeren" role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg></span> <span>Auto importeren</span> </a><a class="sn-tool" href="/gids/autoverzekering" role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/></svg></span> <span>Autoverzekering</span> </a><a class="sn-tool" href="/gids/techniek-onderhoud" role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg></span> <span>Techniek & onderhoud</span> </a><a class="sn-tool" href="/gids/schade-en-wok" role="menuitem"> <span class="sn-tool-ic"><svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/>
170<line x1="12" y1="17" x2="12.01" y2="17"/></svg></span> <span>Schade & WOK</span> </a> </div> </div> <a class="sn-top" href="/blog">Blog</a> <a class="sn-top" href="/begrippenlijst">Begrippenlijst</a> </div> <div class="sn-actions" id="ps-nav-actions"> <a id="ps-acct-link" class="sn-login" href="/inloggen">Inloggen</a> <a id="sn-cta" class="sn-cta" href="/" aria-label="Kenteken check starten"> <svg id="sn-cta-ic-search" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.35-4.35"></path></svg> <svg id="sn-cta-ic-login" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="display:none"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg> <span class="sn-cta-label">Kenteken check</span> <span class="sn-cta-label-short">Kenteken</span> </a> </div>
170<script> 171 (function () { 172 if (window.__snInit) return; 173 window.__snInit = true; 174 document.addEventListener('DOMContentLoaded', function () { 175 var links = document.getElementById('sn-links'); 176 var burger = document.getElementById('sn-burger'); 177 if (!links) return; 178 var nav = links.closest('nav'); 179 var mq = window.matchMedia('(max-width: 940px)'); 180 // Met een open rapport (kenteken-chip in de nav) is er minder ruimte, maar op een 181 // breed scherm past het volledige menu prima; pas onder 1280px klappen we dan in. 182 var mqResults = window.matchMedia('(max-width: 1280px)'); 183 184 // Extra inlog-link onderin het compacte paneel. 185 var mLogin = document.createElement('a'); 186 mLogin.className = 'sn-login-m'; 187 mLogin.href = '/inloggen'; 188 mLogin.textContent = 'Inloggen'; 189 links.appendChild(mLogin); 190 191 // Onder 700px verdwijnt .sn-login (CSS, zelfde breakpoint), dan blijft alleen 192 // de groene kenteken-CTA over. Niet ingelogd was dat een onduidelijke knop 193 // zonder zichtbare inlog-optie in de dichte nav (feedback Stephan, 14-9-2026: 194 // "je weet niet wat je zoekt"). Onder die breedte EN niet ingelogd wordt de 195 // CTA daarom zelf de Inloggen-knop; de kentekenzoeker blijft gewoon op elke 196 // pagina/homepage bereikbaar, dit raakt alleen de snelkoppeling in de nav. 197 var mqLoginHidden = window.matchMedia('(max-width: 700px)'); 198 var cta = document.getElementById('sn-cta'); 199 var ctaFull = cta ? cta.querySelector('.sn-cta-label') : null; 200 var ctaShort = cta ? cta.querySelector('.sn-cta-label-short') : null; 201 var ctaIcSearch = document.getElementById('sn-cta-ic-search'); 202 var ctaIcLogin = document.getElementById('sn-cta-ic-login'); 203 var isLoggedIn = false; 204 function syncCta() { 205 if (!cta) return; 206 if (mqLoginHidden.matches && !isLoggedIn) { 207 cta.href = '/inloggen'; 208 cta.setAttribute('aria-label', 'Inloggen'); 209 if (ctaFull) ctaFull.textContent = 'Inloggen'; 210 if (ctaShort) ctaShort.textContent = 'Inloggen'; 211 if (ctaIcSearch) ctaIcSearch.style.display = 'none'; 212 if (ctaIcLogin) ctaIcLogin.style.display = ''; 213 } else { 214 cta.href = '/'; 215 cta.setAttribute('aria-label', 'Kenteken check starten'); 216 if (ctaFull) ctaFull.textContent = 'Kenteken check'; 217 if (ctaShort) ctaShort.textContent = 'Kenteken'; 218 if (ctaIcSearch) ctaIcSearch.style.display = ''; 219 if (ctaIcLogin) ctaIcLogin.style.display = 'none'; 220 } 221 } 222 syncCta(); 223 if (mqLoginHidden.addEventListener) mqLoginHidden.addEventListener('change', syncCta); 224 else if (mqLoginHidden.addListener) mqLoginHidden.addListener(syncCta); 225 226 function closePanel() { 227 links.classList.remove('sn-open'); 228 if (burger) burger.setAttribute('aria-expanded', 'false'); 229 } 230 231 // Een categoriekop (23-9-2026) hoort verborgen te blijven als GEEN van 232 // zijn tools op het huidige schermformaat zichtbaar is (bv. "Cijfers & 233 // trends" bestaat uitsluitend uit sn-sec-tools, die in het compacte 234 // mobiele paneel allemaal verborgen zijn): anders blijft er een kale kop 235 // zonder tools eronder hangen. Herberekend bij elke compact/desktop- 236 // wissel en na een live nav-menu-patch (zie apply() verderop). 237 function updateCatHeadVisibility() { 238 var list = links.querySelector('.sn-mega .sn-list'); 239 if (!list) return; 240 var isCompact = nav && nav.classList.contains('sn-compact'); 241 Array.prototype.forEach.call(list.querySelectorAll(':scope > span.sn-cat-head'), function (head) { 242 var hasVisible = false; 243 var sib = head.nextElementSibling; 244 while (sib && !sib.classList.contains('sn-cat-head')) { 245 if (sib.classList.contains('sn-tool')) { 246 var hiddenByCompact = isCompact && sib.classList.contains('sn-sec'); 247 var hiddenByDesktop = !isCompact && sib.classList.contains('sn-mobile-only'); 248 if (!hiddenByCompact && !hiddenByDesktop) { hasVisible = true; break; } 249 } 250 sib = sib.nextElementSibling; 251 } 252 head.style.display = hasVisible ? '' : 'none'; 253 }); 254 } 255 // Compact = smal scherm, OF homepage met open rapport op een scherm waar 256 // menu + kenteken-chip niet samen passen (< 1280px). 257 function updateCompact() { 258 var hasResults = document.body.classList.contains('has-results'); 259 var compact = mq.matches || (hasResults && mqResults.matches); 260 if (nav) nav.classList.toggle('sn-compact', compact); 261 if (!compact) closePanel(); 262 updateCatHeadVisibility(); 263 } 264 updateCompact();
265 [mq, mqResults].forEach(function (m) { 266 if (m.addEventListener) m.addEventListener('change', updateCompact); 267 else if (m.addListener) m.addListener(updateCompact); 268 }); 269 new MutationObserver(updateCompact).observe(document.body, { attributes: true, attributeFilter: ['class'] }); 270 271 if (burger) { 272 burger.addEventListener('click', function (e) { 273 // Niet laten doorbubbelen: de generieke document-listener die open 274 // dropdowns sluit zou het zojuist gezette .open direct weer weghalen. 275 e.stopPropagation(); 276 var open = links.classList.toggle('sn-open'); 277 burger.setAttribute('aria-expanded', open ? 'true' : 'false'); 278 // Tools staat bij het openen alvast uitgeklapt (blijft gewoon 279 // dichtklapbaar via de accordeon-toggle). 280 if (open) { 281 var first = links.querySelector('.sn-item'); 282 if (first) first.classList.add('open'); 283 } 284 }); 285 document.addEventListener('click', function (e) { 286 if (links.classList.contains('sn-open') && !links.contains(e.target) && e.target !== burger && !burger.contains(e.target)) { 287 closePanel(); 288 } 289 }); 290 } 291 292 // Desktop: klik-toggle op de dropdown-koppen (naast hover), sluit bij klik erbuiten. 293 links.querySelectorAll('.sn-toggle').forEach(function (btn) { 294 btn.addEventListener('click', function (e) { 295 e.stopPropagation(); 296 var item = btn.parentElement; 297 var was = item.classList.contains('open'); 298 links.querySelectorAll('.sn-item.open').forEach(function (o) { o.classList.remove('open'); }); 299 if (!was) item.classList.add('open'); 300 btn.setAttribute('aria-expanded', was ? 'false' : 'true'); 301 }); 302 }); 303 document.addEventListener('click', function () { 304 links.querySelectorAll('.sn-item.open').forEach(function (o) { o.classList.remove('open'); }); 305 }); 306 307 // Hover-preview: rechts wisselt mee met de tool waar je overheen beweegt. 308 var prev = document.getElementById('sn-preview'); 309 var pIc = document.getElementById('sn-prev-ic'); 310 var pTitle = document.getElementById('sn-prev-title'); 311 var pDesc = document.getElementById('sn-prev-desc'); 312 function wireHoverPreview(a) { 313 if (!prev) return; 314 function show() { 315 links.querySelectorAll('.sn-mega .sn-tool.active').forEach(function (x) { x.classList.remove('active'); }); 316 a.classList.add('active'); 317 prev.href = a.getAttribute('href'); 318 pTitle.textContent = a.getAttribute('data-title') || ''; 319 pDesc.textContent = a.getAttribute('data-desc') || ''; 320 var ic = a.querySelector('.sn-tool-ic svg'); 321 if (ic) pIc.innerHTML = ic.outerHTML.replace('width="17"', 'width="26"').replace('height="17"', 'height="26"'); 322 } 323 a.addEventListener('mouseenter', show); 324 a.addEventListener('focus', show); 325 } 326 links.querySelectorAll('.sn-mega .sn-tool').forEach(wireHoverPreview); 327 328 // ââ Menu-beheer (20-9-2026): live overlay bovenop de statische TOOLS/ 329 // GIDSEN-render hierboven. SiteNavMenu.astro blijft de build-time/ 330 // SEO-/no-JS-basisversie; dit haalt de admin-bewerkte lijst op 331 // (GET /api/nav-menu) en past de DOM aan zodra die afwijkt, met een 332 // sessionStorage-cache zodat dit maximaal één keer per sessie een 333 // netwerkverzoek kost (zelfde patroon als de extensie-store-banner). 334 // Vrijwel geen zichtbare flits: beide dropdowns zijn standaard 335 // ingeklapt, dus de fetch is doorgaans allang klaar vóór een 336 // bezoeker de dropdown daadwerkelijk opent. ââââââââââââââââââââââââ 337 // Iconenpad-kopie van Icon.astro (34 namen); NIEUW icoon toevoegen? 338 // Dan ALTIJD hier, in Icon.astro én in api/index.php's 339 // nav_menu_allowed_icons() bijwerken (zelfde N-plekken-conventie als 340 // de footer-links/MRB-waarschuwingen elders op deze site). 341 var NAV_ICON_PATHS = { 342 search: '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>', 343 car: '<path d="M5 17H3v-4l2-5h11l2 5v4h-2"/><path d="M5 8h14"/><circle cx="7.5" cy="17" r="1.5"/><circle cx="16.5" cy="17" r="1.5"/>', 344 bell: '<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/><path d="M13.73 21a2 2 0 0 1-3.46 0"/>', 345 file: '<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/>', 346 compare: '<circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/><path d="M11 18H8a2 2 0 0 1-2-2V9"/>', 347 fuel: '<line x1="3" y1="22" x2="15" y2="22"/><line x1="4" y1="9" x2="14" y2="9"/><path d="M14 22V4a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v18"/><path d="M14 13h2a2 2 0 0 1 2 2v2a2 2 0 0 0 4 0V9.83a2 2 0 0 0-.59-1.42L18 5"/>', 348 settings: '<circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>', 349 camera: '<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/>', 350 lock: '<rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>', 351 users: '<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>', 352 mail: '<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/>', 353 tool: '<path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/>', 354 star: '<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>', 355 card: '<rect x="1" y="4" width="22" height="16" rx="2" ry="2"/><line x1="1" y1="10" x2="23" y2="10"/>', 356 euro: '<path d="M4 10h11"/><path d="M4 14h9"/><path d="M19 5.5A7 7 0 0 0 8 12a7 7 0 0 0 11 6.5"/>', 357 gauge: '<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>', 358 shield: '<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/>', 359 home: '<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/>', 360 list: '<line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/>
360<line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/>', 361 alert: '<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>', 362 globe: '<circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/>', 363 leaf: '<path d="M17 8C8 10 5.9 16.17 3.82 21.34l1.89.66.95-2.3c.48.17.98.3 1.34.3C19 20 22 3 22 3c-1 2-8 2.25-13 3.25S2 11.5 2 13.5s1.75 3.75 1.75 3.75"/>', 364 calc: '<rect x="4" y="2" width="16" height="20" rx="2"/><line x1="8" y1="6" x2="16" y2="6"/><line x1="8" y1="12" x2="8" y2="12.01"/><line x1="12" y1="12" x2="12" y2="12.01"/><line x1="16" y1="12" x2="16" y2="12.01"/><line x1="8" y1="16" x2="8" y2="16.01"/><line x1="12" y1="16" x2="12" y2="16.01"/><line x1="16" y1="16" x2="16" y2="16.01"/>', 365 bookmark: '<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>', 366 puzzle: '<path d="M4 7h4V6a2 2 0 0 1 4 0v1h4a1 1 0 0 1 1 1v4h1a2 2 0 0 1 0 4h-1v4a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1z"/>', 367 instagram: '<rect x="2" y="2" width="20" height="20" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/>', 368 linkedin: '<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"/><rect x="2" y="9" width="4" height="12"/><circle cx="4" cy="4" r="2"/>', 369 compass: '<circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"/>', 370 key: '<path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/>', 371 download: '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>', 372 trending: '<polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/>', 373 percent: '<line x1="19" y1="5" x2="5" y2="19"/><circle cx="6.5" cy="6.5" r="2.5"/><circle cx="17.5" cy="17.5" r="2.5"/>', 374 database: '<ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/>', 375 chat: '<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/>', 376 }; 377 function navIconSvg(name, size) { 378 var d = NAV_ICON_PATHS[name] || NAV_ICON_PATHS.file; 379 return '<svg xmlns="http://www.w3.org/2000/svg" width="' + size + '" height="' + size + '" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">' + d + '</svg>'; 380 } 381 function navEsc(s) { 382 var d = document.createElement('div'); 383 d.textContent = s == null ? '' : String(s); 384 return d.innerHTML; 385 } 386 function navNodeInner(item, isTools) { 387 var badge = isTools && item.badge ? '<span class="sn-tool-badge">' + navEsc(item.badge) + '</span>' : ''; 388 return '<span class="sn-tool-ic">' + navIconSvg(item.icon, 17) + '</span><span>' + navEsc(item.title) + '</span>' + badge; 389 } 390 // Zelfde 5 sleutels/volgorde/labels als de Astro-frontmatter CATEGORIES 391 // hierboven, api/index.php's nav_menu_allowed_categories() en 392 // functies.astro; bij een NIEUWE categorie alle plekken bijwerken. 393 var NAV_CATEGORIES = [ 394 { key: 'check', label: 'Kenteken-checks' }, 395 { key: 'rekentool', label: 'Rekentools' }, 396 { key: 'cijfers', label: 'Cijfers & trends' }, 397 { key: 'zoeken', label: 'Zoeken & vergelijken' }, 398 { key: 'overig', label: 'Kennis & extra' }, 399 ]; 400 function applyNavSection(container, items, isTools, anchor) { 401 if (!container) return; 402 var existing = {}; 403 Array.prototype.forEach.call(container.querySelectorAll(':scope > a.sn-tool'), function (a) { 404 existing[a.getAttribute('href')] = a; 405 }); 406 // Categoriekoppen hebben geen href om op te reconciliëren en worden bij 407 // elke aanroep vers opgebouwd (deze IIFE draait toch maar één keer per 408 // paginalaad): de statisch door Astro gerenderde koppen eerst weg, zodat 409 // er nooit dubbele of verkeerd-gepositioneerde koppen ontstaan. 410 if (isTools) { 411 Array.prototype.forEach.call(container.querySelectorAll(':scope > span.sn-cat-head'), function (h) { h.remove(); }); 412 } 413 function insertItem(item) { 414 var el = existing[item.href]; 415 var isNew = !el; 416 if (isNew) { 417 el = document.createElement('a'); 418 el.setAttribute('role', 'menuitem'); 419 } else { 420 delete existing[item.href]; 421 } 422 el.className = 'sn-tool' + (isTools && item.sec ? ' sn-sec' : '') + (isTools && item.mobileOnly ? ' sn-mobile-only' : ''); 423 el.setAttribute('href', item.href); 424 if (isTools) { 425 el.setAttribute('data-title', item.title || ''); 426 el.setAttribute('data-desc', item.desc || ''); 427 } 428 el.innerHTML = navNodeInner(item, isTools);
429 container.insertBefore(el, anchor || null); 430 if (isNew && isTools) wireHoverPreview(el); 431 } 432 if (isTools) { 433 NAV_CATEGORIES.forEach(function (c) { 434 var group = items.filter(function (it) { return (it.category || 'overig') === c.key; }); 435 if (!group.length) return; 436 var head = document.createElement('span'); 437 head.className = 'sn-cat-head'; 438 head.textContent = c.label; 439 container.insertBefore(head, anchor || null); 440 group.forEach(insertItem); 441 }); 442 } else { 443 items.forEach(insertItem); 444 } 445 Object.keys(existing).forEach(function (href) { existing[href].remove(); }); 446 } 447 (function () { 448 var cached = null; 449 try { cached = JSON.parse(sessionStorage.getItem('ps-nav-menu') || 'null'); } catch (e) {} 450 function apply(data) { 451 if (!data) return; 452 applyNavSection(links.querySelector('.sn-mega .sn-list'), data.tools || [], true, links.querySelector('.sn-mega .sn-all')); 453 applyNavSection(links.querySelector('.sn-simple'), data.gidsen || [], false, null); 454 updateCatHeadVisibility(); 455 } 456 if (cached) { apply(cached); return; } 457 fetch('/api/nav-menu').then(function (r) { return r.ok ? r.json() : null; }).then(function (d) { 458 if (d && d.ok) { 459 try { sessionStorage.setItem('ps-nav-menu', JSON.stringify(d)); } catch (e) {} 460 apply(d); 461 } 462 }).catch(function () {}); 463 })(); 464 465 // Ingelogd? Dan wordt "Inloggen" een link naar het dashboard. Deze DOM- 466 // update staat sinds 30-9-2026 in een losse, herbruikbare functie: de 467 // fetch hieronder duurt op een traag (mobiel) netwerk merkbaar lang, 468 // waardoor de nav vlak na het inloggen nog even "Inloggen" toont terwijl 469 // de gebruiker al wél is ingelogd (bugmelding Stephan). Pagina's die 470 // ZELF al zeker weten dat er een sessie is (bv. /profiel, meteen na een 471 // geslaagde PS.me()-check aan het begin van de pagina, ongeacht via 472 // welke inlogroute je daar kwam: wachtwoord, 2FA of Google) roepen 473 // window.psNavMarkLoggedIn() direct aan i.p.v. te wachten op deze fetch. 474 function applyLoggedInNav() { 475 if (isLoggedIn) return; 476 var acct = document.getElementById('ps-acct-link'); 477 if (acct) { acct.href = '/profiel'; acct.textContent = 'Mijn kentekens'; } 478 mLogin.href = '/profiel'; 479 mLogin.textContent = 'Mijn kentekens'; 480 isLoggedIn = true; 481 syncCta(); 482 } 483 window.psNavMarkLoggedIn = applyLoggedInNav; 484 // window.__psNavSkipOwnCheck (30-9-2026): pagina's die zelf al een 485 // PS.me()-check doen en hierboven zelf al psNavMarkLoggedIn() aanroepen 486 // (bv. /profiel) zetten deze vlag VOOR dit script draait. Dan
486is deze 487 // aparte fetch overbodig: één sessie-slot-aanvrager minder in de burst 488 // van gelijktijdige aanroepen die zo'n pagina toch al afvuurt (zie de 489 // session_write_close()-toelichting in api/index.php). Op elke andere 490 // pagina (die geen eigen check doet) blijft dit gewoon de enige, nodige 491 // bron van de waarheid. 492 if (!window.__psNavSkipOwnCheck) { 493 try { 494 fetch('/api/auth/me', { credentials: 'same-origin' }) 495 .then(function (r) { return r.ok ? r.json() : null; }) 496 .then(function (j) { 497 var u = j && (j.user || (j.ok && j.email ? j : null)); 498 if (!u) return; 499 applyLoggedInNav(); 500 }) 501 .catch(function () {}); 502 } catch (e) {} 503 } 504 }); 505 })(); 506</script>
506 </div> </nav> <div class="page-shell-content"> <div class="oc-hero-outer"> <div class="tool-hero oc-hero"> <div class="oc-hero-inner"> <div class="oc-hero-grid"> <div class="oc-hero-left"> <div class="th-badges"> <span class="th-badge"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path><polyline points="9 12 11 14 15 10"></polyline></svg> Gratis</span> <span class="th-badge th-badge-new"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v18M3 12h18"></path></svg> Nieuw: AI-fotoscan</span> </div> <h1>Occasion check</h1> <p class="subtitle">Plak de link van een advertentie en krijg binnen seconden een eerlijke analyse: een AankoopScore, rode vlaggen uit de officiële RDW-data, een AI-fotoscan die de advertentiefoto's controleert op schade en roest, een eerlijke prijsindicatie met concreet openingsbod, een proefrit-checklist en een kant-en-klaar bericht aan de verkoper. Volledig gratis: geen premium-rapport, geen creditcard, zonder account.</p> <div class="cta-box"> <h2>Plak een advertentielink</h2> <p>Marktplaats, AutoScout24, Gaspedaal, AutoTrack of AutoWeek</p> <div class="oc-url-row"> <input id="oc-url" type="url" placeholder="https://www.marktplaats.nl/..." autocomplete="off"> <button id="oc-fetch" type="button">Analyseer</button> </div> <button type="button" id="oc-alt-link" class="oc-alt">Of vul het hieronder handmatig in 507<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14M6 13l6 6 6-6"></path></svg> </button> </div> <a class="oc-ext-pill" href="/extensie"> <span class="oc-ext-pill-logos"> <img src="/browser-chrome.svg" alt="Chrome" width="20" height="20"> <img src="/browser-edge.svg" alt="Edge" width="20" height="20"> <img src="/browser-firefox.svg" alt="Firefox" width="20" height="20"> </span> <span class="oc-ext-pill-txt"><strong>PlateScout-extensie</strong><span>Open de occasion check direct vanaf Marktplaats of AutoTrack, met één rechtermuisklik</span></span> <svg class="oc-ext-pill-arrow" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"></path></svg> </a> </div> <aside class="oc-hero-visual"> <!-- Illustratieve voorbeeldanalyse; R-346-VD is een echt kenteken (RDW Open Data), 508 de cijfers hieronder zijn de ECHTE uitkomst van de tool op dit kenteken bij een 509 vraagprijs van 27.500 euro (zelf geverifieerd, geen verzonnen bevindingen). De 510 link eronder opent dezelfde analyse live via de normale zoekflow. --> <div class="oc-mock"> <div class="oc-mock-top"> <span class="oc-mock-plate"><span class="oc-mock-nl">NL</span><b>R-346-VD</b></span> <span class="oc-mock-tag">Voorbeeld</span> </div> <div class="oc-mock-score"> <div class="oc-dial g oc-mock-dial"><span>92</span><small>/ 100</small></div> <div> <b>Volkswagen Golf · 2022</b> <span class="oc-mock-price">Vraagprijs ⬠27.500</span> </div> </div> <div class="oc-mock-flags"> <div class="oc-flag orange"><span class="fdot"></span><div><strong>Vraagprijs boven de indicatie</strong><p>Ligt duidelijk boven onze afschrijvingsindicatie.</p></div></div> <div class="oc-flag green"><span class="fdot"></span><div><strong>APK geldig tot 13-12-2026</strong></div></div> </div> <p class="oc-ai-badge oc-mock-ai-badge">AI-fotoscan (beta)</p> <div class="oc-mock-flags"> <div class="oc-flag green"><span class="fdot"></span><div><strong>Geen schade of roest zichtbaar</strong><p>Op basis van de advertentiefoto's.</p></div></div> </div> </div> <a class="oc-mock-demo" href="/occasion-check?kenteken=R346VD&prijs=27500&km=45000">Bekijk deze voorbeeldanalyse <svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"></path></svg></a> </aside> </div> </div> </div> </div> <div class="oc-trust-bar" id="oc-trust-bar"> <div class="oc-trust-bar-content"> <div class="oc-trust-item"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg> 511100% Gratis 512</div> <div class="oc-trust-item"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg> 513RDW Officiële Data 514</div> <div class="oc-trust-item"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="8.5" cy="7" r="4"></circle><polyline points="17 11 19 13 23 9"></polyline></svg> 515Geen registratie 516</div> </div> <div class="oc-trust-stats">Vandaag al <span id="oc-searches-today"></span> voertuigen opgezocht</div> </div> <div class="container"> <!-- Merk + titel boven het rapport (28-9-2026, Stephan: "mist het logo en 517 Occasion rapport die de kenteken check wel heeft"). Zelfde plek/gevoel 518 als de homepage-hero (logo + "Kenteken rapport"-titel boven de balk), 519 hier statisch (geen typewriter nodig, deze pagina heeft geen losse 520 voor/na-zoek-tekststaat) en alleen zichtbaar in report-mode. --> <div class="oc-report-brand"> <svg style="width:220px;height:auto;display:block;" class="oc-report-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 440.07 60.91"> 521 <defs><style>.cls-pg{fill:#4c8c2b;fill-rule:evenodd;}</style></defs> 522 <g> 523 <g><g> 524 <path d="M66.47,57.2h4.1v-.9l-1.4-.3v-3.5h1.4l2.5,3.5-1.2.3v.9h4.1v-.9l-1.2-.3-3-4.2,2.2-3.7,1.4-.3v-.9h-2.4l-2.5,4.3h-1.3v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v1.1Z"/> 525 <path d="M89.67,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 526 <path d="M109.37,56v-6.8l4.8,8h1.8v-9l1.2-.3v-.9h-3.8v.9l1.2.3v6.9l-4.8-8.1h-3v.9l1.2.3v7.8l-1.2.3v.9h3.9v-.9l-1.4-.3h.1Z"/> 527 <path d="M130.07,57.2h4.4v-.9l-1.4-.3v-7.8h1.9l.4,1.4h.9v-2.6h-7.9v2.6h.9l.4-1.4h1.9v7.8l-1.4.3v.9h-.1Z"/> 528 <path d="M149.87,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 529 <path d="M166.97,57.2h4.1v-.9l-1.4-.3v-3.5h1.4l2.5,3.5-1.2.3v.9h4.1v-.9l-1.2-.3-3-4.2,2.2-3.7,1.4-.3v-.9h-2.4l-2.5,4.3h-1.3v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v1.1Z"/> 530 <path d="M190.07,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 531 <path d="M209.87,56v-6.8l4.8,8h1.8v-9l1.2-.3v-.9h-3.8v.9l1.2.3v6.9l-4.8-8.1h-3v.9l1.2.3v7.8l-1.2.3v.9h3.9v-.9l-1.4-.3h.1Z"/> 532 <path d="M247.67,50.1h1.1v-2.5s-1.6-.7-3.2-.7c-3,0-4.8,2.1-4.8,5.4s1.7,5,4.6,5,3.6-1.5,3.6-1.5l-.6-.9s-1.4,1.2-2.9,1.2-3.1-1.2-3.1-3.8,1.1-4.1,3-4.1,1.9.3,1.9.3l.4,1.7v-.1Z"/> 533 <path d="M261.27,57.2h4.1v-.9l-1.4-.3v-3.5h4.8v3.5l-1.4.3v.9h4.1v-.9l-1.2-.3v-7.8l1.2-.3v-.9h-4.1v.9l1.4.3v3.2h-4.8v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v.9Z"/> 534 <path d="M286.77,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 535 <path d="M310.77,50.1h1.1v-2.5s-1.6-.7-3.2-.7c-3,0-4.8,2.1-4.8,5.4s1.7,5,4.6,5,3.6-1.5,3.6-1.5l-.6-.9s-1.4,1.2-2.9,1.2-3.1-1.2-3.1-3.8,1.1-4.1,3-4.1,1.9.3,1.9.3l.4,1.7v-.1Z"/> 536 <path d="M324.27,57.2h4.1v-.9l-1.4-.3v-3.5h1.4l2.5,3.5-1.2.3v.9h4.1v-.9l-1.2-.3-3-4.2,2.2-3.7,1.4-.3v-.9h-2.4l-2.5,4.3h-1.3v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v1.1Z"/> 537 </g><g> 538 <path d="M66.47,36.81h14.1v-3.9l-3.5-1.4v-6h2.5c8.4,0,13.2-3.8,13.2-11.6s-4.2-9.7-11.2-9.7h-4.4l-10.6.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h-.1ZM77.17,20.11v-10.3h3.7c3.1,0,4.8,2.1,4.8,5.1s-2.2,5.2-6,5.2h-2.5Z"/> 539 <path d="M112.87,31.31h-7.1V9.81l3.5-1.4v-4.2l-14.1.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h23.1v-10.6h-4.4l-1,5.1h0Z"/> 540 <path d="M153.07,32.91l-3.2-1.3-10-27.4h-7.4c0,.1-10.2,27.4-10.2,27.4l-3.4,1.3v3.9h14v-3.9l-3.6-1.3,1.2-3.3h10.3l1.1,3.4-3.5,1.2v3.9h14.7v-3.9h0ZM139.17,23.31h-7.1l3.7-11,3.5,11h-.1Z"/> 541 <path d="M160.87,31.51l-4.4,1.4v3.9h16v-3.9l-4.4-1.4V9.71h4.4l1.2,4.4h4.3V4.11h-26.8v10h4.3l1.2-4.4h4.4v21.8h-.2Z"/> 542 <path d="M200.37,17.41h-9.3v-7.6h7.6l1.2,3.4h4.2V4.31h-13l-10.
5426.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h24.2v-9.3h-4.2l-1.1,3.8h-8.3v-8.8h9.3v-5.2Z"/> 543 <path d="M214.67,26.81h-4.7v8.9s5.1,1.8,10.3,1.8,12.5-3.8,12.5-10.7c0-10.9-15.6-8.7-15.6-14.1s1.6-3.3,4.9-3.3,4.1.7,4.1.7l1.2,3.9h4.3l.2-8.4s-5-1.9-10.2-1.9-11.8,3.4-11.8,9.8c0,11.4,15.6,9,15.6,14.4s-2.6,3.7-5.6,3.7-4.5-1-4.5-1l-.7-3.9v.1Z"/> 544 <path d="M259.27,14.61h4.5l.2-8.8s-5.2-2.2-10.8-2.2c-9.5,0-15.6,6.5-15.6,17.4s5.4,16.4,14.8,16.4,12.1-5,12.1-5l-2.5-4.2s-4.2,3.2-8.8,3.2-7.9-3.1-7.9-10.6,2.8-11.3,7.6-11.3,5.2.7,5.2.7l1.1,4.4h.1Z"/> 545 <path d="M283.77,3.61c-9.4,0-15.3,6.5-15.3,17.1s5.1,16.7,14.3,16.7,15.5-6.9,15.5-17.4-5.3-16.4-14.6-16.4h.1ZM283.57,9.41c4.6,0,6.9,3.2,6.9,10.9s-2.8,11.3-7.4,11.3-6.7-3.5-6.7-11.1,2.5-11.1,7.2-11.1h0Z"/> 546 <path d="M313.17,9.71l3.6-1.4v-4.2l-14.2.2v3.9l3.4,1.4v14.6c0,8.9,3.7,13.1,13,13.1s13.4-4.8,13.4-13.7v-13.9l3.5-1.4v-4.2l-14.3.2v3.9l3.6,1.4v13.9c0,5.5-1.1,8.1-6,8.1s-6.1-2.1-6.1-7.4v-14.6l.1.1Z"/> 547 <path d="M347.67,31.51l-4.4,1.4v3.9h16v-3.9l-4.4-1.4V9.71h4.4l1.2,4.4h4.3V4.11h-26.8v10h4.3l1.2-4.4h4.4v21.8h-.2Z"/> 548 <path d="M368.17,33.21c0,2.7,1.3,4.2,3.9,4.2s4-1.5,4-4.2-1.3-4.2-3.9-4.2-4,1.5-4,4.2Z"/> 549 <path d="M380.67,36.81h13.4v-3.9l-3.6-1.4v-15.6l12.4,21h7.7V9.81l3.5-1.4v-4.2l-13.2.2v3.9l3.4,1.4v15.8l-12.5-21.4-11.1.2v3.9l3.5,1.4v21.8l-3.5,1.4v4Z"/> 550 <path d="M434.67,31.31h-7.1V9.81l3.5-1.4v-4.2l-14.1.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h23.1v-10.6h-4.4l-1,5.1h0Z"/> 551 </g></g> 552 <path class="cls-pg" d="M16.34,3.61c2.52-.66,4.46-1.4,8.46-3.14.58-.27,1.16-.47,1.32-.47s1.05.39,2.06.85c2.06.97,4.7,1.98,6.75,2.6l1.44.43,7.3.08c5.51.04,7.38.12,7.61.23.12.04.19.08.27.16.47.35.43,1.36.43,13.12s-.04,13.04-.16,13.97c-.5,5.32-2.45,10.68-5.4,15.06-1.71,2.56-4.7,5.78-7.14,7.72-2.79,2.25-7.1,4.62-10.56,5.86-1.75.62-2.37.85-2.91.82-.31,0-.58-.12-1.09-.27-9.28-3.11-16.15-8.62-20.57-16.42-1.82-3.26-3.18-7.26-3.77-11.37-.12-.74-.23-2.68-.27-4.35l-.08-2.99.39-.47.39-.47h7.34l7.34-.08.66.31c1.71.82,8.58,4.08,12.34,5.86,2.29,1.09,5.16,2.45,6.41,3.03l2.25,1.05h4.5c2.56,0,4.54-.04,4.58-.12.12-.19.58-2.99.66-4.11l.08-1.01h-5.32l-5.32-.08-3.57-1.75c-7.38-3.57-7.34-3.57-7.84-4.58-.39-.78-.31-1.98.23-2.72.43-.62.66-.74,7.65-4.35l3.57-1.82h10.56v-5.28h-5.36c-5.32,0-5.36,0-6.6-.35-1.55-.43-3.65-1.13-5.2-1.79l-1.2-.5-.08,2.91c-.08,3.14-.08,3.22-.85,3.92-.19.16-2.87,1.59-6.02,3.14l-5.67,2.83h-7.38c-6.44.08-7.41.04-7.76-.12-.12-.08-.23-.12-.35-.19-.47-.39-.47-1.32-.47-7.26s0-6.52.23-6.83c.08-.12.12-.23.19-.31.43-.47,1.36-.47,7.69-.47s6.83,0,8.07-.31h.16ZM17.27,8.54c1.4-.39,4.19-1.36,5.51-1.94.31-.16.62-.19.7-.16.04.04.08.85.08,1.79v1.71l-8.42,4.23h-5.01l-5.01.08v-5.28h10.68l1.48-.43h0ZM32.61,21.66c.31-.16,1.48-.78,2.6-1.36l2.06-1.05h9.7v5.28h-9.59l-2.37-1.13c-1.28-.62-2.48-1.2-2.68-1.24q-.31-.12.23-.43h0l.04-.08ZM5.71,34.04c-.19-.85-.54-3.34-.54-4.04v-.5h9.78l9.32,4.5c5.12,2.48,9.94,4.77,10.71,5.12l1.4.62h8.19l-.62,1.2c-.89,1.79-3.07,5.01-3.77,5.59-.16.16-1.28-.35-6.91-3.14-5.32-2.64-6.79-3.34-7.22-3.34s-1.71.58-7.14,3.38l-6.64,3.38-.39-.43c-.62-.66-2.1-2.68-2.72-3.73-.5-.85-1.48-2.72-1.48-2.91s1.75-.08,3.92-.08c3.57,0,3.96,0,4.39-.23,1.55-.82,1.75-3.22.31-4.31l-.5-.39-4.93-.08-4.93-.08-.16-.66-.08.12ZM28.65,54.77s-.08-1.82-.08-4.08v-4.08l3.77,1.86c2.06,1.05,3.73,1.94,3.73,2.02-.08.19-2.1,1.55-3.65,2.45-1.28.74-3.57,1.86-3.73,1.86h0l-.04-.04ZM15.88,50.54l3.73-1.94c2.06-1.09,3.8-1.94,3.84-1.98s.12,1.82.12,4.08-.04,4.08-.08,4.08-.97-.43-2.06-.97c-1.98-.97-3.77-1.98-4.89-2.83l-.62-.43h-.04Z"/> 553 </g> 554</svg> <h2 class="oc-report-title">Occasion rapport</h2> </div> <div class="card" id="oc-manual-card"> <h2>Gegevens van de occasion</h2> <p id="oc-fetch-note" class="hint" style="display:none"></p> <div class="oc-plate-row"> <label for="oc-plate">Kenteken</label> <div class="plate-wrapper oc-plate-wrapper"> <div class="plate-nl"> <span class="eu-stars"> <svg viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg"><g transform="translate(40,40)"> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(0) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(30) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(60) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(90) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(120) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(150) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(180) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(210) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(240) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(270) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(300) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(330) translate(0,-24)"></polygon> </g></svg> </span> <span class="nl-code">NL</span> </div> <input id="oc-plate" class="plate-input" type="text" maxlength="9" placeholder="AB-123-C" autocomplete="off"> </div> </div> <div class="oc-fields"> <div class="oc-field"> <label for="oc-price">Vraagprijs (euro)</label> <input id="oc-price" type="number" min="1" step="1" placeholder="12500"> </div> <div class="oc-field"> <label for="oc-km">Kilometerstand (optioneel)</label> <input id="oc-km" type="number" min="0" step="1" placeholder="98000"> </div> </div> <button id="oc-run" type="button" class="oc-run">
554 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><path d="m21 21-4.35-4.35"></path></svg> 555Start de analyse 556</button> <p id="oc-status" class="hint" style="min-height:1.3em;margin-top:.6rem"></p> </div> <!-- Direct zichtbare laadstaat (26-9-2026, Stephan: op mobiel zie je niet 557 direct wat er gebeurt na het plakken van een link). Verschijnt METEEN 558 bovenaan (report-mode verbergt de hero/het formulier en scrollt naar 559 boven), dus geen scroll nodig om te zien dat er iets gebeurt. Hergebruikt 560 de echte .card/.oc-dial/.oc-flag-vorm zodat het aanvoelt als een voorstadium 561 van het rapport, niet een los ding. --> <div id="oc-loading" style="display:none"> <div class="oc-photo-hero"> <div class="oc-sk-bar oc-sk-plate"></div> <div class="oc-sk-photo"></div> </div> <div class="card oc-score-card"> <div class="oc-score-wrap"> <div class="oc-dial oc-sk-dial"></div> <div class="oc-score-txt"> <div class="oc-sk-bar oc-sk-title"></div> <div class="oc-sk-bar oc-sk-sub"></div> </div> </div> </div> <div class="card"> <div class="oc-flag"><span class="fdot oc-sk-dot"></span><div><div class="oc-sk-bar oc-sk-line"></div><div class="oc-sk-bar oc-sk-line-short"></div></div></div> <div class="oc-flag"><span class="fdot oc-sk-dot"></span><div><div class="oc-sk-bar oc-sk-line"></div></div></div> <div class="oc-flag"><span class="fdot oc-sk-dot"></span><div><div class="oc-sk-bar oc-sk-line"></div><div class="oc-sk-bar oc-sk-line-short"></div></div></div> </div> <p class="hint" id="oc-loading-status" style="text-align:center">Advertentie ophalenâ¦</p> </div> <div id="oc-result" style="display:none"> <div class="oc-photo-hero" id="oc-photo-hero"> <div class="plate-wrapper oc-result-plate"> <div class="plate-nl"> <span class="eu-stars"> <svg viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg"><g transform="translate(40,40)"> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(0) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(30) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(60) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(90) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(120) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(150) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(180) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(210) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(240) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(270) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(300) translate(0,-24)"></polygon> <polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(330) translate(0,-24)"></polygon> </g></svg> </span> <span class="nl-code">NL</span> </div> <div class="plate-input oc-plate-readonly" id="oc-plate-chip-text"></div> </div> <div class="oc-photo-strip" id="oc-photo-strip"></div> </div> <div class="card oc-score-card"> <div class="oc-score-top"> <span class="oc-verdict-badge" id="oc-verdict-badge"></span> <span class="oc-verdict-pct" id="oc-verdict-pct" hidden></span> <button type="button" id="oc-new-search" class="oc-new-search"> <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 1 2.64 6.36"></path><path d="M3 6v6h6"></path></svg> 562Nieuwe analyse 563</button> </div> <div class="oc-score-wrap"> <div class="oc-dial" id="oc-dial"><span id="oc-score">0</span><small>/ 100</small></div> <div class="oc-score-txt"> <h2 style="margin-top:0">AankoopScore</h2> <p id="oc-vehicle" class="oc-vehicle"></p> <p id="oc-verdict" class="oc-verdict"></p> </div> </div> <button type="button" id="oc-save-portfolio" class="oc-save-btn" hidden> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewB
563ox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/></svg> <span id="oc-save-portfolio-label">Bewaar in mijn portfolio</span> </button> <p class="hint oc-save-login-hint" id="oc-save-login-hint" hidden><a href="/inloggen">Log in</a> om deze check te bewaren in je profiel.</p> <button type="button" id="oc-score-explain-toggle" class="oc-explain-toggle">Toon hoe deze score is opgebouwd</button> <div id="oc-score-explain" class="oc-score-explain" hidden></div> <!-- "Klopte deze analyse?" (29-9-2026, n.a.v. concurrentie-check): 564 alleen voor ingelogde gebruikers, zelfde zichtbaarheidslogica als 565 de bewaarknop (toggleSaveVisibility). --> <div id="oc-feedback-block" class="oc-feedback-block" hidden> <p id="oc-feedback-q" class="oc-feedback-q">Klopte deze analyse met wat je zelf aan de auto zag?</p> <div id="oc-feedback-buttons" class="oc-feedback-buttons"> <button type="button" id="oc-feedback-yes" class="oc-feedback-btn">Ja</button> <button type="button" id="oc-feedback-no" class="oc-feedback-btn">Nee</button> </div> <p id="oc-feedback-thanks" class="hint" hidden>Bedankt voor je feedback.</p> </div> </div> <!-- Eindadvies-blokken (29-9-2026, n.a.v. concurrentie-check): een snelle, 566 samengevatte eerste indruk in 3 blokken vóór de gedetailleerde 567 kaarten hieronder. Vervangt niets, vat samen. --> <div class="card" id="oc-verdict-blocks-card" hidden> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg> Eindadvies</h2> <div id="oc-verdict-blocks"></div> </div> <div class="card"> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg> Bevindingen</h2> <div id="oc-flags"></div> <div id="oc-flags-ai"></div> </div> <!-- Eigenaarschap (29-9-2026, n.a.v. concurrentie-check): aanvullende, 568 prominentere weergave van dezelfde tenaamstellings-brondata die de 569 bestaande "kort/stabiel in bezit"-vlag hierboven al gebruikt (geen 570 nieuwe RDW-data). Bewust GEEN aantal-eigenaren: dat veld bestaat 571 niet in gratis RDW open data (zie de comment bij de vlag verderop 572 in dit bestand). --> <div class="card" id="oc-owner-card" hidden> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg> Eigenaarschap</h2> <div id="oc-owner-block"></div> </div> <div class="card" id="oc-model-defects-card" hidden> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg> Bekende gebreken van dit model</h2> <p class="hint" id="oc-model-defects-disclaimer"></p> <div id="oc-model-defects"></div> <p class="hint" style="margin-top:.6rem"><a id="oc-model-defects-link" href="#">Lees de volledige analyse van de <span id="oc-model-defects-name"></span></a></p> </div> <!-- APK-gebrekenhistorie (29-9-2026, n.a.v. concurrentie-check): zelfde 573 databronnen/aanpak als renderTimeline() in plate-search.js 574 (sgfe-77wx = keuringen, 2u8a-sfar = gebreken, hx2c-gt7k = gebrek- 575 omschrijvingen), hier als eigen kaart i.p.v. in een tijdlijn, want 576 occasion-check heeft geen bredere voertuighistorie-tijdlijn. --> <div class="card" id="oc-apk-history-card" hidden> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg> APK-gebrekenhistorie</h2> <p class="hint">Per keuring: goedgekeurd, met of zonder gemelde gebreken.</p> <div id="oc-apk-history"></div> </div> <div class="card"> <h2> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg> AI-fotoscan: schade herkennen op de advertentiefoto's 577<button type="button" id="oc-photocheck-info" class="oc-info-btn" aria-expanded="false" aria-controls="oc-photocheck-wrap" title="Wat controleren wij zelf op de foto's?"> <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><path d="M12 11v6" stroke-linecap="round"></path><circle cx="12" cy="7.5" r="1" fill="currentColor" stroke="none"></circle></svg> </button> </h2> <p class="hint">Onze AI controleert de advertentiefoto's automatisch op zichtbare schade, roest en kleurverschil. Gratis: 1 scan per uur. <a href="/voordelen">Log in voor 5 scans per uur</a>, plus APK-meldingen en meer.</p> <div id="oc-ai-photocheck"></div> <div id="oc-photocheck-wrap" class="oc-photocheck-wrap" hidden> <p class="oc-checkgroup">Zelf checken op de foto's</p> <div id="oc-photocheck"></div> </div> </div> <div class="card"> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M4 10h11"/><path d="M4 14h9"/><path d="M19 5.5A7 7 0 0 0 8 12a7 7 0 0 0 11 6.5"/></svg> Prijsindicatie</h2> <div id="oc-price-block"></div> </div> <!-- Maandlasten & verzekering (29-9-2026, n.a.v. concurrentie-check): 578 kopieert calcCosts() + de MRB-helperketen verbatim uit 579 autokosten.astro (zie de MRB-waarschuwing in CLAUDE.md, dit is 580 bewust een zevende plek i.p.v. een gedeelde module, past bij hoe 581 dit project al werkt). --> <div class="card" id="oc-costs-card" hidden> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><rect x="4" y="2" width="16" height="20" rx="2"/><line x1="8" y1="6" x2="16" y2="6"/><line x1="8" y1="12" x2="8" y2="12.01"/><line x1="12" y1="12" x2="12" y2="12.01"/>
581<line x1="16" y1="12" x2="16" y2="12.01"/><line x1="8" y1="16" x2="8" y2="16.01"/><line x1="12" y1="16" x2="12" y2="16.01"/><line x1="16" y1="16" x2="16" y2="16.01"/></svg> Maandlasten & verzekering</h2> <p class="hint">Pas de schuifjes aan voor jouw situatie. Reken ook los na op <a href="/autokosten">de maandlasten-tool</a>.</p> <div class="oc-cost-sliders"> <div class="oc-cost-slider-row"> <label for="oc-cost-km">Kilometers per jaar</label> <input type="range" id="oc-cost-km" min="5000" max="40000" step="1000" value="15000"> <span id="oc-cost-km-val" class="oc-cost-slider-val"></span> </div> <div class="oc-cost-slider-row"> <label for="oc-cost-fuel" id="oc-cost-fuel-label">Brandstofprijs</label> <input type="range" id="oc-cost-fuel" min="1.50" max="2.60" step="0.01" value="2.10"> <span id="oc-cost-fuel-val" class="oc-cost-slider-val"></span> </div> <div class="oc-cost-slider-row"> <label for="oc-cost-age">Leeftijd bestuurder</label> <input type="range" id="oc-cost-age" min="18" max="80" step="1" value="40"> <span id="oc-cost-age-val" class="oc-cost-slider-val"></span> </div> </div> <div id="oc-costs-block"></div> </div> <!-- Inruilwaarde & dealerprijs (29-9-2026): afgeleid van de gehesen 582 `indic` hierboven (zelfde ratio's als autowaarde-berekenen.astro), 583 zodat er nooit twee tegenstrijdige particuliere-prijs-getallen op 584 deze pagina staan. --> <div class="card" id="oc-tradein-card" hidden> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/></svg> Inruilwaarde & dealerprijs</h2> <p class="hint">Drie verkoopscenario's op basis van dezelfde prijsindicatie hierboven: snel en zeker bij inruil, meer tijd en geld bij particuliere verkoop, de hoogste prijs bij een dealer (inclusief marge). Reken ook los na op <a href="/autowaarde-berekenen">de autowaarde-tool</a>.</p> <div id="oc-tradein-block"></div> </div> <div class="card"> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg> Onderhandelingsscript</h2> <p class="hint">Concrete punten die je aan de verkoper kunt voorleggen, gebaseerd op de bevindingen hierboven.</p> <div id="oc-script" class="oc-script"></div> <button id="oc-copy" type="button" class="oc-copy">Kopieer script</button> </div> <div class="card"> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/></svg> Bericht aan de verkoper</h2> <p class="hint">Kant-en-klaar eerste bericht, afgestemd op de bevindingen. Plak het in de chat van Marktplaats of AutoScout24.</p> <div id="oc-message" class="oc-script" style="white-space:pre-wrap"></div> <button id="oc-msg-copy" type="button" class="oc-copy">Kopieer bericht</button> </div> <div class="card"> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M13 6h3a2 2 0 0 1 2 2v7"/><path d="M11 18H8a2 2 0 0 1-2-2V9"/></svg> Vergelijkbaar aanbod</h2> <p class="hint">Vergelijk de vraagprijs direct met soortgelijke advertenties op de grote platforms (opent in een nieuw tabblad).</p> <div id="oc-similar" class="oc-links"></div> </div> <div class="card"> <h2><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/>
584<line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg> Proefrit-checklist</h2> <p class="hint">Vink af tijdens de bezichtiging en proefrit. <strong id="oc-check-count"></strong> Ook los te gebruiken (met printknop): <a href="/proefrit-checklist">proefrit-checklist</a>.</p> <div id="oc-checklist"></div> </div> <!-- Delen & exporteren (28-9-2026, Stephan: "zet onderaan ook een share 585 knoppenreeks gelijk aan de kenteken check"). Zelfde opbouw/stijl als 586 de homepage se .share-section (h3+icoon, .share-buttons-grid), hier 587 met drie knoppen i.p.v. vier: geen "Download PDF", die functie is 588 op de homepage nauw verweven met plate-search.js' eigen rapport- 589 secties (currentVehicle + tientallen DOM-ids) en niet 1-op-1 over 590 te nemen zonder een eigen PDF-opmaak voor dit rapport te bouwen. */ --> <div class="oc-share-section" id="oc-share-section"> <h3> <svg viewBox="0 0 24 24" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke="#4c8c2b" width="20" height="20"><circle cx="18" cy="5" r="3"></circle><circle cx="6" cy="12" r="3"></circle><circle cx="18" cy="19" r="3"></circle><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"></line><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"></line></svg> 591Delen 592</h3> <div class="oc-share-buttons"> <button class="oc-share-btn" id="oc-share-whatsapp" type="button"> <svg viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" fill="none"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"></path></svg> 593WhatsApp 594</button> <button class="oc-share-btn" id="oc-share-email" type="button"> <svg viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" fill="none"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg> 595E-mail 596</button> <button class="oc-share-btn" id="oc-share-link" type="button"> <svg viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" fill="none"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg> 597Kopieer link 598</button> </div> </div> <div class="cta-box"> <h2>Bekijk ook het volledige rapport</h2> <p>Alle RDW-gegevens, foto's, kosten en historie van dit kenteken.</p> <p style="margin-top:.75rem"><a id="oc-full-link" href="/" style="display:inline-flex;align-items:center;gap:.45rem;padding:.65rem 1.2rem;border-radius:11px;background:#fff;color:#2f5e18;font-weight:700;text-decoration:none">Open het kentekenrapport</a></p> </div> <p class="hint" style="margin-top:1rem">De AankoopScore is een gratis, geautomatiseerde indicatie op basis van openbare RDW-gegevens en rekenmodellen. Het is geen taxatie, aankoopkeuring of koopadvies; laat een occasion bij twijfel altijd fysiek keuren.</p> </div> <div id="oc-lightbox" class="oc-lightbox" hidden> <button type="button" class="oc-lightbox-close" aria-label="Sluiten"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><path d="M6 6l12 12M18 6 6 18"></path></svg> </button> <button type="button" class="oc-lightbox-prev" aria-label="Vorige foto"> <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 18l-6-6 6-6"></path></svg> </button> <img class="oc-lightbox-img" src="" alt=""> <button type="button" class="oc-lightbox-next" aria-label="Volgende foto"> <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18l6-6-6-6"></path></svg> </button> </div> <div class="card"> <h2>Veelgestelde vragen</h2> <div class="faq-item"> <div class="faq-q">Wat is de AankoopScore? <svg class="faq-arrow" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg></div> <div class="faq-a">
598Een score van 0 tot 100 die aangeeft hoeveel aandachtspunten wij zien bij een occasion, op basis van officiele RDW-gegevens zoals APK, tellerstandoordeel, terugroepacties, importstatus en de vraagprijs ten opzichte van een afschrijvingsindicatie. Het is een gratis indicatie, geen taxatie of aankoopkeuring.</div> </div> <div class="faq-item"> <div class="faq-q">Is de occasion check echt gratis? <svg class="faq-arrow" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg></div> <div class="faq-a">Ja, volledig gratis en zonder account. De analyse gebruikt uitsluitend openbare RDW-data en eigen rekenmodellen.</div> </div> <div class="faq-item"> <div class="faq-q">Welke advertentielinks werken? <svg class="faq-arrow" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg></div> <div class="faq-a">Links van Marktplaats, AutoScout24, Gaspedaal, AutoTrack en AutoWeek. Lukt het uitlezen niet (sommige sites blokkeren dit), dan vul je het kenteken en de vraagprijs gewoon handmatig in.</div> </div> <div class="faq-item"> <div class="faq-q">Zijn de genoemde reparatiekosten bij "Bekende gebreken" exact? <svg class="faq-arrow" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg></div> <div class="faq-a">Nee. Het zijn indicatieve bandbreedtes uit de Nederlandse garagepraktijk, gebaseerd op onze eigen redactionele problemen-gidsen per merk en model, geen offerte of taxatie. Ze zeggen ook niets over de staat van dit specifieke exemplaar; gebruik daarvoor de AankoopScore en Bevindingen.</div> </div> <div class="faq-item"> <div class="faq-q">Kan ik het chassisnummer (VIN) van een auto opzoeken bij PlateScout? <svg class="faq-arrow" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg></div> <div class="faq-a">Nee, de RDW publiceert het chassisnummer zelf nergens in open data, dus wij kunnen het niet tonen of opzoeken. Wel registreert de RDW per kenteken waar het chassisnummer op de auto is aangebracht; die locatie nemen we op in de proefrit-checklist, zodat je zelf ter plekke kunt controleren of het ingeslagen nummer overeenkomt met de kentekencard.</div> </div> </div> <section class="ra-section" data-astro-cid-2zkmu4eg><h2 class="ra-title" data-astro-cid-2zkmu4eg>Slim een occasion kopen: meer lezen</h2><div class="ra-grid" data-astro-cid-2zkmu4eg><a class="ra-card" href="/blog/digitale-service-registratie-dsr-uitgelegd" data-astro-cid-2zkmu4eg><span class="ra-tag ra-tag-kopen" data-astro-cid-2zkmu4eg><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M5 17H3v-4l2-5h11l2 5v4h-2"/><path d="M5 8h14"/><circle cx="7.5" cy="17" r="1.5"/><circle cx="16.5" cy="17" r="1.5"/></svg>Auto kopen</span><h3 data-astro-cid-2zkmu4eg>Digitale Service Registratie (DSR): wat is het en wat zegt het over een occasion?</h3><p data-astro-cid-2zkmu4eg>Steeds meer merken registreren onderhoud digitaal via DSR in plaats van in een papieren boekje. Wat is DSR precies, wat zie je erin, en wat blijft onzichtbaar?</p><span class="ra-more" data-astro-cid-2zkmu4eg>Lees artikel 599<svg width="13" height="13" viewBox="0 0 16 16" fill="none" aria-hidden="true" data-astro-cid-2zkmu4eg><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-2zkmu4eg></path></svg></span></a><a class="ra-card" href="/blog/ex-leaseauto-kopen-waar-op-letten" data-astro-cid-2zkmu4eg><span class="ra-tag ra-tag-kopen" data-astro-cid-2zkmu4eg><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M5 17H3v-4l2-5h11l2 5v4h-2"/><path d="M5 8h14"/><circle cx="7.5" cy="17" r="1.5"/><circle cx="16.5" cy="17" r="1.5"/></svg>Auto kopen</span><h3 data-astro-cid-2zkmu4eg>Ex-lease auto kopen: waar moet je op letten?</h3><p data-astro-cid-2zkmu4eg>Ex-lease auto's zijn vaak goed onderhouden en relatief betaalbaar. Zo controleer je de onderhoudshistorie, het kilometrage en de garantie voordat je koopt.</p><span class="ra-more" data-astro-cid-2zkmu4eg>Lees artikel 600<svg width="13" height="13" viewBox="0 0 16 16" fill="none" aria-hidden="true" data-astro-cid-2zkmu4eg><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-2zkmu4eg></path></svg></span></a><a class="ra-card" href="/blog/populairste-automerk-model-nederland" data-astro-cid-2zkmu4eg><span class="ra-tag ra-tag-kopen" data-astro-cid-2zkmu4eg><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M5 17H3v-4l2-5h11l2 5v4h-2"/><path d="M5 8h14"/><circle cx="7.5" cy="17" r="1.5"/><circle cx="16.5" cy="17" r="1.5"/></svg>Auto kopen</span><h3 data-astro-cid-2zkmu4eg>Dit is het populairste automerk en -model van Nederland</h3><p data-astro-cid-2zkmu4eg>PlateScout analyseerde de RDW-cijfers van 10,8 miljoen personenauto's: Volkswagen is het grootste merk op de Nederlandse weg, en de Volkswagen Polo is met bijna 290.000 exemplaren het populairste model.</p><span class="ra-more" data-astro-cid-2zkmu4eg>Lees artikel 601<svg width="13" height="13" viewBox="0 0 16 16" fill="none" aria-hidden="true" data-astro-cid-2zkmu4eg><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" data-astro-cid-2zkmu4eg></path></svg></span></a></div></section> </div>
601<script src="/js/ps-account.js"></script>
601
601<script> 602 (function () { 603 const $ = (id) => document.getElementById(id); 604 const clean = (s) => (s || '').toUpperCase().replace(/[^A-Z0-9]/g, ''); 605 function fmtPlate(raw) { 606 var s = clean(raw); if (s.length !== 6) return s; 607 var sig = s.replace(/[A-Z]/g, 'L').replace(/[0-9]/g, 'D'); 608 var SP = { LLDDDD:[2,4],DDDDLL:[2,4],DDLLDD:[2,4],LLDDLL:[2,4],LLLLDD:[2,4],DDLLLL:[2,4],DDLLLD:[2,5],DLLLDD:[1,4],LLDDDL:[2,5],LDDDLL:[1,4],LLLDDL:[3,5],LDDLLL:[1,3],DLLDDD:[1,3],DDDLLD:[3,5] }; 609 var sp = SP[sig]; return sp ? s.slice(0,sp[0])+'-'+s.slice(sp[0],sp[1])+'-'+s.slice(sp[1]) : s; 610 } 611 const eur = (n) => '⬠' + Math.round(n).toLocaleString('nl-NL'); 612 const pd = (v) => { if (!v || !/^\d{8}/.test(v)) return null; return new Date(+v.slice(0,4), +v.slice(4,6)-1, +v.slice(6,8)); }; 613 const fmtD = (d) => d ? `${String(d.getDate()).padStart(2,'0')}-${String(d.getMonth()+1).padStart(2,'0')}-${d.getFullYear()}` : ''; 614 // Vaste vertaaltabel code_toelichting_tellerstandoordeel -> RDW-uitleg (bron: 615 // jqs4-4kvw, 15-9-2026, 9 rijen). Zelfde kopie als public/js/plate-search.js 616 // (bewust gedupliceerd, geen bundler in dit project, zie CLAUDE.md-conventie). 617 const TELLER_TOELICHTING = { 618 '00': 'De geregistreerde tellerstand is steeds hoger dan de daarvoor geregistreerde tellerstand. Wij oordelen dan dat de tellerstand logisch verklaarbaar is.', 619 '01': 'Dit voertuig heeft een teller die niet tot 999.999 telt of de teller heeft de maximale tellerstand bereikt en is daarna weer teruggesprongen naar nul. Daarom geven wij geen oordeel over de reeks tellerstanden van dit voertuig.', 620 '02': 'In dit voertuig is de teller vervangen of gerepareerd. Daarom geven wij geen oordeel over de reeks tellerstanden van dit voertuig.', 621 '03': 'De geregistreerde tellerstand is steeds hoger dan de daarvoor geregistreerde tellerstand. Wij oordelen dan dat de tellerstand logisch verklaarbaar is.', 622 '04': "In de reeks tellerstanden is een tellerstand geregistreerd die lager is dan de stand daarvoor. Wij baseren het oordeel 'onlogisch' alleen op metingen na 1 januari 2014.", 623 '05': 'Wij geven geen oordeel over de reeks tellerstanden: dit voertuig is buiten Nederland geregistreerd geweest, of heeft een ander kenteken gekregen.', 624 '06': 'Voor dit voertuig zijn minder dan twee standen geregistreerd. Wij kunnen alleen een oordeel geven over een reeks van tellerstanden.', 625 '07': "De tellerstand heeft van de voormalige Stichting NAP het oordeel 'onlogisch' gekregen. Wij mogen dat oordeel alleen zelf geven bij metingen na 1 januari 2014, dus geven wij geen oordeel over de betrouwbaarheid van de gehele reeks.", 626 NG: 'Niet geregistreerd.', 627 }; 628 const tellerToelichting = (code) => TELLER_TOELICHTING[(code || '').toString().toUpperCase()] || ''; 629 $('oc-plate').addEventListener('input', () => { $('oc-plate').value = fmtPlate($('oc-plate').value); }); 630 631 // Login-bewustzijn (fase C, 2-9-2026): deze pagina had voorheen geen enkele 632 // auth-code. De analyse zelf blijft voor uitgelogde bezoekers ongewijzigd 633 // werken; alleen de "bewaar in portfolio"-knop is aan inloggen gekoppeld. 634 // initAuth() en het einde van runAnalysis() kunnen in willekeurige volgorde 635 // klaar zijn, dus allebei roepen dezelfde toggleSaveVisibility() aan. 636 let currentUser = null; 637 function toggleSaveVisibility() { 638 const resultShown = $('oc-result').style.display === 'block'; 639 $('oc-save-portfolio').hidden = !(resultShown && currentUser); 640 $('oc-save-login-hint').hidden = !(resultShown && !currentUser); 641 $('oc-feedback-block').hidden = !(resultShown && currentUser); 642 } 643 async function initAuth() { 644 currentUser = await PS.me(); 645 toggleSaveVisibility(); 646 } 647 initAuth(); 648 649 // Score-opbouw achter een toggle, ingeklapt: de badge + bevindingen 650 // hieronder geven het antwoord al, dit is voor wie het exact wil narekenen. 651 $('oc-score-explain-toggle').addEventListener('click', () => { 652 const btn = $('oc-score-explain-toggle'); 653 const wrap = $('oc-score-explain'); 654 const open = wrap.hidden; 655 wrap.hidden = !open; 656 btn.textContent = open ? 'Verberg de score-opbouw' : 'Toon hoe deze score is opgebouwd'; 657 }); 658 659 // Handmatige fotocheck-tips achter een i-tje, ingeklapt: voorkomt dat dezelfde 660 // soort tips dubbel op het scherm staan naast de AI-bevindingen zelf. 661 $('oc-photocheck-info').addEventListener('click', () => { 662 const btn = $('oc-photocheck-info'); 663 const wrap = $('oc-photocheck-wrap'); 664 const open = wrap.hidden; 665 wrap.hidden = !open; 666 btn.setAttribute('aria-expanded', String(open)); 667 }); 668 669 // Fotoviewer voor de AI-fotoscan-thumbnails: opent op de pagina zelf 670 // (met vorige/volgende tussen alle getoonde bevindings-foto's) i.p.v. een 671 // nieuw tabblad, zodat je het rapport niet verlaat. 672 (function () { 673 const lb = $('oc-lightbox'); 674 const lbImg = lb.querySelector('.oc-lightbox-img'); 675 const prevBtn = lb.querySelector('.oc-lightbox-prev'); 676 const nextBtn = lb.querySelector('.oc-lightbox-next'); 677 const closeBtn = lb.querySelector('.oc-lightbox-close'); 678 let set = []; 679 let idx = 0; 680 681 function show(i) { 682 idx = ((i % set.length) + set.length) % set.length; 683 lbImg.src = set[idx]; 684 const multi = set.length > 1; 685 prevBtn.style.display = multi ? 'flex' : 'none'; 686 nextBtn.style.display = multi ? 'flex' : 'none'; 687 }
688 function openAt(src) { 689 set = Array.from(document.querySelectorAll('.oc-flag-photo')).map((im) => im.src); 690 show(Math.max(0, set.indexOf(src))); 691 lb.hidden = false; 692 document.body.style.overflow = 'hidden'; 693 } 694 function closeLb() { 695 lb.hidden = true; 696 document.body.style.overflow = ''; 697 } 698 closeBtn.addEventListener('click', closeLb); 699 prevBtn.addEventListener('click', () => show(idx - 1)); 700 nextBtn.addEventListener('click', () => show(idx + 1)); 701 lb.addEventListener('click', (e) => { if (e.target === lb) closeLb(); }); 702 document.addEventListener('keydown', (e) => { 703 if (lb.hidden) return; 704 if (e.key === 'Escape') closeLb(); 705 else if (e.key === 'ArrowLeft') show(idx - 1); 706 else if (e.key === 'ArrowRight') show(idx + 1); 707 }); 708 // Event delegation: thumbnails worden dynamisch (her)gerenderd, dus geen 709 // losse listeners per <img> maar één gedeelde op document. 710 document.addEventListener('click', (e) => { 711 const img = e.target.closest('.oc-flag-photo'); 712 if (img) openAt(img.src); 713 }); 714 document.addEventListener('keydown', (e) => { 715 if (e.key !== 'Enter' && e.key !== ' ') return; 716 const img = e.target.closest && e.target.closest('.oc-flag-photo'); 717 if (img) { e.preventDefault(); openAt(img.src); } 718 }); 719 })(); 720 721 // Report-mode (26-9-2026, Stephan: op mobiel zie je niet direct wat er 722 // gebeurt na het plakken van een link, en het voelt niet als het 723 // kentekenrapport op de homepage). Verbergt de hero/het formulier en 724 // toont meteen, bovenaan de pagina, een laadstaat in de vorm van het 725 // rapport zelf; oogt zo als een nieuwe pagina die laadt, net als het 726 // kentekenrapport. #oc-result wordt pas zichtbaar zodra runAnalysis() 727 // klaar is (zie het einde van die functie). 728 function ocEnterReportMode(statusText) { 729 document.body.classList.add('oc-report-mode'); 730 // Hergebruikt de bestaande 'has-results'-vlag (29-9-2026): SiteNavMenu.astro 731 // luistert daar al op (MutationObserver) om zichzelf compact te maken zodra 732 // een rapport openstaat, zodat de nieuwe kentekenchip naast het logo ruimte 733 // krijgt (anders knijpt de "Kenteken check"-CTA-knop de chip tot bijna niets 734 // op middelgrote/mobiele schermen). Geen eigen compact-logica nodig. 735 document.body.classList.add('has-results'); 736 $('oc-loading-status').textContent = statusText || ''; 737 $('oc-result').style.display = 'none'; 738 $('oc-loading').style.display = 'block'; 739 window.scrollTo(0, 0); 740 } 741 function ocSetLoadingText(t) { $('oc-loading-status').textContent = t; } 742 function ocExitReportMode() { 743 document.body.classList.remove('oc-report-mode', 'has-results'); 744 $('oc-loading').style.display = 'none'; 745 } 746 747 // Kentekenchip in de echte sitenav (29-9-2026): PageNav.astro (gedeeld 748 // door alle contentpagina's) heeft geen kentekenchip-slot, dus wordt 749 // hier client-side, alleen op deze pagina, in .nav-inner geïnjecteerd 750 // (na de logo-link). Zichtbaarheid loopt volledig via de 751 // .oc-nav-plate-CSS-regel hierboven (`body.oc-report-mode`), dit 752 // script hoeft 'm dus nooit zelf te tonen/verbergen. 753 const navLogoLink = document.querySelector('.nav-logo-link'); 754 let navPlateText = null; 755 if (navLogoLink && navLogoLink.parentNode) { 756 const chip = document.createElement('div'); 757 chip.className = 'oc-nav-plate'; 758 chip.innerHTML = '<span class="oc-np-blue"><span class="oc-np-stars"><svg viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg"><g transform="translate(40,40)"><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(0) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(30) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(60) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(90) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(120) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(150) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(180) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(210) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(240) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(270) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(300) translate(0,-24)"/><polygon points="0,-16 4,-5 -6.5,-10 6.5,-10 -4,-5" fill="#fc0" transform="rotate(330) translate(0,-24)"/></g></svg></span><span class="oc-np-nl">NL</span></span><span class="oc-np-text"></span>'; 759 // insertAdjacentElement i.p.v. childNodes-indexering: robuust tegen 760 // whitespace-tekstnodes tussen de logo-link en de rest van .nav-inner. 761 navLogoLink.insertAdjacentElement('afterend', chip); 762 navPlateText = chip.querySelector('.oc-np-text'); 763 } 764 function setNavPlate(formatted) { 765 if (navPlateText) navPlateText.textContent = formatted; 766 } 767 768 // "Vandaag al X voertuigen opgezocht" (29-9-2026): letterlijke kopie van 769 // de sfeer-teller-curve in plate-search.js (todayStatsCurve/-Seed), 770 // BEWUST met dezelfde localStorage-sleutel 'searchStats' zodat dit 771 // dezelfde, al lopende teller van de homepage toont i.p.v. een eigen, 772 // afwijkend tweede getal. Update deze curve altijd op beide plekken 773 // tegelijk als de min/max ooit wijzigt. 774 (function initTodayStats() { 775 const MIN = 3, MAX = 1249; 776 const seed = (n) => { const x = Math.sin(n) * 10000; return x - Math.floor(x); }; 777 const curve = (date) => { 778 const dayMs = 24 * 60 * 60 * 1000; 779 const midnight = new Date(date.getFullYear(), date.getMonth(), date.getDate()); 780 const frac = (date - midnight) / dayMs; 781 const shaped = frac - Math.sin(2 * Math.PI * frac) / (2 * Math.PI); 782 const base = MIN + (MAX - MIN) * shaped; 783 const minuteOfDay = date.getHours() * 60 + date.getMinutes(); 784 const jitter = Math.floor(seed(minuteOfDay) * 6); 785 return Math.round(base) + jitter; 786 }; 787 const today = new Date().toDateString(); 788 let stats = {}; 789 try { stats = JSON.parse(localStorage.getItem('searchStats') || '{}'); } catch (e) {} 790 if (stats.date !== today) stats = { date: today, shown: 0 }; 791 stats.shown = Math.max(stats.shown || 0, curve(new Date())); 792 try { localStorage.setItem('searchStats', JSON.stringify(stats)); } catch (e) {} 793 const el = $('oc-searches-today');
794 if (el) el.textContent = stats.shown.toLocaleString('nl-NL'); 795 })(); 796 797 $('oc-new-search').addEventListener('click', () => { 798 ocExitReportMode(); 799 $('oc-result').style.display = 'none'; 800 $('oc-url').value = ''; 801 $('oc-plate').value = ''; 802 $('oc-price').value = ''; 803 $('oc-km').value = ''; 804 $('oc-fetch-note').style.display = 'none'; 805 $('oc-status').textContent = ''; 806 history.replaceState(null, '', location.pathname); 807 window.scrollTo(0, 0); 808 $('oc-url').focus(); 809 }); 810 811 // Delen-knoppen (28-9-2026), zelfde drie acties/teksten-stijl als de 812 // share-section op de homepage (WhatsApp/e-mail/kopieer link), hier 813 // gevoed door shareState i.p.v. het homepage-brede currentVehicle. 814 $('oc-share-whatsapp').addEventListener('click', () => { 815 if (!shareState) return; 816 const text = (shareState.vName || 'Deze occasion') + '\nKenteken: ' + fmtPlate(shareState.plate) 817 + '\nAankoopScore: ' + shareState.score + '/100 (' + shareState.verdictText + ')' 818 + '\n\nBekijk de volledige analyse: ' + window.location.href; 819 window.open('https://wa.me/?text=' + encodeURIComponent(text), '_blank'); 820 }); 821 $('oc-share-email').addEventListener('click', () => { 822 if (!shareState) return; 823 const subject = 'Occasion check: ' + (shareState.vName || 'auto') + ' (' + fmtPlate(shareState.plate) + ')'; 824 const body = 'Bekijk de AankoopScore en volledige analyse van deze ' + (shareState.vName || 'auto') 825 + ' met kenteken ' + fmtPlate(shareState.plate) + ' (score ' + shareState.score + '/100, ' + shareState.verdictText + '):\n\n' 826 + window.location.href; 827 window.location.href = 'mailto:?subject=' + encodeURIComponent(subject) + '&body=' + encodeURIComponent(body); 828 }); 829 $('oc-share-link').addEventListener('click', (e) => { 830 navigator.clipboard.writeText(window.location.href).then(() => { 831 const btn = e.target.closest('.oc-share-btn'); 832 const original = btn.innerHTML; 833 btn.classList.add('oc-sb-flash'); 834 btn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg> Gekopieerd!'; 835 setTimeout(() => { btn.innerHTML = original; btn.classList.remove('oc-sb-flash'); }, 2000); 836 }); 837 }); 838 839 // Slim URL-veld (29-9-2026, Stephan): apps als Gaspedaal delen een link 840 // vaak met omringende tekst ("Deze Ford Focus heb ik gevonden via..."). 841 // extractUrl() pakt de eerste http(s)-URL uit een grotere tekst, met 842 // trailing leestekens (punt/komma/haakje) die een deel-boodschap er 843 // vaak achteraan plakt, verwijderd. Toegepast op zowel plakken (direct 844 // filteren, zichtbaar in het veld) als vlak vóór het versturen (vangnet 845 // voor typen/slepen i.p.v. plakken). 846 function extractUrl(text) { 847 const m = (text || '').match(/https?:\/\/[^\s]+/i); 848 if (!m) return (text || '').trim(); 849 return m[0].replace(/[).,;!?'"]+$/, ''); 850 } 851 $('oc-url').addEventListener('paste', (e) => { 852 const pasted = (e.clipboardData || window.clipboardData).getData('text'); 853 if (!pasted) return; 854 const cleaned = extractUrl(pasted); 855 if (cleaned !== pasted.trim()) { 856 e.preventDefault(); 857 $('oc-url').value = cleaned; 858 } 859 }); 860 861 // Advertentie ophalen via de backend (CORS) en velden voorvullen. 862 async function fetchAd() { 863 const url = extractUrl($('oc-url').value); 864 if (!url) { $('oc-status').textContent = 'Plak eerst een advertentielink.'; return false; } 865 $('oc-fetch').disabled = true; 866 ocEnterReportMode('Advertentie ophalenâ¦'); 867 try { 868 const r = await PS.api('/occasion/fetch', 'POST', { url }); 869 const d = r.data || {}; 870 if (!r.ok) { ocExitReportMode(); $('oc-status').textContent = d.error || 'Ophalen mislukt. Vul de gegevens handmatig in.'; return false; } 871 const note = $('oc-fetch-note'); 872 if (d.fetched === false) { ocExitReportMode(); note.style.display = 'block'; note.textContent = d.reason || 'Uitlezen lukte niet; vul handmatig in.'; $('oc-status').textContent = ''; return false; } 873 if (d.kenteken) $('oc-plate').value = fmtPlate(d.kenteken); 874 if (d.price) $('oc-price').value = d.price; 875 if (d.km) $('oc-km').value = d.km; 876 note.style.display = 'block'; 877 note.textContent = 'Uitgelezen van ' + (d.source || 'de advertentie') + (d.title ? ': "' + d.title + '"' : '') + (d.kenteken ? '' : ' (geen kenteken gevonden in de advertentie; vul het handmatig in)'); 878 $('oc-status').textContent = ''; 879 if (d.photoCount) { runPhotoScan(url, d.kenteken); } 880 else { 881 // Bugmelding Stephan 30-9-2026 ("zijn de credits op? of zit er een fout?"): 882 // zonder dit bleef de kaart stil leeg (alleen de vaste introtekst) als een 883 // advertentie zelf geen foto's had, precies zo oogt dat als "het werkt niet". 884 $('oc-ai-photocheck').innerHTML = '<p class="oc-ai-badge">AI-fotoscan (beta)</p><p class="hint">Geen advertentiefoto\'s gevonden in deze advertentie om te scannen.</p>'; 885 } 886 if (d.kenteken) { ocSetLoadingText('RDW-gegevens ophalen en analyserenâ¦'); runAnalysis(); return true; } 887 ocExitReportMode(); 888 return false;
889 } catch (e) { 890 ocExitReportMode(); 891 $('oc-status').textContent = 'Ophalen mislukt. Vul de gegevens handmatig in.'; 892 return false; 893 } finally { $('oc-fetch').disabled = false; } 894 } 895 896 // Bekende aandachtspunten per merk/model voor tijdens de proefrit. Bewust een 897 // STATISCHE tabel i.p.v. een live AI-call per bezoeker: de tips hangen alleen af 898 // van merk/model (niet van het individuele kenteken), dus zijn ze vooraf één keer 899 // op te stellen en te hergebruiken, zonder dat elke proefrit-checklist Gemini- 900 // quotum kost. Zelfde onderzoeksbasis als de distributieriem/wielmaten-database 901 // (SPECS_DB in plate-search.js): bekende, veelgenoemde chronische zwakke punten 902 // per motorfamilie/platform, geen incidentele individuele meldingen. 903 const MODEL_TIPS_DB = { 904 'VOLKSWAGEN|GOLF': ['Bij de EA211-motoren (1.0/1.5 TSI) kan de kettingspanner na verloop van tijd rammelen bij koude start: luister de eerste seconden na het starten', 'Oudere DSG7-automaten (droge koppeling) kunnen schokkerig optrekken bij lage snelheid: let hierop bij een vol-gas-test op een oprit', 'Check de achterwielkasten op roest bij bouwjaren van vóór circa 2017'], 905 'VOLKSWAGEN|POLO': ['Zelfde EA211-kettingspanner-aandachtspunt als de Golf: luister bij koude start naar een rammelend geluid', 'Test de elektrische ramen: het mechanisme is een bekend zwak punt'], 906 'VOLKSWAGEN|TIGUAN': ['DSG-automaat: let op schokkerig schakelen bij lage snelheid, vooral bij de droge-koppeling-variant (DSG7)', 'Check de 4Motion-vierwielaandrijving op vreemde geluiden bij het aanzetten in een bocht'], 907 'VOLKSWAGEN|PASSAT': ['DSG-automaat: zelfde aandachtspunt als Golf/Tiguan bij schokkerig optrekken', 'Bij dieselversies: vraag naar het onderhoud van het roetfilter (DPF), vooral bij veel korte ritten'], 908 'SKODA|OCTAVIA': ['Deelt de EA211-motor met de Golf: zelfde kettingspanner-aandachtspunt bij koude start', 'DSG-automaat: let op schokkerig schakelen'], 909 'SKODA|FABIA': ['Zelfde EA211-kettingspanner-punt als de grotere Skoda/VW-modellen'], 910 'SEAT|IBIZA': ['Zelfde EA211-motor als Polo/Fabia: luister bij koude start naar de kettingspanner'], 911 'SEAT|LEON': ['DSG-automaat: let op schokkerig schakelen bij lage snelheid'], 912 'FORD|FIESTA': ['PowerShift-automaat (indien aanwezig): let op schokkerig schakelen en een slippend gevoel bij optrekken, bekend zwak punt', 'EcoBoost 1.0 vóór medio 2019: vraag naar de distributieriem-vervangingshistorie (kwetsbare natte riem in de eerste generatie)'], 913 'FORD|FOCUS': ['PowerShift-automaat: zelfde aandachtspunt als de Fiesta, schokkerig schakelen', 'Check het koelvloeistofreservoir op haarscheurtjes: een bekend zwak punt bij deze generatie', 'EcoBoost 1.0 vóór medio 2019: check de distributieriem-historie'], 914 'FORD|PUMA': ['Mild-hybrid EcoBoost heeft altijd een kettingaandrijving (geen riem-zorgen), maar check wel het 48V-systeem op foutcodes via de boordcomputer'], 915 'FORD|KUGA': ['Bij dieselversies: vraag naar onderhoud van het roetfilter (DPF)'], 916 'OPEL|CORSA': ['PureTech-motor (1.2, gedeeld met Peugeot/Citroën): check op olieverbruik en luister naar een rammelend geluid bij koude start (riemspanner)', 'Vraag naar de olieverversingshistorie: deze motorfamilie is gevoelig voor te lange onderhoudsintervallen'], 917 'PEUGEOT|208': ['PureTech-motor: zelfde aandachtspunt als de Corsa, check olieverbruik en onderhoudshistorie'], 918 'PEUGEOT|2008': ['PureTech-motor: zelfde aandachtspunt, check olieverbruik en onderhoudsintervallen'], 919 'PEUGEOT|308': ['PureTech-motor: check olieverbruik; bij automaat let op schokkerig schakelen'], 920 'CITROEN|C3': ['PureTech-motor: zelfde aandachtspunt als de PSA-zustermodellen, check olieverbruik'], 921 'TOYOTA|YARIS': ['Doorgaans zeer betrouwbaar; bij de hybride-versie: vraag naar de conditie van het hybride-accupakket bij hoge kilometerstand'], 922 'TOYOTA|COROLLA': ['Bij de hybride-versie: check de hybride-accuconditie, met name bij auto\'s met veel stadskilometers'], 923 'TOYOTA|AYGO': ['Doorgaans zeer betrouwbaar;
923 check bij de oudere generatie (gedeeld met Peugeot 107/Citroën C1) vooral op roest bij de wielkasten'], 924 'RENAULT|CLIO': ['Bij de EDC-automaat (dubbelekoppelingsbak): let op rukkerig schakelen bij lage snelheid', 'Bij diesel: vraag naar onderhoud van het roetfilter, gevoelig voor vervuiling bij korte ritjes'], 925 'RENAULT|CAPTUR': ['Zelfde EDC-aandachtspunt als de Clio bij de automaat-versie'], 926 'RENAULT|MEGANE': ['EDC-automaat: let op rukkerig schakelen', 'Check de elektronica: infotainment-storingen komen vaker voor dan bij concurrenten'], 927 'DACIA|SANDERO': ['Eenvoudige, robuuste techniek met doorgaans weinig chronische problemen; check vooral de airco-compressor op een piepend geluid'], 928 'DACIA|DUSTER': ['Zelfde robuuste basis als de Sandero; check de airco en let bij 4x4-versies op de koppeling van de vierwielaandrijving'], 929 'NISSAN|QASHQAI': ['Bij de CVT-automaat (traploos): let op oververhitting bij zwaar of langdurig gebruik, vraag naar de onderhoudshistorie van de transmissie'], 930 'MAZDA|CX-5': ['Doorgaans betrouwbaar; check bij oudere bouwjaren op roest rond de achterwielkasten'], 931 'MAZDA|3': ['Doorgaans betrouwbaar; geen chronische zwakke punten van betekenis bekend'], 932 'VOLVO|XC40': ['Check de infotainment/elektronica op storingen: een vaker gemeld aandachtspunt bij dit model'], 933 'BMW|3ER REIHE': ['Check op olielekkage bij de klepdekselpakking, een bekend punt bij oudere motoren', 'Bij diesel: vraag naar onderhoud van het roetfilter'], 934 'MERCEDES-BENZ|A-KLASSE': ['Check de transmissieprogrammering (DCT/automaat) op schokkerig schakelen', 'Bij diesel: vraag naar het roetfilteronderhoud'], 935 'KIA|PICANTO': ['Doorgaans betrouwbaar; check het koelsysteem op lekkage'], 936 'HYUNDAI|I20': ['Doorgaans betrouwbaar; check het koelsysteem op lekkage'], 937 'MINI|COOPER': ['Bij de oudere N14/N18-motoren: een bekend punt is de kettingspanner van de distributieketting, luister bij koude start', 'Automaat (Getrag DCT): let op schokkerig schakelen'], 938 }; 939 // Zelfde soort merknaam-in-model-probleem als in plate-search.js 940 // (normalizeModelForLookup): RDW herhaalt bij sommige merken het merk in de 941 // handelsbenaming (bv. Toyota "TOYOTA YARIS" i.p.v. "YARIS"). 942 function findModelTips(merk, model) { 943 const m = (merk || '').toUpperCase().trim(); 944 let mo = (model || '').toUpperCase().trim(); 945 if (m && mo.startsWith(m + ' ')) mo = mo.slice(m.length + 1).trim(); 946 return MODEL_TIPS_DB[m + '|' + mo] || null; 947 } 948 949 // Bekende gebreken per merk/model, gegrond op onze eigen redactionele 950 // problemen-artikelen (src/content/blog/<slug>-problemen.md), NIET 951 // AI-gegenereerd per bezoeker. Losse tabel van MODEL_TIPS_DB hierboven: 952 // andere vorm (kosten-bandbreedte + ernst + bronartikel) en ander doel 953 // (kaart "Bekende gebreken", niet de proefrit-checklist). Kosten zijn 954 // BEWUST bandbreedtes, afgerond op tientallen/honderdtallen; nooit een 955 // nep-precies enkel getal. Elk gebrek is herleidbaar tot een letterlijke 956 // passage in het bijbehorende blogartikel (geen AI-giswerk). 957 const MODEL_DEFECTS_DB = { 958 'AUDI|A3': { slug: 'audi-a3-problemen', defects: [ 959 { defect: 'Versleten kettingspanner distributieketting, geratel bij koude start', costMin: 600, costMax: 1500, sev: 'red' }, 960 { defect: 'Verhoogd olieverbruik bij oudere 2.0 benzinemotoren', costMin: 0, costMax: 300, sev: 'orange' }, 961 { defect: 'DSG-automaat schakelt schokkerig of traag bij verwaarloosd onderhoud', costMin: 300, c
961ostMax: 1800, sev: 'red' }, 962 { defect: 'Vervuild roetfilter en EGR-klep bij diesels met veel korte ritten', costMin: 300, costMax: 800, sev: 'orange' }, 963 ] }, 964 'AUDI|A4': { slug: 'audi-a4-problemen', defects: [ 965 { defect: 'Verhoogd olieverbruik bij oudere benzinemotoren', costMin: 0, costMax: 300, sev: 'orange' }, 966 { defect: 'Versleten kettingspanner distributieketting, geratel bij koude start', costMin: 600, costMax: 1500, sev: 'red' }, 967 { defect: 'Automaat schakelt schokkerig bij achterstallig onderhoud', costMin: 400, costMax: 2000, sev: 'red' }, 968 { defect: 'Vervuild roetfilter bij diesels met veel korte ritten', costMin: 300, costMax: 800, sev: 'orange' }, 969 ] }, 970 'AUDI|Q3': { slug: 'audi-q3-problemen', defects: [ 971 { defect: 'DSG-automaat schakelt schokkerig of traag bij verwaarloosd onderhoud', costMin: 300, costMax: 1800, sev: 'red' }, 972 { defect: 'Versleten kettingspanner distributieketting, geratel bij koude start', costMin: 600, costMax: 1500, sev: 'red' }, 973 { defect: 'Vervuild roetfilter en EGR-klep bij diesels met veel korte ritten', costMin: 300, c
973ostMax: 800, sev: 'orange' }, 974 ] }, 975 'BMW|1ER REIHE': { slug: 'bmw-1-serie-problemen', defects: [ 976 { defect: 'Distributieketting kan rekken of breken bij bepaalde dieselmotoren', costMin: 1500, costMax: 2500, sev: 'red' }, 977 { defect: 'VANOS-slijtage: onregelmatig lopen, vermogensverlies of moeilijk starten', costMin: 300, costMax: 800, sev: 'orange' }, 978 { defect: 'Olielekkage bij kleppendeksel en oliefilterbehuizing', costMin: 150, costMax: 400, sev: 'orange' }, 979 { defect: 'Vervuild roetfilter bij diesels met veel korte ritten', costMin: 300, costMax: 800, sev: 'orange' }, 980 ] }, 981 'BMW|3ER REIHE': { slug: 'bmw-3-serie-problemen', defects: [ 982 { defect: 'Distributieketting kan rekken bij hoge kilometerstanden', costMin: 1500, costMax: 2800, sev: 'red' }, 983 { defect: 'Elektrische waterpomp kan uitvallen, risico op oververhitting', costMin: 400, costMax: 900, sev: 'red' }, 984 { defect: 'Wervelkleppen (swirl flaps) kunnen vastlopen of losraken bij diesels', costMin: 500, costMax: 1200, sev: 'red' }, 985 { defect: 'VANOS-slijtage zorgt voor onregelmatig lopen en vermogensverlies', costMin: 300, c
985ostMax: 800, sev: 'orange' }, 986 ] }, 987 'BMW|X1': { slug: 'bmw-x1-problemen', defects: [ 988 { defect: 'Distributieketting kan rekken of falen bij oudere dieselmotoren', costMin: 1500, costMax: 2500, sev: 'red' }, 989 { defect: 'xDrive-aandrijflijn: geluiden of schokken bij verwaarloosd onderhoud', costMin: 300, costMax: 1500, sev: 'red' }, 990 { defect: 'Vervuild roetfilter bij diesels met veel korte ritten', costMin: 300, costMax: 800, sev: 'orange' }, 991 { defect: 'iDrive en sensoren haperen af en toe', costMin: 0, costMax: 400, sev: 'orange' }, 992 ] }, 993 'CITROEN|C3': { slug: 'citroen-c3-problemen', defects: [ 994 { defect: 'Natte distributieriem PureTech kan verslijten, risico op motorschade', costMin: 600, costMax: 3000, sev: 'red' }, 995 { defect: 'Versleten koppeling of actuator bij de oudere ETG-schakelbak', costMin: 600, costMax: 1200, sev: 'red' }, 996 { defect: 'Verhoogd olieverbruik bij vroege PureTech-motoren', costMin: 0, costMax: 300, sev: 'orange' }, 997 ] }, 998 'CITROEN|C4': { slug: 'citroen-c4-problemen', defects: [ 999 { defect: 'Natte distributieriem PureTech kan verslijten, risico op motorschade', costMin: 600, costMax: 3000, sev: 'red' }, 1000 { defect: 'AdBlue-storingen: defecte doseerpomp, kristallisatie of sensorfout', costMin: 300, c
1000ostMax: 900, sev: 'orange' }, 1001 { defect: 'Vervuild roetfilter bij diesels met veel korte ritten', costMin: 300, costMax: 800, sev: 'orange' }, 1002 { defect: 'e-C4: afgebroken laadsessies en lege 12-voltaccu in vroege bouwjaren', costMin: 0, costMax: 250, sev: 'orange' }, 1003 ] }, 1004 'DACIA|DUSTER': { slug: 'dacia-duster-problemen', defects: [ 1005 { defect: '1.2 turbo verbruikt fors olie, risico op turbo- of motorschade', costMin: 0, costMax: 1500, sev: 'red' }, 1006 { defect: 'Vervuild roetfilter en EGR-klep bij diesels met veel korte ritten', costMin: 300, costMax: 800, sev: 'orange' }, 1007 { defect: 'Roest aan de onderzijde, subframe en remleidingen', costMin: 150, costMax: 600, sev: 'orange' }, 1008 { defect: 'Slijtende wiellagers, hoorbaar als bromgeluid', costMin: 150, costMax: 350, sev: 'orange' }, 1009 ] }, 1010 'DACIA|SANDERO': { slug: 'dacia-sandero-problemen', defects: [ 1011 { defect: 'Sneller slijtende draagarmrubbers, stabilisatorstangen en schokdempers', costMin: 150, costMax: 500, sev: 'orange' }, 1012 { defect: 'Turbomotor gevoelig voor uitgesteld olieonderhoud, risico op turboschade', costMin: 0, costMax: 1200, sev: 'red' }, 1013 { defect: 'Vroege koppelingsslijtage bij veel stadsverkeer of trekwerk', costMin: 500, costMax: 900, sev: 'orange' }, 1014 { defect: 'Roest bij wielkastranden, dorpels en onderzijde', costMin: 150, costMax: 600, sev: 'orange' }, 1015 ] }, 1016 'FIAT|500': { slug: 'fiat-500-problemen', defects: [ 1017 { defect: 'Dualogic-automaat schakelt schokkerig, storingen in de actuator', costMin: 600, costMax: 1500, sev: 'red' }, 1018 { defect: 'Verhoogd olieverbruik bij de 0.9 TwinAir-motor', costMin: 0, costMax: 300, sev: 'orange' }, 1019 { defect: 'Roest bij oudere exemplaren, vooral onderzijde en wielkasten', costMin: 150, costMax: 600, sev: 'orange' }, 1020 { defect: 'Elektronica: haperende raambediening, dashboarddisplay of sensoren', costMin: 0, costMax: 300, sev: 'orange' }, 1021 ] }, 1022 'FIAT|PANDA': { slug: 'fiat-panda-problemen', defects: [ 1023 { defect: 'Haperende elektrische stuurbekrachtiging, serieus veiligheidspunt', costMin: 300, c
1023ostMax: 800, sev: 'red' }, 1024 { defect: 'Dualogic-automaat schakelt schokkerig, storingen in het bedienmechanisme', costMin: 600, costMax: 1500, sev: 'red' }, 1025 { defect: 'Versleten draagarmen, fuseekogels en ophangrubbers', costMin: 200, costMax: 600, sev: 'orange' }, 1026 { defect: 'Roest bij oudere exemplaren, vooral onderzijde en wielkasten', costMin: 150, costMax: 600, sev: 'orange' }, 1027 ] }, 1028 'FORD|FIESTA': { slug: 'ford-fiesta-problemen', defects: [ 1029 { defect: 'Powershift-automaat schokt, trilt of slipt, soms met foutmeldingen', costMin: 800, costMax: 2200, sev: 'red' }, 1030 { defect: 'Natte distributieriem 1.0 EcoBoost moet op tijd vervangen worden', costMin: 1200, costMax: 2000, sev: 'red' }, 1031 { defect: 'Koelsysteem 1.0 EcoBoost kan oververhitten bij vroege exemplaren', costMin: 150, costMax: 500, sev: 'orange' }, 1032 { defect: 'Roest bij wielkasten, onderkant en naden bij oudere exemplaren', costMin: 200, costMax: 1200, sev: 'orange' }, 1033 ] }, 1034 'FORD|FOCUS': { slug: 'ford-focus-problemen', defects: [ 1035 { defect: 'Powershift-automaat (3e generatie) schokt, trilt of slipt', costMin: 800, costMax: 2200, sev: 'red' }, 1036 { defect: 'EcoBoost distributieriem en waterpomp: vervolgschade bij achterstallig onderhoud', costMin: 1200, costMax: 2200, sev: 'red' }, 1037 { defect: 'Koelsysteem EcoBoost kan oververhitten bij vroege exemplaren', costMin: 150, costMax: 500, sev: 'orange' }, 1038 { defect: 'Tweemassavliegwiel diesel versleten, rammelt bij stationair', costMin: 600, costMax: 1200, sev: 'orange' }, 1039 ] }, 1040 'FORD|KUGA': { slug: 'ford-kuga-problemen', defects: [ 1041 { defect: 'Automaat (2e generatie) kan schokken of slippen', costMin: 800, costMax: 2200, sev: 'red' }, 1042 { defect: 'EcoBoost 1.5 distributieriem: vervolgschade bij achterstallig onderhoud', costMin: 1200, costMax: 2200, sev: 'red' }, 1043 { defect: 'Koelsysteem EcoBoost kan oververhitten bij vroege exemplaren', costMin: 150, costMax: 500, sev: 'orange' }, 1044 { defect: 'Roetfilter diesel raakt verstopt bij veel korte ritten', costMin: 300, c
1044ostMax: 800, sev: 'orange' }, 1045 ] }, 1046 'HYUNDAI|KONA': { slug: 'hyundai-kona-problemen', defects: [ 1047 { defect: 'DCT 1.6 turbo schokt of aarzelt, kan oververhitten bij slijtage', costMin: 800, costMax: 2000, sev: 'red' }, 1048 { defect: '12-voltaccu loopt leeg bij lange stilstand', costMin: 120, costMax: 220, sev: 'orange' }, 1049 { defect: 'Remschijven roesten vast door overwegend regeneratief remmen', costMin: 150, costMax: 400, sev: 'orange' }, 1050 { defect: 'Koppeling 1.0 turbo slijt vroegtijdig bij sportief rijden', costMin: 500, costMax: 900, sev: 'orange' }, 1051 ] }, 1052 'HYUNDAI|TUCSON': { slug: 'hyundai-tucson-problemen', defects: [ 1053 { defect: 'DCT-automaat schokt of aarzelt bij lage snelheid en in de file', costMin: 800, costMax: 2200, sev: 'red' }, 1054 { defect: 'Roetfilter en EGR-klep vervuild bij veel korte dieselritten', costMin: 300, costMax: 800, sev: 'orange' }, 1055 { defect: 'Koolaanslag op inlaatkleppen bij de 1.6 T-GDI benzinemotor', costMin: 300, c
1055ostMax: 600, sev: 'orange' }, 1056 { defect: '12-voltaccu loopt leeg bij weinig gebruik', costMin: 120, costMax: 220, sev: 'orange' }, 1057 ] }, 1058 'KIA|NIRO': { slug: 'kia-niro-problemen', defects: [ 1059 { defect: '12V-accu loopt leeg bij weinig gebruik, auto start dan niet', costMin: 120, costMax: 220, sev: 'orange' }, 1060 { defect: 'Achterremmen roesten of lopen vast door regeneratief remmen', costMin: 150, costMax: 400, sev: 'orange' }, 1061 { defect: 'Infotainment traag of haperende telefoonkoppeling', costMin: 0, costMax: 300, sev: 'orange' }, 1062 ] }, 1063 'KIA|SPORTAGE': { slug: 'kia-sportage-problemen', defects: [ 1064 { defect: 'Roetfilter en EGR-klep vervuild bij veel korte dieselritten', costMin: 300, costMax: 1200, sev: 'orange' }, 1065 { defect: 'Koolstofafzetting op inlaatkleppen bij directe inspuiting', costMin: 300, costMax: 600, sev: 'orange' }, 1066 { defect: "Kleine software- of sensorstoringen bij rijhulp en camera's", costMin: 0, costMax: 300, sev: 'orange' }, 1067 ] }, 1068 'MAZDA|2': { slug: 'mazda-2-problemen', defects: [ 1069 { defect: 'Roest bij wielkasten, dorpels en portieren (bouwjaar tot 2014)', costMin: 200, costMax: 1200, sev: 'orange' }, 1070 { defect: 'Zwakke accu laat start-stopsysteem onregelmatig schakelen', costMin: 120, costMax: 220, sev: 'orange' }, 1071 { defect: 'Trillende koppeling bij wegrijden', costMin: 400, costMax: 900, sev: 'orange' }, 1072 ] }, 1073 'MAZDA|3': { slug: 'mazda-3-problemen', defects: [ 1074 { defect: 'Koolaanslag in inlaatspruitstuk en kleppen bij SkyActiv-D diesel', costMin: 300, c
1074ostMax: 600, sev: 'orange' }, 1075 { defect: 'Roetfilter regenereert onvoldoende bij kort stadsgebruik', costMin: 300, costMax: 800, sev: 'orange' }, 1076 { defect: 'EGR-klep vervuilt bij de SkyActiv-D diesel', costMin: 200, costMax: 500, sev: 'orange' }, 1077 { defect: 'Tik- of klopgeluiden uit de ophanging, meestal versleten rubbers', costMin: 100, costMax: 300, sev: 'orange' }, 1078 ] }, 1079 'MAZDA|CX-5': { slug: 'mazda-cx5-problemen', defects: [ 1080 { defect: 'Koolaanslag in het inlaatsysteem van de 2.2 diesel bij veel korte ritten', costMin: 200, costMax: 450, sev: 'orange' }, 1081 { defect: 'Roetfilter verstopt bij onvoldoende regeneratie (vooral stadsgebruik)', costMin: 250, costMax: 1200, sev: 'orange' }, 1082 ] }, 1083 'MERCEDES-BENZ|A-KLASSE': { slug: 'mercedes-a-klasse-problemen', defects: [ 1084 { defect: '7G-DCT automaat schakelt schokkerig of krijgt mechatronicastoringen', costMin: 1200, costMax: 2500, sev: 'red' }, 1085 { defect: 'MBUX-infotainment reageert traag, loopt vast of verliest connectiviteit', costMin: 0, costMax: 150, sev: 'orange' }, 1086 { defect: 'Roetfilter verstopt bij diesels door veel korte ritten', costMin: 250, costMax: 1200, sev: 'orange' }, 1087 { defect: 'Turbo verliest vermogen en geeft blauwe rook bij hoge kilometerstand', costMin: 800, costMax: 2000, sev: 'red' }, 1088 ] }, 1089 'MERCEDES-BENZ|C-KLASSE': { slug: 'mercedes-c-klasse-problemen', defects: [ 1090 { defect: 'Distributieketting en kettingspanner slijten, ratelend geluid bij koude start', costMin: 500, costMax: 1000, sev: 'orange' }, 1091 { defect: 'Draagarmen, rubbers en stabilisatorstangen vooras slijten', costMin: 250, costMax: 600, sev: 'orange' }, 1092 { defect: 'Infotainment, sensoren of elektrisch stuurslot haperen', costMin: 150, costMax: 500, sev: 'orange' }, 1093 { defect: 'Roetfilter raakt vervuild bij veel korte ritten (diesel)', costMin: 250, costMax: 1200, sev: 'orange' }, 1094 ] }, 1095 'MERCEDES-BENZ|GLA': { slug: 'mercedes-gla-problemen', defects: [ 1096 { defect: 'Automaat met dubbele koppeling schakelt schokkerig bij verwaarloosd onderhoud', costMin: 1200, costMax: 2500, sev: 'red' }, 1097 { defect: "Infotainment, parkeersensoren of camera's geven storingen", costMin: 0, costMax: 200, sev: 'orange' }, 1098 { defect: 'Vooras en banden slijten sneller door de sportieve afstelling', costMin: 200, costMax: 500, sev: 'orange' }, 1099 { defect: 'Roetfilter raakt vervuild bij dieselversies in de stad', costMin: 250, costMax: 1200, sev: 'orange' }, 1100 ] }, 1101 'MG|4': { slug: 'mg-4-problemen', defects: [ 1102 { defect: 'Infotainmentscherm werd traag, herstartte of verloor telefoonkoppeling', costMin: 0, costMax: 150, sev: 'orange' }, 1103 { defect: '12-voltaccu liep na weken stilstand leeg en gaf storingsmeldingen', costMin: 100, costMax: 250, sev: 'orange' }, 1104 { defect: 'Remschijven roesten in door regeneratief remmen', costMin: 150, costMax: 350, sev: 'orange' }, 1105 { defect: 'Verhoogde bandenslijtage door gewicht en koppel, vooral achteras', costMin: 300, c
1105ostMax: 600, sev: 'orange' }, 1106 ] }, 1107 'MG|ZS': { slug: 'mg-zs-problemen', defects: [ 1108 { defect: '12-voltaccu loopt leeg en veroorzaakt storingsmeldingen', costMin: 100, costMax: 250, sev: 'orange' }, 1109 { defect: 'Infotainmentscherm reageert traag of loopt vast (vooral eerste generatie)', costMin: 0, costMax: 150, sev: 'orange' }, 1110 { defect: 'Laadsessies starten soms niet aan bepaalde publieke laadpalen', costMin: 0, costMax: 150, sev: 'orange' }, 1111 { defect: 'Remschijven roesten oppervlakkig door regeneratief remmen', costMin: 150, costMax: 350, sev: 'orange' }, 1112 ] }, 1113 'MINI|COOPER': { slug: 'mini-cooper-problemen', defects: [ 1114 { defect: 'Distributieketting slijt, ratelend geluid bij koude start, risico op motorschade', costMin: 800, costMax: 1800, sev: 'red' }, 1115 { defect: 'Olielekkage bij kleppendekselpakking of oliefilterhuis', costMin: 150, costMax: 400, sev: 'orange' }, 1116 { defect: 'Koolaanslag op inlaatkleppen bij directe injectie (Cooper S)', costMin: 200, costMax: 450, sev: 'orange' }, 1117 { defect: 'Turbo van de Cooper S verliest vermogen, blauwe rook of fluitend geluid', costMin: 800, costMax: 2000, sev: 'red' }, 1118 ] }, 1119 'NISSAN|JUKE': { slug: 'nissan-juke-problemen', defects: [ 1120 { defect: 'Xtronic CVT-automaat gaat schokken, trillen of oververhitten', costMin: 1500, costMax: 3000, sev: 'red' }, 1121 { defect: '1.2 en 1.6 DIG-T kunnen op termijn wat olie verbruiken', costMin: 0, costMax: 0, sev: 'orange' }, 1122 { defect: 'Roetfilter verstopt bij de 1.5 dCi diesel door korte ritten', costMin: 250, costMax: 1200, sev: 'orange' }, 1123 { defect: 'Infotainment reageert traag of loopt vast', costMin: 0, costMax: 150, sev: 'orange' }, 1124 ] }, 1125 'NISSAN|LEAF': { slug: 'nissan-leaf-problemen', defects: [ 1126 { defect: 'Accupakket degradeert sneller door het ontbreken van actieve koeling', costMin: 3000, costMax: 7000, sev: 'red' }, 1127 { defect: '12-voltaccu geeft storingsmeldingen of laat de auto niet starten', costMin: 80, costMax: 200, sev: 'orange' }, 1128 { defect: 'Remschijven roesten in door regeneratief remmen', costMin: 150, costMax: 350, sev: 'orange' }, 1129 { defect: 'Sensoren en laadklep geven incidentele storingsmeldingen', costMin: 0, costMax: 150, sev: 'orange' }, 1130 ] }, 1131 'NISSAN|QASHQAI': { slug: 'nissan-qashqai-problemen', defects: [ 1132 { defect: 'Xtronic CVT-automaat schokt, oververhit of geeft geen snelheidswinst bij hoge toeren', costMin: 1500, costMax: 3000, sev: 'red' }, 1133 { defect: 'Roetfilter verstopt bij de dCi diesel door veel korte ritten', costMin: 250, costMax: 1200, sev: 'orange' }, 1134 { defect: 'Olieverdunning bij kleine DIG-T motoren door veel korte ritten', costMin: 0, costMax: 0, sev: 'orange' }, 1135 { defect: 'Injectoren en EGR-klep vervuilen of slijten bij de diesel', costMin: 300, c
1135ostMax: 1200, sev: 'orange' }, 1136 ] }, 1137 'OPEL|ASTRA': { slug: 'opel-astra-problemen', defects: [ 1138 { defect: 'Distributieriem in oliebad slijt en kan materiaal loslaten (1.2 PureTech)', costMin: 500, costMax: 1200, sev: 'red' }, 1139 { defect: 'Roetfilter en EGR-klep raken vervuild bij veel korte ritten (diesel)', costMin: 250, costMax: 1200, sev: 'orange' }, 1140 { defect: 'Waterpomp, thermostaat en koolaanslag bij de 1.4 Turbo op hoge kilometerstand', costMin: 200, costMax: 500, sev: 'orange' }, 1141 { defect: 'Infotainment, parkeersensoren en ruitbediening haperen', costMin: 0, costMax: 250, sev: 'orange' }, 1142 ] }, 1143 'OPEL|CORSA': { slug: 'opel-corsa-problemen', defects: [ 1144 { defect: 'Rekkende distributieketting bij oudere benzinemotoren, risico op verspringen', costMin: 600, costMax: 1200, sev: 'red' }, 1145 { defect: 'Versneld slijtende distributieriem in oliebad bij de Corsa F (1.2 turbo)', costMin: 500, costMax: 900, sev: 'red' }, 1146 { defect: 'Schokkerige Easytronic door slijtage koppeling of storing in schakelactuator', costMin: 300, c
1146ostMax: 800, sev: 'orange' }, 1147 { defect: 'Lekkend kunststof thermostaathuis met koelvloeistofverlies', costMin: 150, costMax: 350, sev: 'orange' }, 1148 ] }, 1149 'OPEL|MOKKA': { slug: 'opel-mokka-problemen', defects: [ 1150 { defect: 'Versneld slijtende distributieriem in oliebad bij de 1.2 PureTech', costMin: 500, costMax: 900, sev: 'red' }, 1151 { defect: 'Verstopt roetfilter bij de diesel door veel korte ritten', costMin: 150, costMax: 600, sev: 'orange' }, 1152 { defect: 'Haperende centrale vergrendeling en leeglopende accu bij weinig gebruik', costMin: 0, costMax: 200, sev: 'orange' }, 1153 ] }, 1154 'PEUGEOT|2008': { slug: 'peugeot-2008-problemen', defects: [ 1155 { defect: 'Slijtende distributieriem in oliebad van de 1.2 PureTech, risico op motorschade', costMin: 500, costMax: 900, sev: 'red' }, 1156 { defect: 'Verstopt roetfilter en vervuilende EGR-klep bij de BlueHDi-diesel', costMin: 200, costMax: 600, sev: 'orange' }, 1157 { defect: 'Traag of vastlopend touchscreen en vals alarmerende sensoren', costMin: 0, costMax: 200, sev: 'orange' }, 1158 ] }, 1159 'PEUGEOT|208': { slug: 'peugeot-208-problemen', defects: [ 1160 { defect: 'Slijtende distributieriem in oliebad van de 1.2 PureTech, risico op motorschade', costMin: 500, costMax: 900, sev: 'red' }, 1161 { defect: 'Verstopt roetfilter en AdBlue-storingen bij de BlueHDi-diesel', costMin: 200, costMax: 600, sev: 'orange' }, 1162 { defect: 'Traag of vastlopend touchscreen en vals alarmerende sensoren', costMin: 0, costMax: 200, sev: 'orange' }, 1163 ] }, 1164 'PEUGEOT|3008': { slug: 'peugeot-3008-problemen', defects: [ 1165 { defect: 'Natte distributieriem van de 1.2 PureTech, riskant bij achterstallig onderhoud', costMin: 500, costMax: 900, sev: 'red' }, 1166 { defect: 'Verstopt roetfilter en AdBlue-storingen bij veel korte ritten', costMin: 200, costMax: 600, sev: 'orange' }, 1167 { defect: 'Haperende schermen en vastlopende software van het i-Cockpit', costMin: 0, costMax: 200, sev: 'orange' }, 1168 { defect: 'Tikkende geluiden door slijtage in de ophanging', costMin: 150, costMax: 400, sev: 'orange' }, 1169 ] }, 1170 'PEUGEOT|308': { slug: 'peugeot-308-problemen', defects: [ 1171 { defect: 'Slijtende distributieriem in oliebad van de 1.2 PureTech, risico op motorschade', costMin: 500, costMax: 900, sev: 'red' }, 1172 { defect: 'Verstopt roetfilter en AdBlue-storingen bij de BlueHDi-diesel', costMin: 200, costMax: 600, sev: 'orange' }, 1173 { defect: 'Traag of vastlopend touchscreen en vals alarmerende sensoren', costMin: 0, costMax: 200, sev: 'orange' }, 1174 ] }, 1175 'RENAULT|CAPTUR': { slug: 'renault-captur-problemen', defects: [ 1176 { defect: 'Schokkerige EDC-automaat bij lage snelheid of traag optrekken', costMin: 400, costMax: 1500, sev: 'red' }, 1177 { defect: 'Verstopt roetfilter en vervuilende EGR-klep bij de diesel', costMin: 200, costMax: 600, sev: 'orange' }, 1178 { defect: 'Haperende centrale vergrendeling, ramen of keycard-herkenning', costMin: 0, costMax: 200, sev: 'orange' }, 1179 ] }, 1180 'RENAULT|CLIO': { slug: 'renault-clio-problemen', defects: [ 1181 { defect: 'Schokkerige EDC-automaat bij lage snelheid', costMin: 400, costMax: 1500, sev: 'red' }, 1182 { defect: 'Verstopt roetfilter en vervuilende EGR-klep bij de diesel', costMin: 200, costMax: 600, sev: 'orange' }, 1183 { defect: 'Olieverbruik tussen de beurten bij sommige TCe-benzinemotoren', costMin: 0, costMax: 0, sev: 'orange' }, 1184 { defect: 'Haperende elektrische ramen, vergrendeling of keycard-herkenning', costMin: 0, costMax: 200, sev: 'orange' }, 1185 ] }, 1186 'RENAULT|MEGANE': { slug: 'renault-megane-problemen', defects: [ 1187 { defect: 'Schokkerige EDC-automaat bij lage snelheid', costMin: 400, costMax: 1500, sev: 'red' }, 1188 { defect: 'Verstopt roetfilter en vervuilende EGR-klep bij de diesel', costMin: 200, costMax: 600, sev: 'orange' }, 1189 { defect: 'Olieverbruik tussen de beurten bij de 1.2 TCe', costMin: 0, costMax: 0, sev: 'orange' }, 1190 { defect: 'Traag of vastlopend R-Link-infotainmentscherm', costMin: 0, costMax: 200, sev: 'orange' }, 1191 ] }, 1192 'RENAULT|ZOE': { slug: 'renault-zoe-problemen', defects: [ 1193 { defect: 'Lege of defecte 12V-accu waardoor de auto niet start', costMin: 100, costMax: 250, sev: 'orange' }, 1194 { defect: 'Incidentele laadstoringen aan bepaalde openbare laadpalen', costMin: 0, costMax: 150, sev: 'orange' }, 1195 { defect: 'Trage of vastlopende R-Link multimedia', costMin: 0, costMax: 150, sev: 'orange' }, 1196 { defect: 'Vastzittende of roestende remschijven door weinig gebruik (regeneratief remmen)', costMin: 150, costMax: 400, sev: 'orange' }, 1197 ] }, 1198 'SEAT|ARONA': { slug: 'seat-arona-problemen', defects: [ 1199 { defect: 'Schokkerig of trillend rijgedrag bij lage toeren met de vroege 1.5 TSI', costMin: 0, costMax: 150, sev: 'orange' }, 1200 { defect: 'Vastlopend of traag touchscreen met Bluetooth-storingen', costMin: 0, costMax: 200, sev: 'orange' }, 1201 { defect: 'Sneller slijtende koppeling bij veel stadskilometers', costMin: 500, costMax: 900, sev: 'orange' }, 1202 ] },
1203 'SEAT|IBIZA': { slug: 'seat-ibiza-problemen', defects: [ 1204 { defect: 'Uitgerekte distributieketting bij oudere 1.2/1.4 TSI (geratel bij koude start)', costMin: 700, costMax: 1400, sev: 'red' }, 1205 { defect: 'DSG-automaat schokt of aarzelt zonder tijdig onderhoud van de transmissieolie', costMin: 250, costMax: 2000, sev: 'red' }, 1206 { defect: 'Roetfilter (1.6 TDI) raakt verstopt bij veel korte ritten', costMin: 300, costMax: 900, sev: 'orange' }, 1207 { defect: 'Haperende raammechanismen of een trage centrale vergrendeling', costMin: 100, costMax: 300, sev: 'orange' }, 1208 ] }, 1209 'SEAT|LEON': { slug: 'seat-leon-problemen', defects: [ 1210 { defect: 'Verhoogd olieverbruik bij oudere 1.8/2.0 TSI door slijtage van zuigerveren', costMin: 0, costMax: 1200, sev: 'orange' }, 1211 { defect: 'Uitgerekte distributieketting bij oudere TSI-motoren (geratel bij koude start)', costMin: 700, costMax: 1400, sev: 'red' }, 1212 { defect: 'DSG-automaat schokt of aarzelt zonder tijdig onderhoud van de transmissieolie', costMin: 250, costMax: 2000, sev: 'red' }, 1213 { defect: 'Roetfilter en EGR-klep (2.0 TDI) raken verstopt bij veel korte ritten', costMin: 300, c
1213ostMax: 1000, sev: 'orange' }, 1214 ] }, 1215 'SKODA|FABIA': { slug: 'skoda-fabia-problemen', defects: [ 1216 { defect: 'Uitgerekte distributieketting bij oudere TSI-motoren (geratel bij koude start)', costMin: 600, costMax: 1200, sev: 'red' }, 1217 { defect: 'DSG-automaat schakelt schokkerig zonder tijdig verversen van de transmissieolie', costMin: 250, costMax: 1800, sev: 'red' }, 1218 { defect: 'Losse storingen in elektrische ramen, sensoren of het infotainment', costMin: 100, costMax: 300, sev: 'orange' }, 1219 ] }, 1220 'SKODA|OCTAVIA': { slug: 'skoda-octavia-problemen', defects: [ 1221 { defect: 'Uitgerekte distributieketting bij oudere benzinemotoren (geratel bij koude start)', costMin: 700, costMax: 1400, sev: 'red' }, 1222 { defect: 'DSG-automaat schakelt schokkerig of traag zonder tijdig olieonderhoud', costMin: 250, costMax: 2000, sev: 'red' }, 1223 { defect: 'Vervuild roetfilter en EGR-klep bij diesels met veel korte ritten', costMin: 300, costMax: 1000, sev: 'orange' }, 1224 { defect: 'Losse storingen in sensoren, verlichting of het infotainment', costMin: 100, costMax: 350, sev: 'orange' }, 1225 ] }, 1226 'SUZUKI|SWIFT': { slug: 'suzuki-swift-problemen', defects: [ 1227 { defect: 'Roest bij modellen van voor 2017 aan wielkasten, dorpels en bodemplaat', costMin: 200, costMax: 1200, sev: 'orange' }, 1228 { defect: 'Rammelende distributieketting of kettingspanner bij koude start', costMin: 500, costMax: 1200, sev: 'red' }, 1229 { defect: 'Slijtende koppeling bij hoge kilometerstand of veel stadsgebruik', costMin: 500, costMax: 900, sev: 'orange' }, 1230 { defect: 'Beperkte levensduur van de kleine SHVS mild-hybride accu', costMin: 300, c
1230ostMax: 600, sev: 'orange' }, 1231 ] }, 1232 'SUZUKI|VITARA': { slug: 'suzuki-vitara-problemen', defects: [ 1233 { defect: 'Roetfilter (1.6 diesel) raakt verstopt bij overwegend korte ritten', costMin: 300, costMax: 900, sev: 'orange' }, 1234 { defect: 'Koolaanslag en verhoogd turborisico bij Boosterjet-motoren zonder tijdig olieonderhoud', costMin: 800, costMax: 1800, sev: 'red' }, 1235 { defect: 'Tik- of klopgeluiden uit de ophanging door versleten rubbers of schokdempers', costMin: 200, costMax: 600, sev: 'orange' }, 1236 ] }, 1237 'TESLA|MODEL 3': { slug: 'tesla-model-3-problemen', defects: [ 1238 { defect: 'Krakende of klokkende voorwielophanging (fusees, draagarmrubbers, stabilisatorstang)', costMin: 300, costMax: 700, sev: 'orange' }, 1239 { defect: 'Remschijven roesten door weinig gebruik van de mechanische rem', costMin: 150, costMax: 500, sev: 'orange' }, 1240 { defect: 'Bouwkwaliteit: condens in lampen, wisselende paneelnaden, lekkende kofferbakrubbers', costMin: 100, costMax: 400, sev: 'orange' }, 1241 { defect: 'Verzwakte 12-voltaccu geeft meldingen of opstartproblemen', costMin: 150, costMax: 300, sev: 'orange' }, 1242 ] }, 1243 'TESLA|MODEL Y': { slug: 'tesla-model-y-problemen', defects: [ 1244 { defect: 'Krakende of klokkende voorwielophanging, vooral bij vroege bouwjaren', costMin: 300, c
1244ostMax: 700, sev: 'orange' }, 1245 { defect: 'Kraakgeluiden uit panoramisch glasdak en interieurpanelen bij temperatuurwisseling', costMin: 100, costMax: 300, sev: 'orange' }, 1246 { defect: 'Remschijven roesten door weinig gebruik van de mechanische rem', costMin: 150, costMax: 500, sev: 'orange' }, 1247 { defect: 'Verzwakte 12-voltaccu geeft vage meldingen of trage opstart', costMin: 150, costMax: 300, sev: 'orange' }, 1248 ] }, 1249 'TOYOTA|AYGO': { slug: 'toyota-aygo-problemen', defects: [ 1250 { defect: 'Slijtende koppeling, vooral bij veel stadsgebruik', costMin: 500, costMax: 800, sev: 'orange' }, 1251 { defect: 'Roestende uitlaat en lichte roestplekken aan de onderkant bij oudere exemplaren', costMin: 150, costMax: 500, sev: 'orange' }, 1252 ] }, 1253 'TOYOTA|COROLLA': { slug: 'toyota-corolla-problemen', defects: [ 1254 { defect: '12-voltaccu liep bij vroege bouwjaren leeg na lange stilstand', costMin: 150, costMax: 300, sev: 'orange' }, 1255 { defect: 'Remschijven roesten of klauwen lopen aan door weinig gebruik van de rem', costMin: 150, costMax: 500, sev: 'orange' }, 1256 ] }, 1257 'TOYOTA|RAV4': { slug: 'toyota-rav4-problemen', defects: [ 1258 { defect: '12V-accu loopt leeg bij hybride door weinig rijden', costMin: 100, costMax: 250, sev: 'orange' }, 1259 { defect: 'Achterremmen roesten of lopen vast door weinig gebruik bij hybride', costMin: 150, costMax: 400, sev: 'orange' }, 1260 { defect: 'Roetfilter, EGR-klep of turbo geven problemen bij oudere diesel met korte ritten', costMin: 400, costMax: 1800, sev: 'red' }, 1261 ] }, 1262 'TOYOTA|YARIS': { slug: 'toyota-yaris-problemen', defects: [ 1263 { defect: 'Remmen roesten oppervlakkig of zitten vast bij hybride door weinig gebruik', costMin: 150, costMax: 350, sev: 'orange' }, 1264 { defect: 'Roest bij oudere Yaris aan wielkasten, dorpels en achterklep', costMin: 150, costMax: 800, sev: 'orange' }, 1265 { defect: 'Zwakke 12-voltaccu veroorzaakt vage storingen en startproblemen', costMin: 100, costMax: 250, sev: 'orange' }, 1266 ] }, 1267 'VOLVO|V40': { slug: 'volvo-v40-problemen', defects: [ 1268 { defect: 'Verstopt roetfilter bij dieselversies door veel korte ritten', costMin: 300, c
1268ostMax: 900, sev: 'orange' }, 1269 { defect: 'Sensus-infotainment kan traag reageren of vastlopen', costMin: 0, costMax: 300, sev: 'orange' }, 1270 { defect: 'Dubbele koppeling schakelt schokkerig of slijt bij hoge kilometerstand', costMin: 1000, costMax: 2200, sev: 'red' }, 1271 { defect: 'Ongelijke slijtage van de voorbanden door uitlijning of ophanging', costMin: 100, costMax: 400, sev: 'orange' }, 1272 ] }, 1273 'VOLVO|V60': { slug: 'volvo-v60-problemen', defects: [ 1274 { defect: 'Verstopt roetfilter bij de dieselmotoren', costMin: 300, costMax: 900, sev: 'orange' }, 1275 { defect: 'Haperende EGR-klep en versleten injectoren bij de vijfcilinder-diesel', costMin: 400, costMax: 1500, sev: 'red' }, 1276 { defect: 'Distributieriem moet op tijd vervangen worden, anders risico op motorschade', costMin: 400, costMax: 900, sev: 'red' }, 1277 { defect: '12V-accu loopt leeg bij de plug-in versies', costMin: 150, costMax: 300, sev: 'orange' }, 1278 ] }, 1279 'VOLVO|XC40': { slug: 'volvo-xc40-problemen', defects: [ 1280 { defect: '12V-accu loopt leeg bij plug-in en elektrische versies', costMin: 150, costMax: 300, sev: 'orange' }, 1281 { defect: 'Infotainment-software hapert of loopt vast', costMin: 0, costMax: 300, sev: 'orange' }, 1282 { defect: 'Remschijven roesten bij elektrische versies door weinig remgebruik', costMin: 100, costMax: 300, sev: 'orange' }, 1283 ] }, 1284 'VOLKSWAGEN|GOLF': { slug: 'vw-golf-problemen', defects: [ 1285 { defect: 'Distributieketting rekt bij vroege 1.2 en 1.4 TSI-motoren', costMin: 600, costMax: 1200, sev: 'red' }, 1286 { defect: 'DSG-automaat schokt bij optrekken of geeft mechatronicastoring', costMin: 800, costMax: 2000, sev: 'red' }, 1287 { defect: 'Waterpomp met kunststof onderdelen kan gaan lekken', costMin: 300, c
1287ostMax: 600, sev: 'orange' }, 1288 { defect: 'Verhoogd olieverbruik bij sommige oudere TSI-motoren', costMin: 0, costMax: 1000, sev: 'orange' }, 1289 ] }, 1290 'VOLKSWAGEN|ID.3': { slug: 'vw-id3-problemen', defects: [ 1291 { defect: 'Software van vroege modellen hapert of vertoont bugs in infotainment', costMin: 0, costMax: 300, sev: 'orange' }, 1292 { defect: '12V-accu geeft soms problemen, auto reageert dan niet', costMin: 150, costMax: 350, sev: 'orange' }, 1293 ] }, 1294 'VOLKSWAGEN|PASSAT': { slug: 'vw-passat-problemen', defects: [ 1295 { defect: 'Roetfilter of EGR-klep raakt verstopt bij de 2.0 TDI door korte ritten', costMin: 300, costMax: 900, sev: 'orange' }, 1296 { defect: 'DSG-automaat schokt bij optrekken of geeft mechatronicastoring', costMin: 800, costMax: 2000, sev: 'red' }, 1297 { defect: 'Distributieriem moet op tijd vervangen worden, anders forse schade', costMin: 400, costMax: 900, sev: 'red' }, 1298 { defect: 'Turbo kan bij hoge kilometerstand slijten, merkbaar aan vermogensverlies', costMin: 800, costMax: 1800, sev: 'red' }, 1299 ] }, 1300 'VOLKSWAGEN|POLO': { slug: 'vw-polo-problemen', defects: [ 1301 { defect: 'Distributieketting rekt bij de vroege 1.2 TSI', costMin: 600, costMax: 1200, sev: 'red' }, 1302 { defect: 'Koppeling slijt door veel stadsgebruik, merkbaar aan slippen', costMin: 400, costMax: 900, sev: 'orange' }, 1303 { defect: 'Roetfilter raakt verstopt bij de TDI door korte ritten', costMin: 300, c
1303ostMax: 900, sev: 'orange' }, 1304 { defect: 'Kleine elektronicastoringen zoals raambediening of vergrendeling', costMin: 0, costMax: 300, sev: 'orange' }, 1305 ] }, 1306 'VOLKSWAGEN|TIGUAN': { slug: 'vw-tiguan-problemen', defects: [ 1307 { defect: 'Distributieketting rekt bij de vroege 1.4 TSI', costMin: 600, costMax: 1200, sev: 'red' }, 1308 { defect: 'Verhoogd olieverbruik bij sommige 2.0 TSI-motoren door zuigerveren', costMin: 0, costMax: 1000, sev: 'orange' }, 1309 { defect: 'DSG-automaat schokt bij optrekken of geeft storingen', costMin: 800, costMax: 2000, sev: 'red' }, 1310 { defect: '4Motion-aandrijving vraagt periodiek onderhoud, anders slijtage', costMin: 200, costMax: 600, sev: 'orange' }, 1311 ] }, 1312 }; 1313 // Zelfde normalisatie als findModelTips: RDW-sleutel is MERK|MODEL, 1314 // met dezelfde merk-in-model-correctie. 1315 function findModelDefects(merk, model) { 1316 const m = (merk || '').toUpperCase().trim(); 1317 let mo = (model || '').toUpperCase().trim(); 1318 if (m && mo.startsWith(m + ' ')) mo = mo.slice(m.length + 1).trim(); 1319 return MODEL_DEFECTS_DB[m + '|' + mo] || null; 1320 } 1321 1322 // RDW publiceert het chassisnummer (VIN) zelf nergens in open data, wel 1323 // WAAR het op dit specifieke voertuig is aangebracht (m9d7-ebf2's 1324 // plaats_chassisnummer, bv. "r. op bodemplaat by voorzitting"). Dat veld is 1325 // geschreven voor keurmeesters, niet voor kopers: alleen de meest opake 1326 // 1-letter-afkortingen worden hier uitgeschreven, de rest (vaktermen als 1327 // "schutbord"/"deurstyl") blijft staan, leesbaar genoeg in context. Leeg bij 1328 // een flink deel van de voertuigen (RDW vult dit veld niet altijd), dan geen 1329 // checklist-item tonen i.p.v. een gegokte locatie. 1330 function humanizeChassisLocation(raw) { 1331 if (!raw) return null; 1332 const s = String(raw) 1333 .replace(/\br\.\s*/gi, 'rechts ') 1334 .replace(/\bl\.\s*/gi, 'links ') 1335 .replace(/\bv\.\s*/gi, 'voor ') 1336 .replace(/\ba\.\s*/gi, 'achter ') 1337 .replace(/\bby\b/gi, 'bij') 1338 .replace(/\s+/g, ' ') 1339 .trim(); 1340 return s || null; 1341 } 1342 1343 // Zelfde escape-patroon als elders (o.a. ps-report-extra.js): de AI-fotoscan 1344 // stopt vrije tekst (Gemini's omschrijving/samenvatting, uiteindelijk gevoed 1345 // met de door de verkoper geschreven advertentietekst) rechtstreeks in 1346 // innerHTML; zonder escapen zou een geprepareerde advertentie HTML/JS in de 1347 // pagina kunnen krijgen. 1348 function esc(s) { return String(s == null ? '' : s).replace(/[<>&"]/g, (c) => ({ '<': '<', '>': '>', '&': '&', '"': '"' }[c])); } 1349 1350 // AI-fotoscan (beta): stuurt de al opgehaalde advertentiefoto's naar de 1351 // backend, die ze laat beoordelen op zichtbare schade/roest/kleurverschil. 1352 function aiFlagTitle(it) { 1353 const type = { roest: 'Roest', schade: 'Schade', kleurverschil: 'Kleurverschil', slijtage: 'Slijtage', advertentietekst: 'Advertentietekst' }[it.type] || 'Aandachtspunt'; 1354 return { sev: it.ernst === 'hoog' ? 'red' : 'orange', type }; 1355 } 1356 // Eén bevinding kan op meerdere foto's te zien zijn ("fotos": [1,3]); oudere 1357 // vorm ("foto": 1) blijft ook ondersteund. 1358 function flagFotoNummers(it) { 1359 return Array.isArray(it.fotos) ? it.fotos : (it.foto ? [it.foto] : []); 1360 } 1361 function photoThumbs(it, photos) { 1362 const nums = flagFotoNummers(it); 1363 if (!Array.isArray(photos) || !nums.length) return ''; 1364 const imgs = nums.map((n) => { 1365 const src = photos[n - 1]; 1366 return src ? '<img class="oc-flag-photo" src="' + src + '" alt="Advertentiefoto ' + n + '" loading="lazy" role="button" tabindex="0">' : ''; 1367 }).join(''); 1368 return imgs ? '<div class="oc-flag-photos">' + imgs + '</div>' : ''; 1369 } 1370 function aiFlagRow(it, photos, prefix) { 1371 const { sev, type } = aiFlagTitle(it); 1372 const nums = flagFotoNummers(it); 1373 // Bevindingen uit de advertentietekst zijn niet foto-gebonden: geen "Foto X"-label. 1374 let title; 1375 if (it.type === 'advertentietekst') { 1376 title = (prefix ? prefix + ', ' : '') + type; 1377 } else { 1378 const fotoLabel = nums.length ? ('Foto' + (nums.length > 1 ? '\'s' : '') + ' ' + nums.join(', ')) : 'Foto onbekend'; 1379 title = (prefix ? prefix + ', ' : '') + fotoLabel + ': ' + type; 1380 } 1381 return '<div class="oc-flag ' + sev + '"><span class="fdot"></span><div><strong>' + title + '</strong><p>' + esc(it.omschrijving || '') + '</p>' + photoThumbs(it, photos) + '</div></div>'; 1382 } 1383 const skeletonRows = (n) => '<div class="oc-ai-skeleton">' + Array.from({ length: n }, () => 1384 '<div class="sk-row"><span class="sk-dot"></span><div class="sk-lines"><div class="sk-bar w30"></div><div class="sk-bar w90"></div></div></div>' 1385 ).join('') + '</div>'; 1386
1387 // Bericht aan de verkoper: wordt in runAnalysis() opgebouwd uit de RDW- 1388 // bevindingen, maar de AI-fotoscan (die vaak later klaar is) kan er nog een 1389 // vraag aan toevoegen. msgState/aiExtraVragen zijn losse variabelen zodat het 1390 // niet uitmaakt welke van de twee als eerste klaar is. 1391 let msgState = null; 1392 let aiExtraVragen = []; 1393 // Voedt de "Delen"-knoppen onderaan (WhatsApp/e-mail/kopieer link, 28-9-2026), 1394 // zelfde soort losse state-object als msgState hierboven: gevuld zodra de 1395 // analyse klaar is, de knoppen zelf lezen 'm pas bij een klik. 1396 let shareState = null; 1397 function buildBericht(state) { 1398 const vragen = state.vragen.concat(aiExtraVragen); 1399 return 'Beste verkoper,\n\nIk heb serieuze interesse in de ' + (state.vName || 'auto') + ' met kenteken ' + fmtPlate(state.plate) 1400 + (state.price ? ' die u aanbiedt voor ' + eur(state.price) : '') + '. Voordat ik langskom heb ik een paar vragen:\n\n' 1401 + vragen.map((q) => '- ' + q).join('\n') 1402 + '\n\nDaarnaast wil ik graag een proefrit maken met een koude motor. Wanneer schikt het om te komen kijken?\n\nMet vriendelijke groet'; 1403 } 1404 function renderBericht() { 1405 if (!msgState) return; 1406 const bericht = buildBericht(msgState); 1407 $('oc-message').textContent = bericht; 1408 $('oc-msg-copy').onclick = () => { 1409 navigator.clipboard.writeText(bericht).then(() => { $('oc-msg-copy').textContent = 'Gekopieerd'; setTimeout(() => { $('oc-msg-copy').textContent = 'Kopieer bericht'; }, 1600); }); 1410 }; 1411 } 1412 1413 async function runPhotoScan(url, kenteken) { 1414 aiExtraVragen = []; 1415 const box = $('oc-ai-photocheck'); 1416 box.innerHTML = '<p class="oc-ai-badge">AI-fotoscan (beta)</p>' + 1417 '<p class="hint" style="margin-bottom:.8rem">Foto\'s worden gecontroleerd op zichtbare schade en roestâ¦</p>' + 1418 skeletonRows(2); 1419 // Ook een placeholder in de Bevindingen-lijst, zodat direct duidelijk is 1420 // dat de AI-fotoscan nog loopt en er zo aandachtspunten bij kunnen komen. 1421 $('oc-flags-ai').innerHTML = skeletonRows(1); 1422 try { 1423 const r = await PS.api('/occasion/photoscan', 'POST', { url, kenteken }); 1424 const d = r.data || {}; 1425 if (!r.ok || !d.scanned) { 1426 // Altijd een reden tonen (29-9-2026, bugmelding Stephan: "ik zie geen 1427 // AI-antwoord"), niet alleen bij een quotum-melding. Zonder dit werd 1428 // het vak stil leeggemaakt bij elke andere non-scan-reden (geen foto's 1429 // gevonden, advertentie nog niet opgehaald, feature uitgeschakeld), 1430 // wat leek alsof er niets gebeurde. 1431 const cta = (d.rateLimited && !d.loggedIn) ? ' <a href="/voordelen">Log in voor 5 scans per uur</a>.' : ''; 1432 box.innerHTML = '<p class="oc-ai-badge">AI-fotoscan (beta)</p><p class="hint">' + esc(d.reason || 'De AI-fotoscan kon nu niet worden uitgevoerd.') + cta + '</p>'; 1433 $('oc-flags-ai').innerHTML = ''; 1434 return; 1435 } 1436 const items = Array.isArray(d.bevindingen) ? d.bevindingen : []; 1437 const photos = Array.isArray(d.photos) ? d.photos : []; 1438 let html = '<p class="oc-ai-badge">AI-fotoscan (beta)</p>'; 1439 if (d.geen_zichtbare_problemen || !items.length) { 1440 const okText = esc(d.samenvatting || 'De AI-scan van de advertentiefoto\'s zag geen duidelijke schade, roest of kleurverschil.'); 1441 html += '<div class="oc-flag green"><span class="fdot"></span><div><strong>Geen duidelijke problemen zichtbaar</strong><p>' + okText + '</p></div></div>'; 1442 $('oc-flags-ai').innerHTML = '<div class="oc-flag green"><span class="fdot"></span><div><strong>AI-fotoscan: geen duidelijke problemen zichtbaar</strong><p>' + okText + '</p></div></div>'; 1443 } else { 1444 html += items.map((it) => aiFlagRow(it, photos, null)).join(''); 1445 if (d.samenvatting) html += '<p class="hint" style="margin-top:.5rem">' + esc(d.samenvatting) + '</p>'; 1446 // Zelfde bevindingen ook in de Bevindingen-kaart, met "AI-fotoscan" in de 1447 // titel zodat duidelijk is dat dit uit de foto's komt en niet uit RDW-data. 1448 $('oc-flags-ai').innerHTML = items.map((it) => aiFlagRow(it, photos, 'AI-fotoscan')).join(''); 1449 // Ook een vraag toevoegen aan het bericht aan de verkoper. 1450 const samenvattingClean = (d.samenvatting || 'mogelijke aandachtspunten').replace(/\.+$/, ''); 1451 aiExtraVragen = ['Onze AI-fotoscan van de advertentiefoto\'s signaleerde
1451: ' + samenvattingClean + '. Kunt u dit toelichten, en eventueel scherpe foto\'s van dichtbij delen?']; 1452 renderBericht(); 1453 } 1454 html += '<p class="hint" style="margin-top:.6rem">Geautomatiseerde AI-beoordeling op basis van de advertentiefoto\'s; geen vervanging voor een fysieke inspectie of keuring.</p>'; 1455 box.innerHTML = html; 1456 } catch (e) { 1457 box.innerHTML = '<p class="oc-ai-badge">AI-fotoscan (beta)</p><p class="hint">De AI-fotoscan kon nu niet worden uitgevoerd. Probeer het later opnieuw.</p>'; 1458 $('oc-flags-ai').innerHTML = ''; 1459 } 1460 } 1461 $('oc-fetch').addEventListener('click', fetchAd); 1462 1463 // Zelfde scrollIntoView-patroon als de deeplink-flow hieronder gebruikt 1464 // (?kenteken= zonder prijs): naar het handmatige invoerblok scrollen en 1465 // meteen het kenteken-veld focussen, verzoek Stephan 14-9-2026. 1466 $('oc-alt-link').addEventListener('click', () => { 1467 $('oc-manual-card').scrollIntoView({ behavior: 'smooth', block: 'center' }); 1468 $('oc-plate').focus(); 1469 }); 1470 1471 // Alleen hier loggen (niet in runAnalysis() zelf): de advertentie-route via 1472 // fetchAd() roept runAnalysis() intern aan en logt al server-side in 1473 // POST /occasion/fetch. Deze knop is de kenteken-only route, die de server 1474 // verder nooit raakt, dus die heeft een eigen client-side logregel nodig. 1475 $('oc-run').addEventListener('click', () => { 1476 const plate = clean($('oc-plate').value); 1477 if (plate.length >= 4) PS.api('/tool-usage', 'POST', { tool: 'occasion-check', kenteken: plate }).catch(() => {}); 1478 runAnalysis(); 1479 }); 1480 1481 async function rdw(url) { const r = await fetch(url); return r.json(); } 1482 1483 // Echte advertentiefoto's bovenaan het rapport (26-9-2026, Stephan: "net als 1484 // de kenteken check"). Hergebruikt het bestaande, publieke GET /listings- 1485 // endpoint (al gebruikt door het kentekenrapport zelf voor de 1486 // Advertentiegeschiedenis-sectie), puur kenteken-gebaseerd: werkt dus ook 1487 // in het handmatige pad (geen link geplakt), zolang er ooit een advertentie 1488 // voor dit kenteken is gearchiveerd. Geen foto's gevonden: de strook blijft 1489 // gewoon leeg, geen foutmelding (evenmin een fallback naar generieke 1490 // fabrieksrenders, dat is bewust een ander soort visual dan dit rapport, 1491 // dat over één specifieke advertentie gaat). 1492 async function loadReportPhotos(plate) { 1493 const strip = $('oc-photo-strip'); 1494 strip.innerHTML = ''; 1495 // Eén automatische herhaalpoging (26-9-2026): deze aanroep loopt vaak 1496 // gelijktijdig met een stuk of wat andere verzoeken die dezelfde paginalaad 1497 // afvuurt (csrf/tool-usage/auth-me/announce/etc.), wat lokaal soms een 1498 // voorbijgaande "database is locked" geeft (bekend SQLite-gedrag onder 1499 // gelijktijdige belasting, zie CLAUDE.md); zonder retry blijft de strook dan 1500 // stil leeg terwijl de foto's er wel degelijk zijn. 1501 for (let attempt = 0; attempt < 2; attempt++) { 1502 try { 1503 const r = await fetch('/api/listings?kenteken=' + encodeURIComponent(plate)); 1504 if (!r.ok) throw new Error('http ' + r.status); 1505 const d = await r.json(); 1506 const listing = (d.listings || [])[0]; 1507 const photos = listing && Array.isArray(listing.photos) ? listing.photos : []; 1508 strip.innerHTML = photos.map((p, i) => 1509 '<img class="oc-flag-photo" src="' + p.url + '" alt="Advertentiefoto ' + (i + 1) + '" loading="' + (i === 0 ? 'eager' : 'lazy') + '" role="button" tabindex="0">' 1510 ).join(''); 1511 return; 1512 } catch (e) { 1513 if (attempt === 0) await new Promise((res) => setTimeout(res, 500)); 1514 // Tweede poging ook mislukt: strook blijft stil leeg, geen foutmelding 1515 // (zelfde eerlijke "geen foto's gevonden"-gedrag als voorheen). 1516 } 1517 } 1518 } 1519 1520 // ââ Maandlasten-kostenmodel, verbatim overgenomen uit autokosten.astro 1521 // (calcCosts + de MRB-helperketen, Wet MRB 2026). Dit is bewust een
1522 // zevende plek naast de al bestaande zes (zie CLAUDE.md); bij een 1523 // jaarwissel ALLE plekken bijwerken. `vehicleAge` hergebruikt de al 1524 // bestaande `pd()`-datumparser hierboven i.p.v. een eigen parseDate. ââ 1525 function vehicleAge(s) { 1526 const d = pd(s); 1527 if (!d) return null; 1528 return Math.max(0, (Date.now() - d.getTime()) / (365.25 * 24 * 3600 * 1000)); 1529 } 1530 const OC_MRB_OPCENTEN_2026 = { 1531 'Groningen': 95.7, 'Friesland': 92.1, 'Drenthe': 92.0, 'Overijssel': 82.2, 1532 'Flevoland': 84.7, 'Gelderland': 98.3, 'Utrecht': 86.4, 'Noord-Holland': 82.1, 1533 'Zuid-Holland': 104.4, 'Zeeland': 84.4, 'Noord-Brabant': 87.0, 'Limburg': 88.5 1534 }; 1535 function mrbWeight(v) { 1536 const m = v.massa_ledig_voertuig ? parseInt(v.massa_ledig_voertuig) : (v.massa_rijklaar ? parseInt(v.massa_rijklaar) - 100 : null); 1537 if (!m || m < 0) return null; 1538 const w = 100 * Math.floor((m + 49) / 100); 1539 return Math.max(500, w); 1540 } 1541 function mrbRijksdeel(w) { 1542 if (w <= 500) return 21.46; 1543 if (w === 600) return 29.12; 1544 if (w === 700) return 37.00; 1545 if (w === 800) return 48.30; 1546 if (w <= 3200) return 64.24 + ((w - 900) / 100) * 17.27; 1547 return 474.12 + ((w - 3300) / 100) * 12.00; 1548 } 1549 function mrbBrandstofToeslag(w, soort) { 1550 if (soort === 'diesel') { 1551 if (w <= 500) return 84.14; 1552 if (w === 600) return 99.59; 1553 if (w === 700) return 115.03; 1554 if (w === 800) return 130.76; 1555 return 153.00 + ((w - 900) / 100) * 16.57; 1556 } 1557 if (soort === 'lpg') { 1558 if (w <= 500) return 98.71; 1559 if (w === 600) return 118.32; 1560 if (w === 700) return 137.95; 1561 if (w === 800) return 157.54; 1562 return 172.08 + ((w - 900) / 100) * 18.22; 1563 } 1564 if (soort === 'cng') { 1565 if (w <= 800) return 0; 1566 return 19.05 + ((w - 900) / 100) * 19.05; 1567 } 1568 return 0; 1569 } 1570 function mrbOpcentenGrondslagYear(w) { 1571 const T = { 500: 57.99, 600: 69.34, 700: 81.59, 800: 107.91, 900: 136.50, 1000: 183.24, 1100: 229.98, 1200: 276.72, 1300: 323.45, 1400: 370.19, 1500: 416.93, 1600: 463.67 }; 1572 if (T[w] !== undefined) return T[w]; 1573 if (w < 500) return 57.99; 1574 return Math.min(1398.48, 463.67 + ((w - 1600) / 100) * 46.74); 1575 } 1576 function mrbFuelKind(fuel) { 1577 const t = (fuel.brandstof_omschrijving || '').toUpperCase(); 1578 const hybridClass = (fuel.klasse_hybride_elektrisch_voertuig || '').toUpperCase(); 1579 const hasCombustion = t.indexOf('BENZINE') > -1 || t.indexOf('DIESEL') > -1 || t.indexOf('LPG') > -1 || t.indexOf('CNG') > -1 || t.indexOf('GAS') > -1 || t.indexOf('ALCOHOL') > -1; 1580 const isPureElectric = (t.indexOf('ELEKTR') > -1 || t.indexOf('WATERSTOF') > -1) && !hasCombustion; 1581 if (isPureElectric && !hybridClass) return { vrijgesteld: true }; 1582 if (t.indexOf('DIESEL') > -1) return { soort: 'diesel' }; 1583 if (t.indexOf('CNG') > -1 || t.indexOf('AARDGAS') > -1) return { soort: 'cng' }; 1584 if (t.indexOf('LPG') > -1 || t.indexOf('GAS') > -1) return { soort: 'lpg' }; 1585 return { soort: 'benzine' }; 1586 } 1587 function mrbQuarterly(w, kind, det, opcentenPct) { 1588 let rijk = mrbRijksdeel(w) + mrbBrandstofToeslag(w, kind.soort); 1589 const detYear = det ? det.getFullYear() : null; 1590 if (kind.soort === 'diesel' && detYear && detYear < 2011) rijk *= 1.19; 1591 const grondslagKwartaal = mrbOpcentenGrondslagYear(w) / 4; 1592 const opcenten = grondslagKwartaal * (opcentenPct / 100); 1593 return Math.round((rijk + opcenten) * 100) / 100; 1594 } 1595 function estimateRoadTax(v, fuel) { 1596 const w = mrbWeight(v); 1597 if (!w) return null; 1598 const kind = mrbFuelKind(fuel); 1599 if (kind.vrijgesteld) return 0; 1600 const pcts = Object.keys(OC_MRB_OPCENTEN_2026).map((k) => OC_MRB_OPCENTEN_2026[k]); 1601 const avg = pcts.reduce((s, p) => s + p, 0) / pcts.length; 1602 const det = pd(v.datum_eerste_toelating); 1603 return Math.round(mrbQuarterly(w, kind, det, avg)); 1604 } 1605 // isElectric() = zelfde check als isFullyElectric hieronder in calcCosts(), 1606 // hier apart beschikbaar zodat het schuifje-label/eenheid en de kosten- 1607 // berekening nooit uit elkaar kunnen lopen (bug 29-9-2026: een hybride met 1608 // "Elektriciteit" als eerste brandstofregel liet het label "Stroomprijs" 1609 // met â¬/L zien, terwijl calcCosts 'm terecht als benzine doorrekende omdat 1610 // de hybridClass-uitzondering hier ontbrak). Identiek aan autokosten.astro. 1611 function isElectric(fuel) { 1612 const t = (fuel.brandstof_omschrijving || '').toUpperCase(); 1613 const hc = (fuel.klasse_hybride_elektrisch_voertuig || '').toUpperCase(); 1614 const comb = t.indexOf('BENZINE') > -1 || t.indexOf('DIESEL') > -1; 1615 return t.indexOf('ELEKTR') > -1 && !comb && !hc; 1616 } 1617 function setCostFuelSlider(fuel) { 1618 const s = $('oc-cost-fuel'); 1619 if (isElectric(fuel)) { 1620 s.min = '0.20'; s.max = '0.50'; s.step = '0.01'; s.value = '0.30'; 1621 } else if ((fuel.brandstof_omschrijving || '').toUpperCase().indexOf('DIESEL') > -1) { 1622 s.min = '1.30'; s.max = '2.20'; s.step = '0.01'; s.value = '1.85'; 1623 } else { 1624 s.min = '1.50'; s.max = '2.60'; s.step = '0.01'; s.value = '2.10'; 1625 } 1626 } 1627 function calcCosts(v, fuel, opts) { 1628 const costs = []; 1629 const weight = v.massa_rijklaar ? parseInt(v.massa_rijklaar) : 1200; 1630 const fuelType = (fuel.brandstof_omschrijving || '').toUpperCase(); 1631 const hybridClass = (fuel.klasse_hybride_elektrisch_voertuig || '').toUpperCase(); 1632 const hasCombustion = fuelType.indexOf('BENZINE') > -1 || fuelType.indexOf('DIESEL') > -1; 1633 const isPureElectric = fuelType.indexOf('ELEKTR') > -1 && !hasCombustion; 1634 const isFullyElectric = isPureElectric && !hybridClass; 1635 const isDiesel = fuelType.indexOf('DIESEL') > -1; 1636 const consumption = fuel.brandstofverbruik_gecombineerd ? parseFloat(fuel.brandstofverbruik_gecombineerd) : null; 1637 const age = vehicleAge(v.datum_eerste_toelating) || 3; 1638 const catPrice = v.catalogusprijs ? parseInt(v.catalogusprijs) : 20000;
1639 const kmPerMaand = opts.kmPerJaar / 12; 1640 1641 if (isFullyElectric) { 1642 const kwh = consumption || 18; 1643 costs.push({ label: 'Energie (stroom)', amount: Math.round(kwh / 100 * kmPerMaand * opts.fuelPrice) }); 1644 } else { 1645 const lPer100 = consumption || (isDiesel ? 5.5 : 7.0); 1646 costs.push({ label: 'Brandstof', amount: Math.round(lPer100 / 100 * kmPerMaand * opts.fuelPrice) }); 1647 } 1648 1649 const taxQ = estimateRoadTax(v, fuel); 1650 costs.push({ label: 'Wegenbelasting', amount: taxQ !== null ? Math.round(taxQ / 3) : 0 }); 1651 1652 let insurance; 1653 if (catPrice > 50000) insurance = 140; 1654 else if (catPrice > 30000) insurance = 105; 1655 else if (catPrice > 20000) insurance = 85; 1656 else if (catPrice > 10000) insurance = 65; 1657 else insurance = 50; 1658 if (isDiesel) insurance = Math.round(insurance * 1.1); 1659 if (opts.driverAge < 24) insurance = Math.round(insurance * 1.55); 1660 else if (opts.driverAge < 28) insurance = Math.round(insurance * 1.25); 1661 else if (opts.driverAge < 35) insurance = Math.round(insurance * 1.08); 1662 else if (opts.driverAge > 65) insurance = Math.round(insurance * 1.12); 1663 costs.push({ label: 'Verzekering', amount: insurance }); 1664 1665 const premium = ['BMW', 'AUDI', 'MERCEDES-BENZ', 'VOLVO', 'PORSCHE', 'JAGUAR', 'LAND ROVER', 'LEXUS', 'MASERATI', 'ALFA ROMEO']; 1666 const isPremium = premium.indexOf((v.merk || '').toUpperCase()) > -1; 1667 let maintenance; 1668 if (isFullyElectric) maintenance = isPremium ? 60 : 35; 1669 else if (isPremium) maintenance = age > 5 ? 120 : 85; 1670 else maintenance = age > 5 ? 75 : 50; 1671 if (opts.kmPerJaar > 25000) maintenance = Math.round(maintenance * 1.2); 1672 costs.push({ label: 'Onderhoud', amount: maintenance }); 1673 1674 let tires = isFullyElectric ? 25 : 18; 1675 if (weight > 1800) tires += 8; 1676 if (opts.kmPerJaar > 25000) tires = Math.round(tires * 1.3); 1677 costs.push({ label: 'Banden', amount: tires }); 1678 1679 if (age < 10) { 1680 const depRate = age < 3 ? 0.12 : (age < 6 ? 0.08 : 0.05); 1681 const dep = Math.min(Math.round(catPrice * depRate / 12), 500); 1682 if (dep > 0) costs.push({ label: 'Afschrijving', amount: dep }); 1683 } 1684 return costs; 1685 } 1686 1687 // State voor de Maandlasten-kaart: opgeslagen zodat de sliders live kunnen 1688 // herberekenen zonder de RDW-data opnieuw op te halen. 1689 let ocCostsState = null; 1690 function renderCostsCard() { 1691 if (!ocCostsState) return; 1692 const { v, fuel } = ocCostsState; 1693 const kmPerJaar = parseInt($('oc-cost-km').value, 10); 1694 const fuelPrice = parseFloat($('oc-cost-fuel').value); 1695 const driverAge = parseInt($('oc-cost-age').value, 10); 1696 $('oc-cost-km-val').textContent = kmPerJaar.toLocaleString('nl-NL') + ' km'; 1697 const elec = isElectric(fuel); 1698 const fuelLabel = elec ? 'Stroomprijs' : ((fuel.brandstof_omschrijving || '').toUpperCase().indexOf('DIESEL') > -1 ? 'Dieselprijs' : 'Brandstofprijs'); 1699 $('oc-cost-fuel-label').textContent = fuelLabel; 1700 $('oc-cost-fuel-val').textContent = '⬠' + fuelPrice.toFixed(2).replace('.', ',') + (elec ? '/kWh' : '/L'); 1701 $('oc-cost-age-val').textContent = driverAge + ' jaar'; 1702 1703 const costs = calcCosts(v, fuel, { kmPerJaar, fuelPrice, driverAge }); 1704 const total = costs.reduce((s, c) => s + c.amount, 0); 1705 const perKm = kmPerJaar > 0 ? (total * 12 / kmPerJaar) : 0; 1706 let html = costs.map((c) => '<div class="info-row"><span class="lbl">' + c.label + '</span><span class="val">' + eur(c.amount) + '</span></div>').join(''); 1707 html += '<div class="info-row oc-bid"><span class="lbl">Totaal per maand</span><span class="val">' + eur(total) + '</span></div>'; 1708 html += '<div class="info-row"><span class="lbl">Kosten per kilometer</span><span class="val">⬠' + perKm.toFixed(2).replace('.', ',') + '</span></div>'; 1709 html += '<p class="hint" style="margin-top:.6rem">Indicatie op basis van RDW-gegevens en gemiddelde tarieven. Werkelijke kosten hangen af van je rijstijl, verzekeraar, dealer en woonprovincie. Financiering of lease zit hier niet in.</p>'; 1710 $('oc-costs-block').innerHTML = html; 1711 } 1712 ['oc-cost-km', 'oc-cost-fuel', 'oc-cost-age'].forEach((id) => { 1713 $(id).addEventListener('input', renderCostsCard); 1714 }); 1715
1716 async function runAnalysis() { 1717 const plate = clean($('oc-plate').value); 1718 const price = parseInt($('oc-price').value, 10) || null; 1719 const km = parseInt($('oc-km').value, 10) || null; 1720 if (plate.length < 4) { $('oc-status').textContent = 'Vul een geldig kenteken in.'; return; } 1721 $('oc-run').disabled = true; 1722 // Idempotent: fetchAd() kan report-mode al hebben geopend (advertentie-pad), 1723 // deze knop-only-route (handmatig kenteken) opent 'm hier voor het eerst. 1724 ocEnterReportMode('RDW-gegevens ophalen en analyserenâ¦'); 1725 let v = null, fuel = null; 1726 try { 1727 const vr = await rdw('https://opendata.rdw.nl/resource/m9d7-ebf2.json?kenteken=' + plate); 1728 v = vr && vr[0]; 1729 const fr = await rdw('https://opendata.rdw.nl/resource/8ys7-d773.json?kenteken=' + plate + '&$limit=1'); 1730 fuel = fr && fr[0]; 1731 } catch (e) {} 1732 $('oc-run').disabled = false; 1733 if (!v) { ocExitReportMode(); $('oc-status').textContent = 'Kenteken niet gevonden in de RDW-database.'; return; } 1734 $('oc-status').textContent = ''; 1735 1736 // Carrosserie + transmissie (29-9-2026, n.a.v. concurrentie-check): 1737 // zelfde databronnen als de hoofd-kentekencheck (ps-report-extra.js 1738 // renderSpecs/plate-search.js), hier los opgehaald voor de 1739 // advertentiegegevens-regel. Best-effort: een lege/mislukte fetch 1740 // laat de rest van het rapport ongemoeid. 1741 let carrosserieType = null, transmissieType = null; 1742 try { 1743 const cr = await rdw('https://opendata.rdw.nl/resource/vezc-m2t6.json?kenteken=' + plate); 1744 carrosserieType = cr && cr[0] && cr[0].type_carrosserie_europese_omschrijving || null; 1745 if (v.typegoedkeuringsnummer && v.variant && v.uitvoering) { 1746 const tgkWhere = "typegoedkeuringsnummer='" + v.typegoedkeuringsnummer.replace(/'/g, "''") + "' AND codevarianttgk='" + v.variant.replace(/'/g, "''") + "' AND codeuitvoeringtgk='" + v.uitvoering.replace(/'/g, "''") + "'"; 1747 const tr = await rdw('https://opendata.rdw.nl/resource/7rjk-eycs.json?$where=' + encodeURIComponent(tgkWhere)); 1748 const versn = tr && tr[0]; 1749 if (versn) { 1750 const bakType = { M: 'Handgeschakeld', A: 'Automaat', C: 'CVT (traploos)' }[versn.codetypeversnellingsbak] || versn.codetypeversnellingsbak; 1751 transmissieType = bakType || null; 1752 } 1753 } 1754 } catch (e) {} 1755 1756 // URL bijwerken met de analyse-parameters (28-9-2026): zonder dit zou de 1757 // nieuwe "Delen"-sectie (window.location.href) bij een handmatig ingevoerde 1758 // analyse een kale /occasion-check-link delen die het rapport niet meer 1759 // reproduceert. Zelfde parameternamen als de deeplink-IIFE hieronder leest 1760 // (kenteken/prijs/km), dus een gedeelde link opent de analyse weer identiek. 1761 const shareParams = new URLSearchParams(); 1762 shareParams.set('kenteken', plate); 1763 if (price) shareParams.set('prijs', String(price)); 1764 if (km) shareParams.set('km', String(km)); 1765 history.replaceState(null, '', location.pathname + '?' + shareParams.toString()); 1766 1767 $('oc-plate-chip-text').textContent = fmtPlate(plate); 1768 setNavPlate(fmtPlate(plate)); 1769 loadReportPhotos(plate); 1770 // Handmatig pad (geen advertentielink, of de extensie-terugval na een 1771 // geblokkeerde uitlees): runPhotoScan() wordt dan nooit aangeroepen, dus 1772 // zonder dit bleef de AI-fotoscan-kaart stil leeg (zelfde bugmelding als 1773 // hierboven bij fetchAd(), "zijn de credits op? of zit er een fout?"). 1774 // Check op een nog LEEG vak i.p.v. op oc-url.value: fetchAd() heeft er op 1775 // dit punt (synchroon, vóór de eerste await in runPhotoScan()) al ofwel de 1776 // laadskeleton ofwel een eigen boodschap in gezet, dus deze check 1777 // overschrijft die gevallen niet en vangt alleen de gevallen waarin nog 1778 // niets is gezet. 1779 if (!$('oc-ai-photocheck').innerHTML.trim()) { 1780 $('oc-ai-photocheck').innerHTML = $('oc-url').value 1781 ? '<p class="oc-ai-badge">AI-fotoscan (beta)</p><p class="hint">
1781De advertentie kon niet automatisch worden uitgelezen, dus er kon geen AI-fotoscan worden uitgevoerd.</p>' 1782 : '<p class="oc-ai-badge">AI-fotoscan (beta)</p><p class="hint">Plak de advertentielink bovenaan voor een AI-fotoscan van de foto\'s.</p>'; 1783 } 1784 1785 const today = new Date(); 1786 const flags = []; // {sev: red|orange|green, title, text, script, impact} 1787 let score = 100; 1788 1789 // APK 1790 const apk = pd(v.vervaldatum_apk); 1791 if (!apk) { flags.push({ sev: 'orange', cat: 'rdw', title: 'Geen APK-datum bekend', text: 'Mogelijk een nieuw of bijzonder voertuig. Vraag ernaar.', script: null, impact: -5 }); score -= 5; } 1792 else { 1793 const days = Math.round((apk - today) / 86400000); 1794 if (days < 0) { flags.push({ sev: 'red', cat: 'rdw', title: 'APK is verlopen (' + fmtD(apk) + ')', text: 'Met een verlopen APK mag de auto de weg niet op.', script: 'De APK is verlopen op ' + fmtD(apk) + '. Ik wil dat de auto met verse APK geleverd wordt, of ik verreken de keuring en eventuele reparatiepunten in de prijs.', impact: -25 }); score -= 25; } 1795 else if (days <= 60) { flags.push({ sev: 'orange', cat: 'rdw', title: 'APK verloopt binnenkort (' + fmtD(apk) + ', nog ' + days + ' dagen)', text: 'Een keuring kost 30 tot 70 euro plus eventuele reparatiepunten.', script: 'De APK verloopt al over ' + days + ' dagen. Ik wil levering met nieuwe APK, of een korting voor de keuring en mogelijke reparatiepunten.', impact: -8 }); score -= 8; } 1796 else { flags.push({ sev: 'green', cat: 'rdw', title: 'APK geldig tot ' + fmtD(apk), text: 'Ruim geldig.', script: null, impact: 0 }); } 1797 } 1798 // WOK (tolerante veldnaam) 1799 const wok = (v.wacht_op_keuren || v.wok_status || '').toString(); 1800 if (/^ja$/i.test(wok)) { flags.push({ sev: 'red', cat: 'rdw', title: 'WOK-melding (Wachten Op Keuren)', text: 'De auto mag de weg niet op tot een RDW-herkeuring. Vaak na schade.', script: 'Er staat een WOK-melding geregistreerd. Zolang die niet is opgeheven na RDW-herkeuring is de auto voor mij hooguit interessant tegen een fors lagere prijs.', impact: -35 }); score -= 35; } 1801 // Tellerstand (toelichting: RDW-dataset jqs4-4kvw, zie TELLER_TOELICHTING hierboven) 1802 const teller = (v.tellerstandoordeel || '').toString(); 1803 const tellerUitleg = tellerToelichting(v.code_toelichting_tellerstandoordeel); 1804 if (/onlogisch/i.test(teller)) { flags.push({ sev: 'red', cat: 'rdw', title: 'Tellerstandoordeel: onlogisch', text: tellerUitleg || 'De geregistreerde kilometerstanden zijn niet logisch verklaarbaar.', script: 'Het NAP-tellerstandoordeel is "onlogisch". Zonder sluitende verklaring met documentatie is dat een serieuze waardedrukker; daar moet de prijs op aangepast worden.', impact: -30 }); score -= 30; } 1805 else if (/logisch/i.test(teller)) { flags.push({ sev: 'green', cat: 'rdw', title: 'Tellerstandoordeel: logisch', text: 'De kilometerhistorie is logisch verklaarbaar volgens de RDW.', script: null, impact: 0 }); } 1806 else if (teller) { flags.push({ sev: 'orange', cat: 'rdw', title: 'Tellerstandoordeel: ' + teller, text: tellerUitleg || 'De RDW geeft voor dit voertuig geen eenduidig logisch/onlogisch-oordeel.', script: null, impact: 0 }); } 1807 // Terugroepactie 1808 if (/^ja$/i.test((v.openstaande_terugroepactie_indicator || '').toString())) { 1809 flags.push({ sev: 'orange', cat: 'rdw', title: 'Openstaande terugroepactie', text: 'Er staat een recall open. Herstel is gratis bij de dealer, maar moet wel gebeuren.', script: 'Er staat een terugroepactie open. Ik wil dat die aantoonbaar is uitgevoerd voor de overdracht.', impact: -10 }); 1810 score -= 10; 1811 } 1812 // Import 1813 const det = pd(v.datum_eerste_toelating); 1814 const detNl = pd(v.datum_eerste_tenaamstelling_in_nederland); 1815 if (det && detNl && (detNl - det) > 180 * 86400000) { 1816 flags.push({ sev: 'orange', cat: 'rdw', title: 'Importvoertuig', text: 'Eerste toelating (' + fmtD(det) + ') ligt ruim voor de eerste Nederlandse registratie (' + fmtD(detNl) + ').', script: 'De auto is geimporteerd. Ik wil de buitenlandse historie en onderhoudsdocumentatie zien; zonder die papieren hoort dat in de prijs verwerkt te zijn.', impact: -4 }); 1817 score -= 4; 1818 } 1819 // Kort in bezit / stabiel in bezit. "Aantal eigenaren" is bewust NIET 1820 // toegevoegd: dat veld bestaat niet in de gratis RDW Open Data (zelf 1821 // geverifieerd op de live API, 30-8-2026), alleen de tenaamstellingsdatum 1822 // die hieronder al gebruikt wordt. Een volledige eigenarenhistorie zou via 1823 // een betaalde bron (RDC/VWE) moeten, dat is een apart, later traject. 1824 const ten = pd(v.datum_tenaamstelling); 1825 if (ten && (today - ten) < 90 * 86400000) { 1826 flags.push({ sev: 'orange', cat: 'rdw', title: 'Kort in bezit (tenaamstelling ' + fmtD(ten) + ')', text: 'De huidige eigenaar heeft de auto minder dan drie maanden. Vraag wa
1826arom hij alweer weg moet.', script: 'De auto staat pas sinds ' + fmtD(ten) + ' op naam. Waarom wordt hij zo snel weer verkocht?', impact: -8 }); 1827 score -= 8; 1828 } else if (ten && (today - ten) > 2 * 365.25 * 86400000) { 1829 const jaren = Math.floor((today - ten) / (365.25 * 86400000)); 1830 flags.push({ sev: 'green', cat: 'rdw', title: 'Stabiel in bezit (ruim ' + jaren + ' jaar op naam)', text: 'De huidige eigenaar heeft de auto al ruim ' + jaren + ' jaar op naam. Dat is doorgaans een goed teken; een auto die snel weer verkocht wordt, wordt vaker om die reden bekeken.', script: null, impact: 0 }); 1831 } 1832 // Eigenaarschap-kaart: zelfde tenaamstellings-brondata als de vlag 1833 // hierboven, prominenter getoond. Bewust geen eigenarenaantal (zie 1834 // de toelichting bij de vlag). 1835 if (ten) { 1836 const dagen = Math.floor((today - ten) / 86400000); 1837 const jaren = Math.floor(dagen / 365.25); 1838 let duurTxt; 1839 if (dagen < 90) duurTxt = 'nog maar ' + dagen + ' dagen'; 1840 else if (jaren < 1) duurTxt = 'ruim ' + Math.floor(dagen / 30.44) + ' maanden'; 1841 else duurTxt = 'ruim ' + jaren + ' jaar'; 1842 let duiding; 1843 if (dagen < 90) duiding = 'Kort bezit is geen dealbreaker, maar vraag altijd waarom de auto zo snel weer te koop staat.'; 1844 else if (jaren >= 2) duiding = 'Een lang bezit is doorgaans een goed teken: de vorige eigenaar had geen haast om ervan af te zijn.'; 1845 else duiding = 'Een gemiddelde bezitsduur, geen bijzonderheid.'; 1846 $('oc-owner-card').hidden = false; 1847 $('oc-owner-block').innerHTML = 1848 '<div class="info-row"><span class="lbl">Op naam sinds</span><span class="val">' + fmtD(ten) + '</span></div>' + 1849 '<div class="info-row"><span class="lbl">Huidige eigenaar in bezit</span><span class="val">' + duurTxt + '</span></div>' + 1850 '<div class="info-row"><span class="lbl">Aantal eigenaren</span><span class="val" style="color:#5f6368">Niet beschikbaar</span></div>' + 1851 '<p class="hint" style="margin-top:.6rem">' + duiding + '</p>' + 1852 '<p class="hint">De RDW-registratie houdt geen totaal-aantal-eigenaren bij, alleen hoe lang de huidige eigenaar de auto al op naam heeft.</p>'; 1853 } else { 1854 $('oc-owner-card').hidden = true; 1855 } 1856 // Ex-taxi 1857 if (/^ja$/i.test((v.taxi_indicator || '').toString())) { 1858 flags.push({ sev: 'orange', cat: 'rdw', title: 'Taxi-verleden', text: 'De auto is (ooit) als taxi geregistreerd: doorgaans intensief gebruikt.', script: 'De auto heeft een taxi-verleden; dat drukt de waarde aanzienlijk.', impact: -12 }); 1859 score -= 12; 1860 } 1861 // WAM 1862 if (/^nee$/i.test((v.wam_verzekerd || '').toString())) { 1863 flags.push({ sev: 'orange', cat: 'rdw', title: 'Niet WAM-verzekerd geregistreerd', text: 'Kan kloppen bij handelaarsvoorraad (dealers verzekeren voorraadwagens vaak pas bij verkoop) of een geschorst kenteken (tijdelijk van de weg, bijvoorbeeld tijdens een langere stalling). Vraag de verkoper naar de reden en controleer de status.', script: null, impact: -3 }); 1864 score -= 3; 1865 } 1866 1867 const cat = parseInt(v.catalogusprijs, 10) || null; 1868 const age = det ? Math.max(0, (today - det) / (365.25 * 86400000)) : null; 1869 const fuelName = (fuel && fuel.brandstof_omschrijving || '').toLowerCase(); 1870 1871 // Kilometrage-normering: km per jaar afgezet tegen wat normaal is voor dit brandstoftype. 1872 let kmYear = null; 1873 if (km && age && age > 0.5) { 1874 kmYear = Math.round(km / age); 1875 let norm = [8000, 14000], type = 'benzineauto'; 1876 if (fuelName.includes('diesel')) { norm = [15000, 25000]; type = 'dieselauto'; } 1877 else if (fuelName.includes('elektr')) { norm = [10000, 20000]; type = 'elektrische auto'; } 1878 else if (fuelName.includes('lpg') || fuelName.includes('cng')) { norm = [15000, 25000]; type = 'auto op ' + fuelName.toUpperCase(); } 1879 const normTxt = norm[0].toLocaleString('nl-NL') + ' tot ' + norm[1].toLocaleStr
1879ing('nl-NL') + ' km per jaar'; 1880 if (kmYear > norm[1] * 1.15) { 1881 flags.push({ sev: 'orange', cat: 'technisch', title: 'Hoge jaarkilometrage: ' + kmYear.toLocaleString('nl-NL') + ' km per jaar', text: 'Meer dan normaal voor een ' + type + ' van deze leeftijd (' + normTxt + '). Meer slijtage aan motor, koppeling en onderstel.', script: 'De auto heeft met ' + kmYear.toLocaleString('nl-NL') + ' km per jaar duidelijk meer gereden dan gemiddeld; ik wil de complete onderhoudshistorie zien en dat hoort in de prijs terug te komen.', impact: -6 }); 1882 score -= 6; 1883 } else if (kmYear < norm[0] * 0.55) { 1884 flags.push({ sev: 'orange', cat: 'technisch', title: 'Opvallend lage jaarkilometrage: ' + kmYear.toLocaleString('nl-NL') + ' km per jaar', text: 'Ver onder het normale bereik (' + normTxt + '). Kan kloppen bij een tweede auto, maar lang stilstaan is ook slecht (banden, remmen, rubbers); controleer of de stand aannemelijk is.', script: null, impact: 0 }); 1885 } else { 1886 flags.push({ sev: 'green', cat: 'technisch', title: 'Kilometrage past bij de leeftijd (' + kmYear.toLocaleString('nl-NL') + ' km per jaar)', text: 'Binnen het normale bereik van ' + normTxt + ' voor een ' + type + '.', script: null, impact: 0 }); 1887 } 1888 } 1889 1890 // Prijsindicatie op basis van catalogusprijs en leeftijd (afschrijvingscurve). 1891 // indic wordt buiten dit blok gehesen zodat de Maandlasten- en 1892 // Inruilwaarde-kaarten verderop 'm kunnen hergebruiken (zelfde anker, 1893 // nooit twee tegenstrijdige particuliere-prijs-getallen op de pagina). 1894 let priceHtml = ''; 1895 let indic = null; 1896 if (cat && age !== null) { 1897 // Afvlakkende afschrijvingscurve: jaar 1 hard, daarna steeds vlakker 1898 // (oude auto's houden restwaarde; een vaste -15% per jaar waardeert een 1899 // auto van 15+ jaar op vrijwel nul en dat klopt niet met de markt). 1900 const fases = [[1, 0.78], [4, 0.89], [10, 0.91], [99, 0.94]]; 1901 let rest = 1, vorige = 0; 1902 for (const [tot, factor] of fases) { 1903 rest *= Math.pow(factor, Math.max(0, Math.min(age, tot) - vorige)); 1904 vorige = tot; 1905 if (age <= tot) break; 1906 } 1907 indic = cat * Math.max(rest, 0.04); 1908 if (km && km > 0 && age > 0) { 1909 const kmPerYear = km / age; 1910 if (kmPerYear > 22000) indic *= 0.9; 1911 else if (kmPerYear < 8000) indic *= 1.05; 1912 } 1913 priceHtml += '<div class="info-row"><span class="lbl">Nieuwprijs (catalogus)</span><span class="val">' + eur(cat) + '</span></div>'; 1914 priceHtml += '<div class="info-row"><span class="lbl">Eerlijke prijsindicatie</span><span class="val">' + eur(indic * 0.85) + ' tot ' + eur(indic * 1.15) + '</span></div>'; 1915 if (price) { 1916 priceHtml += '<div class="info-row"><span class="lbl">Vraagprijs</span><span class="val">' + eur(price) + '</span></div>'; 1917 const diff = Math.round(price - indic); 1918 priceHtml += '<div class="info-row"><span class="lbl">Verschil met de indicatie</span><span class="val" style="color:' + (diff > 0 ? '#a12727' : '#2f5e18') + '">' + (diff > 0 ? '+ ' : '- ') + eur(Math.abs(diff)) + '</span></div>'; 1919 const pct = Math.round((price - indic) / indic * 100); 1920 priceHtml += '<div class="info-row"><span class="lbl">T.o.v. marktwaarde</span><span class="val" style="color:' + (pct > 0 ? '#a12727' : '#2f5e18') + '">' + (pct > 0 ? '+ ' : '- ') + Math.abs(pct) + '%</span></div>'; 1921 setVerdictPct(pct); 1922 if (price > indic * 1.3) { flags.push({ sev: 'orange', cat: 'prijs', title: 'Vraagprijs boven de indicatie', text: 'De vraagprijs ligt duidelijk boven onze afschrijvingsindicatie.', script: 'Op basis van nieuwprijs en leeftijd kom ik op een indicatie van ongeveer ' + eur(indic) + '. De vraagprijs zit daar ruim boven; daar wil ik het over hebben.', impact: -8 }); score -= 8; } 1923 else if (price < indic * 0.5) { flags.push({ sev: 'orange', cat: 'prijs', title: 'Opvallend lage vraagprijs', text: 'Fors onder de indicatie. Kan een koopje zijn, maar wees alert op verborgen gebreken.', script: null, impact: -5 }); score -= 5; } 1924 else { flags.push({ sev: 'green', cat: 'prijs', title: 'Vraagprijs binnen de bandbreedte', text: 'De vraagprijs past bij leeftijd en nieuwprijs.', script: null, impact: 0 }); } 1925 1926 // Concreet openingsbod: laagste van vraagprijs en indicatie, minus een 1927 // korting voor de gevonden aandachtspunten (afgerond op 50 euro). 1928 const reds = flags.filter((f) => f.sev === 'red').length; 1929 const oranges = flags.filter((f) => f.sev === 'orange').length;
1930 const korting = Math.min(0.25, 0.05 + 0.05 * reds + 0.02 * oranges); 1931 const bod = Math.max(250, Math.round((Math.min(price, indic) * (1 - korting)) / 50) * 50); 1932 if (bod < price) { 1933 priceHtml += '<div class="info-row oc-bid"><span class="lbl">Concreet openingsbod</span><span class="val">' + eur(bod) + '</span></div>'; 1934 priceHtml += '<p class="hint" style="margin-top:.5rem">Openingsbod = de laagste van vraagprijs en indicatie, min ' + Math.round(korting * 100) + '% voor de aandachtspunten hierboven. Reken op een eindprijs ergens tussen je openingsbod en de vraagprijs.</p>'; 1935 // Besparingspotentieel (29-9-2026, n.a.v. concurrentie-check): het 1936 // verschil tussen vraagprijs en openingsbod, al berekend hierboven, 1937 // nu ook als los, herkenbaar label. Bewust "tot" en "bij een 1938 // geslaagde onderhandeling" i.p.v. een harde belofte: dit is een 1939 // richtbedrag, geen gegarandeerde besparing. 1940 const besparing = price - bod; 1941 priceHtml += '<div class="info-row oc-bid"><span class="lbl">Besparingspotentieel</span><span class="val" style="color:#2f5e18">tot ' + eur(besparing) + '</span></div>'; 1942 priceHtml += '<p class="hint">Bij een geslaagde onderhandeling naar je openingsbod. Een richtbedrag, geen gegarandeerde besparing.</p>'; 1943 } 1944 } 1945 priceHtml += '<p class="hint" style="margin-top:.6rem">Indicatie op basis van een afschrijvingscurve over de catalogusprijs' + (km ? ' en de kilometerstand' : '') + '. Uitvoering, opties en staat zijn niet meegewogen.</p>'; 1946 } else { 1947 priceHtml = '<p class="hint">Geen catalogusprijs beschikbaar in de RDW-data; prijsindicatie niet mogelijk.' + (price ? ' Vraagprijs: ' + eur(price) + '.' : '') + '</p>'; 1948 } 1949 $('oc-price-block').innerHTML = priceHtml; 1950 1951 // Maandlasten & verzekering: v/fuel zijn hier al bekend, geen nieuwe
1952 // RDW-fetch nodig. Km/jaar-slider start op de al berekende kmYear 1953 // (bekende kilometerstand) i.p.v. het generieke 15.000-default, zodat 1954 // de eerste weergave meteen persoonlijk is. 1955 if (v && fuel) { 1956 ocCostsState = { v, fuel }; 1957 if (kmYear) $('oc-cost-km').value = String(Math.max(5000, Math.min(40000, Math.round(kmYear / 1000) * 1000))); 1958 setCostFuelSlider(fuel); 1959 $('oc-costs-card').hidden = false; 1960 renderCostsCard(); 1961 } else { 1962 ocCostsState = null; 1963 $('oc-costs-card').hidden = true; 1964 } 1965 1966 // Inruilwaarde & dealerprijs: afgeleid van de al gehesen `indic` 1967 // (zelfde ratio's als autowaarde-berekenen.astro), nooit een tweede, 1968 // losse berekening. 1969 if (indic) { 1970 const inruil = Math.round(indic * (0.78 / 0.97) / 100) * 100; 1971 const dealer = Math.round(indic * (1.12 / 0.97) / 100) * 100; 1972 $('oc-tradein-card').hidden = false; 1973 $('oc-tradein-block').innerHTML = 1974 '<div class="info-row"><span class="lbl">Inruilwaarde bij handelaar</span><span class="val">' + eur(inruil) + '</span></div>' + 1975 '<div class="info-row"><span class="lbl">Particuliere verkoopprijs</span><span class="val">' + eur(indic * 0.85) + ' tot ' + eur(indic * 1.15) + '</span></div>' + 1976 '<div class="info-row"><span class="lbl">Dealerprijs (incl. marge)</span><span class="val">' + eur(dealer) + '</span></div>'; 1977 } else { 1978 $('oc-tradein-card').hidden = true; 1979 } 1980 1981 // Score en oordeel 1982 score = Math.max(5, Math.min(100, Math.round(score))); 1983 const dial = $('oc-dial'); 1984 dial.className = 'oc-dial ' + (score >= 75 ? 'g' : score >= 50 ? 'o' : 'r'); 1985 $('oc-score').textContent = score; 1986 const name = [v.merk, v.handelsbenaming].filter(Boolean).join(' '); 1987 $('oc-vehicle').textContent = fmtPlate(plate) + (name ? ' · ' + name : '') + (det ? ' · ' + det.getFullYear() : '') + (fuel && fuel.brandstof_omschrijving ? ' · ' + fuel.brandstof_omschrijving : '') + (transmissieType ? ' · ' + transmissieType : '') + (carrosserieType ? ' · ' + carrosserieType : ''); 1988 $('oc-verdict').textContent = score >= 75 1989 ? 'Weinig aandachtspunten in de officiele registraties. Rijd en keur de auto alsnog voor je koopt.' 1990 : score >= 50 1991 ? 'Er zijn aandachtspunten. Neem de bevindingen hieronder mee in je gesprek en beslissing.' 1992 : 'Serieuze rode vlaggen in de registraties. Wees terughoudend en laat de auto grondig keuren.'; 1993 1994 // Besluit-badge boven de score: eerst het oordeel in gewone taal, dan pas 1995 // het cijfer en de details eronder (zelfde volgorde als concurrenten als 1996 // VoertuigCheck/AutoCheck hanteren, zelf bekeken 30-8-2026). 1997 const verdictBadge = $('oc-verdict-badge'); 1998 if (score >= 75) { verdictBadge.textContent = 'Goede deal'; verdictBadge.className = 'oc-verdict-badge g'; } 1999 else if (score >= 50) { verdictBadge.textContent = 'Kritisch bekijken'; verdictBadge.className = 'oc-verdict-badge o'; } 2000 else { verdictBadge.textContent = 'Afraden'; verdictBadge.className = 'oc-verdict-badge r'; } 2001 2002 function setVerdictPct(pct) { 2003 const el = $('oc-verdict-pct'); 2004 if (!el) return; 2005 el.hidden = false; 2006 el.textContent = (pct > 0 ? '+ ' : '- ') + Math.abs(pct) + '% t.o.v. marktwaarde'; 2007 el.className = 'oc-verdict-pct ' + (pct > 0 ? 'red' : 'green'); 2008 } 2009 2010 // GA4 event 2011 if (typeof gtag === 'function') { 2012 gtag('event', 'occasion_advies_bekeken', { 2013 kenteken: plate, 2014 merk: v.merk || '', 2015 model: v.handelsbenaming || '', 2016 score: score, 2017 oordeel: verdictBadge.textContent, 2018 prijs: price || '', 2019 km: km || '', 2020 }); 2021 } 2022 2023 // Bevindingen 2024 const order = { red: 0, orange: 1, green: 2 }; 2025 flags.sort((a, b) => order[a.sev] - order[b.sev]); 2026 $('oc-flags').innerHTML = flags.map((f) => 2027 '<div class="oc-flag ' + f.sev + '"><span class="fdot"></span><div><strong>' + f.title + '</strong><p>' + f.text + '</p></div></div>' 2028 ).join(''); 2029 2030 // Score-opbouw: exact dezelfde flags/impact die score bepaalden, zodat dit 2031 // nooit uit de pas kan lopen met het getoonde cijfer. 2032 const deductions = flags.filter((f) => f.impact); 2033 const explainRows = deductions.length 2034 ? deductions.map((f) => '<div class="oc-explain-row"><span>' + f.title + '</span><span class="oc-explain-impact">' + f.impact + '</span></div>').join('') 2035 : '<p class="hint">Geen puntenaftrek: alle gecontroleerde RDW-gegevens zagen er netjes uit.</p>'; 2036 $('oc-score-explain').innerHTML = '<div class="oc-explain-row oc-explain-start"><span>Startpunt</span><span>100</span></div>' 2037 + explainRows 2038 + '<div class="oc-explain-row oc-explain-total"><span>AankoopScore</span><span>
2038' + score + '</span></div>' 2039 + '<p class="hint" style="margin-top:.6rem">De score is een optelsom van puntenaftrek op basis van officiele RDW-gegevens (APK, WOK, tellerstandoordeel, terugroepacties, import, kilometrage en prijs). De AI-fotoscan telt hier nog niet in mee, bekijk die apart hieronder.</p>'; 2040 2041 // Onderhandelingsscript 2042 const lines = flags.filter((f) => f.script).map((f) => f.script); 2043 if (!lines.length) lines.push('De registraties zien er netjes uit. Onderhandel op onderhoudshistorie, banden, beurt en leveringsvoorwaarden: vraag om een verse beurt of nieuwe APK bij levering.'); 2044 lines.push('Kunnen we het eens worden als deze punten netjes geregeld of verrekend worden?'); 2045 $('oc-script').innerHTML = '<ul>' + lines.map((l) => '<li>' + l + '</li>').join('') + '</ul>'; 2046 $('oc-copy').onclick = () => { 2047 navigator.clipboard.writeText(lines.map((l) => '- ' + l).join('\n')).then(() => { $('oc-copy').textContent = 'Gekopieerd'; setTimeout(() => { $('oc-copy').textContent = 'Kopieer script'; }, 1600); }); 2048 }; 2049 2050 // Bericht aan de verkoper: interesse + vragen op basis van de bevindingen. 2051 const vragen = []; 2052 const heeft = (t) => flags.some((f) => f.title.indexOf(t) === 0); 2053 if (heeft('Importvoertuig')) vragen.push('Is de buitenlandse onderhoudshistorie aanwezig en in te zien?'); 2054 if (heeft('Openstaande terugroepactie')) vragen.push('Is de openstaande terugroepactie inmiddels uitgevoerd bij de dealer?'); 2055 if (heeft('Kort in bezit')) vragen.push('Wat is de reden dat de auto alweer te koop staat?'); 2056 if (heeft('Hoge jaarkilometrage')) vragen.push('Is de onderhoudshistorie compleet en aantoonbaar (facturen of dealeronderhoud)?'); 2057 if (heeft('APK is verlopen') || heeft('APK verloopt binnenkort')) vragen.push('Wordt de auto met een nieuwe APK geleverd?'); 2058 if (heeft('Tellerstandoordeel: onlogisch')) vragen.push('Hoe verklaart u het onlogische NAP-tellerstandoordeel?'); 2059 vragen.push('Zijn er gebreken, storingen of geplande reparaties die ik moet weten?'); 2060 vragen.push('Is er recent nog onderhoud gedaan (beurt, banden, remmen)?'); 2061 const vName = [v.merk, v.handelsbenaming].filter(Boolean).join(' '); 2062 // AI-fotoscan is vaak nog niet klaar op dit punt; msgState/renderBericht() 2063 // zorgen dat de vraag alsnog wordt toegevoegd zodra die binnenkomt. 2064 msgState = { vName, plate, price, vragen }; 2065 renderBericht(); 2066 shareState = { vName, plate, score, verdictText: verdictBadge.textContent }; 2067 2068 // Vergelijkbaar aanbod: zoeklinks per platform voor merk + model + bouwjaar. 2069 const slug = (s) => (s || '').toLowerCase().trim().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, ''); 2070 const merkS = slug(v.merk), modelS = slug((v.handelsbenaming || '').split(' ')[0]); 2071 const yr = det ? det.getFullYear() : null; 2072 if (merkS && modelS) { 2073 const q = encodeURIComponent(((v.merk || '') + ' ' + (v.handelsbenaming || '').split(' ')[0]).toLowerCase().trim()); 2074 const ext = '<svg width="12" height="12" viewBox="0 0 16 16" fill="none"><path d="M6 3h7v7M13 3 7 9M11 13H3V5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>'; 2075 $('oc-similar').innerHTML = 2076 '<a href="https://www.marktplaats.nl/q/' + q + '/" target="_blank" rel="noopener"><img src="/Marktplaats_logo.svg" alt="Marktplaats" /> ' + ext + '</a>' + 2077 '<a href="https://www.autoscout24.nl/lst/' + merkS + '/' + modelS + (yr ? '?fregfrom=' + (yr - 1) + '&fregto=' + (yr + 1) : '') + '" target="_blank" rel="noopener"><img src="/auto24-logo.svg" alt="AutoScout24" /> ' + ext + '</a>' + 2078 '<a href="https://www.gaspedaal.nl/' + merkS + '/' + modelS + (yr ? '?bmin=' + (yr - 1) + '&bmax=' + (yr + 1) : '') + '" target="_blank" rel="noopener"><span class="oc-gp">Gaspedaal<b>.nl</b></span> ' + ext + '</a>' + 2079 '<a href="https://www.autotrack.nl/occasions/' + merkS + '/' + modelS + '" target="_blank" rel="noopener"><img src="/autotrack-logo.svg" alt="AutoTrack" /> ' + ext + '</a>' + 2080 '<a href="https://www.autoweek.nl/occasions/' + merkS + '/' + modelS + '/" target="_blank" rel="noopener"><img src="/AutoWeek-logo.svg" alt="AutoWeek" /> ' + ext + '</a>'; 2081 } else {
2082 $('oc-similar').innerHTML = '<p class="hint">Geen merk of model bekend voor dit kenteken.</p>'; 2083 } 2084 2085 // Bekende gebreken van dit model: eigen redactionele data (MODEL_DEFECTS_DB), 2086 // niet AI-gegokt. Geen match -> kaart blijft verborgen (hidden-attribuut), 2087 // geen lege/kapotte kaart. Raakt bewust NOOIT flags/score hierboven: puur 2088 // informatief, los van de RDW-gegronde AankoopScore van dit specifieke voertuig. 2089 const modelDefects = findModelDefects(v.merk, v.handelsbenaming); 2090 if (modelDefects && modelDefects.defects.length) { 2091 const costTxt = (d) => { 2092 if (d.costMax === 0) return 'geen vast reparatiebedrag, houd dit in de gaten tijdens onderhoud'; 2093 if (d.costMin === 0) return 'tot ' + eur(d.costMax) + ' (indicatie)'; 2094 return eur(d.costMin) + ' tot ' + eur(d.costMax); 2095 }; 2096 // Geschatte totale reparatiekosten (29-9-2026, n.a.v. concurrentie-check): 2097 // een opgetelde bandbreedte over ALLE bekende aandachtspunten van dit 2098 // model samen. Bewust een WORST-CASE-optelling, geen individuele 2099 // schatting voor déze auto (die kan nul van deze punten hebben); vandaar 2100 // de expliciete disclaimer eronder, zelfde toon als de losse bedragen. 2101 const totalMin = modelDefects.defects.reduce((s, d) => s + d.costMin, 0); 2102 const totalMax = modelDefects.defects.reduce((s, d) => s + d.costMax, 0); 2103 const totalHtml = totalMax > 0 2104 ? '<div class="info-row oc-bid"><span class="lbl">Geschatte reparatiekosten (als alles optreedt)</span><span class="val">' + eur(totalMin) + ' tot ' + eur(totalMax) + '</span></div>' 2105 : ''; 2106 $('oc-model-defects').innerHTML = totalHtml + modelDefects.defects.map((d) => 2107 '<div class="oc-flag ' + esc(d.sev) + '"><span class="fdot"></span><div><strong>' + esc(d.defect) + '</strong>' + 2108 '<p>Indicatie reparatiekosten: ' + costTxt(d) + '</p></div></div>' 2109 ).join(''); 2110 $('oc-model-defects-disclaimer').textContent = 'Dit zijn bekende aandachtspunten voor de ' + (vName || 'dit model') + ' in het algemeen, gebaseerd op onze eigen redactionele problemen-gids. Het zegt niets over de staat van dit specifieke exemplaar: gebruik de AankoopScore en Bevindingen hierboven voor de RDW-gegevens van deze auto. De genoemde kosten (ook het totaal bovenaan) zijn indicatieve bandbreedtes uit de Nederlandse garagepraktijk voor het geval ALLE genoemde punten zich voordoen, geen offerte, taxatie of voorspelling voor dit specifieke exemplaar.'; 2111 $('oc-model-defects-name').textContent = vName || 'dit model'; 2112 $('oc-model-defects-link').href = '/blog/' + esc(modelDefects.slug); 2113 $('oc-model-defects-card').hidden = false; 2114 } else { 2115 $('oc-model-defects-card').hidden = true; 2116 } 2117 2118 // APK-gebrekenhistorie: zelfde bronnen als renderTimeline() in 2119 // plate-search.js. Best-effort, mag nooit de rest van het rapport 2120 // blokkeren; bij een fout of geen keuringen blijft de kaart verborgen. 2121 // lastApkHadDefects (buiten de try gehesen) voedt het Eindadvies-blok 2122 // "Technische conditie" verderop. 2123 let lastApkHadDefects = null; 2124 try { 2125 const keuringenRows = await rdw('https://opendata.rdw.nl/resource/sgfe-77wx.json?kenteken=' + plate + '&$order=meld_datum_door_keuringsinstantie_dt DESC&$limit=50'); 2126 const apkKeuringen = (keuringenRows || []).filter((k) => (k.soort_melding_ki_omschrijving || '').toLowerCase() === 'periodieke controle'); 2127 if (apkKeuringen.length) { 2128 const gebrekenRows = await rdw('https://opendata.rdw.nl/resource/2u8a-sfar.json?kenteken=' + plate + '&$limit=200'); 2129 const gebrekIds = [...new Set((gebrekenRows || []).map((g) => g.gebrek_identificatie).filter(Boolean))]; 2130 let gebrekDescr = {}; 2131 if (gebrekIds.length) { 2132 const where = gebrekIds.map((id) => "'" + id.replace(/'/g, "''") + "'").join(','); 2133 const lookup = await rdw('https://opendata.rdw.nl/resource/hx2
2133c-gt7k.json?$where=' + encodeURIComponent('gebrek_identificatie in(' + where + ')') + '&$limit=400'); 2134 (lookup || []).forEach((l) => { gebrekDescr[l.gebrek_identificatie] = l.gebrek_omschrijving; }); 2135 } 2136 const defectsByDate = {}; 2137 (gebrekenRows || []).forEach((g) => { 2138 const dKey = g.meld_datum_door_keuringsinstantie || ''; 2139 (defectsByDate[dKey] = defectsByDate[dKey] || []).push(gebrekDescr[g.gebrek_identificatie] || ('Gebrek #' + g.gebrek_identificatie)); 2140 }); 2141 const rowsHtml = apkKeuringen.map((k) => { 2142 const defects = defectsByDate[k.meld_datum_door_keuringsinstantie] || []; 2143 const dEl = pd(k.meld_datum_door_keuringsinstantie); 2144 const titel = defects.length ? 'Goedgekeurd (met opmerkingen)' : 'Goedgekeurd, geen gebreken'; 2145 const sev = defects.length ? 'orange' : 'green'; 2146 return '<div class="oc-flag ' + sev + '"><span class="fdot"></span><div><strong>' + esc(dEl ? fmtD(dEl) : '') + ' · ' + esc(titel) + '</strong>' + 2147 (defects.length ? '<p>' + esc(defects.join(', ')) + '</p>' : '') + 2148 (k.vervaldatum_keuring ? '<p class="hint" style="margin:.2rem 0 0">Geldig gemaakt tot ' + esc(fmtD(pd(k.vervaldatum_keuring))) + '</p>' : '') + 2149 '</div></div>'; 2150 }).join(''); 2151 $('oc-apk-history').innerHTML = rowsHtml; 2152 $('oc-apk-history-card').hidden = false; 2153 lastApkHadDefects = (defectsByDate[apkKeuringen[0].meld_datum_door_keuringsinstantie] || []).length > 0; 2154 } else { 2155 $('oc-apk-history-card').hidden = true; 2156 } 2157 } catch (e) { 2158 $('oc-apk-history-card').hidden = true; 2159 } 2160 2161 // Proefrit-checklist, deels afgestemd op het brandstoftype. Bekende 2162 // aandachtspunten voor dit specifieke merk/model (indien bekend) staan als 2163 // eerste, apart gelabelde groep vooraan. 2164 const isEV = fuelName.includes('elektr'); 2165 const isDieselCar = fuelName.includes('diesel'); 2166 const modelTips = findModelTips(v.merk, v.handelsbenaming); 2167 const chassisLoc = humanizeChassisLocation(v.plaats_chassisnummer); 2168 const checklist = [ 2169 ...(modelTips ? [['Bekend bij dit model (' + (vName || 'dit model') + ')', modelTips]] : []), 2170 ['Voor je instapt', [ 2171 ...(chassisLoc ? ['Controleer of het ingeslagen chassisnummer overeenkomt met de kentekencard. Locatie volgens de RDW: ' + esc(chassisLoc) + '.'] : []), 2172 'Vraag of de motor koud is (voel de motorkap): een vooraf warmgedraaide motor kan startproblemen verhullen', 2173 'Loop rond de auto: kleurverschil tussen panelen, ongelijke naden, deuken en roest (dorpels, wielkasten)', 2174 'Check banden: profiel, gelijkmatige slijtage, hetzelfde merk per as en de DOT-code (ouderdom)', 2175 'Kijk onder de auto en motorkap: lekkage van olie of koelvloeistof, staat van de vloeistoffen', 2176 ]], 2177 ['In de auto', [ 2178 'Test alle elektronica: ramen, spiegels, airco (koelt hij echt?), navigatie, camera en sensoren', 2179 'Vergelijk de slijtage van stuur, pook en pedalen met de kilometerstand', 2180 'Controleer of alle waarschuwingslampjes even aangaan bij contact en daarna uitgaan', 2181 'Kijk of boordcomputer en tellerstand overeenkomen met de advertentie', 2182 ]], 2183 ['Tijdens de proefrit', [ 2184 'Start zelf de koude motor en luister naar tikken, rammelen of onregelmatig stationair draaien', 2185 'Rem een keer stevig op een lege weg: de auto moet recht blijven en niet trillen', 2186 'Laat het stuur op een rechte weg even los: de auto hoort rechtdoor te blijven rijden', 2187 isEV ? 'Let op de actieradius bij volle lading en vraag naar de accugezondheid (SoH-rapport)' : 'Schakel door alle versnellingen: overgangen horen soepel en zonder schokken te gaan', 2188 isDieselCar ? 'Rijd een stuk op snelheid door: veel korte stukjes vervuilen het roetfilter (DPF)' : 'Geef vol gas op een oprit: geen rook, haperingen of vermogensverlies', 2189 'Test cruisecontrol, rijhulpsystemen en de handrem (op een helling als het kan)', 2190 ]], 2191 ['Na de proefrit', [ 2192 'Start de warme motor nog een keer: ook warm hoort hij direct aan te slaan', 2193 'Kijk nogmaals onder de auto op de parkeerplek: verse druppels verraden lekkage', 2194 'Vraag onderhoudshistorie, facturen en het aantal sleutels; controleer het serviceboekje', 2195 ]], 2196 ]; 2197 let ci = 0; 2198 $('oc-checklist').innerHTML = checklist.map(([groep, items]) => 2199 '<p class="oc-checkgroup">' + groep + '</p>' + items.map((item) => 2200 '<label class="oc-check"><input type="checkbox" data-ci="' + (ci++) + '"><span>' + item + '</span></label>' 2201 ).join('') 2202 ).join(''); 2203 const totalChecks = ci; 2204 const updateCount = () => { 2205 const done = $('oc-checklist').querySelectorAll('input:checked').length; 2206 $('oc-check-count').textContent = done + ' van ' + totalChecks + ' gecheckt'; 2207 }; 2208 $('oc-checklist').querySelectorAll('input').forEach((cb) => cb.addEventListener('change', updateCount)); 2209 updateCount(); 2210 2211 // Eindadvies-blokken: een samenvatting in 3 stukken, gebouwd uit data 2212 // die hierboven al berekend is (geen nieuwe RDW-fetches). "cat" op elke 2213 // vlag (toegevoegd 29-9-2026) bepaalt welke bij "RDW & historie" horen 2214 // (registratie-/historiegegevens) en welke bij "Technische conditie" 2215 // (kilometrage-slijtage); prijs-vlaggen (cat 'prijs') horen bij geen van 2216 // beide, die staan al in de Prijsindicatie-kaart. Proefrit-advies komt 2217 // niet uit vlaggen maar uit de checklist/modelTips hierboven. 2218 (function renderVerdictBlocks() {
2219 const worstSev = (arr) => arr.some((f) => f.sev === 'red') ? 'red' : (arr.some((f) => f.sev === 'orange') ? 'orange' : 'green'); 2220 const blocks = []; 2221 2222 // Blok 1: Technische conditie 2223 const techFlags = flags.filter((f) => f.cat === 'technisch'); 2224 const hasKnownDefects = !!(modelDefects && modelDefects.defects.length); 2225 let techSev = worstSev(techFlags); 2226 if (lastApkHadDefects === true && techSev !== 'red') techSev = 'orange'; 2227 if (hasKnownDefects && techSev === 'green') techSev = 'orange'; 2228 const techBits = []; 2229 if (techFlags.length) techBits.push(techFlags[0].title.toLowerCase()); 2230 if (lastApkHadDefects === true) techBits.push('de laatste APK-keuring had opmerkingen'); 2231 if (hasKnownDefects) techBits.push(modelDefects.defects.length + ' bekende aandachtspunten voor dit model'); 2232 const techText = techBits.length ? techBits.join('; ') + '.' : 'Geen bijzondere technische aandachtspunten gevonden in de RDW-gegevens.'; 2233 2234 // Blok 2: RDW & historie 2235 const rdwFlags = flags.filter((f) => f.cat === 'rdw'); 2236 const rdwSev = worstSev(rdwFlags); 2237 const rdwOranges = rdwFlags.filter((f) => f.sev !== 'green').length; 2238 const rdwText = rdwOranges > 0 2239 ? rdwOranges + ' aandachtspunt' + (rdwOranges === 1 ? '' : 'en') + ' in de RDW-registratie, zie Bevindingen hieronder voor details.' 2240 : 'Geen bijzonderheden in de officiele RDW-registratie (APK, tellerstand, terugroepacties, eigenaarschap).'; 2241 2242 // Blok 3: Proefrit-advies 2243 const proefritSev = modelTips ? 'orange' : 'green'; 2244 const proefritText = modelTips 2245 ? 'Dit model heeft bekende aandachtspunten; die staan als eerste, apart gelabelde groep in de proefrit-checklist hieronder.' 2246 : 'Geen modelspecifieke aandachtspunten bekend; de standaard proefrit-checklist hieronder volstaat.'; 2247 2248 blocks.push({ titel: 'Technische conditie', sev: techSev, text: techText }); 2249 blocks.push({ titel: 'RDW & historie', sev: rdwSev, text: rdwText }); 2250 blocks.push({ titel: 'Proefrit-advies', sev: proefritSev, text: proefritText }); 2251 2252 $('oc-verdict-blocks').innerHTML = blocks.map((b) => 2253 '<div class="oc-vblock oc-vblock-' + b.sev + '"><span class="oc-vblock-dot"></span><div><strong>' + esc(b.titel) + '</strong><p>' + esc(b.text) + '</p></div></div>' 2254 ).join(''); 2255 $('oc-verdict-blocks-card').hidden = false; 2256 })(); 2257 2258 // Fotocheck: schadeverleden herkennen op advertentiefoto's. 2259 const fotochecks = [ 2260 ['Kleurverschil tussen panelen', 'Een deur of bumper met een netto andere tint dan de rest wijst op overspuiten na schade.'], 2261 ['Spuitnevel en kitranden', 'Zoom in op rubbers, sierlijsten en deurranden: matte nevel of onstrakke kitranden verraden plaatwerk.'], 2262 ['Ongelijke naden', 'De naden tussen motorkap, spatborden en deuren horen overal even breed te zijn.'], 2263 ['Banden en velgen', 'Vier verschillende bandenmerken of een afwijkende velg wijst op zuinig (schade)herstel.'], 2264 ['Reflecties in de lak', 'Volg de weerspiegeling van gebouwen of lucht over de flank: golvingen verraden plamuur.'], 2265 ['Interieurslijtage versus tellerstand', 'Een gladgesleten stuur bij 60.000 km klopt niet; vergelijk met de opgegeven stand.'], 2266 ['Wat NIET op de foto staat', 'Ontbreken motorruimte, kofferbak of een hele zijde? Vraag die foto\'s op voor je gaat rijden.'], 2267 ['Locatie en achtergrond', 'Handelsterrein terwijl de advertentie "particulier" zegt? Dat is een bekende rode vlag.'], 2268 ]; 2269 $('oc-photocheck').innerHTML = fotochecks.map((f, i) => 2270 '<div class="oc-photo"><span class="pnum">' + (i + 1) + '</span><div><strong>' + f[0] + '</strong><p style="margin:.1rem 0 0">' + f[1] + '</p></div></div>' 2271 ).join(''); 2272 2273 $('oc-full-link').href = '/?kenteken=' + encodeURIComponent(plate); 2274 $('oc-loading').style.display = 'none'; 2275 $('oc-result').style.display = 'block'; 2276 window.scrollTo(0, 0); 2277 2278 // "Bewaar in mijn portfolio": alleen zichtbaar voor ingelogde bezoekers, 2279 // vangt plate/price/km/v/score op uit de sluiting van deze analyse. 2280 const saveBtn = $('oc-save-portfolio'); 2281 const saveBtnLabel = $('oc-save-portfolio-label'); 2282 saveBtn.disabled = false;
2283 saveBtnLabel.textContent = 'Bewaar in mijn portfolio'; 2284 toggleSaveVisibility(); 2285 saveBtn.onclick = async () => { 2286 saveBtn.disabled = true; 2287 const r = await PS.api('/occasion/save', 'POST', { 2288 kenteken: plate, 2289 url: extractUrl($('oc-url').value) || null, 2290 price, km, score, 2291 vehicle_label: [v && v.merk, v && v.handelsbenaming].filter(Boolean).join(' ') || null, 2292 }); 2293 if (r.ok) { 2294 saveBtnLabel.textContent = 'Bewaard â'; 2295 // GA4 event 2296 if (typeof gtag === 'function') gtag('event', 'occasion_opgeslagen_portfolio', { kenteken: plate, score: score }); 2297 } 2298 else { saveBtn.disabled = false; saveBtnLabel.textContent = 'Opslaan mislukt, probeer opnieuw'; } 2299 }; 2300 2301 // "Klopte deze analyse?" Ja/Nee 2302 const fbYes = $('oc-feedback-yes'), fbNo = $('oc-feedback-no'); 2303 const sendFeedback = async (matched, btn, otherBtn) => { 2304 btn.disabled = true; otherBtn.disabled = true; 2305 btn.classList.add('oc-fb-picked'); 2306 const r = await PS.api('/occasion/feedback', 'POST', { kenteken: plate, url: extractUrl($('oc-url').value) || null, score, matched }); 2307 if (r.ok) { 2308 $('oc-feedback-q').hidden = true; 2309 $('oc-feedback-buttons').hidden = true; 2310 $('oc-feedback-thanks').hidden = false; 2311 } else { 2312 btn.disabled = false; otherBtn.disabled = false; btn.classList.remove('oc-fb-picked'); 2313 } 2314 }; 2315 fbYes.disabled = false; fbNo.disabled = false; fbYes.classList.remove('oc-fb-picked'); fbNo.classList.remove('oc-fb-picked'); 2316 $('oc-feedback-buttons').hidden = false; $('oc-feedback-thanks').hidden = true; 2317 $('oc-feedback-q').hidden = false; 2318 fbYes.onclick = () => sendFeedback(true, fbYes, fbNo); 2319 fbNo.onclick = () => sendFeedback(false, fbNo, fbYes); 2320 } 2321 2322 // Deeplinks: 2323 // - vanuit het kentekenrapport: ?kenteken=XX (alleen het kenteken klaarzetten) 2324 // - vanuit de browserextensie op een advertentie: ?url=<adlink> => automatisch uitlezen, 2325 // met ?prijs=/?km= als client-side terugval als de server de site blokkeert. 2326 (function () { 2327 const q = new URLSearchParams(location.search); 2328 const qk = q.get('kenteken'), qp = q.get('prijs'), qkm = q.get('km'), qurl = q.get('url'); 2329 if (qk && clean(qk).length >= 4) $('oc-plate').value = fmtPlate(qk); 2330 if (qp && /^\d+$/.test(qp)) $('oc-price').value = qp; 2331 if (qkm && /^\d+$/.test(qkm)) $('oc-km').value = qkm; 2332 if (qurl && /^https?:\/\//i.test(qurl)) $('oc-url').value = qurl; 2333 const havePlate = () => clean($('oc-plate').value).length >= 4; 2334 2335 if ($('oc-url').value) { 2336 // fetchAd() zelf opent report-mode (hero/formulier weg, laadstaat 2337 // bovenaan zichtbaar), dus geen losse status/scroll hier meer nodig. 2338 fetchAd().then((ran) => { 2339 // Server-uitlees geblokkeerd, maar extensie gaf al kenteken + prijs mee: analyseer alsnog. 2340 if (!ran && havePlate() && $('oc-price').value) runAnalysis(); 2341 }); 2342 } else if (havePlate() && $('oc-price').value) { 2343 runAnalysis(); 2344 } else if (havePlate()) { 2345 $('oc-status').textContent = 'Kenteken staat klaar. Vul de vraagprijs en kilometerstand uit de advertentie in.'; 2346 setTimeout(() => { 2347 $('oc-manual-card').scrollIntoView({ behavior: 'smooth', block: 'center' }); 2348 $('oc-price').focus(); 2349 }, 300); 2350 } 2351 })(); 2352 })(); 2353 </script>
2353 </div> <footer class="site-footer" data-astro-cid-gcn2mc3v> <div class="sf-inner" data-astro-cid-gcn2mc3v> <div class="sf-grid" data-astro-cid-gcn2mc3v> <div class="sf-brand" data-astro-cid-gcn2mc3v> <a href="/" class="sf-logo" aria-label="PlateScout home" data-astro-cid-gcn2mc3v><svg style="width:200px;height:auto;display:block;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 440.07 60.91"> 2354 <defs><style>.cls-pg{fill:#4c8c2b;fill-rule:evenodd;}</style></defs> 2355 <g> 2356 <g><g> 2357 <path d="M66.47,57.2h4.1v-.9l-1.4-.3v-3.5h1.4l2.5,3.5-1.2.3v.9h4.1v-.9l-1.2-.3-3-4.2,2.2-3.7,1.4-.3v-.9h-2.4l-2.5,4.3h-1.3v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v1.1Z"/> 2358 <path d="M89.67,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 2359 <path d="M109.37,56v-6.8l4.8,8h1.8v-9l1.2-.3v-.9h-3.8v.9l1.2.3v6.9l-4.8-8.1h-3v.9l1.2.3v7.8l-1.2.3v.9h3.9v-.9l-1.4-.3h.1Z"/> 2360 <path d="M130.07,57.2h4.4v-.9l-1.4-.3v-7.8h1.9l.4,1.4h.9v-2.6h-7.9v2.6h.9l.4-1.4h1.9v7.8l-1.4.3v.9h-.1Z"/> 2361 <path d="M149.87,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 2362 <path d="M166.97,57.2h4.1v-.9l-1.4-.3v-3.5h1.4l2.5,3.5-1.2.3v.9h4.1v-.9l-1.2-.3-3-4.2,2.2-3.7,1.4-.3v-.9h-2.4l-2.5,4.3h-1.3v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v1.1Z"/> 2363 <path d="M190.07,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 2364 <path d="M209.87,56v-6.8l4.8,8h1.8v-9l1.2-.3v-.9h-3.8v.9l1.2.3v6.9l-4.8-8.1h-3v.9l1.2.3v7.8l-1.2.3v.9h3.9v-.9l-1.4-.3h.1Z"/> 2365 <path d="M247.67,50.1h1.1v-2.5s-1.6-.7-3.2-.7c-3,0-4.8,2.1-4.8,5.4s1.7,5,4.6,5,3.6-1.5,3.6-1.5l-.6-.9s-1.4,1.2-2.9,1.2-3.1-1.2-3.1-3.8,1.1-4.1,3-4.1,1.9.3,1.9.3l.4,1.7v-.1Z"/> 2366 <path d="M261.27,57.2h4.1v-.9l-1.4-.3v-3.5h4.8v3.5l-1.4.3v.9h4.1v-.9l-1.2-.3v-7.8l1.2-.3v-.9h-4.1v.9l1.4.3v3.2h-4.8v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v.9Z"/> 2367 <path d="M286.77,51.3v-3.1h3.1l.4,1.3h.9v-2.5h-7.2v.9l1.2.3v7.8l-1.2.3v.9h7.3v-2.6h-.9l-.3,1.4h-3.3v-3.5h3.3v-1.2h-3.3Z"/> 2368 <path d="M310.77,50.1h1.1v-2.5s-1.6-.7-3.2-.7c-3,0-4.8,2.1-4.8,5.4s1.7,5,4.6,5,3.6-1.5,3.6-1.5l-.6-.9s-1.4,1.2-2.9,1.2-3.1-1.2-3.1-3.8,1.1-4.1,3-4.1,1.9.3,1.9.3l.4,1.7v-.1Z"/> 2369 <path d="M324.27,57.2h4.1v-.9l-1.4-.3v-3.5h1.4l2.5,3.5-1.2.3v.9h4.1v-.9l-1.2-.3-3-4.2,2.2-3.7,1.4-.3v-.9h-2.4l-2.5,4.3h-1.3v-3.2l1.4-.3v-.9h-4.1v.9l1.2.3v7.8l-1.2.3v1.1Z"/> 2370 </g><g> 2371 <path d="M66.47,36.81h14.1v-3.9l-3.5-1.4v-6h2.5c8.4,0,13.2-3.8,13.2-11.6s-4.2-9.7-11.2-9.7h-4.4l-10.6.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h-.1ZM77.17,20.11v-10.3h3.7c3.1,0,4.8,2.1,4.8,5.1s-2.2,5.2-6,5.2h-2.5Z"/> 2372 <path d="M112.87,31.31h-7.1V9.81l3.5-1.4v-4.2l-14.1.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h23.1v-10.6h-4.4l-1,5.1h0Z"/> 2373 <path d="M153.07,32.91l-3.2-1.3-10-27.4h-7.4c0,.1-10.2,27.4-10.2,27.4l-3.4,1.3v3.9h14v-3.9l-3.6-1.3,1.2-3.3h10.3l1.1,3.4-3.5,1.2v3.9h14.7v-3.9h0ZM139.17,23.31h-7.1l3.7-11,3.5,11h-.1Z"/> 2374 <path d="M160.87,31.51l-4.4,1.4v3.9h16v-3.9l-4.4-1.4V9.71h4.4l1.2,4.4h4.3V4.11h-26.8v10h4.3l1.2-4.4h4.4v21.8h-.2Z"/> 2375 <path d="M200.37,17.41h-9.3v-7.6h7.6l1.2,3.4h4.2V4.31h-13l-10.6.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h24.2v-9.3h-4.2l-1.1,3.8h-8.3v-8.8h9.3v-5.2Z"/> 2376 <path d="M214.67,26.81h-4.7v8.9s5.1,1.8,10.3,1.8,12.5-3.8,12.5-10.7c0-10.9-15.6-8.7-15.6-14.1s1.6-3.3,4.9-3.3,4.1.7,4.1.7l1.2,3.9h4.3l.2-8.4s-5-1.9-10.2-1.9-11.8,3.4-11.8,9.8c0,11.4,15.6,9,15.6,14.4s-2.6,3.7-5.6,3.7-4.5-1-4.5-1l-.7-3.9v.1Z"/> 2377 <path d="M259.27,14.61h4.5l.2-8.8s-5.2-2.2-10.8-2.2c-9.5,0-15.6,6.5-15.6,17.4s5.4,16.4,14.8,16.4,12.1-5,12.1-5l-2.5-4.2s-4.2,3.2-8.8,3.2-7.9-3.1-7.9-10.6,2.8-11.3,7.6-11.3,5.2.7,5.2.7l1.1,4.4h.1Z"/> 2378 <path d="M283.77,3.61c-9.4,0-15.3,6.5-15.3,17.1s5.1,16.7,14.3,16.7,15.5-6.9,15.5-17.4-5.3-16.4-14.6-16.4h.1ZM283.57,9.41c4.6,0,6.9,3.2,6.9,10.9s-2.8,11.3-7.4,11.3-6.7-3.5-6.7-11.1,2.5-11.1,7.2-11.1h0Z"/> 2379 <path d="M313.17,9.71l3.6-1.4v-4.2l-14.2.2v3.9l3.4,1.4v14.6c0,8.9,3.7,13.1,13,13.1s13.4-4.8,13.4-13.7v-13.9l3.5-1.4v-4.2l-14.3.2v3.9l3.6,1.4v13.9c0,5.5-1.1,8.1-6,8.1s-6.1-2.1-6.1-7.4v-14.6l.1.1Z"/> 2380 <path d="M347.67,31.51l-4.4,1.4v3.9h16v-3.9l-4.4-1.4V9.71h4.4l1.2,4.4h4.3V4.11h-26.8v10h4.3l1.2-4.4h4.4v21.8h-.2Z"/> 2381 <path d="M368.17,33.21c0,2.7,1.3,4.2,3.9,4.2s4-1.5,4-4.2-1.3-4.2-3.9-4.2-4,1.5-4,4.2Z"/> 2382 <path d="M380.67,36.81h13.4v-3.9l-3.6-1.4v-15.6l12.4,21h7.7V9.81l3.5-1.4v-4.2l-13.2.2v3.9l3.4,1.4v15.8l-12.5-21.4-11.1.2v3.9l3.5,1.4v21.8l-3.5,1.4v4Z"/> 2383 <path d="M434.67,31.31h-7.1V9.81l3.5-1.4v-4.2l-14.1.2v3.9l3.5,1.4v21.8l-3.5,1.4v3.9h23.1v-10.6h-4.4l-1,5.1h0Z"/> 2384 </g></g> 2385 <path class="cls-pg" d="M16.34,3.61c2.52-.66,4.46-1.4,8.46-3.14.58-.27,1.16-.47,1.32-.47s1.05.39,2.06.85c2.06.97,4.7,1.98,6.75,2.6l1.44.43,7.3.08c5.51.04,7.38.12,7.61.23.12.04.19.08.27.16.47.35.43,1.36.43,13.12s-.04,13.04-.16,13.97c-.5,5.32-2.45,10.68-5.4,15.06-1.71,2.56-4.7,5.78-7.14,7.72-2.79,2.25-7.1,4.62-10.56,5.86-1.75.62-2.37.85-2.91.82-.31,0-.58-.12-1.09-.27-9.28-3.11-16.15-8.62-20.57-16.42-1.82-3.26-3.18-7.26-3.77-11.37-.12-.74-.23-2.68-.27-4.35l-.08-2.99.39-.47.39-.47h7.34l7.34-.08.66.31c1.71.82,8.58,4.08,12.34,5.86,2.29,1.09,5.16,2.45,6.41,3.03l2.25,1.05h4.5c2.56,0,4.54-.04,4.58-.12.12-.19.58-2.99.66-4.11l.08-1.01h-5.32l-5.32-.08-3.57-1.75c-7.38-3.57-7.34-3.57-7.84-4.58-.39-.78-.31-1.98.23-2.72.43-.62.66-.74,7.65-4.35l3.57-1.82h10.56v-5.28h-5.36c-5.32,0-5.36,0-6.6-.35-1.55-.43-3.65-1.13-5.2-1.79l-1.2-.5-.08,2.91c-.08,3.14-.08,3.22-.85,3.92-.19.16-2.87,1.59-6.02,3.14l-5.67,2.83h-7.38c-6.44.08-7.41.04-7.76-.12-.12-.08-.23-.12-.35-.19-.47-.39-.47-1.32-.47-7.26s0-6.52.23-6.83c.08-.12.12-.23.19-.31.43-.47,1.36-.47,7.69-.47s6.83,0,8.07-.31h.16ZM17.27,8.54c1.4-.39,4.19-1.36,5.51-1.94.31-.16.62-.19.7-.16.
238504.04.08.85.08,1.79v1.71l-8.42,4.23h-5.01l-5.01.08v-5.28h10.68l1.48-.43h0ZM32.61,21.66c.31-.16,1.48-.78,2.6-1.36l2.06-1.05h9.7v5.28h-9.59l-2.37-1.13c-1.28-.62-2.48-1.2-2.68-1.24q-.31-.12.23-.43h0l.04-.08ZM5.71,34.04c-.19-.85-.54-3.34-.54-4.04v-.5h9.78l9.32,4.5c5.12,2.48,9.94,4.77,10.71,5.12l1.4.62h8.19l-.62,1.2c-.89,1.79-3.07,5.01-3.77,5.59-.16.16-1.28-.35-6.91-3.14-5.32-2.64-6.79-3.34-7.22-3.34s-1.71.58-7.14,3.38l-6.64,3.38-.39-.43c-.62-.66-2.1-2.68-2.72-3.73-.5-.85-1.48-2.72-1.48-2.91s1.75-.08,3.92-.08c3.57,0,3.96,0,4.39-.23,1.55-.82,1.75-3.22.31-4.31l-.5-.39-4.93-.08-4.93-.08-.16-.66-.08.12ZM28.65,54.77s-.08-1.82-.08-4.08v-4.08l3.77,1.86c2.06,1.05,3.73,1.94,3.73,2.02-.08.19-2.1,1.55-3.65,2.45-1.28.74-3.57,1.86-3.73,1.86h0l-.04-.04ZM15.88,50.54l3.73-1.94c2.06-1.09,3.8-1.94,3.84-1.98s.12,1.82.12,4.08-.04,4.08-.08,4.08-.97-.43-2.06-.97c-1.98-.97-3.77-1.98-4.89-2.83l-.62-.43h-.04Z"/> 2386 </g> 2387</svg></a> <p data-astro-cid-gcn2mc3v>De snelste gratis kenteken check van Nederland. Alle RDW gegevens, APK status en voertuighistorie direct beschikbaar, zonder registratie.</p> </div> <div class="sf-col" data-astro-cid-gcn2mc3v> <p class="sf-h" data-astro-cid-gcn2mc3v>Controleer</p> <ul data-astro-cid-gcn2mc3v> <li data-astro-cid-gcn2mc3v><a href="/occasion-check" data-astro-cid-gcn2mc3v>Occasion check</a></li> <li data-astro-cid-gcn2mc3v><a href="/apk-check" data-astro-cid-gcn2mc3v>APK check</a></li> <li data-astro-cid-gcn2mc3v><a href="/nap-tellerstand" data-astro-cid-gcn2mc3v>NAP tellerstand</a></li> <li data-astro-cid-gcn2mc3v><a href="/terugroepactie-check" data-astro-cid-gcn2mc3v>Terugroepacties</a></li> <li data-astro-cid-gcn2mc3v><a href="/apk-gebreken" data-astro-cid-gcn2mc3v>APK-gebreken</a></li> <li data-astro-cid-gcn2mc3v><a href="/scan" data-astro-cid-gcn2mc3v>Kenteken scannen</a></li> </ul> </div> <div class="sf-col" data-astro-cid-gcn2mc3v> <p class="sf-h" data-astro-cid-gcn2mc3v>Belasting & import</p> <ul data-astro-cid-gcn2mc3v> <li data-astro-cid-gcn2mc3v><a href="/wegenbelasting" data-astro-cid-gcn2mc3v>Wegenbelasting</a></li> <li data-astro-cid-gcn2mc3v><a href="/autokosten" data-astro-cid-gcn2mc3v>Autokosten per maand</a></li> <li data-astro-cid-gcn2mc3v><a href="/bpm-berekenen" data-astro-cid-gcn2mc3v>BPM berekenen</a></li> <li data-astro-cid-gcn2mc3v><a href="/motorrijtuigenbelasting" data-astro-cid-gcn2mc3v>Motorrijtuigenbelasting</a></li> <li data-astro-cid-gcn2mc3v><a href="/import-check" data-astro-cid-gcn2mc3v>Import check</a></li> <li data-astro-cid-gcn2mc3v><a href="/milieuzone-check" data-astro-cid-gcn2mc3v>Milieuzone check</a></li> </ul> </div> <div class="sf-col" data-astro-cid-gcn2mc3v> <p class="sf-h" data-astro-cid-gcn2mc3v>Gidsen</p> <ul data-astro-cid-gcn2mc3v> <li data-astro-cid-gcn2mc3v><a href="/gids/elektrisch-rijden" data-astro-cid-gcn2mc3v>Elektrisch rijden</a></li> <li data-astro-cid-gcn2mc3v><a href="/gids/auto-importeren" data-astro-cid-gcn2mc3v>Auto importeren</a></li> <li data-astro-cid-gcn2mc3v><a href="/gids/autoverzekering" data-astro-cid-gcn2mc3v>Autoverzekering</a></li> <li data-astro-cid-gcn2mc3v><a href="/gids/techniek-onderhoud" data-astro-cid-gcn2mc3v>Techniek & onderhoud</a></li> <li data-astro-cid-gcn2mc3v><a href="/gids/schade-en-wok" data-astro-cid-gcn2mc3v>Schade & WOK</a></li> <li data-astro-cid-gcn2mc3v><a href="/proefrit-checklist" data-astro-cid-gcn2mc3v>Proefrit-checklist</a></li> <li data-astro-cid-gcn2mc3v><a href="/begrippenlijst" data-astro-cid-gcn2mc3v>Begrippenlijst</a></li> </ul> </div> <div class="sf-col" data-astro-cid-gcn2mc3v> <p class="sf-h" data-astro-cid-gcn2mc3v>Extra tools</p> <ul data-astro-cid-gcn2mc3v> <li data-astro-cid-gcn2mc3v><a href="/laatste-kentekens" data-astro-cid-gcn2mc3v>Laatste kentekens</a></li> <li data-astro-cid-gcn2mc3v><a href="/kentekenvoorspeller" data-astro-cid-gcn2mc3v>Kentekenvoorspeller</a></li> <li data-astro-cid-gcn2mc3v><a href="/autostatistieken" data-astro-cid-gcn2mc3v>Autoregistraties Nederland</a></li> <li data-astro-cid-gcn2mc3v><a href="/kenteken-zoeken" data-astro-cid-gcn2mc3v>Kenteken zoeken op onderdeel</a></li> <li data-astro-cid-gcn2mc3v><a href="/auto-herkenning" data-astro-cid-gcn2mc3v>AI auto-herkenning</a></li> <li data-astro-cid-gcn2mc3v><a href="/onderhoudspaspoort" data-astro-cid-gcn2mc3v>Onderhoudspaspoort</a></li> </ul> </div> <div class="sf-col" data-astro-cid-gcn2mc3v> <p class="sf-h" data-astro-cid-gcn2mc3v>Informatie</p> <ul data-astro-cid-gcn2mc3v> <li data-astro-cid-gcn2mc3v><a href="/functies" data-astro-cid-gcn2mc3v>Alle functies</a></li> <li data-astro-cid-gcn2mc3v><a href="/voordelen" data-astro-cid-gcn2mc3v>Accountvoordelen</a></li> <li data-astro-cid-gcn2mc3v><a href="/extensie" data-astro-cid-gcn2mc3v>Browserextensie</a></li> <li data-astro-cid-gcn2mc3v><a href="/over-ons" data-astro-cid-gcn2mc3v>Over ons</a></li> <li data-astro-cid-gcn2mc3v><a href="/blog" data-astro-cid-gcn2mc3v>Blog</a></li> <li data-astro-cid-gcn2mc3v><a href="/rdw-open-data" data-astro-cid-gcn2mc3v>RDW Open Data</a></li> <li data-astro-cid-gcn2mc3v><a href="/apk-keuring" data-astro-cid-gcn2mc3v>Over APK keuring</a></li> <li data-astro-cid-gcn2mc3v><a href="/kentekencheck-vergelijken" data-astro-cid-gcn2mc3v>Vergelijk kentekencheckers</a></li> </ul> </div> </div> <div class="sf-bottom" data-astro-cid-gcn2mc3v> <p data-astro-cid-gcn2mc3v>© 2026 PlateScout</p> <div class="sf-legal" data-astro-cid-gcn2mc3v> <a href="/privacy" data-astro-cid-gcn2mc3v>Privacy</a> <a href="/disclaimer" data-astro-cid-gcn2mc3v>Disclaimer</a> <a href="/voorwaarden" data-astro-cid-gcn2mc3v>Gebruiksvoorwaarden</a> <a href="/contact" data-astro-cid-gcn2mc3v>Contact</a> </div> <div class="sf-social" data-astro-cid-gcn2mc3v> <a href="https://www.instagram.com/platescout.nl/" target="_blank" rel="noopener" aria-label="PlateScout op Instagram" data-astro-cid-gcn2mc3v><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/></svg></a> <a href="https://linkedin.com/company/platescout" target="_blank" rel="noopener" aria-label="PlateScout op LinkedIn" data-astro-cid-gcn2mc3v><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class aria-hidden="true"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"/><rect x="2" y="9" width="4" height="12"/><circle cx="4" cy="4" r="2"/></svg></a> </div> </div> </div> </footer> </div>
2387<script> 2388 document.querySelectorAll('.faq-item').forEach((item) => { 2389 const q = item.querySelector('.faq-q'); 2390 if (q) q.addEventListener('click', () => item.classList.toggle('open')); 2391 }); 2392 </script>
2392 <!-- Cookiebanner (AVG): rendert direct mee (goed voor LCP); html.psc-done 2393 (gezet in de head, voor de eerste paint) verbergt hem na een eerdere keuze. --> <div id="ps-cookie" class="psc" role="dialog" aria-label="Cookievoorkeuren"> <div class="psc-head"> <span class="psc-ic"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path><polyline points="9 12 11 14 15 10"></polyline></svg> </span> <strong>Cookies op PlateScout</strong> </div> <p>We gebruiken cookies voor <strong>anonieme statistieken</strong> (Google Analytics) en, als je bent ingelogd, paginabezoek-inzicht in ons CRM (HubSpot). Geen advertenties, geen verkoop van gegevens. Lees meer in ons <a href="/privacy">privacybeleid</a>.</p> <div class="psc-actions"> <button id="psc-accept" type="button" class="psc-btn psc-accept">Accepteren</button> <button id="psc-decline" type="button" class="psc-btn psc-decline">Alleen noodzakelijk</button> </div> </div>
2393<script> 2394 (function () { 2395 var box = document.getElementById('ps-cookie'); 2396 if (!box) return; 2397 function done(v) { 2398 try { localStorage.setItem('ps-consent', v); } catch (e) {} 2399 document.documentElement.classList.add('psc-done'); 2400 if (v === 'granted' && window.__psLoadAnalytics) window.__psLoadAnalytics(); 2401 } 2402 document.getElementById('psc-accept').addEventListener('click', function () { done('granted'); }); 2403 document.getElementById('psc-decline').addEventListener('click', function () { done('denied'); }); 2404 })(); 2405 </script>
2405 <!-- Extensie-banner: verschijnt in desktop Chrome, Edge of Firefox, maar alleen als de 2406 store voor dÃe browser AAN staat in het adminportaal (live via GET /api/extension/stores, 2407 met sessionStorage-cache). Verder: pas na de cookiekeuze, niet op /extensie zelf, en 2408 weggeklikt = weg (localStorage ps-ext-banner: '1' permanent, 't:<epoch>' = snooze). --> <div id="ps-ext" class="pse" role="complementary" aria-label="PlateScout browserextensie"> <button id="pse-close" type="button" class="pse-x" aria-label="Sluiten"> <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> </button> <div class="pse-head"> <span class="pse-ic"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path><polyline points="9 12 11 14 15 10"></polyline></svg> </span> <strong id="pse-title">PlateScout voor Chrome</strong> </div> <p>Doe een <strong>gratis kentekencheck</strong> direct vanaf occasions op Marktplaats, AutoTrack, Gaspedaal, AutoScout24 en AutoWeek.</p> <div class="pse-actions"> <a class="pse-btn pse-primary" id="pse-store" href="https://chromewebstore.google.com/detail/phojgbmdcfmmchjpjbjahbdbolabadck" target="_blank" rel="noopener">Open Chrome Web Store</a> <a class="pse-btn pse-secondary" href="/extensie">Meer informatie</a> </div> </div>
2408<script> 2409 (function () { 2410 var box = document.getElementById('ps-ext'); 2411 if (!box) return; 2412 try { 2413 // 'ps-ext-banner': '1' = permanent weg (kruisje of store-klik); 2414 // 't:<epoch>' = gesnoozed tot dat moment ("Meer informatie"-klik: 7 dagen). 2415 var seen = localStorage.getItem('ps-ext-banner'); 2416 if (seen === '1') return; 2417 if (seen && seen.slice(0, 2) === 't:' && Date.now() < +seen.slice(2)) return; 2418 if (!localStorage.getItem('ps-consent')) return; // cookiebanner gaat voor 2419 } catch (e) { return; } 2420 if (location.pathname.indexOf('/extensie') === 0) return; 2421 2422 // Desktopbrowser bepalen: Client Hints waar mogelijk (Edge/Brave/Opera hebben daar 2423 // een eigen brand), anders UA. Firefox heeft geen Client Hints en valt op UA terug. 2424 var browser = null; 2425 var uad = navigator.userAgentData; 2426 if (uad && uad.brands) { 2427 if (!uad.mobile) { 2428 if (uad.brands.some(function (b) { return b.brand === 'Microsoft Edge'; })) browser = 'edge'; 2429 else if (uad.brands.some(function (b) { return b.brand === 'Google Chrome'; })) browser = 'chrome'; 2430 } 2431 } else { 2432 var ua = navigator.userAgent; 2433 if (/Mobile|Android|iPhone|iPad/.test(ua)) browser = null; 2434 else if (/Firefox\//.test(ua) && !/Seamonkey/.test(ua)) browser = 'firefox'; 2435 else if (/Edg\//.test(ua)) browser = 'edge'; 2436 else if (/Chrome\/\d+/.test(ua) && !/OPR\/|SamsungBrowser|Vivaldi|YaBrowser|CriOS/.test(ua)) browser = 'chrome'; 2437 } 2438 if (navigator.brave) browser = null; 2439 2440 // QA-haakje: ?ext-banner=1 forceert tonen (Chrome-variant in andere browsers); 2441 // cookie-keuze en wegklik-status blijven gelden. 2442 var force = /[?&]ext-banner=1/.test(location.search); 2443 if (!browser && !force) return; 2444 if (!browser) browser = 'chrome'; 2445 var NAMES = { chrome: ['Chrome', 'Chrome Web Store'], edge: ['Edge', 'Microsoft Edge Add-ons'], firefox: ['Firefox', 'Firefox Add-ons'] }; 2446 2447 function show(stores) { 2448 var st = stores && stores[browser]; 2449 if ((!st || !st.active) && !force) return; // store voor deze browser staat (nog) uit 2450 if (st && st.url) document.getElementById('pse-store').href = st.url; 2451 document.getElementById('pse-title').textContent = 'PlateScout voor ' + NAMES[browser][0]; 2452 document.getElementById('pse-store').textContent = 'Open ' + NAMES[browser][1]; 2453 box.style.display = 'block'; 2454 function hide(val) { 2455 try { localStorage.setItem('ps-ext-banner', val); } catch (e) {} 2456 box.style.display = 'none'; 2457 } 2458 // Kruisje = bewust afgewezen; store-klik = doel bereikt: allebei permanent weg. 2459 // "Meer informatie" = interesse: 7 dagen snoozen en daarna nog eens tonen. 2460 document.getElementById('pse-close').addEventListener('click', function () { hide('1'); }); 2461 box.querySelectorAll('a').forEach(function (a) { 2462 a.addEventListener('click', function () { 2463 var info = (a.getAttribute('href') || '').indexOf('/extensie') === 0; 2464 hide(info ? 't:' + (Date.now() + 7 * 864e5) : '1'); 2465 }); 2466 }); 2467 } 2468 2469 // Live adminstatus, met sessionStorage-cache (max 1 API-call per sessie). 2470 var cached = null; 2471 try { cached = JSON.parse(sessionStorage.getItem('ps-ext-stores') || 'null'); } catch (e) {} 2472 if (cached) { show(cached); return; } 2473 fetch('/api/extension/stores').then(function (r) { return r.json(); }).then(function (d) { 2474 if (d && d.ok && d.stores) { 2475 try { sessionStorage.setItem('ps-ext-stores', JSON.stringify(d.stores)); } catch (e) {} 2476 show(d.stores); 2477 } else if (force) { show(null); } 2478 }).catch(function () { if (force) show(null); }); 2479 })(); 2480 </script>
2480 <!-- Installatiebanner (PWA, 7-9-2026): vangt 'beforeinstallprompt' af (alleen 2481 Chromium-browsers geven dit event; Safari/Firefox nooit, daar blijft de 2482 banner dus altijd uit, installeren kan daar alleen via het eigen browsermenu). 2483 Beide adminschakelaars moeten aan staan (PWA-algeheel + deze banner apart), 2484 plus dezelfde wegklik/snooze-mechaniek als de extensiebanner. --> <div id="ps-install" class="psi" role="complementary" aria-label="PlateScout installeren"> <button id="psi-close" type="button" class="psi-x" aria-label="Sluiten"> <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> </button> <div class="psi-head"> <span class="psi-ic"> <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="2" width="14" height="20" rx="2"></rect><line x1="12" y1="18" x2="12.01" y2="18"></line></svg> </span> <strong>Installeer PlateScout als app</strong> </div> <p>Snel bij je kentekenchecks, rechtstreeks vanaf je beginscherm.</p> <div class="psi-actions"> <button id="psi-install" type="button" class="psi-btn psi-primary">Installeren</button> <button id="psi-later" type="button" class="psi-btn psi-secondary">Niet nu</button> </div> </div>
2484<script> 2485 (function () { 2486 // window.PSInstall: gedeelde toegang tot het opgevangen beforeinstallprompt-event, 2487 // zodat ook paginalokale install-knoppen (bv. /app) 'm kunnen triggeren zonder 2488 // zelf een eigen listener te registreren (het event vuurt maar één keer af). 2489 var deferredPrompt = null; 2490 window.PSInstall = { 2491 available: function () { return !!deferredPrompt; }, 2492 trigger: function () { 2493 if (!deferredPrompt) return Promise.resolve(false); 2494 var p = deferredPrompt; 2495 deferredPrompt = null; 2496 p.prompt(); 2497 return p.userChoice.then(function (choice) { 2498 try { localStorage.setItem('ps-install-banner', '1'); } catch (e) {} 2499 return choice.outcome === 'accepted'; 2500 }); 2501 }, 2502 }; 2503 2504 var box = document.getElementById('ps-install'); 2505 if (!box) return; 2506 var serverAllows = null; 2507 2508 function hide(val) { 2509 try { localStorage.setItem('ps-install-banner', val); } catch (e) {} 2510 box.style.display = 'none'; 2511 } 2512 2513 function isMobileDevice() { 2514 var uad = navigator.userAgentData; 2515 if (uad && typeof uad.mobile === 'boolean') return uad.mobile; 2516 return /Mobile|Android|iPhone|iPad/.test(navigator.userAgent); 2517 } 2518 2519 function maybeShow() { 2520 // Desktop Chrome/Edge geven 'beforeinstallprompt' net zo goed af (desktop-PWA- 2521 // installatie bestaat echt), maar "installeer als app" is alleen relevant op 2522 // mobiel (verzoek Stephan, 23-9-2026, gevonden nadat de banner op desktop 2523 // verscheen); op desktop blijft deferredPrompt gewoon gevangen zodat /app's 2524 // eigen "Installeren"-knop (window.PSInstall.trigger()) er nog steeds werkt. 2525 if (!isMobileDevice()) return; 2526 if (!deferredPrompt || serverAllows !== true) return; 2527 try { 2528 // 'ps-install-banner': '1' = permanent weg (kruisje, geïnstalleerd, of 2529 // daadwerkelijk op Installeren geklikt); 't:<epoch>' = 7 dagen gesnoozed. 2530 var seen = localStorage.getItem('ps-install-banner'); 2531 if (seen === '1') return; 2532 if (seen && seen.slice(0, 2) === 't:' && Date.now() < +seen.slice(2)) return; 2533 if (!localStorage.getItem('ps-consent')) return; // cookiebanner gaat voor 2534 } catch (e) { return; } 2535 box.style.display = 'block'; 2536 } 2537 2538 window.addEventListener('beforeinstallprompt', function (e) { 2539 e.preventDefault(); 2540 deferredPrompt = e; 2541 maybeShow(); 2542 }); 2543 window.addEventListener('appinstalled', function () { hide('1'); deferredPrompt = null; }); 2544 2545 document.getElementById('psi-close').addEventListener('click', function () { hide('1'); }); 2546 document.getElementById('psi-later').addEventListener('click', function () { hide('t:' + (Date.now() + 7 * 864e5)); }); 2547 document.getElementById('psi-install').addEventListener('click', function () { 2548 box.style.display = 'none'; 2549 window.PSInstall.trigger(); 2550 }); 2551 2552 // Live adminstatus (beide schakelaars), met sessionStorage-cache (max 1 call/sessie). 2553 var cached = null; 2554 try { cached = sessionStorage.getItem('ps-install-allowed'); } catch (e) {} 2555 if (cached !== null) { 2556 serverAllows = cached === '1'; 2557 maybeShow(); 2558 } else { 2559 fetch('/api/pwa-status', { credentials: 'same-origin' }).then(function (r) { return r.json(); }).then(function (d) { 2560 serverAllows = !!(d && d.ok && d.enabled !== false && d.install_banner !== false); 2561 try { sessionStorage.setItem('ps-install-allowed', serverAllows ? '1' : '0'); } catch (e) {} 2562 maybeShow(); 2563 }).catch(function () { serverAllows = false; }); 2564 } 2565 })(); 2566 </script>
2566 </body> </html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.