{"id":610,"date":"2015-07-29T13:49:24","date_gmt":"2015-07-29T13:49:24","guid":{"rendered":"https:\/\/sichu-blockart-eduskill.sites.qsandbox.com\/?page_id=11"},"modified":"2026-09-27T13:10:51","modified_gmt":"2026-09-27T12:10:51","slug":"blog","status":"publish","type":"page","link":"https:\/\/cctvacademy.be\/nl\/blog\/","title":{"rendered":"Blog"},"content":{"rendered":"\t\t<div data-elementor-type=\"masteriyo-course-archive-page\" data-elementor-id=\"610\" class=\"elementor elementor-610\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e87c0b8 e-flex e-con-boxed e-con e-parent\" data-id=\"e87c0b8\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3151f42 elementor-widget elementor-widget-text-editor\" data-id=\"3151f42\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>under construction<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-5714e7d e-flex e-con-boxed e-con e-parent\" data-id=\"5714e7d\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-971478b elementor-widget elementor-widget-html\" data-id=\"971478b\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<style>\n\/* ==========================================================\n   CCTV ACADEMY\n   SMART KNOWLEDGE HUB\n   WARM BLUEPRINT \/ EDITORIAL EDITION\n   ========================================================== *\/\n\n#cctv-knowledge{\n  --paper:#f2ead8;\n  --paper-light:#fbf7ed;\n  --paper-soft:#e9ddc7;\n  --paper-deep:#ddcbaa;\n\n  --ink:#191b18;\n  --muted:#5b5d54;\n\n  --blue:#285e72;\n  --blue-dark:#173f51;\n  --blue-deep:#102f3d;\n\n  --red:#c9362e;\n  --red-dark:#a92d27;\n\n  --yellow:#e3ab40;\n  --orange:#d9822e;\n  --green:#566b4d;\n  --purple:#685c79;\n\n  --line:rgba(25,32,29,.20);\n  --line-dark:rgba(25,32,29,.42);\n\n  position:relative;\n  isolation:isolate;\n  overflow:hidden;\n\n  max-width:1320px;\n  margin:0 auto;\n\n  color:var(--ink);\n\n  background:\n    linear-gradient(\n      rgba(40,50,45,.03) 1px,\n      transparent 1px\n    ),\n    linear-gradient(\n      90deg,\n      rgba(40,50,45,.03) 1px,\n      transparent 1px\n    ),\n    radial-gradient(\n      circle at 8% 8%,\n      rgba(201,54,46,.045),\n      transparent 24%\n    ),\n    radial-gradient(\n      circle at 94% 30%,\n      rgba(40,94,114,.05),\n      transparent 25%\n    ),\n    var(--paper);\n\n  background-size:\n    34px 34px,\n    34px 34px,\n    auto,\n    auto,\n    auto;\n\n  font-family:Arial,Helvetica,sans-serif;\n  font-size:16px;\n  line-height:1.7;\n}\n\n\n#cctv-knowledge *,\n#cctv-knowledge *::before,\n#cctv-knowledge *::after{\n  box-sizing:border-box;\n}\n\n\n#cctv-knowledge a{\n  color:inherit;\n  text-decoration:none;\n}\n\n\n#cctv-knowledge img{\n  display:block;\n  max-width:100%;\n}\n\n\n#cctv-knowledge button,\n#cctv-knowledge input{\n  font:inherit;\n}\n\n\n#cctv-knowledge button{\n  cursor:pointer;\n}\n\n\n.cvk-wrap{\n  position:relative;\n  z-index:2;\n\n  width:min(1180px,calc(100% - 56px));\n  margin:0 auto;\n}\n\n\n\/* ==========================================================\n   BLUEPRINT GUIDES\n   ========================================================== *\/\n\n.cvk-guide{\n  position:absolute;\n  z-index:0;\n\n  top:0;\n  bottom:0;\n\n  width:1px;\n\n  border-left:1px dashed rgba(29,39,35,.12);\n\n  pointer-events:none;\n}\n\n\n.cvk-guide--left{\n  left:50px;\n}\n\n\n.cvk-guide--middle{\n  left:50%;\n}\n\n\n.cvk-guide--right{\n  right:50px;\n}\n\n\n\/* ==========================================================\n   TYPOGRAPHY\n   ========================================================== *\/\n\n.cvk-eyebrow{\n  display:flex;\n  align-items:center;\n  gap:11px;\n\n  margin-bottom:17px;\n\n  color:var(--blue);\n\n  font-size:10px;\n  font-weight:900;\n  letter-spacing:.14em;\n  text-transform:uppercase;\n}\n\n\n.cvk-eyebrow::before{\n  content:\"\";\n\n  width:35px;\n  height:3px;\n\n  flex:0 0 auto;\n\n  background:var(--red);\n\n  transform:rotate(-2deg);\n}\n\n\n.cvk-title{\n  max-width:900px;\n\n  margin:0 0 22px;\n\n  color:var(--ink);\n\n  font-family:Georgia,\"Times New Roman\",serif;\n  font-size:clamp(38px,5vw,62px);\n  font-weight:900;\n  line-height:.98;\n  letter-spacing:-.045em;\n}\n\n\n.cvk-title span{\n  color:var(--red);\n}\n\n\n.cvk-lead{\n  max-width:800px;\n\n  margin:0;\n\n  color:var(--muted);\n\n  font-size:18px;\n  line-height:1.8;\n}\n\n\n\/* ==========================================================\n   BUTTONS\n   ========================================================== *\/\n\n.cvk-button,\n.cvk-btn{\n  display:inline-flex;\n  align-items:center;\n  justify-content:center;\n  gap:9px;\n\n  min-height:50px;\n  padding:12px 21px;\n\n  border:2px solid var(--ink);\n\n  background:var(--red);\n  color:#fff!important;\n\n  font-size:12px;\n  font-weight:900;\n\n  box-shadow:5px 5px 0 var(--ink);\n\n  transition:\n    transform .2s ease,\n    box-shadow .2s ease,\n    background .2s ease;\n}\n\n\n.cvk-button::after{\n  content:\"\u2192\";\n}\n\n\n.cvk-button:hover,\n.cvk-btn:hover{\n  transform:translate(3px,3px);\n\n  box-shadow:2px 2px 0 var(--ink);\n}\n\n\n.cvk-button--paper{\n  background:var(--paper-light);\n\n  color:var(--ink)!important;\n}\n\n\n\/* ==========================================================\n   HEADER\n   ========================================================== *\/\n\n.cvk-header{\n  position:relative;\n  z-index:10;\n\n  padding:24px 0;\n}\n\n\n.cvk-nav{\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  gap:24px;\n\n  padding:13px 17px;\n\n  border:1px solid var(--line-dark);\n\n  background:rgba(251,247,237,.84);\n}\n\n\n.cvk-brand{\n  display:flex;\n  align-items:center;\n  gap:12px;\n}\n\n\n.cvk-brand-mark{\n  display:grid;\n  place-items:center;\n\n  width:42px;\n  height:42px;\n\n  border:1px solid var(--ink);\n\n  background:var(--blue);\n  color:#fff;\n\n  font-family:Georgia,serif;\n  font-size:13px;\n  font-weight:900;\n\n  box-shadow:3px 3px 0 var(--ink);\n}\n\n\n.cvk-brand strong{\n  display:block;\n\n  color:var(--blue-dark);\n\n  font-size:13px;\n}\n\n\n.cvk-brand small{\n  display:block;\n\n  margin-top:2px;\n\n  color:var(--muted);\n\n  font-size:8px;\n  font-weight:900;\n  letter-spacing:.12em;\n}\n\n\n.cvk-links{\n  display:flex;\n  gap:5px;\n}\n\n\n.cvk-links a{\n  padding:8px 10px;\n\n  color:var(--muted);\n\n  font-size:10px;\n  font-weight:900;\n}\n\n\n.cvk-links a:hover,\n.cvk-links a.active{\n  color:var(--red);\n}\n\n\n.cvk-nav-cta{\n  padding:8px 11px;\n\n  border:1px solid var(--ink);\n\n  background:var(--yellow);\n  color:var(--ink)!important;\n\n  font-size:10px;\n  font-weight:900;\n\n  box-shadow:3px 3px 0 var(--ink);\n}\n\n\n\/* ==========================================================\n   HERO\n   ========================================================== *\/\n\n.cvk-hero{\n  position:relative;\n\n  margin:0 28px 145px;\n  padding:42px;\n\n  border:1px solid var(--line-dark);\n\n  background:\n    linear-gradient(\n      rgba(40,50,45,.04) 1px,\n      transparent 1px\n    ),\n    linear-gradient(\n      90deg,\n      rgba(40,50,45,.04) 1px,\n      transparent 1px\n    ),\n    var(--paper-light);\n\n  background-size:38px 38px;\n\n  box-shadow:\n    0 20px 60px rgba(56,43,24,.08),\n    inset 0 0 100px rgba(120,92,43,.04);\n}\n\n\n.cvk-hero::before,\n.cvk-hero::after{\n  content:\"\";\n\n  position:absolute;\n\n  width:74px;\n  height:74px;\n\n  pointer-events:none;\n}\n\n\n.cvk-hero::before{\n  left:15px;\n  top:15px;\n\n  border-top:1px solid var(--ink);\n  border-left:1px solid var(--ink);\n}\n\n\n.cvk-hero::after{\n  right:15px;\n  bottom:15px;\n\n  border-right:1px solid var(--ink);\n  border-bottom:1px solid var(--ink);\n}\n\n\n.cvk-hero-meta{\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  gap:20px;\n\n  margin-bottom:30px;\n  padding-bottom:14px;\n\n  border-bottom:1px solid var(--line);\n}\n\n\n.cvk-hero-meta strong{\n  color:var(--blue);\n\n  font-size:10px;\n  font-weight:900;\n  letter-spacing:.14em;\n  text-transform:uppercase;\n}\n\n\n.cvk-hero-meta span{\n  color:var(--muted);\n\n  font-family:\"Comic Sans MS\",\"Bradley Hand\",cursive;\n  font-size:14px;\n\n  transform:rotate(-2deg);\n}\n\n\n.cvk-hero-grid{\n  display:grid;\n  grid-template-columns:.9fr 1.1fr;\n  gap:52px;\n\n  align-items:center;\n}\n\n\n.cvk-hero-label{\n  display:inline-flex;\n  align-items:center;\n  gap:8px;\n\n  margin-bottom:24px;\n  padding:8px 12px;\n\n  border:1px solid var(--ink);\n\n  background:var(--yellow);\n\n  font-size:9px;\n  font-weight:900;\n  letter-spacing:.11em;\n  text-transform:uppercase;\n\n  box-shadow:3px 3px 0 var(--ink);\n\n  transform:rotate(-1deg);\n}\n\n\n.cvk-hero-label b{\n  padding:3px 6px;\n\n  background:var(--green);\n  color:#fff;\n}\n\n\n.cvk-hero h1{\n  max-width:640px;\n\n  margin:0 0 26px;\n\n  color:var(--ink);\n\n  font-family:Georgia,\"Times New Roman\",serif;\n  font-size:clamp(49px,6vw,80px);\n  font-weight:900;\n  line-height:.9;\n  letter-spacing:-.055em;\n}\n\n\n.cvk-hero h1 span{\n  display:block;\n\n  margin-top:14px;\n\n  color:var(--red);\n\n  font-family:\"Comic Sans MS\",\"Bradley Hand\",cursive;\n  font-size:.59em;\n  line-height:1.05;\n\n  transform:rotate(-2deg);\n}\n\n\n.cvk-hero-copy p{\n  max-width:620px;\n\n  color:var(--muted);\n\n  font-size:18px;\n}\n\n\n.cvk-hero-copy strong{\n  color:var(--ink);\n}\n\n\n.cvk-hero-info{\n  display:flex;\n  flex-wrap:wrap;\n  gap:8px;\n\n  margin-top:27px;\n}\n\n\n.cvk-hero-info span{\n  padding:6px 9px;\n\n  border:1px solid var(--line-dark);\n\n  background:var(--paper-soft);\n\n  font-size:9px;\n  font-weight:900;\n}\n\n\n\/* ==========================================================\n   HERO ARTWORK\n   ========================================================== *\/\n\n.cvk-hero-art{\n  position:relative;\n\n  min-height:630px;\n}\n\n\n.cvk-art-frame{\n  position:relative;\n\n  display:flex;\n  align-items:center;\n  justify-content:center;\n\n  min-height:600px;\n\n  margin:0;\n  padding:12px;\n\n  border:1px solid var(--line-dark);\n\n  background:#f5ecd9;\n\n  box-shadow:9px 10px 0 rgba(24,26,25,.09);\n\n  transform:rotate(.65deg);\n}\n\n\n.cvk-art-frame::before{\n  content:\"\";\n\n  position:absolute;\n  inset:20px;\n\n  border:1px solid rgba(28,36,33,.12);\n\n  pointer-events:none;\n}\n\n\n.cvk-art-frame img{\n  width:100%;\n  max-height:575px;\n\n  object-fit:contain;\n\n  mix-blend-mode:multiply;\n}\n\n\n.cvk-art-note{\n  position:absolute;\n  z-index:4;\n\n  left:-5px;\n  top:55px;\n\n  max-width:180px;\n\n  padding:11px 14px;\n\n  border:1px solid var(--ink);\n\n  background:var(--blue);\n  color:#fff;\n\n  font-family:\"Comic Sans MS\",\"Bradley Hand\",cursive;\n  font-size:15px;\n  line-height:1.2;\n\n  box-shadow:4px 4px 0 var(--ink);\n\n  transform:rotate(-4deg);\n}\n\n\n.cvk-art-note strong{\n  color:#ffd36a;\n}\n\n\n.cvk-art-caption{\n  position:absolute;\n\n  right:0;\n  bottom:0;\n\n  padding:5px 8px;\n\n  background:var(--paper-light);\n\n  color:var(--muted);\n\n  font-size:8px;\n  font-weight:900;\n  letter-spacing:.1em;\n  text-transform:uppercase;\n}\n\n\n\/* ==========================================================\n   SMART SEARCH\n   ========================================================== *\/\n\n.cvk-search-wrap{\n  position:relative;\n  z-index:5;\n\n  width:min(1080px,calc(100% - 56px));\n\n  margin:-205px auto 125px;\n  padding-top:130px;\n}\n\n\n.cvk-search{\n  padding:29px;\n\n  border:2px solid var(--ink);\n\n  background:var(--paper-light);\n\n  box-shadow:8px 9px 0 var(--ink);\n}\n\n\n.smart-label{\n  display:flex;\n  align-items:center;\n  gap:9px;\n\n  margin-bottom:14px;\n\n  color:var(--blue);\n\n  font-size:9px;\n  font-weight:900;\n  letter-spacing:.13em;\n  text-transform:uppercase;\n}\n\n\n.smart-label::before{\n  content:\"\u25cf\";\n\n  color:var(--green);\n}\n\n\n.search-row{\n  display:grid;\n  grid-template-columns:minmax(0,1fr) auto;\n  gap:11px;\n}\n\n\n.search-field{\n  position:relative;\n}\n\n\n\/* GEEN VERGROOTGLAS\n   tekst start gewoon links *\/\n\n.search-input{\n  width:100%;\n  min-height:61px;\n\n  padding:0 48px 0 16px;\n\n  border:1px solid var(--line-dark);\n  border-radius:0;\n\n  outline:none;\n\n  background:#fff;\n  color:var(--ink);\n\n  font-size:15px;\n}\n\n\n.search-input::placeholder{\n  color:#8d8c82;\n}\n\n\n.search-input:focus{\n  border:2px solid var(--blue);\n\n  box-shadow:3px 3px 0 var(--blue);\n}\n\n\n.clear-search{\n  position:absolute;\n\n  right:13px;\n  top:50%;\n\n  display:none;\n  place-items:center;\n\n  width:29px;\n  height:29px;\n\n  border:1px solid var(--line-dark);\n  border-radius:0;\n\n  background:var(--paper-soft);\n  color:var(--ink);\n\n  transform:translateY(-50%);\n}\n\n\n.clear-search.visible{\n  display:grid;\n}\n\n\n.search-button{\n  min-width:175px;\n\n  border:2px solid var(--ink);\n\n  background:var(--red);\n  color:#fff;\n\n  font-size:12px;\n  font-weight:900;\n\n  box-shadow:4px 4px 0 var(--ink);\n}\n\n\n.search-button:hover{\n  background:var(--red-dark);\n}\n\n\n.search-button.is-loading{\n  opacity:.7;\n\n  cursor:progress;\n}\n\n\n.search-examples{\n  display:flex;\n  flex-wrap:wrap;\n  gap:7px;\n\n  margin-top:16px;\n}\n\n\n.search-examples > span{\n  display:flex;\n  align-items:center;\n\n  color:var(--muted);\n\n  font-size:9px;\n  font-weight:900;\n}\n\n\n.example-search{\n  padding:6px 9px;\n\n  border:1px solid var(--line-dark);\n  border-radius:0;\n\n  background:var(--paper-soft);\n  color:var(--muted);\n\n  font-size:9px;\n  font-weight:900;\n}\n\n\n.example-search:hover{\n  border-color:var(--red);\n\n  color:var(--red);\n}\n\n\n.search-intelligence{\n  display:none;\n\n  margin-top:18px;\n  padding-top:17px;\n\n  border-top:1px solid var(--line);\n}\n\n\n.search-intelligence.visible{\n  display:block;\n}\n\n\n.interpretation{\n  display:flex;\n  flex-wrap:wrap;\n  align-items:center;\n  gap:7px;\n}\n\n\n.interpretation-label{\n  color:var(--muted);\n\n  font-size:9px;\n  font-weight:900;\n}\n\n\n.concept-chip{\n  padding:5px 8px;\n\n  border:1px solid var(--blue);\n\n  background:#e6ede9;\n  color:var(--blue);\n\n  font-size:8px;\n  font-weight:900;\n}\n\n\n.search-scope{\n  margin-top:9px;\n\n  color:var(--muted);\n\n  font-size:8px;\n}\n\n\n\/* ==========================================================\n   FEATURED ARTICLE\n   ========================================================== *\/\n\n.cvk-featured{\n  margin-bottom:145px;\n}\n\n\n.featured-card{\n  display:grid;\n  grid-template-columns:1fr 1fr;\n\n  overflow:hidden;\n\n  min-height:480px;\n\n  border:1px solid var(--ink);\n\n  background:var(--blue-dark);\n\n  box-shadow:9px 10px 0 var(--ink);\n}\n\n\n.featured-visual{\n  position:relative;\n  overflow:hidden;\n\n  min-height:470px;\n\n  background:\n    linear-gradient(\n      rgba(255,255,255,.04) 1px,\n      transparent 1px\n    ),\n    linear-gradient(\n      90deg,\n      rgba(255,255,255,.04) 1px,\n      transparent 1px\n    ),\n    var(--blue-deep);\n\n  background-size:31px 31px;\n}\n\n\n.featured-placeholder,\n.image-placeholder{\n  position:absolute;\n  inset:0;\n\n  display:grid;\n  place-items:center;\n\n  color:rgba(255,255,255,.25);\n}\n\n\n.featured-placeholder svg{\n  width:90px;\n}\n\n\n.featured-visual img{\n  position:absolute;\n  inset:0;\n\n  width:100%;\n  height:100%;\n\n  object-fit:cover;\n\n  opacity:0;\n\n  filter:\n    sepia(.12)\n    saturate(.75)\n    contrast(1.05);\n\n  transition:\n    opacity .3s ease,\n    transform .4s ease;\n}\n\n\n.featured-visual img.loaded{\n  opacity:.72;\n}\n\n\n.featured-card:hover\n.featured-visual img.loaded{\n  transform:scale(1.035);\n}\n\n\n.featured-content{\n  display:flex;\n  flex-direction:column;\n  justify-content:center;\n\n  padding:48px;\n\n  color:#fff;\n}\n\n\n.featured-label{\n  margin-bottom:18px;\n\n  color:#f0bd4d;\n\n  font-size:9px;\n  font-weight:900;\n  letter-spacing:.14em;\n  text-transform:uppercase;\n}\n\n\n.featured-topic{\n  margin-bottom:9px;\n\n  color:#b7ced4;\n\n  font-size:9px;\n  font-weight:900;\n  text-transform:uppercase;\n}\n\n\n.featured-title{\n  margin:0;\n\n  color:#fff;\n\n  font-family:Georgia,serif;\n  font-size:clamp(30px,4vw,46px);\n  line-height:1.05;\n}\n\n\n.featured-excerpt{\n  margin:19px 0 25px;\n\n  color:#d3dedb;\n\n  font-size:13px;\n}\n\n\n.featured-footer{\n  display:flex;\n  align-items:center;\n  justify-content:space-between;\n  gap:18px;\n\n  margin-top:auto;\n}\n\n\n.read-more{\n  color:#f0bd4d!important;\n\n  font-size:11px;\n  font-weight:900;\n}\n\n\n.featured-date{\n  color:#9cafaf;\n\n  font-size:9px;\n}\n\n\n\/* ==========================================================\n   KNOWLEDGE RESULTS\n   ========================================================== *\/\n\n.cvk-knowledge{\n  margin-bottom:145px;\n\n  scroll-margin-top:25px;\n}\n\n\n.results-head{\n  display:grid;\n  grid-template-columns:minmax(0,1fr) auto;\n  gap:35px;\n\n  align-items:start;\n\n  margin-bottom:34px;\n}\n\n\n.result-summary{\n  padding:7px 10px;\n\n  border:1px solid var(--line-dark);\n\n  background:var(--paper-light);\n  color:var(--muted);\n\n  font-size:9px;\n  font-weight:900;\n}\n\n\n.result-query{\n  display:none;\n\n  margin-top:12px;\n\n  color:var(--muted);\n\n  font-size:11px;\n}\n\n\n.result-query.visible{\n  display:block;\n}\n\n\n.result-query strong{\n  color:var(--ink);\n}\n\n\n\/* ==========================================================\n   SEARCH PROGRESS\n   ========================================================== *\/\n\n.search-progress{\n  display:none;\n\n  grid-template-columns:auto 1fr auto;\n  gap:15px;\n\n  align-items:center;\n\n  margin-top:22px;\n  padding:15px;\n\n  border:1px solid var(--blue);\n\n  background:#e9eee8;\n}\n\n\n.search-progress.visible{\n  display:grid;\n}\n\n\n.search-progress.has-results{\n  border-color:var(--green);\n\n  background:#e9eedf;\n}\n\n\n.search-spinner{\n  width:39px;\n  height:39px;\n\n  border:5px solid rgba(40,94,114,.15);\n  border-top-color:var(--blue);\n  border-radius:50%;\n\n  animation:cvk-spin .75s linear infinite;\n}\n\n\n@keyframes cvk-spin{\n  to{\n    transform:rotate(360deg);\n  }\n}\n\n\n.search-progress-copy strong{\n  display:block;\n\n  color:var(--blue-dark);\n\n  font-size:12px;\n}\n\n\n.search-progress-copy > span{\n  display:block;\n\n  margin-top:2px;\n\n  color:var(--muted);\n\n  font-size:9px;\n}\n\n\n.search-progress-bar{\n  overflow:hidden;\n\n  height:5px;\n\n  margin-top:9px;\n\n  background:var(--paper-deep);\n}\n\n\n.search-progress-value{\n  width:0;\n  height:100%;\n\n  background:var(--red);\n\n  transition:width .2s ease;\n}\n\n\n.speed-status{\n  display:flex;\n  flex-wrap:wrap;\n  gap:5px;\n\n  margin-top:8px;\n}\n\n\n.speed-chip{\n  padding:3px 6px;\n\n  border:1px solid var(--line-dark);\n\n  color:var(--muted);\n\n  font-size:7px;\n  font-weight:900;\n}\n\n\n.speed-chip.done{\n  border-color:var(--green);\n\n  color:var(--green);\n}\n\n\n.search-countdown{\n  min-width:65px;\n\n  padding:8px;\n\n  border:1px solid var(--line-dark);\n\n  background:var(--paper-light);\n\n  text-align:center;\n}\n\n\n.search-countdown strong{\n  display:block;\n\n  color:var(--red);\n\n  font-family:Georgia,serif;\n  font-size:23px;\n  line-height:1;\n}\n\n\n.search-countdown span{\n  display:block;\n\n  margin-top:4px;\n\n  color:var(--muted);\n\n  font-size:7px;\n  font-weight:900;\n}\n\n\n.live-result-note{\n  display:none;\n\n  margin-bottom:18px;\n  padding:11px 13px;\n\n  border-left:4px solid var(--green);\n\n  background:#e8eddf;\n\n  color:var(--green);\n\n  font-size:9px;\n  font-weight:900;\n}\n\n\n.live-result-note.visible{\n  display:block;\n}\n\n\n\/* ==========================================================\n   ARTICLE GRID\n   ========================================================== *\/\n\n.article-grid{\n  display:grid;\n  grid-template-columns:repeat(3,1fr);\n  gap:20px;\n}\n\n\n.article-card{\n  position:relative;\n  overflow:hidden;\n\n  display:flex;\n  flex-direction:column;\n\n  min-height:100%;\n\n  border:1px solid var(--line-dark);\n\n  background:var(--paper-light);\n\n  box-shadow:5px 6px 0 rgba(24,26,25,.07);\n\n  transition:\n    transform .2s ease,\n    box-shadow .2s ease;\n}\n\n\n.article-card:hover{\n  transform:translateY(-5px);\n\n  box-shadow:8px 9px 0 rgba(24,26,25,.11);\n}\n\n\n.article-image{\n  position:relative;\n  overflow:hidden;\n\n  aspect-ratio:16 \/ 9;\n\n  border-bottom:1px solid var(--line-dark);\n\n  background:\n    linear-gradient(\n      rgba(40,94,114,.06) 1px,\n      transparent 1px\n    ),\n    linear-gradient(\n      90deg,\n      rgba(40,94,114,.06) 1px,\n      transparent 1px\n    ),\n    var(--paper-soft);\n\n  background-size:24px 24px;\n}\n\n\n.image-placeholder{\n  color:var(--blue);\n}\n\n\n.image-placeholder svg{\n  width:58px;\n}\n\n\n.article-image img{\n  position:absolute;\n  inset:0;\n\n  width:100%;\n  height:100%;\n\n  object-fit:cover;\n\n  opacity:0;\n\n  filter:\n    sepia(.1)\n    saturate(.76)\n    contrast(1.04);\n\n  transition:\n    opacity .3s ease,\n    transform .4s ease;\n}\n\n\n.article-image img.loaded{\n  opacity:1;\n}\n\n\n.article-card:hover\n.article-image img.loaded{\n  transform:scale(1.04);\n}\n\n\n.topic-badge{\n  position:absolute;\n  z-index:3;\n\n  left:11px;\n  top:11px;\n\n  padding:5px 8px;\n\n  border:1px solid var(--ink);\n\n  background:var(--yellow);\n  color:var(--ink);\n\n  font-size:8px;\n  font-weight:900;\n}\n\n\n.relevance{\n  position:absolute;\n  z-index:3;\n\n  right:11px;\n  top:11px;\n\n  padding:5px 8px;\n\n  border:1px solid var(--ink);\n\n  background:var(--green);\n  color:#fff;\n\n  font-size:7px;\n  font-weight:900;\n}\n\n\n.article-body{\n  display:flex;\n  flex:1;\n  flex-direction:column;\n\n  padding:21px;\n}\n\n\n.article-meta{\n  display:flex;\n  align-items:center;\n  gap:7px;\n\n  margin-bottom:10px;\n\n  color:var(--muted);\n\n  font-size:8px;\n  font-weight:900;\n}\n\n\n.meta-dot{\n  width:3px;\n  height:3px;\n\n  border-radius:50%;\n\n  background:var(--red);\n}\n\n\n.article-title{\n  margin:0;\n\n  color:var(--blue-dark);\n\n  font-family:Georgia,serif;\n  font-size:20px;\n  line-height:1.2;\n}\n\n\n.article-excerpt{\n  margin:11px 0 18px;\n\n  color:var(--muted);\n\n  font-size:11px;\n}\n\n\n.matched-on{\n  margin-bottom:15px;\n\n  color:var(--green);\n\n  font-size:8px;\n  font-weight:900;\n}\n\n\n.article-footer{\n  display:flex;\n  justify-content:space-between;\n\n  margin-top:auto;\n  padding-top:15px;\n\n  border-top:1px solid var(--line);\n\n  color:var(--red);\n\n  font-size:9px;\n  font-weight:900;\n}\n\n\n\/* ==========================================================\n   EMPTY \/ LOAD MORE\n   ========================================================== *\/\n\n.empty{\n  grid-column:1 \/ -1;\n\n  padding:55px 24px;\n\n  border:2px dashed var(--blue);\n\n  background:var(--paper-light);\n\n  text-align:center;\n}\n\n\n.empty h3{\n  margin:0;\n\n  font-family:Georgia,serif;\n}\n\n\n.empty p{\n  color:var(--muted);\n\n  font-size:11px;\n}\n\n\n.load-more-wrap{\n  display:flex;\n  justify-content:center;\n\n  margin-top:37px;\n}\n\n\n.load-more{\n  display:none;\n\n  background:var(--paper-light);\n\n  color:var(--ink)!important;\n}\n\n\n\/* ==========================================================\n   LEARNING BRIDGE\n   ========================================================== *\/\n\n.cvk-learning{\n  display:grid;\n  grid-template-columns:1fr .8fr;\n  gap:50px;\n\n  align-items:center;\n\n  margin-bottom:145px;\n  padding:47px;\n\n  border:2px solid var(--ink);\n\n  background:\n    linear-gradient(\n      rgba(255,255,255,.035) 1px,\n      transparent 1px\n    ),\n    linear-gradient(\n      90deg,\n      rgba(255,255,255,.035) 1px,\n      transparent 1px\n    ),\n    var(--blue-dark);\n\n  background-size:31px 31px;\n\n  color:#fff;\n\n  box-shadow:9px 10px 0 var(--ink);\n}\n\n\n.cvk-learning .cvk-eyebrow{\n  color:#d7e4e6;\n}\n\n\n.cvk-learning .cvk-eyebrow::before{\n  background:var(--yellow);\n}\n\n\n.cvk-learning h2{\n  margin:0 0 19px;\n\n  color:#fff;\n\n  font-family:Georgia,serif;\n  font-size:clamp(36px,4.5vw,55px);\n  line-height:.98;\n}\n\n\n.cvk-learning h2 span{\n  display:block;\n\n  margin-top:8px;\n\n  color:#f0bd4d;\n\n  font-family:\"Comic Sans MS\",\"Bradley Hand\",cursive;\n}\n\n\n.cvk-learning p{\n  max-width:690px;\n\n  color:#d6e1df;\n}\n\n\n.cvk-learning-actions{\n  display:flex;\n  flex-wrap:wrap;\n  gap:11px;\n\n  margin-top:27px;\n}\n\n\n.cvk-learning-card{\n  position:relative;\n\n  min-height:400px;\n}\n\n\n.cvk-learning-art{\n  height:370px;\n\n  margin:0;\n  padding:9px;\n\n  border:1px solid rgba(255,255,255,.25);\n\n  background:#efe4cf;\n\n  box-shadow:6px 7px 0 #0a1110;\n\n  transform:rotate(2deg);\n}\n\n\n.cvk-learning-art img{\n  width:100%;\n  height:100%;\n\n  object-fit:contain;\n\n  mix-blend-mode:multiply;\n}\n\n\n.cvk-learning-note{\n  position:absolute;\n\n  left:-8px;\n  bottom:13px;\n\n  padding:10px 12px;\n\n  border:1px solid var(--ink);\n\n  background:var(--red);\n  color:#fff;\n\n  font-family:\"Comic Sans MS\",\"Bradley Hand\",cursive;\n  font-size:14px;\n\n  box-shadow:4px 4px 0 var(--ink);\n\n  transform:rotate(-4deg);\n}\n\n\n\/* ==========================================================\n   FOOTER\n   ========================================================== *\/\n\n.cvk-footer{\n  padding:55px 0 30px;\n\n  border-top:1px solid var(--line-dark);\n\n  background:#e8dcc5;\n}\n\n\n.cvk-footer-grid{\n  display:grid;\n  grid-template-columns:1.3fr repeat(3,.7fr);\n  gap:40px;\n\n  padding-bottom:40px;\n\n  border-bottom:1px solid var(--line-dark);\n}\n\n\n.cvk-footer-brand strong{\n  color:var(--blue-dark);\n\n  font-family:Georgia,serif;\n  font-size:21px;\n}\n\n\n.cvk-footer-brand p{\n  max-width:350px;\n\n  color:var(--muted);\n\n  font-size:10px;\n}\n\n\n.cvk-footer-column h4{\n  margin:0 0 10px;\n\n  color:var(--red);\n\n  font-size:9px;\n  text-transform:uppercase;\n}\n\n\n.cvk-footer-column a{\n  display:block;\n\n  margin-top:7px;\n\n  color:var(--muted);\n\n  font-size:10px;\n}\n\n\n.cvk-footer-column a:hover{\n  color:var(--red);\n}\n\n\n.cvk-footer-bottom{\n  display:flex;\n  justify-content:space-between;\n  gap:20px;\n\n  padding-top:23px;\n\n  color:var(--muted);\n\n  font-size:9px;\n}\n\n\n.cvk-status::before{\n  content:\"\u25cf\";\n\n  margin-right:7px;\n\n  color:var(--green);\n}\n\n\n\/* ==========================================================\n   RESPONSIVE\n   ========================================================== *\/\n\n@media(max-width:1000px){\n\n  .cvk-links{\n    display:none;\n  }\n\n\n  .cvk-hero-grid,\n  .featured-card,\n  .cvk-learning{\n    grid-template-columns:1fr;\n  }\n\n\n  .cvk-hero-art{\n    width:100%;\n    max-width:750px;\n\n    margin:0 auto;\n  }\n\n\n  .article-grid{\n    grid-template-columns:1fr 1fr;\n  }\n\n\n  .cvk-footer-grid{\n    grid-template-columns:1fr 1fr;\n  }\n\n}\n\n\n@media(max-width:700px){\n\n  .cvk-wrap{\n    width:min(100% - 28px,1180px);\n  }\n\n\n  .cvk-guide{\n    display:none;\n  }\n\n\n  .cvk-header{\n    padding:14px 0;\n  }\n\n\n  .cvk-nav{\n    padding:10px;\n  }\n\n\n  .cvk-brand small{\n    display:none;\n  }\n\n\n  .cvk-nav-cta{\n    font-size:8px;\n  }\n\n\n  .cvk-hero{\n    margin:0 14px 110px;\n    padding:24px 19px 30px;\n  }\n\n\n  .cvk-hero-meta{\n    align-items:flex-start;\n    flex-direction:column;\n  }\n\n\n  .cvk-hero h1{\n    font-size:45px;\n  }\n\n\n  .cvk-hero-art{\n    min-height:500px;\n  }\n\n\n  .cvk-art-frame{\n    min-height:475px;\n  }\n\n\n  .cvk-art-frame img{\n    max-height:450px;\n  }\n\n\n  .cvk-art-note{\n    left:4px;\n    top:30px;\n\n    max-width:145px;\n\n    font-size:13px;\n  }\n\n\n  .cvk-search-wrap{\n    width:min(100% - 28px,1080px);\n\n    margin:-170px auto 90px;\n    padding-top:100px;\n  }\n\n\n  .cvk-search{\n    padding:20px;\n  }\n\n\n  .search-row{\n    grid-template-columns:1fr;\n  }\n\n\n  .search-button{\n    min-height:52px;\n  }\n\n\n  .results-head{\n    grid-template-columns:1fr;\n  }\n\n\n  .search-progress{\n    grid-template-columns:auto 1fr;\n  }\n\n\n  .search-countdown{\n    grid-column:1 \/ -1;\n  }\n\n\n  .article-grid{\n    grid-template-columns:1fr;\n  }\n\n\n  .featured-content{\n    padding:30px 23px;\n  }\n\n\n  .featured-visual{\n    min-height:300px;\n  }\n\n\n  .cvk-learning{\n    padding:29px 21px;\n  }\n\n\n  .cvk-learning-art{\n    height:330px;\n  }\n\n\n  .cvk-footer-grid{\n    grid-template-columns:1fr;\n  }\n\n\n  .cvk-footer-bottom{\n    flex-direction:column;\n  }\n\n}\n\n\n@media(prefers-reduced-motion:reduce){\n\n  #cctv-knowledge *,\n  #cctv-knowledge *::before,\n  #cctv-knowledge *::after{\n    animation:none!important;\n    transition:none!important;\n  }\n\n}\n\n\/* ==========================================================\n   CCTV ACADEMY \u00b7 LANGUAGE SWITCHER\n   ========================================================== *\/\n#cctv-knowledge .cctv-language-bar{\n  display:flex;\n  justify-content:flex-end;\n  align-items:center;\n  gap:10px;\n  width:min(1180px,calc(100% - 56px));\n  margin:0 auto;\n  padding:18px 0 0;\n  color:var(--ink);\n  font-size:12px;\n  font-weight:800;\n  letter-spacing:.04em;\n}\n#cctv-knowledge .cctv-language-bar__label{\n  color:var(--muted);\n}\n#cctv-knowledge .cctv-language-switcher{\n  display:inline-flex;\n  overflow:hidden;\n  border:1px solid var(--line-dark);\n  background:var(--paper-light);\n  box-shadow:3px 3px 0 rgba(24,26,25,.10);\n}\n#cctv-knowledge .cctv-language-switcher button{\n  appearance:none;\n  border:0;\n  border-right:1px solid var(--line-dark);\n  padding:7px 11px;\n  background:transparent;\n  color:var(--blue-dark);\n  font:inherit;\n  font-size:12px;\n  font-weight:900;\n  cursor:pointer;\n  transition:.18s ease;\n}\n#cctv-knowledge .cctv-language-switcher button:last-child{\n  border-right:0;\n}\n#cctv-knowledge .cctv-language-switcher button:hover{\n  background:var(--paper-soft);\n}\n#cctv-knowledge .cctv-language-switcher button.is-active{\n  background:var(--red);\n  color:#fff;\n}\n@media(max-width:700px){\n  #cctv-knowledge .cctv-language-bar{\n    width:min(100% - 28px,1180px);\n    justify-content:space-between;\n    gap:8px;\n    padding-top:14px;\n  }\n  #cctv-knowledge .cctv-language-bar__label{font-size:11px;}\n  #cctv-knowledge .cctv-language-switcher button{padding:7px 10px;}\n}\n<\/style>\n<main id=\"cctv-knowledge\"><div aria-label=\"Taalkeuze \u00b7 S\u00e9lecteur de langue \u00b7 Language selector\" class=\"cctv-language-bar\"><span class=\"cctv-language-bar__label\">Taal \u00b7 Langue \u00b7 Language<\/span><div aria-label=\"NL \/ FR \/ EN\" class=\"cctv-language-switcher\" role=\"group\"><button aria-pressed=\"false\" data-lang=\"nl\" type=\"button\">NL<\/button><button aria-pressed=\"false\" data-lang=\"fr\" type=\"button\">FR<\/button><button aria-pressed=\"false\" data-lang=\"en\" type=\"button\">EN<\/button><\/div><\/div>\n<span aria-hidden=\"true\" class=\"cvk-guide cvk-guide--left\">\n<\/span>\n<span aria-hidden=\"true\" class=\"cvk-guide cvk-guide--middle\">\n<\/span>\n<span aria-hidden=\"true\" class=\"cvk-guide cvk-guide--right\">\n<\/span>\n<!-- ======================================================\n       HEADER\n       ====================================================== -->\n<header class=\"cvk-header\">\n<div class=\"cvk-wrap\">\n<div class=\"cvk-nav\">\n<a class=\"cvk-brand\" href=\"https:\/\/cctvacademy.be\/nl\/\">\n<span class=\"cvk-brand-mark\">\n            CCTV\n          <\/span>\n<span>\n<strong>\n              CCTV Academy\n            <\/strong>\n<small>\n              CCTV \u00b7 AI \u00b7 SECURITY \u00b7 TRAINING\n            <\/small>\n<\/span>\n<\/a>\n<nav class=\"cvk-links\">\n<a href=\"https:\/\/cctvacademy.be\/nl\/\">\n            Home\n          <\/a>\n<a class=\"active\" href=\"https:\/\/cctvacademy.be\/nl\/blog\/\">\n            Kennisbank\n          <\/a>\n<a href=\"https:\/\/cctvacademy.be\/nl\/opleidingen\/\">\n            Opleidingen\n          <\/a>\n<a href=\"https:\/\/cctvacademy.be\/nl\/contact\/\">\n            Contact\n          <\/a>\n<\/nav>\n<a class=\"cvk-nav-cta\" href=\"https:\/\/cctvacademy.be\/nl\/opleidingen\/\">\n\n          Bekijk opleidingen \u2197\n\n        <\/a>\n<\/div>\n<\/div>\n<\/header>\n<!-- ======================================================\n       HERO\n       ====================================================== -->\n<section class=\"cvk-hero\">\n<div class=\"cvk-hero-meta\">\n<strong>\n        CCTV Academy \u00b7 Smart Knowledge Search\n      <\/strong>\n<span>\n        vraag \u2192 techniek \u2192 antwoord\n      <\/span>\n<\/div>\n<div class=\"cvk-hero-grid\">\n<div class=\"cvk-hero-copy\">\n<div class=\"cvk-hero-label\">\n<b>\n            LIVE\n          <\/b>\n\n          CCTV Kennisbank\n\n        <\/div>\n<h1>\n\n          Zoek een probleem.\n\n          <span>\n            Vind de oplossing.\n          <\/span>\n<\/h1>\n<p>\n\n          Doorzoek de CCTV Academy-kennisbank\n          in gewone taal.\n\n          Zoek bijvoorbeeld op\n\n          <strong>\n            \u201ccamera neemt geen nummerplaat\u201d,\n            \u201choe reset ik mijn NVR?\u201d\n          <\/strong>\n\n          of\n\n          <strong>\n            \u201cmag ik mijn buur filmen?\u201d.\n          <\/strong>\n<\/p>\n<p>\n\n          De zoekmachine koppelt\n          jouw vraag automatisch\n          aan relevante technische CCTV-termen.\n\n        <\/p>\n<div class=\"cvk-hero-info\">\n<span>\n            CCTV-synoniemen\n          <\/span>\n<span>\n            Relevantie\n          <\/span>\n<span>\n            Slim zoeken\n          <\/span>\n<\/div>\n<\/div>\n<div class=\"cvk-hero-art\">\n<div class=\"cvk-art-note\">\n\n          Niet zoeken naar\n          de juiste knop.\n\n          <br\/><br\/>\n<strong>\n            Begrijpen wat er gebeurt.\n          <\/strong>\n<\/div>\n<figure class=\"cvk-art-frame\">\n<img data-recalc-dims=\"1\" alt=\"CCTV Academy technische Micro-Learning illustratie\" decoding=\"async\" fetchpriority=\"high\" loading=\"eager\" src=\"https:\/\/i0.wp.com\/cctvacademy.be\/wp-content\/uploads\/2026\/09\/CCTV-Academy-Wouter-Rooseboom-CCTV-Micro-Learning.png?w=812&#038;ssl=1\"\/>\n<\/figure>\n<span class=\"cvk-art-caption\">\n          Fig. 01 \u00b7 CCTV Academy Knowledge Map\n        <\/span>\n<\/div>\n<\/div>\n<\/section>\n<!-- ======================================================\n       SMART SEARCH\n       ====================================================== -->\n<section class=\"cvk-search-wrap\">\n<div class=\"cvk-search\">\n<div class=\"smart-label\">\n        Slim zoeken in CCTV kennis\n      <\/div>\n<div class=\"search-row\">\n<div class=\"search-field\">\n<input aria-label=\"Doorzoek de CCTV kennisbank\" autocomplete=\"off\" class=\"search-input\" id=\"searchInput\" placeholder=\"Beschrijf je vraag: bv. camera neemt geen nummerplaat...\" spellcheck=\"false\" type=\"search\"\/>\n<button aria-label=\"Zoekopdracht wissen\" class=\"clear-search\" id=\"clearSearch\" type=\"button\">\n\n            \u00d7\n\n          <\/button>\n<\/div>\n<button class=\"search-button\" id=\"searchButton\" type=\"button\">\n\n          Zoek in kennisbank\n\n        <\/button>\n<\/div>\n<div class=\"search-examples\">\n<span>\n          Probeer:\n        <\/span>\n<button class=\"example-search\" data-query=\"camera neemt geen nummerplaat\" type=\"button\">\n\n          Nummerplaat niet leesbaar\n\n        <\/button>\n<button class=\"example-search\" data-query=\"hoe reset ik mijn NVR\" type=\"button\">\n\n          NVR resetten\n\n        <\/button>\n<button class=\"example-search\" data-query=\"mag ik mijn buur filmen\" type=\"button\">\n\n          Buur filmen\n\n        <\/button>\n<button class=\"example-search\" data-query=\"PoE voeding camera\" type=\"button\">\n\n          PoE voeding\n\n        <\/button>\n<button class=\"example-search\" data-query=\"camerabeelden smartphone\" type=\"button\">\n\n          Smartphone\n\n        <\/button>\n<\/div>\n<div class=\"search-intelligence\" id=\"searchIntelligence\">\n<div class=\"interpretation\" id=\"interpretation\">\n<\/div>\n<div class=\"search-scope\">\n\n          Jouw vraag wordt gecombineerd\n          met technische CCTV-termen\n          en doorzocht\n          in de bestaande WordPress-kennisbank.\n\n        <\/div>\n<\/div>\n<\/div>\n<\/section>\n<!-- ======================================================\n       FEATURED\n       ====================================================== -->\n<section class=\"cvk-featured\">\n<div class=\"cvk-wrap\">\n<span class=\"cvk-eyebrow\">\n        Nieuw in de kennisbank\n      <\/span>\n<article class=\"featured-card\">\n<div class=\"featured-visual\">\n<div class=\"featured-placeholder\">\n<svg aria-hidden=\"true\" fill=\"none\" viewbox=\"0 0 100 70\">\n<rect height=\"40\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"2.5\" width=\"58\" x=\"7\" y=\"15\">\n<\/rect>\n<path d=\"m65 26 28-11v40L65 44\" stroke=\"currentColor\" stroke-width=\"2.5\">\n<\/path>\n<\/svg>\n<\/div>\n<img decoding=\"async\" alt=\"\" id=\"featuredImage\" src=\"\"\/>\n<\/div>\n<div class=\"featured-content\">\n<span class=\"featured-label\">\n            Laatste technische artikel\n          <\/span>\n<span class=\"featured-topic\" id=\"featuredTopic\">\n\n            CCTV Academy\n\n          <\/span>\n<h2 class=\"featured-title\" id=\"featuredTitle\">\n\n            Kennisbank wordt geladen\u2026\n\n          <\/h2>\n<p class=\"featured-excerpt\" id=\"featuredExcerpt\">\n\n            De nieuwste praktische CCTV-kennis\n            wordt opgehaald.\n\n          <\/p>\n<div class=\"featured-footer\">\n<a class=\"read-more\" href=\"#\" id=\"featuredLink\">\n\n              Lees artikel \u2192\n\n            <\/a>\n<span class=\"featured-date\" id=\"featuredDate\">\n\n              CCTV Academy\n\n            <\/span>\n<\/div>\n<\/div>\n<\/article>\n<\/div>\n<\/section>\n<!-- ======================================================\n       KNOWLEDGE RESULTS\n       ====================================================== -->\n<section class=\"cvk-knowledge\" id=\"kennisbank\">\n<div class=\"cvk-wrap\">\n<div class=\"results-head\">\n<div>\n<span class=\"cvk-eyebrow\">\n            CCTV Kennisbank\n          <\/span>\n<h2 class=\"cvk-title\" id=\"searchResultsTitle\">\n\n            Vind precies\n\n            <span>\n              wat je nodig hebt.\n            <\/span>\n<\/h2>\n<div aria-live=\"polite\" class=\"search-progress\" id=\"searchProgress\">\n<div class=\"search-spinner\">\n<\/div>\n<div class=\"search-progress-copy\">\n<strong id=\"searchProgressTitle\">\n                Kennisbank wordt doorzocht\u2026\n              <\/strong>\n<span id=\"searchProgressDetail\">\n                Zoekvraag analyseren.\n              <\/span>\n<div class=\"search-progress-bar\">\n<div class=\"search-progress-value\" id=\"searchProgressValue\">\n<\/div>\n<\/div>\n<div class=\"speed-status\" id=\"speedStatus\">\n<\/div>\n<\/div>\n<div class=\"search-countdown\">\n<strong id=\"searchCountdown\">\n                8\n              <\/strong>\n<span>\n                sec richttijd\n              <\/span>\n<\/div>\n<\/div>\n<div class=\"result-query\" id=\"resultQuery\">\n<\/div>\n<\/div>\n<div class=\"result-summary\" id=\"resultSummary\">\n\n          Artikels laden...\n\n        <\/div>\n<\/div>\n<div class=\"live-result-note\" id=\"liveResultNote\">\n\n        De eerste resultaten zijn beschikbaar.\n        Andere technische zoekroutes\n        worden nog gecontroleerd.\n\n      <\/div>\n<div class=\"article-grid\" id=\"articleGrid\">\n<\/div>\n<div class=\"load-more-wrap\">\n<button class=\"cvk-btn load-more\" id=\"loadMore\" type=\"button\">\n\n          Meer resultaten tonen\n\n        <\/button>\n<\/div>\n<\/div>\n<\/section>\n<!-- ======================================================\n       LEARNING BRIDGE\n       ====================================================== -->\n<section class=\"cvk-wrap\">\n<div class=\"cvk-learning\">\n<div>\n<span class=\"cvk-eyebrow\">\n          Van zoeken naar kunnen\n        <\/span>\n<h2>\n\n          Een artikel geeft antwoord.\n\n          <span>\n            Zelf testen geeft inzicht.\n          <\/span>\n<\/h2>\n<p>\n\n          Wil je camera's,\n          NVR's,\n          IP-netwerken\n          en AI-functies\n          niet alleen opzoeken,\n          maar ook zelf aansluiten,\n          configureren\n          en testen?\n\n        <\/p>\n<div class=\"cvk-learning-actions\">\n<a class=\"cvk-button\" href=\"https:\/\/cctvacademy.be\/nl\/opleidingen\/\">\n\n            Bekijk opleidingen\n\n          <\/a>\n<a class=\"cvk-button cvk-button--paper\" href=\"https:\/\/cctvacademy.be\/nl\/contact\/\">\n\n            Stel een vraag\n\n          <\/a>\n<\/div>\n<\/div>\n<div class=\"cvk-learning-card\">\n<figure class=\"cvk-learning-art\">\n<img data-recalc-dims=\"1\" alt=\"CCTV Academy Micro-Learning\" decoding=\"async\" loading=\"lazy\" src=\"https:\/\/i0.wp.com\/cctvacademy.be\/wp-content\/uploads\/2026\/09\/CCTV-Academy-Wouter-Rooseboom-CCTV-Micro-Learning.png?w=812&#038;ssl=1\"\/>\n<\/figure>\n<div class=\"cvk-learning-note\">\n\n          lezen \u2192 aansluiten<br\/>\n          configureren \u2192 testen\n\n        <\/div>\n<\/div>\n<\/div>\n<\/section>\n<!-- ======================================================\n       FOOTER\n       ====================================================== -->\n<footer class=\"cvk-footer\">\n<div class=\"cvk-wrap\">\n<div class=\"cvk-footer-grid\">\n<div class=\"cvk-footer-brand\">\n<strong>\n            CCTV Academy\n          <\/strong>\n<p>\n            Praktische CCTV-kennis\n            en opleidingen\n            voor installateurs,\n            integratoren\n            en beveiligingsprofessionals.\n          <\/p>\n<\/div>\n<div class=\"cvk-footer-column\">\n<h4>\n            Kennis\n          <\/h4>\n<a href=\"#kennisbank\">\n            Kennisbank\n          <\/a>\n<a href=\"#kennisbank\">\n            ANPR\n          <\/a>\n<a href=\"#kennisbank\">\n            AI-CCTV\n          <\/a>\n<\/div>\n<div class=\"cvk-footer-column\">\n<h4>\n            Opleidingen\n          <\/h4>\n<a href=\"https:\/\/cctvacademy.be\/nl\/opleidingen\/\">\n            Basis CCTV\n          <\/a>\n<a href=\"https:\/\/cctvacademy.be\/nl\/opleidingen\/\">\n            Basis AI\n          <\/a>\n<a href=\"https:\/\/cctvacademy.be\/nl\/opleidingen\/\">\n            Advanced AI\n          <\/a>\n<\/div>\n<div class=\"cvk-footer-column\">\n<h4>\n            CCTV Academy\n          <\/h4>\n<a href=\"https:\/\/cctvacademy.be\/nl\/\">\n            Home\n          <\/a>\n<a href=\"https:\/\/cctvacademy.be\/nl\/contact\/\">\n            Contact\n          <\/a>\n<\/div>\n<\/div>\n<div class=\"cvk-footer-bottom\">\n<span>\n          \u00a9 2026 Wouter Rooseboom \/ CCTV Academy\n        <\/span>\n<span class=\"cvk-status\">\n          Smart Knowledge Search actief\n        <\/span>\n<\/div>\n<\/div>\n<\/footer>\n<\/main>\n<script>\n(function(){\n  \"use strict\";\n\n  var STORAGE_KEY = \"cctv_academy_language\";\n  var EVENT_NAME = \"cctvAcademyLanguageChange\";\n  var root = document.getElementById(\"cctv-knowledge\");\n  if (!root) return;\n\n  var translations = {\"fr\":{\"CCTV\":\"CCTV\",\"CCTV Academy\":\"CCTV Academy\",\"CCTV \u00b7 AI \u00b7 SECURITY \u00b7 TRAINING\":\"CCTV \u00b7 IA \u00b7 S\u00c9CURIT\u00c9 \u00b7 FORMATION\",\"Home\":\"Accueil\",\"Kennisbank\":\"Base de connaissances\",\"Opleidingen\":\"Formations\",\"Contact\":\"Contact\",\"Bekijk opleidingen \u2197\":\"Voir les formations \u2197\",\"CCTV Academy \u00b7 Smart Knowledge Search\":\"CCTV Academy \u00b7 Recherche intelligente\",\"vraag \u2192 techniek \u2192 antwoord\":\"question \u2192 technique \u2192 r\u00e9ponse\",\"LIVE\":\"EN DIRECT\",\"CCTV Kennisbank\":\"Base de connaissances CCTV\",\"Zoek een probleem.\":\"Recherchez un probl\u00e8me.\",\"Vind de oplossing.\":\"Trouvez la solution.\",\"Doorzoek de CCTV Academy-kennisbank in gewone taal. Zoek bijvoorbeeld op\":\"Recherchez dans la base de connaissances CCTV Academy en langage courant. Essayez par exemple\",\"\u201ccamera neemt geen nummerplaat\u201d, \u201choe reset ik mijn NVR?\u201d\":\"\u00ab la cam\u00e9ra ne lit pas la plaque \u00bb, \u00ab comment r\u00e9initialiser mon NVR ? \u00bb\",\"of\":\"ou\",\"\u201cmag ik mijn buur filmen?\u201d.\":\"\u00ab puis-je filmer mon voisin ? \u00bb.\",\"De zoekmachine koppelt jouw vraag automatisch aan relevante technische CCTV-termen.\":\"Le moteur de recherche associe automatiquement votre question aux termes techniques CCTV pertinents.\",\"CCTV-synoniemen\":\"Synonymes CCTV\",\"Relevantie\":\"Pertinence\",\"Slim zoeken\":\"Recherche intelligente\",\"Niet zoeken naar de juiste knop.\":\"Ne cherchez pas le bon bouton.\",\"Begrijpen wat er gebeurt.\":\"Comprenez ce qui se passe.\",\"Fig. 01 \u00b7 CCTV Academy Knowledge Map\":\"Fig. 01 \u00b7 Carte des connaissances CCTV Academy\",\"Slim zoeken in CCTV kennis\":\"Recherche intelligente dans les connaissances CCTV\",\"\u00d7\":\"\u00d7\",\"Zoek in kennisbank\":\"Rechercher dans la base\",\"Probeer:\":\"Essayez :\",\"Nummerplaat niet leesbaar\":\"Plaque illisible\",\"NVR resetten\":\"R\u00e9initialiser le NVR\",\"Buur filmen\":\"Filmer le voisin\",\"PoE voeding\":\"Alimentation PoE\",\"Smartphone\":\"Smartphone\",\"Jouw vraag wordt gecombineerd met technische CCTV-termen en doorzocht in de bestaande WordPress-kennisbank.\":\"Votre question est combin\u00e9e \u00e0 des termes techniques CCTV puis recherch\u00e9e dans la base de connaissances WordPress existante.\",\"Nieuw in de kennisbank\":\"Nouveau dans la base de connaissances\",\"Laatste technische artikel\":\"Dernier article technique\",\"Kennisbank wordt geladen\u2026\":\"Chargement de la base de connaissances\u2026\",\"De nieuwste praktische CCTV-kennis wordt opgehaald.\":\"Les derni\u00e8res connaissances pratiques en CCTV sont en cours de chargement.\",\"Lees artikel \u2192\":\"Lire l\u2019article \u2192\",\"Vind precies\":\"Trouvez exactement\",\"wat je nodig hebt.\":\"ce dont vous avez besoin.\",\"Kennisbank wordt doorzocht\u2026\":\"Recherche dans la base de connaissances\u2026\",\"Zoekvraag analyseren.\":\"Analyse de la requ\u00eate.\",\"8\":\"8\",\"sec richttijd\":\"s cible\",\"Artikels laden...\":\"Chargement des articles...\",\"De eerste resultaten zijn beschikbaar. Andere technische zoekroutes worden nog gecontroleerd.\":\"Les premiers r\u00e9sultats sont disponibles. D\u2019autres pistes de recherche technique sont encore en cours de v\u00e9rification.\",\"Meer resultaten tonen\":\"Afficher plus de r\u00e9sultats\",\"Van zoeken naar kunnen\":\"De la recherche \u00e0 la ma\u00eetrise\",\"Een artikel geeft antwoord.\":\"Un article apporte une r\u00e9ponse.\",\"Zelf testen geeft inzicht.\":\"Tester soi-m\u00eame apporte la compr\u00e9hension.\",\"Wil je camera's, NVR's, IP-netwerken en AI-functies niet alleen opzoeken, maar ook zelf aansluiten, configureren en testen?\":\"Vous voulez non seulement rechercher des informations sur les cam\u00e9ras, NVR, r\u00e9seaux IP et fonctions IA, mais aussi les connecter, les configurer et les tester vous-m\u00eame ?\",\"Bekijk opleidingen\":\"Voir les formations\",\"Stel een vraag\":\"Poser une question\",\"lezen \u2192 aansluiten\":\"lire \u2192 connecter\",\"configureren \u2192 testen\":\"configurer \u2192 tester\",\"Praktische CCTV-kennis en opleidingen voor installateurs, integratoren en beveiligingsprofessionals.\":\"Connaissances pratiques en CCTV et formations pour installateurs, int\u00e9grateurs et professionnels de la s\u00e9curit\u00e9.\",\"Kennis\":\"Connaissances\",\"ANPR\":\"ANPR\",\"AI-CCTV\":\"CCTV IA\",\"Basis CCTV\":\"CCTV de base\",\"Basis AI\":\"IA de base\",\"Advanced AI\":\"IA avanc\u00e9e\",\"\u00a9 2026 Wouter Rooseboom \/ CCTV Academy\":\"\u00a9 2026 Wouter Rooseboom \/ CCTV Academy\",\"Smart Knowledge Search actief\":\"Recherche intelligente active\",\"ANPR \/ nummerplaat\":\"ANPR \/ plaque d\u2019immatriculation\",\"NVR \/ recorder\":\"NVR \/ enregistreur\",\"PoE \/ voeding\":\"PoE \/ alimentation\",\"IP-netwerk\":\"R\u00e9seau IP\",\"Wetgeving \/ privacy\":\"L\u00e9gislation \/ vie priv\u00e9e\",\"Smartphone \/ DMSS\":\"Smartphone \/ DMSS\",\"Reset \/ wachtwoord\":\"R\u00e9initialisation \/ mot de passe\",\"CCTV Wetgeving\":\"L\u00e9gislation CCTV\",\"IP Netwerken\":\"R\u00e9seaux IP\",\"NVR & Opname\":\"NVR & enregistrement\",\"Stap voor stap\":\"Pas \u00e0 pas\",\"CCTV Techniek\":\"Technique CCTV\",\"titel\":\"titre\",\"samenvatting\":\"r\u00e9sum\u00e9\",\"inhoud\":\"contenu\",\"technische term\":\"terme technique\",\"Relevante match\":\"R\u00e9sultat pertinent\",\"Gevonden via:\":\"Trouv\u00e9 via :\",\"Bekijk uitleg\":\"Voir l\u2019explication\",\"Geen passend artikel gevonden.\":\"Aucun article correspondant n\u2019a \u00e9t\u00e9 trouv\u00e9.\",\"Probeer bijvoorbeeld ANPR, NVR, PoE, IP-netwerk, AI of wetgeving.\":\"Essayez par exemple ANPR, NVR, PoE, r\u00e9seau IP, IA ou l\u00e9gislation.\",\"Zoekresultaten voor\":\"R\u00e9sultats de recherche pour\",\"Letterlijke zoekopdracht\":\"Requ\u00eate litt\u00e9rale\",\"Zoekopdracht ge\u00efnterpreteerd als:\":\"Requ\u00eate interpr\u00e9t\u00e9e comme :\",\"Bekijk het nieuwste artikel uit de CCTV Academy kennisbank.\":\"Consultez le dernier article de la base de connaissances CCTV Academy.\",\"Zoeken\u2026\":\"Recherche\u2026\",\"Eerste resultaten gevonden\":\"Premiers r\u00e9sultats trouv\u00e9s\",\"Zoeken en rangschikken voltooid.\":\"Recherche et classement termin\u00e9s.\",\"route\":\"piste\",\"De kennisbank kan momenteel niet geladen worden.\":\"La base de connaissances ne peut pas \u00eatre charg\u00e9e pour le moment.\",\"Controleer de WordPress REST API of probeer later opnieuw.\":\"V\u00e9rifiez l\u2019API REST WordPress ou r\u00e9essayez plus tard.\",\"API niet bereikbaar\":\"API inaccessible\"},\"en\":{\"CCTV\":\"CCTV\",\"CCTV Academy\":\"CCTV Academy\",\"CCTV \u00b7 AI \u00b7 SECURITY \u00b7 TRAINING\":\"CCTV \u00b7 AI \u00b7 SECURITY \u00b7 TRAINING\",\"Home\":\"Home\",\"Kennisbank\":\"Knowledge base\",\"Opleidingen\":\"Training\",\"Contact\":\"Contact\",\"Bekijk opleidingen \u2197\":\"View training \u2197\",\"CCTV Academy \u00b7 Smart Knowledge Search\":\"CCTV Academy \u00b7 Smart Knowledge Search\",\"vraag \u2192 techniek \u2192 antwoord\":\"question \u2192 technology \u2192 answer\",\"LIVE\":\"LIVE\",\"CCTV Kennisbank\":\"CCTV Knowledge Base\",\"Zoek een probleem.\":\"Search a problem.\",\"Vind de oplossing.\":\"Find the solution.\",\"Doorzoek de CCTV Academy-kennisbank in gewone taal. Zoek bijvoorbeeld op\":\"Search the CCTV Academy knowledge base in everyday language. For example, search for\",\"\u201ccamera neemt geen nummerplaat\u201d, \u201choe reset ik mijn NVR?\u201d\":\"\u201ccamera cannot read a number plate\u201d, \u201chow do I reset my NVR?\u201d\",\"of\":\"or\",\"\u201cmag ik mijn buur filmen?\u201d.\":\"\u201cmay I film my neighbour?\u201d.\",\"De zoekmachine koppelt jouw vraag automatisch aan relevante technische CCTV-termen.\":\"The search engine automatically links your question to relevant technical CCTV terms.\",\"CCTV-synoniemen\":\"CCTV synonyms\",\"Relevantie\":\"Relevance\",\"Slim zoeken\":\"Smart search\",\"Niet zoeken naar de juiste knop.\":\"Do not just search for the right button.\",\"Begrijpen wat er gebeurt.\":\"Understand what is happening.\",\"Fig. 01 \u00b7 CCTV Academy Knowledge Map\":\"Fig. 01 \u00b7 CCTV Academy Knowledge Map\",\"Slim zoeken in CCTV kennis\":\"Smart search across CCTV knowledge\",\"\u00d7\":\"\u00d7\",\"Zoek in kennisbank\":\"Search knowledge base\",\"Probeer:\":\"Try:\",\"Nummerplaat niet leesbaar\":\"Number plate unreadable\",\"NVR resetten\":\"Reset NVR\",\"Buur filmen\":\"Film a neighbour\",\"PoE voeding\":\"PoE power\",\"Smartphone\":\"Smartphone\",\"Jouw vraag wordt gecombineerd met technische CCTV-termen en doorzocht in de bestaande WordPress-kennisbank.\":\"Your question is combined with technical CCTV terms and searched across the existing WordPress knowledge base.\",\"Nieuw in de kennisbank\":\"New in the knowledge base\",\"Laatste technische artikel\":\"Latest technical article\",\"Kennisbank wordt geladen\u2026\":\"Knowledge base is loading\u2026\",\"De nieuwste praktische CCTV-kennis wordt opgehaald.\":\"The latest practical CCTV knowledge is being loaded.\",\"Lees artikel \u2192\":\"Read article \u2192\",\"Vind precies\":\"Find exactly\",\"wat je nodig hebt.\":\"what you need.\",\"Kennisbank wordt doorzocht\u2026\":\"Searching the knowledge base\u2026\",\"Zoekvraag analyseren.\":\"Analysing search query.\",\"8\":\"8\",\"sec richttijd\":\"sec target\",\"Artikels laden...\":\"Loading articles...\",\"De eerste resultaten zijn beschikbaar. Andere technische zoekroutes worden nog gecontroleerd.\":\"The first results are available. Other technical search routes are still being checked.\",\"Meer resultaten tonen\":\"Show more results\",\"Van zoeken naar kunnen\":\"From searching to doing\",\"Een artikel geeft antwoord.\":\"An article gives you an answer.\",\"Zelf testen geeft inzicht.\":\"Testing it yourself builds understanding.\",\"Wil je camera's, NVR's, IP-netwerken en AI-functies niet alleen opzoeken, maar ook zelf aansluiten, configureren en testen?\":\"Do you want to do more than look up cameras, NVRs, IP networks and AI functions\u2014and actually connect, configure and test them yourself?\",\"Bekijk opleidingen\":\"View training\",\"Stel een vraag\":\"Ask a question\",\"lezen \u2192 aansluiten\":\"read \u2192 connect\",\"configureren \u2192 testen\":\"configure \u2192 test\",\"Praktische CCTV-kennis en opleidingen voor installateurs, integratoren en beveiligingsprofessionals.\":\"Practical CCTV knowledge and training for installers, integrators and security professionals.\",\"Kennis\":\"Knowledge\",\"ANPR\":\"ANPR\",\"AI-CCTV\":\"AI CCTV\",\"Basis CCTV\":\"CCTV Basics\",\"Basis AI\":\"Basic AI\",\"Advanced AI\":\"Advanced AI\",\"\u00a9 2026 Wouter Rooseboom \/ CCTV Academy\":\"\u00a9 2026 Wouter Rooseboom \/ CCTV Academy\",\"Smart Knowledge Search actief\":\"Smart Knowledge Search active\",\"ANPR \/ nummerplaat\":\"ANPR \/ number plate\",\"NVR \/ recorder\":\"NVR \/ recorder\",\"PoE \/ voeding\":\"PoE \/ power\",\"IP-netwerk\":\"IP network\",\"Wetgeving \/ privacy\":\"Legislation \/ privacy\",\"Smartphone \/ DMSS\":\"Smartphone \/ DMSS\",\"Reset \/ wachtwoord\":\"Reset \/ password\",\"CCTV Wetgeving\":\"CCTV legislation\",\"IP Netwerken\":\"IP networks\",\"NVR & Opname\":\"NVR & recording\",\"Stap voor stap\":\"Step by step\",\"CCTV Techniek\":\"CCTV technology\",\"titel\":\"title\",\"samenvatting\":\"summary\",\"inhoud\":\"content\",\"technische term\":\"technical term\",\"Relevante match\":\"Relevant match\",\"Gevonden via:\":\"Found via:\",\"Bekijk uitleg\":\"View explanation\",\"Geen passend artikel gevonden.\":\"No matching article found.\",\"Probeer bijvoorbeeld ANPR, NVR, PoE, IP-netwerk, AI of wetgeving.\":\"Try ANPR, NVR, PoE, IP network, AI or legislation.\",\"Zoekresultaten voor\":\"Search results for\",\"Letterlijke zoekopdracht\":\"Literal search query\",\"Zoekopdracht ge\u00efnterpreteerd als:\":\"Search query interpreted as:\",\"Bekijk het nieuwste artikel uit de CCTV Academy kennisbank.\":\"View the latest article from the CCTV Academy knowledge base.\",\"Zoeken\u2026\":\"Searching\u2026\",\"Eerste resultaten gevonden\":\"First results found\",\"Zoeken en rangschikken voltooid.\":\"Search and ranking completed.\",\"route\":\"route\",\"De kennisbank kan momenteel niet geladen worden.\":\"The knowledge base cannot be loaded at the moment.\",\"Controleer de WordPress REST API of probeer later opnieuw.\":\"Check the WordPress REST API or try again later.\",\"API niet bereikbaar\":\"API unavailable\"}};\n  var attributeTranslations = {\"fr\":{\"CCTV Academy technische Micro-Learning illustratie\":\"Illustration technique Micro-Learning de CCTV Academy\",\"Doorzoek de CCTV kennisbank\":\"Rechercher dans la base de connaissances CCTV\",\"Beschrijf je vraag: bv. camera neemt geen nummerplaat...\":\"D\u00e9crivez votre question : p. ex. la cam\u00e9ra ne lit pas la plaque...\",\"Zoekopdracht wissen\":\"Effacer la recherche\",\"CCTV Academy Micro-Learning\":\"CCTV Academy Micro-Learning\",\"camera neemt geen nummerplaat\":\"la cam\u00e9ra ne lit pas la plaque\",\"hoe reset ik mijn NVR\":\"comment r\u00e9initialiser mon NVR\",\"mag ik mijn buur filmen\":\"puis-je filmer mon voisin\",\"PoE voeding camera\":\"alimentation PoE cam\u00e9ra\",\"camerabeelden smartphone\":\"images cam\u00e9ra smartphone\"},\"en\":{\"CCTV Academy technische Micro-Learning illustratie\":\"CCTV Academy technical Micro-Learning illustration\",\"Doorzoek de CCTV kennisbank\":\"Search the CCTV knowledge base\",\"Beschrijf je vraag: bv. camera neemt geen nummerplaat...\":\"Describe your question: e.g. camera cannot read a number plate...\",\"Zoekopdracht wissen\":\"Clear search\",\"CCTV Academy Micro-Learning\":\"CCTV Academy Micro-Learning\",\"camera neemt geen nummerplaat\":\"camera cannot read a number plate\",\"hoe reset ik mijn NVR\":\"how do I reset my NVR\",\"mag ik mijn buur filmen\":\"may I film my neighbour\",\"PoE voeding camera\":\"PoE power camera\",\"camerabeelden smartphone\":\"camera footage smartphone\"}};\n  var validLanguages = [\"nl\",\"fr\",\"en\"];\n  var currentLanguage = \"nl\";\n  var textRecords = [];\n  var attributeRecords = [];\n  var dynamicOriginals = new WeakMap();\n  var staticNodes = new WeakSet();\n\n  function normalizeTranslationKey(value) {\n    return String(value || \"\").replace(\/\\s+\/g, \" \").trim();\n  }\n\n  function translateText(original, lang) {\n    var key = normalizeTranslationKey(original);\n    if (lang === \"nl\") return key;\n    var table = translations[lang];\n    return table && Object.prototype.hasOwnProperty.call(table, key)\n      ? table[key]\n      : key;\n  }\n\n  function translateAttribute(original, lang) {\n    var key = normalizeTranslationKey(original);\n    if (lang === \"nl\") return key;\n    var table = attributeTranslations[lang];\n    return table && Object.prototype.hasOwnProperty.call(table, key)\n      ? table[key]\n      : key;\n  }\n\n  function preserveOuterWhitespace(original, translated) {\n    var source = String(original || \"\");\n    var leading = (source.match(\/^\\s*\/) || [\"\"])[0];\n    var trailing = (source.match(\/\\s*$\/) || [\"\"])[0];\n    return leading + translated + trailing;\n  }\n\n  function collectStaticText() {\n    var walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n    var node;\n    while ((node = walker.nextNode())) {\n      var parent = node.parentElement;\n      if (!parent || parent.closest(\"script,style,.cctv-language-bar\")) continue;\n      if (!normalizeTranslationKey(node.nodeValue)) continue;\n      textRecords.push({node:node, original:node.nodeValue});\n      staticNodes.add(node);\n    }\n  }\n\n  function collectAttributes() {\n    root.querySelectorAll(\"[alt],[aria-label],[title],[placeholder],[data-query]\").forEach(function(el) {\n      if (el.closest(\".cctv-language-bar\")) return;\n      [\"alt\",\"aria-label\",\"title\",\"placeholder\",\"data-query\"].forEach(function(attr) {\n        if (el.hasAttribute(attr) && normalizeTranslationKey(el.getAttribute(attr))) {\n          attributeRecords.push({\n            element:el,\n            attribute:attr,\n            original:el.getAttribute(attr)\n          });\n        }\n      });\n    });\n  }\n\n  function translateDynamicValue(original, lang) {\n    var key = normalizeTranslationKey(original);\n    var exact = translateText(key, lang);\n    if (exact !== key || lang === \"nl\") return exact;\n\n    var m;\n    if ((m = key.match(\/^(\\d+) resultaten?$\/))) {\n      if (lang === \"fr\") return m[1] + (m[1] === \"1\" ? \" r\u00e9sultat\" : \" r\u00e9sultats\");\n      if (lang === \"en\") return m[1] + (m[1] === \"1\" ? \" result\" : \" results\");\n    }\n\n    if ((m = key.match(\/^(\\d+) zoekroute wordt gecontroleerd\\.$\/))) {\n      if (lang === \"fr\") return m[1] + \" piste de recherche est v\u00e9rifi\u00e9e.\";\n      if (lang === \"en\") return m[1] + \" search route is being checked.\";\n    }\n\n    if ((m = key.match(\/^(\\d+) zoekroutes worden gecontroleerd\\.$\/))) {\n      if (lang === \"fr\") return m[1] + \" pistes de recherche sont v\u00e9rifi\u00e9es.\";\n      if (lang === \"en\") return m[1] + \" search routes are being checked.\";\n    }\n\n    if ((m = key.match(\/^(\\d+) van (\\d+) zoekroutes gecontroleerd\\.$\/))) {\n      if (lang === \"fr\") return m[1] + \" sur \" + m[2] + \" pistes de recherche v\u00e9rifi\u00e9es.\";\n      if (lang === \"en\") return m[1] + \" of \" + m[2] + \" search routes checked.\";\n    }\n\n    if ((m = key.match(\/^(\\d+) relevant artikel gevonden$\/))) {\n      if (lang === \"fr\") return m[1] + \" article pertinent trouv\u00e9\";\n      if (lang === \"en\") return m[1] + \" relevant article found\";\n    }\n\n    if ((m = key.match(\/^(\\d+) relevante artikels gevonden$\/))) {\n      if (lang === \"fr\") return m[1] + \" articles pertinents trouv\u00e9s\";\n      if (lang === \"en\") return m[1] + \" relevant articles found\";\n    }\n\n    if ((m = key.match(\/^\u2713 route (\\d+)$\/))) {\n      if (lang === \"fr\") return \"\u2713 piste \" + m[1];\n      if (lang === \"en\") return \"\u2713 route \" + m[1];\n    }\n\n    if ((m = key.match(\/^route (\\d+)$\/))) {\n      if (lang === \"fr\") return \"piste \" + m[1];\n      if (lang === \"en\") return \"route \" + m[1];\n    }\n\n    if (key.indexOf(\"Gevonden via:\") === 0) {\n      var rest = key.slice(\"Gevonden via:\".length).trim();\n      var pieces = rest.split(\",\").map(function(x){return translateText(x.trim(), lang);});\n      return translateText(\"Gevonden via:\", lang) + \" \" + pieces.join(\", \");\n    }\n\n    return key;\n  }\n\n  function translateDynamicTree(start, lang) {\n    var nodes = [];\n    if (start && start.nodeType === Node.TEXT_NODE) nodes.push(start);\n    if (start && start.nodeType === Node.ELEMENT_NODE) {\n      var w = document.createTreeWalker(start, NodeFilter.SHOW_TEXT);\n      var n;\n      while ((n = w.nextNode())) nodes.push(n);\n    }\n    nodes.forEach(function(node) {\n      var parent = node.parentElement;\n      if (!parent || parent.closest(\"script,style,.cctv-language-bar\")) return;\n      if (staticNodes.has(node)) return;\n      var value = normalizeTranslationKey(node.nodeValue);\n      if (!value) return;\n      var table = translations[lang];\n      var isExternalContent =\n        parent.closest(\".article-title,.article-excerpt\") ||\n        parent.id === \"featuredTitle\" ||\n        parent.id === \"featuredExcerpt\";\n      if (\n        isExternalContent &&\n        !(table && Object.prototype.hasOwnProperty.call(table, value))\n      ) return;\n      if (!dynamicOriginals.has(node)) dynamicOriginals.set(node, node.nodeValue);\n      var original = dynamicOriginals.get(node);\n      var translated = translateDynamicValue(original, lang);\n      node.nodeValue = preserveOuterWhitespace(original, translated);\n    });\n  }\n\n  function applyLanguage(lang, persist) {\n    if (validLanguages.indexOf(lang) === -1) lang = \"nl\";\n    currentLanguage = lang;\n\n    textRecords.forEach(function(record) {\n      var translated = translateText(record.original, lang);\n      record.node.nodeValue = preserveOuterWhitespace(record.original, translated);\n    });\n\n    attributeRecords.forEach(function(record) {\n      record.element.setAttribute(\n        record.attribute,\n        translateAttribute(record.original, lang)\n      );\n    });\n\n    translateDynamicTree(root, lang);\n\n    root.dataset.language = lang;\n    root.setAttribute(\"lang\", lang);\n    document.documentElement.lang = lang;\n\n    root.querySelectorAll(\".cctv-language-switcher button[data-lang]\").forEach(function(btn) {\n      var active = btn.getAttribute(\"data-lang\") === lang;\n      btn.classList.toggle(\"is-active\", active);\n      btn.setAttribute(\"aria-pressed\", active ? \"true\" : \"false\");\n    });\n\n    if (persist !== false) {\n      try { localStorage.setItem(STORAGE_KEY, lang); } catch (e) {}\n    }\n\n    window.dispatchEvent(new CustomEvent(EVENT_NAME, {\n      detail:{language:lang}\n    }));\n  }\n\n  function setLanguage(lang) {\n    applyLanguage(String(lang || \"\").toLowerCase(), true);\n  }\n\n  collectStaticText();\n  collectAttributes();\n\n  var observer = new MutationObserver(function(mutations) {\n    mutations.forEach(function(mutation) {\n      mutation.addedNodes.forEach(function(node) {\n        translateDynamicTree(node, currentLanguage);\n      });\n    });\n  });\n  observer.observe(root, {childList:true, subtree:true});\n\n  root.querySelectorAll(\".cctv-language-switcher button[data-lang]\").forEach(function(btn) {\n    btn.addEventListener(\"click\", function() {\n      setLanguage(btn.getAttribute(\"data-lang\"));\n    });\n  });\n\n  var queryLang = new URL(window.location.href).searchParams.get(\"lang\");\n  queryLang = queryLang ? queryLang.toLowerCase() : \"\";\n  var storedLang = \"\";\n  try { storedLang = (localStorage.getItem(STORAGE_KEY) || \"\").toLowerCase(); } catch (e) {}\n\n  var initialLanguage =\n    validLanguages.indexOf(queryLang) !== -1 ? queryLang :\n    validLanguages.indexOf(storedLang) !== -1 ? storedLang :\n    \"nl\";\n\n  applyLanguage(initialLanguage, true);\n\n  window.addEventListener(\"storage\", function(event) {\n    var value = String(event.newValue || \"\").toLowerCase();\n    if (event.key === STORAGE_KEY && validLanguages.indexOf(value) !== -1) {\n      applyLanguage(value, false);\n    }\n  });\n\n  window.CCTVKnowledgeI18n = {\n    t:function(key){ return translateDynamicValue(key, currentLanguage); },\n    get:function(){ return currentLanguage; },\n    locale:function(){\n      return currentLanguage === \"fr\" ? \"fr-BE\" :\n             currentLanguage === \"en\" ? \"en-GB\" : \"nl-BE\";\n    }\n  };\n\n  window.CCTVAcademyLanguage = {\n    set:setLanguage,\n    get:function(){ return currentLanguage; }\n  };\n})();\n<\/script><script>\n(function(){\n\n\"use strict\";\n\n\n\/* ==========================================================\n   CONFIG\n   ========================================================== *\/\n\nconst CONFIG = {\n\n  postsApi:\n    \"https:\/\/cctvacademy.be\/wp-json\/wp\/v2\/posts\",\n\n  mediaApi:\n    \"https:\/\/cctvacademy.be\/wp-json\/wp\/v2\/media\",\n\n  browsePosts:18,\n\n  searchPerTerm:25,\n\n  maxSearchRoutes:5,\n\n  initialVisible:12,\n\n  loadIncrement:12,\n\n  countdownStart:8,\n\n  cacheLifetime:\n    30 * 60 * 1000\n\n};\n\n\n\/* ==========================================================\n   DOM\n   ========================================================== *\/\n\nconst searchInput =\n  document.getElementById(\n    \"searchInput\"\n  );\n\nconst searchButton =\n  document.getElementById(\n    \"searchButton\"\n  );\n\nconst clearSearch =\n  document.getElementById(\n    \"clearSearch\"\n  );\n\nconst searchIntelligence =\n  document.getElementById(\n    \"searchIntelligence\"\n  );\n\nconst interpretation =\n  document.getElementById(\n    \"interpretation\"\n  );\n\nconst articleGrid =\n  document.getElementById(\n    \"articleGrid\"\n  );\n\nconst resultSummary =\n  document.getElementById(\n    \"resultSummary\"\n  );\n\nconst resultQuery =\n  document.getElementById(\n    \"resultQuery\"\n  );\n\nconst loadMore =\n  document.getElementById(\n    \"loadMore\"\n  );\n\nconst searchProgress =\n  document.getElementById(\n    \"searchProgress\"\n  );\n\nconst searchProgressTitle =\n  document.getElementById(\n    \"searchProgressTitle\"\n  );\n\nconst searchProgressDetail =\n  document.getElementById(\n    \"searchProgressDetail\"\n  );\n\nconst searchProgressValue =\n  document.getElementById(\n    \"searchProgressValue\"\n  );\n\nconst searchCountdown =\n  document.getElementById(\n    \"searchCountdown\"\n  );\n\nconst speedStatus =\n  document.getElementById(\n    \"speedStatus\"\n  );\n\nconst liveResultNote =\n  document.getElementById(\n    \"liveResultNote\"\n  );\n\nconst searchResultsTitle =\n  document.getElementById(\n    \"searchResultsTitle\"\n  );\n\n\nif(\n  !searchInput ||\n  !searchButton ||\n  !articleGrid\n){\n  return;\n}\n\n\n\/* ==========================================================\n   STATE\n   ========================================================== *\/\n\nconst state = {\n\n  browsePosts:[],\n\n  searchResults:[],\n\n  query:\"\",\n\n  visible:\n    CONFIG.initialVisible,\n\n  controller:null,\n\n  countdownTimer:null,\n\n  mediaCache:\n    loadMediaCache()\n\n};\n\n\n\/* ==========================================================\n   CCTV CONCEPTS\n   ========================================================== *\/\n\nconst CONCEPTS = {\n\n  anpr:{\n\n    label:\n      \"ANPR \/ nummerplaat\",\n\n    search:[\n      \"ANPR\",\n      \"nummerplaat\",\n      \"LPR\"\n    ],\n\n    detect:[\n      \"anpr\",\n      \"nummerplaat\",\n      \"nummerplaten\",\n      \"nummerplaatherkenning\",\n      \"kenteken\",\n      \"plaque\",\n      \"immatriculation\",\n      \"number plate\",\n      \"license plate\",\n      \"lpr\"\n    ]\n\n  },\n\n\n  nvr:{\n\n    label:\n      \"NVR \/ recorder\",\n\n    search:[\n      \"NVR\",\n      \"recorder\",\n      \"opnamesysteem\",\n      \"enregistreur\",\n      \"recording system\"\n    ],\n\n    detect:[\n      \"nvr\",\n      \"recorder\",\n      \"xvr\",\n      \"dvr\",\n      \"opnamesysteem\"\n    ]\n\n  },\n\n\n  poe:{\n\n    label:\n      \"PoE \/ voeding\",\n\n    search:[\n      \"PoE\",\n      \"voeding\",\n      \"power over ethernet\"\n    ],\n\n    detect:[\n      \"poe\",\n      \"epoe\",\n      \"voeding\",\n      \"alimentation\",\n      \"power\",\n      \"power over ethernet\",\n      \"watt\"\n    ]\n\n  },\n\n\n  network:{\n\n    label:\n      \"IP-netwerk\",\n\n    search:[\n      \"IP netwerk\",\n      \"IP adres\",\n      \"DHCP\",\n      \"router\"\n    ],\n\n    detect:[\n      \"ip\",\n      \"netwerk\",\n      \"r\u00e9seau\",\n      \"network\",\n      \"subnet\",\n      \"gateway\",\n      \"router\",\n      \"dhcp\",\n      \"switch\",\n      \"lan\",\n      \"wan\"\n    ]\n\n  },\n\n\n  ai:{\n\n    label:\n      \"AI-CCTV\",\n\n    search:[\n      \"AI CCTV\",\n      \"AI detectie\",\n      \"IVS\",\n      \"SMD\"\n    ],\n\n    detect:[\n      \"ai\",\n      \"ia\",\n      \"ivs\",\n      \"smd\",\n      \"acupick\",\n      \"wizsense\",\n      \"detectie\",\n      \"d\u00e9tection\",\n      \"detection\"\n    ]\n\n  },\n\n\n  law:{\n\n    label:\n      \"Wetgeving \/ privacy\",\n\n    search:[\n      \"camerawet\",\n      \"privacy\",\n      \"wetgeving\"\n    ],\n\n    detect:[\n      \"camerawet\",\n      \"privacy\",\n      \"wetgeving\",\n      \"l\u00e9gislation\",\n      \"legislation\",\n      \"vie priv\u00e9e\",\n      \"privacy\",\n      \"proportionaliteit\",\n      \"werknemer\",\n      \"buur\",\n      \"voisin\",\n      \"neighbor\",\n      \"neighbour\",\n      \"filmer\",\n      \"film\",\n      \"pictogram\"\n    ]\n\n  },\n\n\n  mobile:{\n\n    label:\n      \"Smartphone \/ DMSS\",\n\n    search:[\n      \"DMSS\",\n      \"smartphone\",\n      \"meldingen\"\n    ],\n\n    detect:[\n      \"smartphone\",\n      \"telefoon\",\n      \"t\u00e9l\u00e9phone\",\n      \"phone\",\n      \"gsm\",\n      \"dmss\",\n      \"melding\"\n    ]\n\n  },\n\n\n  reset:{\n\n    label:\n      \"Reset \/ wachtwoord\",\n\n    search:[\n      \"factory reset\",\n      \"reset\",\n      \"wachtwoord\"\n    ],\n\n    detect:[\n      \"reset\",\n      \"factory reset\",\n      \"fabrieksinstellingen\",\n      \"wachtwoord\",\n      \"mot de passe\",\n      \"password\"\n    ]\n\n  }\n\n};\n\n\n\/* ==========================================================\n   HELPERS\n   ========================================================== *\/\n\nfunction normalize(value){\n\n  return String(value || \"\")\n    .toLowerCase()\n    .normalize(\"NFD\")\n    .replace(\n      \/[\\u0300-\\u036f]\/g,\n      \"\"\n    )\n    .replace(\n      \/[^\\p{L}\\p{N}+.]+\/gu,\n      \" \"\n    )\n    .replace(\n      \/\\s+\/g,\n      \" \"\n    )\n    .trim();\n\n}\n\n\nfunction stripHTML(value){\n\n  const node =\n    document.createElement(\n      \"div\"\n    );\n\n\n  node.innerHTML =\n    value || \"\";\n\n\n  return (\n    node.textContent ||\n    node.innerText ||\n    \"\"\n  )\n  .replace(\n    \/\\s+\/g,\n    \" \"\n  )\n  .trim();\n\n}\n\n\nfunction decodeHTML(value){\n\n  const node =\n    document.createElement(\n      \"textarea\"\n    );\n\n\n  node.innerHTML =\n    value || \"\";\n\n\n  return node.value;\n\n}\n\n\nfunction escapeHTML(value){\n\n  return String(value || \"\")\n    .replace(\/&\/g,\"&amp;\")\n    .replace(\/<\/g,\"&lt;\")\n    .replace(\/>\/g,\"&gt;\")\n    .replace(\/\"\/g,\"&quot;\")\n    .replace(\/'\/g,\"&#039;\");\n\n}\n\n\nfunction truncate(\n  value,\n  length\n){\n\n  const text =\n    String(value || \"\");\n\n\n  if(\n    text.length <= length\n  ){\n    return text;\n  }\n\n\n  return (\n    text\n      .slice(\n        0,\n        length\n      )\n      .trim()\n    +\n    \"\u2026\"\n  );\n\n}\n\n\nfunction formatDate(value){\n\n  try{\n\n    return new Intl.DateTimeFormat(\n      (window.CCTVKnowledgeI18n ? window.CCTVKnowledgeI18n.locale() : \"nl-BE\"),\n      {\n        day:\"numeric\",\n        month:\"short\",\n        year:\"numeric\"\n      }\n    )\n    .format(\n      new Date(value)\n    );\n\n  }\n\n  catch(error){\n\n    return \"CCTV Academy\";\n\n  }\n\n}\n\n\n\/* ==========================================================\n   CONCEPT DETECTION\n   ========================================================== *\/\n\nfunction findConcepts(query){\n\n  const value =\n    normalize(query);\n\n\n  return Object\n    .values(CONCEPTS)\n    .filter(\n      concept =>\n        concept.detect.some(\n          term =>\n            value.includes(\n              normalize(term)\n            )\n        )\n    );\n\n}\n\n\nfunction buildSearchRoutes(query){\n\n  const routes =\n    new Set();\n\n\n  routes.add(\n    query.trim()\n  );\n\n\n  findConcepts(query)\n    .forEach(\n      concept => {\n\n        concept.search\n          .slice(0,2)\n          .forEach(\n            term =>\n              routes.add(term)\n          );\n\n      }\n    );\n\n\n  normalize(query)\n    .split(\" \")\n    .filter(\n      word =>\n        word.length >= 4\n    )\n    .slice(0,2)\n    .forEach(\n      word =>\n        routes.add(word)\n    );\n\n\n  return Array\n    .from(routes)\n    .filter(Boolean)\n    .slice(\n      0,\n      CONFIG.maxSearchRoutes\n    );\n\n}\n\n\n\/* ==========================================================\n   CLASSIFICATION\n   Alleen nog gebruikt voor de labels op artikelen.\n   Geen filterknoppen meer.\n   ========================================================== *\/\n\nfunction classify(post){\n\n  const text =\n    normalize(\n      decodeHTML(\n        post.title?.rendered\n      )\n      +\n      \" \"\n      +\n      stripHTML(\n        post.excerpt?.rendered\n      )\n      +\n      \" \"\n      +\n      stripHTML(\n        post.content?.rendered\n      )\n    );\n\n\n  if(\n    \/(anpr|nummerplaat|kenteken|lpr)\/.test(\n      text\n    )\n  ){\n\n    return {\n      id:\"anpr\",\n      label:\"ANPR\"\n    };\n\n  }\n\n\n  if(\n    \/(camerawet|wetgeving|privacy|proportionaliteit|werknemer|pictogram)\/.test(\n      text\n    )\n  ){\n\n    return {\n      id:\"law\",\n      label:\"CCTV Wetgeving\"\n    };\n\n  }\n\n\n  if(\n    \/(subnet|gateway|router|dhcp|switch|poe|epoe|ip adres|lan|wan)\/.test(\n      text\n    )\n  ){\n\n    return {\n      id:\"network\",\n      label:\"IP Netwerken\"\n    };\n\n  }\n\n\n  if(\n    \/(nvr|xvr|dvr|recorder|opnamesysteem|opslag|harde schijf)\/.test(\n      text\n    )\n  ){\n\n    return {\n      id:\"nvr\",\n      label:\"NVR & Opname\"\n    };\n\n  }\n\n\n  if(\n    \/(stap voor stap|stap per stap|configuratie|hoe installeer|hoe programmeer)\/.test(\n      text\n    )\n  ){\n\n    return {\n      id:\"howto\",\n      label:\"Stap voor stap\"\n    };\n\n  }\n\n\n  if(\n    \/(\\bai\\b|ivs|smd|acupick|wizsense|detectie)\/.test(\n      text\n    )\n  ){\n\n    return {\n      id:\"ai\",\n      label:\"AI-CCTV\"\n    };\n\n  }\n\n\n  return {\n    id:\"technical\",\n    label:\"CCTV Techniek\"\n  };\n\n}\n\n\n\/* ==========================================================\n   WORDPRESS API\n   ========================================================== *\/\n\nasync function fetchPosts(\n  params,\n  signal\n){\n\n  const url =\n    new URL(\n      CONFIG.postsApi\n    );\n\n\n  Object.entries(\n    params\n  )\n  .forEach(\n    ([key,value]) => {\n\n      url.searchParams.set(\n        key,\n        value\n      );\n\n    }\n  );\n\n\n  url.searchParams.set(\n    \"_fields\",\n    \"id,date,link,slug,title,excerpt,content,featured_media\"\n  );\n\n\n  const response =\n    await fetch(\n      url.toString(),\n      {\n        signal\n      }\n    );\n\n\n  if(\n    !response.ok\n  ){\n\n    throw new Error(\n      \"WordPress API fout\"\n    );\n\n  }\n\n\n  return response.json();\n\n}\n\n\n\/* ==========================================================\n   SCORING\n   ========================================================== *\/\n\nfunction scorePost(\n  post,\n  query,\n  route\n){\n\n  const q =\n    normalize(query);\n\n  const r =\n    normalize(route);\n\n\n  const title =\n    normalize(\n      decodeHTML(\n        post.title?.rendered\n      )\n    );\n\n\n  const excerpt =\n    normalize(\n      stripHTML(\n        post.excerpt?.rendered\n      )\n    );\n\n\n  const content =\n    normalize(\n      stripHTML(\n        post.content?.rendered\n      )\n    );\n\n\n  const all =\n    title +\n    \" \" +\n    excerpt +\n    \" \" +\n    content;\n\n\n  let score = 0;\n\n  const matched =\n    new Set();\n\n\n  if(\n    q &&\n    title.includes(q)\n  ){\n\n    score += 100;\n\n    matched.add(\n      \"titel\"\n    );\n\n  }\n\n\n  if(\n    q &&\n    excerpt.includes(q)\n  ){\n\n    score += 45;\n\n    matched.add(\n      \"samenvatting\"\n    );\n\n  }\n\n\n  if(\n    q &&\n    content.includes(q)\n  ){\n\n    score += 25;\n\n    matched.add(\n      \"inhoud\"\n    );\n\n  }\n\n\n  if(\n    r &&\n    title.includes(r)\n  ){\n\n    score += 35;\n\n    matched.add(\n      \"technische term\"\n    );\n\n  }\n\n\n  if(\n    r &&\n    all.includes(r)\n  ){\n\n    score += 15;\n\n  }\n\n\n  normalize(query)\n    .split(\" \")\n    .filter(\n      word =>\n        word.length > 3\n    )\n    .forEach(\n      word => {\n\n        if(\n          title.includes(word)\n        ){\n\n          score += 11;\n\n        }\n\n        else if(\n          excerpt.includes(word)\n        ){\n\n          score += 6;\n\n        }\n\n        else if(\n          content.includes(word)\n        ){\n\n          score += 2;\n\n        }\n\n      }\n    );\n\n\n  return {\n\n    score,\n\n    matched:\n      Array.from(\n        matched\n      )\n      .slice(\n        0,\n        3\n      )\n\n  };\n\n}\n\n\n\/* ==========================================================\n   CACHE\n   ========================================================== *\/\n\nfunction cacheKey(query){\n\n  return (\n    \"cctv_knowledge_\" +\n    normalize(query)\n  );\n\n}\n\n\nfunction getCachedSearch(query){\n\n  try{\n\n    const raw =\n      sessionStorage.getItem(\n        cacheKey(query)\n      );\n\n\n    if(\n      !raw\n    ){\n      return null;\n    }\n\n\n    const data =\n      JSON.parse(raw);\n\n\n    if(\n      Date.now() -\n      data.time >\n      CONFIG.cacheLifetime\n    ){\n\n      sessionStorage.removeItem(\n        cacheKey(query)\n      );\n\n      return null;\n\n    }\n\n\n    return data.results;\n\n  }\n\n  catch(error){\n\n    return null;\n\n  }\n\n}\n\n\nfunction saveCachedSearch(\n  query,\n  results\n){\n\n  try{\n\n    sessionStorage.setItem(\n      cacheKey(query),\n      JSON.stringify({\n        time:\n          Date.now(),\n\n        results:\n          results.slice(\n            0,\n            60\n          )\n      })\n    );\n\n  }\n\n  catch(error){\n\n    \/* cache is optioneel *\/\n\n  }\n\n}\n\n\n\/* ==========================================================\n   MEDIA CACHE\n   ========================================================== *\/\n\nfunction loadMediaCache(){\n\n  try{\n\n    return JSON.parse(\n      sessionStorage.getItem(\n        \"cctv_knowledge_media\"\n      )\n      ||\n      \"{}\"\n    );\n\n  }\n\n  catch(error){\n\n    return {};\n\n  }\n\n}\n\n\nfunction saveMediaCache(){\n\n  try{\n\n    sessionStorage.setItem(\n      \"cctv_knowledge_media\",\n      JSON.stringify(\n        state.mediaCache\n      )\n    );\n\n  }\n\n  catch(error){\n\n    \/* optioneel *\/\n\n  }\n\n}\n\n\nfunction bestMediaURL(item){\n\n  return (\n    item?.media_details\n      ?.sizes\n      ?.medium_large\n      ?.source_url\n    ||\n    item?.media_details\n      ?.sizes\n      ?.large\n      ?.source_url\n    ||\n    item?.source_url\n    ||\n    \"\"\n  );\n\n}\n\n\nfunction applyMedia(\n  id,\n  url\n){\n\n  if(\n    !id ||\n    !url\n  ){\n    return;\n  }\n\n\n  document\n    .querySelectorAll(\n      `[data-media-id=\"${id}\"]`\n    )\n    .forEach(\n      image => {\n\n        image.src =\n          url;\n\n        image.classList.add(\n          \"loaded\"\n        );\n\n      }\n    );\n\n}\n\n\nasync function hydrateImages(posts){\n\n  const ids =\n    Array.from(\n      new Set(\n        posts\n          .map(\n            post =>\n              Number(\n                post.featured_media\n              )\n          )\n          .filter(Boolean)\n      )\n    );\n\n\n  ids.forEach(\n    id => {\n\n      if(\n        state.mediaCache[id]\n      ){\n\n        applyMedia(\n          id,\n          state.mediaCache[id]\n        );\n\n      }\n\n    }\n  );\n\n\n  const missing =\n    ids.filter(\n      id =>\n        !state.mediaCache[id]\n    );\n\n\n  if(\n    !missing.length\n  ){\n    return;\n  }\n\n\n  try{\n\n    const url =\n      new URL(\n        CONFIG.mediaApi\n      );\n\n\n    url.searchParams.set(\n      \"include\",\n      missing.join(\",\")\n    );\n\n\n    url.searchParams.set(\n      \"per_page\",\n      Math.min(\n        100,\n        missing.length\n      )\n    );\n\n\n    url.searchParams.set(\n      \"_fields\",\n      \"id,source_url,media_details\"\n    );\n\n\n    const response =\n      await fetch(\n        url.toString()\n      );\n\n\n    if(\n      !response.ok\n    ){\n      return;\n    }\n\n\n    const media =\n      await response.json();\n\n\n    media.forEach(\n      item => {\n\n        const image =\n          bestMediaURL(item);\n\n\n        if(\n          !image\n        ){\n          return;\n        }\n\n\n        state.mediaCache[\n          item.id\n        ] =\n          image;\n\n\n        applyMedia(\n          item.id,\n          image\n        );\n\n      }\n    );\n\n\n    saveMediaCache();\n\n  }\n\n  catch(error){\n\n    \/* afbeeldingen blokkeren de pagina niet *\/\n\n  }\n\n}\n\n\n\/* ==========================================================\n   ARTICLE CARD\n   ========================================================== *\/\n\nfunction createCard(item){\n\n  const post =\n    item.post;\n\n\n  const topic =\n    item.topic ||\n    classify(post);\n\n\n  const title =\n    decodeHTML(\n      post.title?.rendered\n    );\n\n\n  const excerpt =\n    truncate(\n      stripHTML(\n        post.excerpt?.rendered\n      )\n      ||\n      stripHTML(\n        post.content?.rendered\n      ),\n      155\n    );\n\n\n  const mediaId =\n    Number(\n      post.featured_media\n    );\n\n\n  const image =\n    state.mediaCache[\n      mediaId\n    ];\n\n\n  return `\n\n    <a\n      class=\"article-card\"\n      href=\"${escapeHTML(post.link)}\">\n\n\n      <div class=\"article-image\">\n\n\n        <div class=\"image-placeholder\">\n\n          <svg\n            viewBox=\"0 0 70 50\"\n            fill=\"none\"\n            aria-hidden=\"true\">\n\n            <rect\n              x=\"5\"\n              y=\"11\"\n              width=\"40\"\n              height=\"28\"\n              rx=\"2\"\n              stroke=\"currentColor\"\n              stroke-width=\"2\">\n            <\/rect>\n\n            <path\n              d=\"m45 18 20-8v29l-20-8\"\n              stroke=\"currentColor\"\n              stroke-width=\"2\">\n            <\/path>\n\n          <\/svg>\n\n        <\/div>\n\n\n        ${\n          mediaId\n          ?\n          `\n          <img\n            ${\n              image\n              ?\n              `src=\"${escapeHTML(image)}\"`\n              :\n              \"\"\n            }\n            class=\"${image ? \"loaded\" : \"\"}\"\n            data-media-id=\"${mediaId}\"\n            alt=\"${escapeHTML(title)}\"\n            loading=\"lazy\">\n          `\n          :\n          \"\"\n        }\n\n\n        <span class=\"topic-badge\">\n          ${escapeHTML(topic.label)}\n        <\/span>\n\n\n        ${\n          state.query\n          ?\n          `\n          <span class=\"relevance\">\n            Relevante match\n          <\/span>\n          `\n          :\n          \"\"\n        }\n\n\n      <\/div>\n\n\n      <div class=\"article-body\">\n\n\n        <div class=\"article-meta\">\n\n          <span>\n            ${formatDate(post.date)}\n          <\/span>\n\n          <span class=\"meta-dot\">\n          <\/span>\n\n          <span>\n            CCTV Academy\n          <\/span>\n\n        <\/div>\n\n\n        <h3 class=\"article-title\">\n          ${escapeHTML(title)}\n        <\/h3>\n\n\n        <p class=\"article-excerpt\">\n          ${escapeHTML(excerpt)}\n        <\/p>\n\n\n        ${\n          item.matched?.length\n          ?\n          `\n          <div class=\"matched-on\">\n\n            Gevonden via:\n            ${escapeHTML(\n              item.matched.join(\", \")\n            )}\n\n          <\/div>\n          `\n          :\n          \"\"\n        }\n\n\n        <div class=\"article-footer\">\n\n          <span>\n            Bekijk uitleg\n          <\/span>\n\n          <span>\n            \u2192\n          <\/span>\n\n        <\/div>\n\n\n      <\/div>\n\n\n    <\/a>\n\n  `;\n\n}\n\n\n\/* ==========================================================\n   RESULTS\n   Geen filterlogica meer.\n   ========================================================== *\/\n\nfunction getActiveResults(){\n\n  if(\n    state.query\n  ){\n\n    return state.searchResults;\n\n  }\n\n\n  return state.browsePosts.map(\n    post => ({\n\n      post,\n\n      score:0,\n\n      matched:[],\n\n      topic:\n        classify(post)\n\n    })\n  );\n\n}\n\n\nfunction renderResults(){\n\n  const allResults =\n    getActiveResults();\n\n\n  const results =\n    allResults.slice(\n      0,\n      state.visible\n    );\n\n\n  if(\n    !results.length\n  ){\n\n    articleGrid.innerHTML = `\n\n      <div class=\"empty\">\n\n        <h3>\n          Geen passend artikel gevonden.\n        <\/h3>\n\n        <p>\n          Probeer bijvoorbeeld\n          ANPR,\n          NVR,\n          PoE,\n          IP-netwerk,\n          AI\n          of wetgeving.\n        <\/p>\n\n      <\/div>\n\n    `;\n\n\n    resultSummary.textContent =\n      \"0 resultaten\";\n\n\n    loadMore.style.display =\n      \"none\";\n\n\n    updateQueryText();\n\n    return;\n\n  }\n\n\n  articleGrid.innerHTML =\n    results\n      .map(createCard)\n      .join(\"\");\n\n\n  resultSummary.textContent =\n    allResults.length\n    +\n    (\n      allResults.length === 1\n        ? \" resultaat\"\n        : \" resultaten\"\n    );\n\n\n  loadMore.style.display =\n    state.visible <\n    allResults.length\n\n      ? \"inline-flex\"\n\n      : \"none\";\n\n\n  updateQueryText();\n\n\n  hydrateImages(\n    results.map(\n      item =>\n        item.post\n    )\n  );\n\n}\n\n\nfunction updateQueryText(){\n\n  if(\n    !state.query\n  ){\n\n    resultQuery.classList.remove(\n      \"visible\"\n    );\n\n\n    resultQuery.innerHTML =\n      \"\";\n\n\n    return;\n\n  }\n\n\n  resultQuery.innerHTML = `\n\n    Zoekresultaten voor\n\n    <strong>\n      \u201c${escapeHTML(state.query)}\u201d\n    <\/strong>\n\n  `;\n\n\n  resultQuery.classList.add(\n    \"visible\"\n  );\n\n}\n\n\n\/* ==========================================================\n   INTERPRETATION\n   ========================================================== *\/\n\nfunction renderInterpretation(query){\n\n  const concepts =\n    findConcepts(query);\n\n\n  const labels =\n    concepts.length\n\n      ? concepts.map(\n          concept =>\n            concept.label\n        )\n\n      : [\n          \"Letterlijke zoekopdracht\"\n        ];\n\n\n  interpretation.innerHTML = `\n\n    <span class=\"interpretation-label\">\n      Zoekopdracht ge\u00efnterpreteerd als:\n    <\/span>\n\n    ${\n      labels\n        .map(\n          label => `\n\n            <span class=\"concept-chip\">\n              ${escapeHTML(label)}\n            <\/span>\n\n          `\n        )\n        .join(\"\")\n    }\n\n  `;\n\n\n  searchIntelligence.classList.add(\n    \"visible\"\n  );\n\n}\n\n\n\/* ==========================================================\n   FEATURED ARTICLE\n   ========================================================== *\/\n\nfunction renderFeatured(post){\n\n  const topic =\n    classify(post);\n\n\n  const title =\n    decodeHTML(\n      post.title?.rendered\n    );\n\n\n  const excerpt =\n    truncate(\n      stripHTML(\n        post.excerpt?.rendered\n      ),\n      245\n    );\n\n\n  document.getElementById(\n    \"featuredTopic\"\n  ).textContent =\n    topic.label;\n\n\n  document.getElementById(\n    \"featuredTitle\"\n  ).textContent =\n    title;\n\n\n  document.getElementById(\n    \"featuredExcerpt\"\n  ).textContent =\n    excerpt\n    ||\n    \"Bekijk het nieuwste artikel uit de CCTV Academy kennisbank.\";\n\n\n  document.getElementById(\n    \"featuredDate\"\n  ).textContent =\n    formatDate(\n      post.date\n    );\n\n\n  document.getElementById(\n    \"featuredLink\"\n  ).href =\n    post.link;\n\n\n  const mediaId =\n    Number(\n      post.featured_media\n    );\n\n\n  const featuredImage =\n    document.getElementById(\n      \"featuredImage\"\n    );\n\n\n  featuredImage.dataset.mediaId =\n    mediaId || \"\";\n\n\n  hydrateImages(\n    [post]\n  );\n\n}\n\n\n\/* ==========================================================\n   PROGRESS\n   ========================================================== *\/\n\nfunction startProgress(routeCount){\n\n  clearInterval(\n    state.countdownTimer\n  );\n\n\n  let remaining =\n    CONFIG.countdownStart;\n\n\n  searchCountdown.textContent =\n    remaining;\n\n\n  searchProgressValue.style.width =\n    \"5%\";\n\n\n  searchProgress.classList.remove(\n    \"has-results\"\n  );\n\n\n  searchProgress.classList.add(\n    \"visible\"\n  );\n\n\n  searchProgressTitle.textContent =\n    \"Kennisbank wordt doorzocht\u2026\";\n\n\n  searchProgressDetail.textContent =\n    routeCount\n    +\n    (\n      routeCount === 1\n        ? \" zoekroute wordt gecontroleerd.\"\n        : \" zoekroutes worden gecontroleerd.\"\n    );\n\n\n  speedStatus.innerHTML =\n    Array.from({\n      length:\n        routeCount\n    })\n    .map(\n      (_,index) => `\n\n        <span\n          class=\"speed-chip\"\n          data-route=\"${index}\">\n\n          route ${index + 1}\n\n        <\/span>\n\n      `\n    )\n    .join(\"\");\n\n\n  searchButton.textContent =\n    \"Zoeken\u2026\";\n\n\n  searchButton.classList.add(\n    \"is-loading\"\n  );\n\n\n  state.countdownTimer =\n    setInterval(\n      function(){\n\n        remaining =\n          Math.max(\n            0,\n            remaining - 1\n          );\n\n\n        searchCountdown.textContent =\n          remaining;\n\n\n        if(\n          remaining === 0\n        ){\n\n          clearInterval(\n            state.countdownTimer\n          );\n\n        }\n\n      },\n      1000\n    );\n\n}\n\n\nfunction updateProgress(\n  index,\n  completed,\n  total,\n  hasResults\n){\n\n  const chip =\n    speedStatus.querySelector(\n      `[data-route=\"${index}\"]`\n    );\n\n\n  if(\n    chip\n  ){\n\n    chip.classList.add(\n      \"done\"\n    );\n\n\n    chip.textContent =\n      \"\u2713 route \"\n      +\n      (index + 1);\n\n  }\n\n\n  searchProgressValue.style.width =\n    Math.round(\n      completed \/\n      total *\n      100\n    )\n    +\n    \"%\";\n\n\n  searchProgressDetail.textContent =\n    completed\n    +\n    \" van \"\n    +\n    total\n    +\n    \" zoekroutes gecontroleerd.\";\n\n\n  if(\n    hasResults\n  ){\n\n    searchProgress.classList.add(\n      \"has-results\"\n    );\n\n\n    searchProgressTitle.textContent =\n      \"Eerste resultaten gevonden\";\n\n\n    liveResultNote.classList.add(\n      \"visible\"\n    );\n\n  }\n\n}\n\n\nfunction finishProgress(count){\n\n  clearInterval(\n    state.countdownTimer\n  );\n\n\n  searchProgressValue.style.width =\n    \"100%\";\n\n\n  searchCountdown.textContent =\n    \"\u2713\";\n\n\n  searchProgress.classList.add(\n    \"has-results\"\n  );\n\n\n  searchProgressTitle.textContent =\n    count\n    +\n    (\n      count === 1\n        ? \" relevant artikel gevonden\"\n        : \" relevante artikels gevonden\"\n    );\n\n\n  searchProgressDetail.textContent =\n    \"Zoeken en rangschikken voltooid.\";\n\n\n  searchButton.textContent =\n    \"Zoek in kennisbank\";\n\n\n  searchButton.classList.remove(\n    \"is-loading\"\n  );\n\n\n  setTimeout(\n    function(){\n\n      searchProgress.classList.remove(\n        \"visible\"\n      );\n\n\n      liveResultNote.classList.remove(\n        \"visible\"\n      );\n\n    },\n    1400\n  );\n\n}\n\n\n\/* ==========================================================\n   SEARCH\n   ========================================================== *\/\n\nasync function executeSearch(){\n\n  const query =\n    searchInput.value.trim();\n\n\n  if(\n    !query\n  ){\n\n    resetSearch();\n\n    return;\n\n  }\n\n\n  if(\n    state.controller\n  ){\n\n    state.controller.abort();\n\n  }\n\n\n  state.controller =\n    new AbortController();\n\n\n  const signal =\n    state.controller.signal;\n\n\n  state.query =\n    query;\n\n\n  state.visible =\n    CONFIG.initialVisible;\n\n\n  clearSearch.classList.add(\n    \"visible\"\n  );\n\n\n  renderInterpretation(\n    query\n  );\n\n\n  updateURL();\n\n\n  if(\n    searchResultsTitle\n  ){\n\n    searchResultsTitle.scrollIntoView({\n\n      behavior:\n        window.matchMedia(\n          \"(prefers-reduced-motion: reduce)\"\n        ).matches\n          ? \"auto\"\n          : \"smooth\",\n\n      block:\n        \"start\"\n\n    });\n\n  }\n\n\n  const cached =\n    getCachedSearch(\n      query\n    );\n\n\n  if(\n    cached &&\n    cached.length\n  ){\n\n    state.searchResults =\n      cached;\n\n\n    renderResults();\n\n\n    searchButton.textContent =\n      \"Zoek in kennisbank\";\n\n\n    searchButton.classList.remove(\n      \"is-loading\"\n    );\n\n\n    return;\n\n  }\n\n\n  const routes =\n    buildSearchRoutes(\n      query\n    );\n\n\n  startProgress(\n    routes.length\n  );\n\n\n  const candidates =\n    new Map();\n\n\n  let completed =\n    0;\n\n\n  await Promise.allSettled(\n\n    routes.map(\n\n      async (\n        route,\n        index\n      ) => {\n\n        try{\n\n          const posts =\n            await fetchPosts(\n              {\n                search:\n                  route,\n\n                per_page:\n                  CONFIG.searchPerTerm,\n\n                orderby:\n                  \"relevance\",\n\n                order:\n                  \"desc\"\n              },\n              signal\n            );\n\n\n          posts.forEach(\n            post => {\n\n              const scoring =\n                scorePost(\n                  post,\n                  query,\n                  route\n                );\n\n\n              const existing =\n                candidates.get(\n                  post.id\n                );\n\n\n              if(\n                !existing\n              ){\n\n                candidates.set(\n                  post.id,\n                  {\n\n                    post,\n\n                    score:\n                      scoring.score,\n\n                    matched:\n                      scoring.matched,\n\n                    topic:\n                      classify(post)\n\n                  }\n                );\n\n              }\n\n              else{\n\n                existing.score +=\n                  Math.max(\n                    2,\n                    scoring.score * .15\n                  );\n\n\n                existing.matched =\n                  Array.from(\n                    new Set([\n                      ...existing.matched,\n                      ...scoring.matched\n                    ])\n                  )\n                  .slice(\n                    0,\n                    3\n                  );\n\n              }\n\n            }\n          );\n\n\n          completed++;\n\n\n          state.searchResults =\n            Array.from(\n              candidates.values()\n            )\n            .sort(\n              (a,b) =>\n                b.score -\n                a.score\n            );\n\n\n          if(\n            state.searchResults.length\n          ){\n\n            renderResults();\n\n          }\n\n\n          updateProgress(\n            index,\n            completed,\n            routes.length,\n            candidates.size > 0\n          );\n\n        }\n\n        catch(error){\n\n          if(\n            error.name ===\n            \"AbortError\"\n          ){\n\n            return;\n\n          }\n\n\n          completed++;\n\n\n          updateProgress(\n            index,\n            completed,\n            routes.length,\n            candidates.size > 0\n          );\n\n        }\n\n      }\n\n    )\n\n  );\n\n\n  if(\n    signal.aborted\n  ){\n    return;\n  }\n\n\n  state.searchResults =\n    Array.from(\n      candidates.values()\n    )\n    .sort(\n      (a,b) =>\n        b.score -\n        a.score\n\n        ||\n\n        new Date(\n          b.post.date\n        )\n        -\n        new Date(\n          a.post.date\n        )\n    );\n\n\n  saveCachedSearch(\n    query,\n    state.searchResults\n  );\n\n\n  renderResults();\n\n\n  finishProgress(\n    state.searchResults.length\n  );\n\n}\n\n\n\/* ==========================================================\n   RESET\n   ========================================================== *\/\n\nfunction resetSearch(){\n\n  if(\n    state.controller\n  ){\n\n    state.controller.abort();\n\n  }\n\n\n  state.query =\n    \"\";\n\n\n  state.searchResults =\n    [];\n\n\n  state.visible =\n    CONFIG.initialVisible;\n\n\n  clearInterval(\n    state.countdownTimer\n  );\n\n\n  searchProgress.classList.remove(\n    \"visible\",\n    \"has-results\"\n  );\n\n\n  searchProgressValue.style.width =\n    \"0%\";\n\n\n  searchCountdown.textContent =\n    CONFIG.countdownStart;\n\n\n  searchIntelligence.classList.remove(\n    \"visible\"\n  );\n\n\n  liveResultNote.classList.remove(\n    \"visible\"\n  );\n\n\n  clearSearch.classList.remove(\n    \"visible\"\n  );\n\n\n  searchButton.textContent =\n    \"Zoek in kennisbank\";\n\n\n  searchButton.classList.remove(\n    \"is-loading\"\n  );\n\n\n  renderResults();\n\n\n  updateURL();\n\n}\n\n\n\/* ==========================================================\n   URL\n   Alleen zoekterm.\n   Geen topic\/filter-parameter meer.\n   ========================================================== *\/\n\nfunction updateURL(){\n\n  const url =\n    new URL(\n      window.location.href\n    );\n\n\n  if(\n    state.query\n  ){\n\n    url.searchParams.set(\n      \"q\",\n      state.query\n    );\n\n  }\n\n  else{\n\n    url.searchParams.delete(\n      \"q\"\n    );\n\n  }\n\n\n  url.searchParams.delete(\n    \"topic\"\n  );\n\n\n  history.replaceState(\n    {},\n    \"\",\n    url\n  );\n\n}\n\n\n\/* ==========================================================\n   EVENTS\n   ========================================================== *\/\n\nsearchButton.addEventListener(\n  \"click\",\n  executeSearch\n);\n\n\nsearchInput.addEventListener(\n  \"keydown\",\n  event => {\n\n    if(\n      event.key ===\n      \"Enter\"\n    ){\n\n      executeSearch();\n\n    }\n\n  }\n);\n\n\nsearchInput.addEventListener(\n  \"input\",\n  function(){\n\n    clearSearch.classList.toggle(\n      \"visible\",\n      Boolean(\n        searchInput.value\n      )\n    );\n\n\n    if(\n      searchInput.value === \"\"\n      &&\n      state.query\n    ){\n\n      resetSearch();\n\n    }\n\n  }\n);\n\n\nclearSearch.addEventListener(\n  \"click\",\n  function(){\n\n    searchInput.value =\n      \"\";\n\n\n    resetSearch();\n\n\n    searchInput.focus();\n\n  }\n);\n\n\ndocument\n  .querySelectorAll(\n    \".example-search\"\n  )\n  .forEach(\n    button => {\n\n      button.addEventListener(\n        \"click\",\n        function(){\n\n          searchInput.value =\n            button.dataset.query;\n\n\n          executeSearch();\n\n        }\n      );\n\n    }\n  );\n\n\nloadMore.addEventListener(\n  \"click\",\n  function(){\n\n    state.visible +=\n      CONFIG.loadIncrement;\n\n\n    renderResults();\n\n  }\n);\n\n\n\/* ==========================================================\n   INITIAL POSTS\n   ========================================================== *\/\n\nasync function loadInitialPosts(){\n\n  try{\n\n    const posts =\n      await fetchPosts(\n        {\n          per_page:\n            CONFIG.browsePosts,\n\n          orderby:\n            \"date\",\n\n          order:\n            \"desc\"\n        }\n      );\n\n\n    state.browsePosts =\n      posts;\n\n\n    renderResults();\n\n\n    if(\n      posts[0]\n    ){\n\n      renderFeatured(\n        posts[0]\n      );\n\n    }\n\n\n    hydrateImages(\n      posts\n    );\n\n  }\n\n  catch(error){\n\n    articleGrid.innerHTML = `\n\n      <div class=\"empty\">\n\n        <h3>\n          De kennisbank kan momenteel niet geladen worden.\n        <\/h3>\n\n        <p>\n          Controleer de WordPress REST API\n          of probeer later opnieuw.\n        <\/p>\n\n      <\/div>\n\n    `;\n\n\n    resultSummary.textContent =\n      \"API niet bereikbaar\";\n\n  }\n\n}\n\n\n\/* ==========================================================\n   RESTORE SEARCH FROM URL\n   ========================================================== *\/\n\nconst params =\n  new URLSearchParams(\n    window.location.search\n  );\n\n\nconst qParam =\n  params.get(\n    \"q\"\n  );\n\n\nloadInitialPosts()\n  .then(\n    function(){\n\n      if(\n        qParam\n      ){\n\n        searchInput.value =\n          qParam;\n\n\n        clearSearch.classList.add(\n          \"visible\"\n        );\n\n\n        executeSearch();\n\n      }\n\n    }\n  );\n\n\n})();\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-46de81e e-flex e-con-boxed e-con e-parent\" data-id=\"46de81e\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-d2d27ee elementor-widget elementor-widget-spacer\" data-id=\"d2d27ee\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-3ec24f7 e-flex e-con-boxed e-con e-parent\" data-id=\"3ec24f7\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-6ea40dc elementor-widget elementor-widget-video\" data-id=\"6ea40dc\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;video_type&quot;:&quot;hosted&quot;,&quot;autoplay&quot;:&quot;yes&quot;,&quot;mute&quot;:&quot;yes&quot;,&quot;loop&quot;:&quot;yes&quot;,&quot;play_on_mobile&quot;:&quot;yes&quot;}\" data-widget_type=\"video.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"e-hosted-video elementor-wrapper elementor-open-inline\">\n\t\t\t\t\t<video class=\"elementor-video\" src=\"https:\/\/cctvacademy.be\/wp-content\/uploads\/2026\/03\/PixVerse_V6_Image_Text_360P_maak_een_nieuwe_af.mp4\" autoplay=\"\" loop=\"\" muted=\"muted\" playsinline=\"\" controlsList=\"nodownload\"><\/video>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-267b1e4 e-flex e-con-boxed e-con e-parent\" data-id=\"267b1e4\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-46dd0bb elementor-widget elementor-widget-text-editor\" data-id=\"46dd0bb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<h6><span style=\"color: #ffffff;\">\u201cWaar traditionele camera\u2019s alleen terugkijken,\u00a0<\/span><br \/><span style=\"color: #ffffff;\">kijkt AI-CCTV vooruit.\u201d<\/span><\/h6>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-6df6208 e-flex e-con-boxed e-con e-parent\" data-id=\"6df6208\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-d2deb40 elementor-widget elementor-widget-spacer\" data-id=\"d2deb40\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-53f204f e-flex e-con-boxed e-con e-parent\" data-id=\"53f204f\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-6e11281 elementor-widget elementor-widget-spacer\" data-id=\"6e11281\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>under construction Taal \u00b7 Langue \u00b7 LanguageNLFREN CCTV CCTV Academy CCTV \u00b7 AI \u00b7 SECURITY \u00b7 TRAINING Home Kennisbank Opleidingen Contact Bekijk opleidingen \u2197 CCTV Academy \u00b7 Smart Knowledge Search vraag \u2192 techniek \u2192 antwoord LIVE CCTV Kennisbank Zoek een probleem. Vind de oplossing. Doorzoek de CCTV Academy-kennisbank in gewone taal. Zoek bijvoorbeeld op \u201ccamera [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"open","template":"elementor_canvas","meta":{"_acf_changed":false,"zakra_page_container_layout":"customizer","zakra_page_sidebar_layout":"customizer","zakra_remove_content_margin":false,"zakra_sidebar":"customizer","zakra_transparent_header":"customizer","zakra_logo":0,"zakra_main_header_style":"default","zakra_menu_item_color":"","zakra_menu_item_hover_color":"","zakra_menu_item_active_color":"","zakra_menu_active_style":"","zakra_page_header":true,"_glsr_average":0,"_glsr_ranking":0,"_glsr_reviews":0,"footnotes":""},"class_list":["post-610","page","type-page","status-publish","hentry"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Blog - RAS\/AIS CCTV Academy<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cctvacademy.be\/nl\/blog\/\" \/>\n<meta property=\"og:locale\" content=\"nl_BE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Blog - RAS\/AIS CCTV Academy\" \/>\n<meta property=\"og:description\" content=\"under construction Taal \u00b7 Langue \u00b7 LanguageNLFREN CCTV CCTV Academy CCTV \u00b7 AI \u00b7 SECURITY \u00b7 TRAINING Home Kennisbank Opleidingen Contact Bekijk opleidingen \u2197 CCTV Academy \u00b7 Smart Knowledge Search vraag \u2192 techniek \u2192 antwoord LIVE CCTV Kennisbank Zoek een probleem. Vind de oplossing. Doorzoek de CCTV Academy-kennisbank in gewone taal. Zoek bijvoorbeeld op \u201ccamera [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cctvacademy.be\/nl\/blog\/\" \/>\n<meta property=\"og:site_name\" content=\"RAS\/AIS CCTV Academy\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/profile.php?id=61576769152561\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-27T12:10:51+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/cctvacademy.be\/wp-content\/uploads\/2026\/09\/CCTV-Academy-Wouter-Rooseboom-CCTV-Micro-Learning.png\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/cctvacademy.be\\\/blog\\\/\",\"url\":\"https:\\\/\\\/cctvacademy.be\\\/blog\\\/\",\"name\":\"Blog - RAS\\\/AIS CCTV Academy\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/cctvacademy.be\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/cctvacademy.be\\\/blog\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/cctvacademy.be\\\/blog\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/cctvacademy.be\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/CCTV-Academy-Wouter-Rooseboom-CCTV-Micro-Learning.png\",\"datePublished\":\"2015-07-29T13:49:24+00:00\",\"dateModified\":\"2026-09-27T12:10:51+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/cctvacademy.be\\\/blog\\\/#breadcrumb\"},\"inLanguage\":\"nl-BE\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/cctvacademy.be\\\/blog\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"nl-BE\",\"@id\":\"https:\\\/\\\/cctvacademy.be\\\/blog\\\/#primaryimage\",\"url\":\"https:\\\/\\\/cctvacademy.be\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/CCTV-Academy-Wouter-Rooseboom-CCTV-Micro-Learning.png\",\"contentUrl\":\"https:\\\/\\\/cctvacademy.be\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/CCTV-Academy-Wouter-Rooseboom-CCTV-Micro-Learning.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/cctvacademy.be\\\/blog\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/cctvacademy.be\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/cctvacademy.be\\\/#website\",\"url\":\"https:\\\/\\\/cctvacademy.be\\\/\",\"name\":\"CCTV Academy\",\"description\":\"CCTV Opleidingen en CCTV Micro Learning\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/cctvacademy.be\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"nl-BE\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Blog - RAS\/AIS CCTV Academy","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cctvacademy.be\/nl\/blog\/","og_locale":"nl_BE","og_type":"article","og_title":"Blog - RAS\/AIS CCTV Academy","og_description":"under construction Taal \u00b7 Langue \u00b7 LanguageNLFREN CCTV CCTV Academy CCTV \u00b7 AI \u00b7 SECURITY \u00b7 TRAINING Home Kennisbank Opleidingen Contact Bekijk opleidingen \u2197 CCTV Academy \u00b7 Smart Knowledge Search vraag \u2192 techniek \u2192 antwoord LIVE CCTV Kennisbank Zoek een probleem. Vind de oplossing. Doorzoek de CCTV Academy-kennisbank in gewone taal. Zoek bijvoorbeeld op \u201ccamera [&hellip;]","og_url":"https:\/\/cctvacademy.be\/nl\/blog\/","og_site_name":"RAS\/AIS CCTV Academy","article_publisher":"https:\/\/www.facebook.com\/profile.php?id=61576769152561","article_modified_time":"2026-09-27T12:10:51+00:00","og_image":[{"url":"https:\/\/cctvacademy.be\/wp-content\/uploads\/2026\/09\/CCTV-Academy-Wouter-Rooseboom-CCTV-Micro-Learning.png","type":"","width":"","height":""}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/cctvacademy.be\/blog\/","url":"https:\/\/cctvacademy.be\/blog\/","name":"Blog - RAS\/AIS CCTV Academy","isPartOf":{"@id":"https:\/\/cctvacademy.be\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cctvacademy.be\/blog\/#primaryimage"},"image":{"@id":"https:\/\/cctvacademy.be\/blog\/#primaryimage"},"thumbnailUrl":"https:\/\/cctvacademy.be\/wp-content\/uploads\/2026\/09\/CCTV-Academy-Wouter-Rooseboom-CCTV-Micro-Learning.png","datePublished":"2015-07-29T13:49:24+00:00","dateModified":"2026-09-27T12:10:51+00:00","breadcrumb":{"@id":"https:\/\/cctvacademy.be\/blog\/#breadcrumb"},"inLanguage":"nl-BE","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cctvacademy.be\/blog\/"]}]},{"@type":"ImageObject","inLanguage":"nl-BE","@id":"https:\/\/cctvacademy.be\/blog\/#primaryimage","url":"https:\/\/cctvacademy.be\/wp-content\/uploads\/2026\/09\/CCTV-Academy-Wouter-Rooseboom-CCTV-Micro-Learning.png","contentUrl":"https:\/\/cctvacademy.be\/wp-content\/uploads\/2026\/09\/CCTV-Academy-Wouter-Rooseboom-CCTV-Micro-Learning.png"},{"@type":"BreadcrumbList","@id":"https:\/\/cctvacademy.be\/blog\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cctvacademy.be\/"},{"@type":"ListItem","position":2,"name":"Blog"}]},{"@type":"WebSite","@id":"https:\/\/cctvacademy.be\/#website","url":"https:\/\/cctvacademy.be\/","name":"CCTV Academy","description":"CCTV Opleidingen en CCTV Micro Learning","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cctvacademy.be\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"nl-BE"}]}},"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/cctvacademy.be\/nl\/wp-json\/wp\/v2\/pages\/610","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cctvacademy.be\/nl\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/cctvacademy.be\/nl\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/cctvacademy.be\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cctvacademy.be\/nl\/wp-json\/wp\/v2\/comments?post=610"}],"version-history":[{"count":0,"href":"https:\/\/cctvacademy.be\/nl\/wp-json\/wp\/v2\/pages\/610\/revisions"}],"wp:attachment":[{"href":"https:\/\/cctvacademy.be\/nl\/wp-json\/wp\/v2\/media?parent=610"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}