PageSourceSearch

https://robertsaientoetsing.pages.dev/interactief/

html robertsaientoetsing.pages.dev collected 2026-10-03 05:54:02 UTC 80,139 bytes, 1,994 lines download raw bytes

1<!DOCTYPE html>
2<html lang="nl">
3<head>
4<meta charset="UTF-8">
5<meta name="viewport" content="width=device-width, initial-scale=1.0">
6<title>Toolkit 'AI, curriculum en toetsing'</title>
7<style>
8  :root{
9    --kleur-header:#d3104c;
10    --groen:#bfe6c2;
11    --groen-rand:#7cc684;
12    --geel:#fdeeb3;
13    --geel-rand:#e9cf6a;
14    --rood:#f4c2c4;
15    --rood-rand:#df8c8f;
16  }
17  *{box-sizing:border-box;}
18  html,body{height:100%;}
19  body{
20    margin:0;
21    font-family:"Segoe UI",Tahoma,Arial,sans-serif;
22    color:#1f1f1f;
23    background:#fff;
24    display:flex;
25    flex-direction:column;
26    height:100vh;
27    overflow:hidden;
28  }
29
30  /* ---------- Header ---------- */
31  header{
32    background:var(--kleur-header);
33    color:#fff;
34    padding:7px 12px;
35    display:flex;
36    align-items:center;
37    justify-content:space-between;
38    flex:0 0 auto;
39    box-shadow:0 2px 6px rgba(0,0,0,.2);
40    z-index:50;
41  }
42  header h1{
43    margin:0;
44    font-size:11px;
45    font-weight:600;
46    letter-spacing:.2px;
47  }
48  .header-actions{
49    position:relative;
50    display:flex;
51    align-items:center;
52    gap:6px;
53  }
54  .icon-btn{
55    width:23px;height:23px;
56    border-radius:50%;
57    border:1px solid rgba(255,255,255,.85);
58    background:rgba(255,255,255,.12);
59    color:#fff;
60    font-size:11px;
61    font-weight:700;
62    cursor:pointer;
63    display:flex;align-items:center;justify-content:center;
64    transition:background .15s;
65  }
66  .icon-btn:hover{background:rgba(255,255,255,.28);}
67
68  /* ---------- Settings popover ---------- */
69  .popover{
70    position:absolute;
71    top:30px;right:0;
72    background:#fff;
73    color:#1f1f1f;
74    border:1px solid #ddd;
75    border-radius:10px;
76    box-shadow:0 8px 24px rgba(0,0,0,.18);
77    padding:14px 16px;
78    min-width:200px;
79    display:none;
80    z-index:60;
81  }
82  .popover.open{display:block;}
83  .popover h3{margin:0 0 10px;font-size:13px;color:#888;text-transform:uppercase;letter-spacing:.5px;}
84  .popover label{
85    display:flex;align-items:center;gap:10px;
86    padding:6px 4px;font-size:14px;cursor:pointer;border-radius:6px;
87  }
88  .popover label:hover{background:#f5f5f5;}
89  .popover input[type=checkbox]{width:17px;height:17px;accent-color:var(--kleur-header);cursor:pointer;}
90
91  /* ---------- Toolbar (invoer) ---------- */
92  .toolbar{
93    flex:0 0 auto;
94    display:flex;
95    gap:6px;
96    padding:7px 12px;
97    background:#fafafa;
98    border-bottom:1px solid #eee;
99    align-items:center;
100  }
101  .toolbar input{
102    flex:1;
103    max-width:252px;
104    padding:6px 8px;
105    border:1px solid #ccc;
106    border-radius:6px;
107    font-size:8.5px;
108    outline:none;
109  }
110  .toolbar input:focus{border-color:var(--kleur-header);box-shadow:0 0 0 2px rgba(211,16,76,.15);}
111  .toolbar button{
112    padding:6px 12px;
113    background:var(--kleur-header);
114    color:#fff;
115    border:none;
116    border-radius:6px;
117    font-size:8.5px;font-weight:600;
118    cursor:pointer;
119    transition:filter .15s;
120  }
121  .toolbar button:hover{filter:brightness(1.08);}
122  .toolbar .hint{font-size:7.5px;color:#999;margin-left:4px;}
123
124  /* ---------- Whiteboard ---------- */
125  #whiteboard{
126    position:relative;
127    flex:1 1 auto;
128    overflow:hidden;
129  }
130  .board-grid{
131    position:absolute;
132    inset:0;
133    display:flex;
134    flex-direction:column;
135  }
136  .grid-row{display:flex;}
137  .grid-row.titles{flex:0 0 auto;}
138  .grid-row.band-row{flex:1 1 0;}
139  /* 'i'-knopje achter een balk-label */
140  .info-i{
141    display:inline-flex;align-items:center;justify-content:center;
142    width:18px;height:18px;
143    margin-left:6px;
144    border-radius:50%;
145    border:1px solid #555;
146    background:#fff;
147    color:#333;
148    font-family:Georgia,'Times New Roman',serif;
149    font-style:italic;
150    font-weight:700;
151    font-size:11px;
152    line-height:1;
153    cursor:pointer;
154    vertical-align:middle;
155    padding:0;
156  }
157  .info-i:hover{background:#333;color:#fff;border-color:#333;}
158  /* ---------- Brede modal + inschattingsmatrix ---------- */
159  .modal.modal-wide{max-width:1140px;}
160  .matrix{
161    display:flex;
162    margin-top:16px;
163    border:1px solid #cfcfcf;
164    border-radius:8px;
165    overflow:hidden;
166  }
167  .matrix-col{
168    flex:1 1 0;
169    display:flex;
170    flex-direction:column;
171    border-right:2px solid #fff;
172    min-width:0;
173  }
174  .matrix-col:last-child{border-right:none;}
175  .matrix-head{
176    background:var(--kleur-header);
177    color:#fff;
178    padding:10px 12px;
179    text-align:center;
180    font-weight:600;
181    font-size:12.5px;
182    line-height:1.35;
183  }
184  .matrix-cell{
185    flex:1 1 auto;
186    padding:10px 12px;
187    font-size:12px;
188    line-height:1.4;
189  }
190  .matrix-cell ul{margin:0;padding-left:18px;}
191  .matrix-cell li{margin:5px 0;}
192  .matrix-cell p{margin:10px 0 0;}
193  .matrix-foot{
194    padding:9px 12px;
195    font-size:12px;
196    border-top:2px solid #fff;
197  }
198  .col-groen .matrix-cell,.col-groen .matrix-foot{background:var(--groen);}
199  .col-geel  .matrix-cell,.col-geel  .matrix-foot{background:var(--geel);}
200  .col-rood  .matrix-cell,.col-rood  .matrix-foot{background:var(--rood);}
201  .matrix-col.highlight{outline:3px solid #d3104c;outline-offset:-3px;}
202  @media (max-width:720px){ .matrix{flex-direction:column;} .matrix-col{border-right:none;border-bottom:2px solid #fff;} }
203  .cell{
204    flex:1 1 0;
205    min-width:0;
206    border-right:2px solid #fff;
207  }
208  .cell:last-child{border-right:none;}
209  .cell.title{
210    text-align:center;
211    font-weight:700;
212    font-size:10.5px;
213    padding:5.5px 3px;
214    background:#f0f0f0;
215    color:#333;
216  }
217  .cell.band.groen{background:var(--groen);}
218  .cell.band.geel{background:var(--geel);}
219  .cell.band.rood{background:var(--rood);}
220  /* horizontale label-balken over de VOLLEDIGE breedte */
221  .level-label{
222    flex:0 0 auto;
223    text-align:center;
224    font-weight:600;
225    font-size:12.5px;
226    padding:8px 10px;
227    color:#2a2a2a;
228    border-top:2px solid #fff;
229    border-bottom:1px solid rgba(0,0,0,.12);
230  }
231  .level-label.groen-label{background:#dff0e1;}
232  .level-label.geel-label{background:#fdf3cc;}
233  .level-label.rood-label{background:#f8dadb;}
234
235  /* ---------- Verplaatsbare blokjes ---------- */
236  .note{
237    position:absolute;
238    width:85px;
239    z-index:10;
240    user-select:none;
241  }
242  /* status-icoon boven het blokje: geel ?, rood !, groen vinkje */
243  .note .note-icon{
244    display:none;
245    width:20px;height:20px;
246    line-height:20px;
247    margin:0 auto 2px;
248    text-align:center;
249    border-radius:50%;
250    font-weight:800;
251    font-size:13px;
252    box-shadow:0 1px 3px rgba(0,0,0,.25);
253    cursor:pointer;
254  }
255  .note .note-icon.active{display:block;}
256  .icon-geel{background:#f1c40f;color:#4a3b00;}
257  .icon-rood{background:#e2342a;color:#fff;}
258  .icon-groen{background:#1e9e54;color:#fff;}
259  .note .body{
260    background:#fff;
261    border:2px solid #000;
262    border-radius:6px;
263    padding:6px 8px;
264    font-size:11px;
265    line-height:1.2;
266    text-align:center;
267    word-break:break-word;
268    cursor:grab;
269    box-shadow:0 3px 8px rgba(0,0,0,.18);
270    min-height:22px;
271    display:flex;align-items:center;justify-content:center;
272  }
273  .note .body:hover{background:#fafafa;}
274  .note .body:active{cursor:grabbing;}
275
276  /* ---------- Info modal ---------- */
277  .modal-overlay{
278    position:fixed;inset:0;
279    background:rgba(0,0,0,.45);
280    display:none;
281    align-items:center;justify-content:center;
282    z-index:100;padding:20px;
283  }
284  .modal-overlay.open{display:flex;}
285  .modal{
286    background:#fff;
287    border-radius:14px;
288    max-width:560px;width:100%;
289    max-height:85vh;overflow:auto;
290    box-shadow:0 20px 50px rgba(0,0,0,.3);
291  }
292  .modal-header{
293    background:var(--kleur-header);
294    color:#fff;
295    padding:14px 20px;
296    display:flex;align-items:center;justify-content:space-between;
297    border-radius:14px 14px 0 0;
298    position:sticky;top:0;
299  }
300  .modal-header h2{margin:0;font-size:17px;}
301  .modal-header .close{cursor:pointer;font-size:22px;line-height:1;background:none;border:none;color:#fff;}
302  .modal-body{padding:20px 22px;font-size:14px;line-height:1.55;color:#2a2a2a;}
303  .modal-body h3{margin:18px 0 8px;font-size:14px;color:var(--kleur-header);}
304  .modal-body h3:first-child{margin-top:0;}
305  .legend{display:flex;gap:8px;align-items:center;margin:6px 0;font-size:13px;}
306  .swatch{width:18px;height:18px;border-radius:4px;flex:0 0 auto;border:1px solid rgba(0,0,0,.15);}
307  .icon-legend{width:20px;height:20px;line-height:20px;border-radius:50%;flex:0 0 auto;text-align:center;font-weight:800;font-size:13px;}
308  .modal-body ul{margin:6px 0;padding-left:20px;}
309  .modal-body li{margin:3px 0;}
310  .instructie-box{
311    margin-top:6px;
312    background:#f6f6f6;
313    border:1px dashed #ccc;
314    border-radius:8px;
315    padding:14px;
316    color:#666;
317    font-style:italic;
318  }
319
320  /* ---------- Toast melding ---------- */
321  #toast{
322    position:fixed;
323    bottom:22px;left:50%;
324    transform:translateX(-50%) translateY(20px);
325    background:#333;color:#fff;
326    padding:10px 18px;
327    border-radius:8px;
328    font-size:13px;
329    opacity:0;
330    pointer-events:none;
331    transition:opacity .25s, transform .25s;
332    z-index:200;
333  }
334  #toast.show{opacity:1;transform:translateX(-50%) translateY(0);}
335
336
337  /* ---------- Hoofdnavigatie met vier onderdelen ---------- */
338  .app-tabs{
339    flex:0 0 auto;
340    display:grid;
341    grid-template-columns:repeat(4,minmax(0,1fr));
342    background:#fff;
343    border-bottom:1px solid #d8d8d8;
344    box-shadow:0 2px 8px rgba(0,0,0,.12);
345    position:relative;
346    z-index:300;
347  }
348  .app-tab{
349    min-width:0;
350    height:45px;
351    min-height:45px;
352    padding:3px 14px;
353    border:0;
354    border-right:1px solid #ddd;
355    border-bottom:4px solid transparent;
356    background:#f5f5f5;
357    color:#292929;
358    font:600 14px/1.15 "Segoe UI",Tahoma,Arial,sans-serif;
359    text-align:center;
360    cursor:pointer;
361    transition:background .15s,color .15s,border-color .15s;
362  }
363  .app-tab:last-child{border-right:0;}
364  .app-tab:hover{background:#fff;}
365  .app-tab:focus-visible{outline:3px solid rgba(211,16,76,.3);outline-offset:-3px;}
366  .app-tab[aria-selected="true"]{
367    background:var(--kleur-header);
368    border-bottom-color:var(--kleur-header);
369    color:#fff;
370  }
371  .app-panels{
372    flex:1 1 auto;
373    min-height:0;
374    position:relative;
375    overflow:hidden;
376  }
377  .app-panel{
378    position:absolute;
379    inset:0;
380    min-width:0;
381    min-height:0;
382    display:none;
383    background:#fff;
384  }
385  .app-panel.active{display:flex;}
386  #panel-scan{flex-direction:column;overflow:hidden;}
387  #panel-toolkit,
388  #panel-flowchart{overflow:hidden;}
389  .embedded-page{
390    display:block;
391    width:100%;
392    height:100%;
393    border:0;
394    background:#fff;
395  }
396  #panel-cards{
397    overflow:auto;
398    background:#f7f7f7;
399    color:#111;
400    padding:22px clamp(18px,4vw,64px) 20px;
401  }
402  .cards-shell{
403    width:min(1120px,100%);
404    min-height:100%;
405    margin:auto;
406    display:flex;
407    flex-direction:column;
408    align-items:stretch;
409    gap:14px;
410  }
411  .cards-header{
412    display:block;
413    flex:0 0 auto;
414    padding:0;
415    background:transparent;
416    color:#111;
417    box-shadow:none;
418    position:static;
419    z-index:auto;
420  }
421  .cards-header h2{
422    margin:0 0 14px;
423    color:#111;
424    font-size:28px;
425    line-height:1.1;
426    font-weight:800;
427    font-style:normal;
428    text-align:center;
429  }
430  .card-categories{
431    display:grid;
432    grid-template-columns:repeat(3,minmax(0,1fr));
433    gap:12px;
434  }
435  .card-category{
436    min-height:48px;
437    padding:9px 14px;
438    border:2px solid #d8d8d8;
439    border-radius:9px;
440    background:#fff;
441    color:#292929;
442    font:700 14px/1.25 "Segoe UI",Tahoma,Arial,sans-serif;
443    cursor:pointer;
444    transition:background .15s,color .15s,border-color .15s,box-shadow .15s;
445  }
446  .card-category:hover{
447    border-color:var(--kleur-header);
448    box-shadow:0 2px 8px rgba(0,0,0,.08);
449  }
450  .card-category:focus-visible{
451    outline:3px solid rgba(211,16,76,.25);
452    outline-offset:2px;
453  }
454  .card-category[aria-selected="true"]{
455    background:var(--kleur-header);
456    border-color:var(--kleur-header);
457    color:#fff;
458  }
459  .conversation-card{
460    position:relative;
461    flex:1 1 330px;
462    min-height:330px;
463    max-height:470px;
464    display:flex;
465    align-items:center;
466    justify-content:center;
467    padding:52px clamp(28px,7vw,90px) 62px;
468    background:#fff;
469    border:2px solid #ddd;
470    border-radius:14px;
471    box-shadow:0 7px 20px rgba(0,0,0,.09);
472  }
473  .card-warning{
474    padding:13px 18px;
475    border:1px solid #e0c16b;
476    border-radius:5px;
477    background:#fff1c9;
478    color:#29230f;
479    font-size:15px;
480    line-height:1.45;
481  }
482  .card-warning[hidden]{display:none;}
483  .card-content{
484    width:100%;
485    max-width:930px;
486    text-align:center;
487  }
488  .card-kicker{
489    margin-bottom:26px;
490    color:#999;
491    font-size:12px;
492    font-weight:500;
493    letter-spacing:1.2px;
494  }
495  #cardQuestion{
496    margin:0;
497    color:#003b49;
498    font-size:clamp(21px,2.15vw,29px);
499    line-height:1.42;
500    font-weight:800;
501  }
502  #cardSubtext{
503    max-width:900px;
504    margin:16px auto 0;
505    color:#4e4e4e;
506    font-size:clamp(13px,1.3vw,16px);
507    line-height:1.55;
508    font-style:italic;
509    font-weight:400;
510  }
511  #cardSubtext[hidden]{display:none;}
512  .card-counter{
513    position:absolute;
514    left:0;
515    right:0;
516    bottom:25px;
517    color:#aaa;
518    font-size:14px;
519    text-align:center;
520  }
521  .card-navigation{
522    display:flex;
523    justify-content:center;
524    gap:12px;
525  }
526  .card-navigation button{
527    min-width:122px;
528    min-height:42px;
529    padding:9px 18px;
530    border:0;
531    border-radius:8px;
532    background:#003b49;
533    color:#fff;
534    font:700 14px/1.2 "Segoe UI",Tahoma,Arial,sans-serif;
535    cursor:pointer;
536    transition:background .15s,transform .05s;
537  }
538  .card-navigation button:hover{background:#005467;}
539  .card-navigation button:active{transform:translateY(1px);}
540  .card-navigation button:focus-visible{
541    outline:3px solid rgba(0,59,73,.25);
542    outline-offset:2px;
543  }
544
545  /* Scanbediening: invoer en vier acties in één balk */
546  #panel-scan .header-actions{
547    flex:0 0 auto;
548    gap:10px;
549    margin-left:auto;
550  }
551  #panel-scan .icon-btn{
552    width:38px;
553    height:38px;
554    font-size:18px;
555    border-color:var(--kleur-header);
556    background:var(--kleur-header);
557    color:#fff;
558  }
559  #panel-scan .icon-btn:hover{background:#b90e42;}
560  #panel-scan .popover{top:50px;}
561  #panel-scan > .toolbar{
562    gap:10px;
563    padding:12px 20px;
564    min-width:0;
565  }
566  #panel-scan > .toolbar input{
567    max-width:420px;
568    padding:10px 14px;
569    border-radius:10px;
570    font-size:14px;
571  }
572  #panel-scan > .toolbar button{
573    padding:10px 20px;
574    border-radius:10px;
575    font-size:14px;
576  }
577  #panel-scan > .toolbar .hint{
578    flex:1 1 auto;
579    min-width:180px;
580    font-size:12.5px;
581    margin-left:7px;
582  }
583
584  @media (max-width:760px){
585    .app-tab{
586      height:58px;
587      min-height:58px;
588      padding:4px;
589    }
590    #panel-scan > .toolbar{flex-wrap:wrap;}
591    #panel-scan > .toolbar .hint{order:4;flex-basis:100%;margin-left:0;}
592    #panel-scan .header-actions{margin-left:0;}
593    #panel-cards{padding:16px 12px;}
594    .cards-header h2{font-size:23px;}
595    .card-categories{grid-template-columns:1fr;gap:7px;}
596    .card-category{min-height:40px;padding:7px 10px;font-size:12px;}
597    .conversation-card{
598      min-height:360px;
599      max-height:none;
600      padding:38px 22px 58px;
601    }
602    .card-kicker{margin-bottom:18px;}
603    #cardQuestion{font-size:20px;line-height:1.35;}
604    #cardSubtext{font-size:13px;line-height:1.45;}
605  }
606
607</style>
608</head>
609<body>
610  <nav class="app-tabs" aria-label="Onderdelen AI, curriculum en toetsing" role="tablist">
611    <button class="app-tab" id="tab-toolkit" type="button" role="tab" aria-controls="panel-toolkit" aria-selected="false" tabindex="-1">1) Toolkit 'AI, curriculum en toetsing'</button>
612    <button class="app-tab" id="tab-scan" type="button" role="tab" aria-controls="panel-scan" aria-selected="true">2) Scan AI-bewust curriculum- en toetsprogramma</button>
613    <button class="app-tab" id="tab-flowchart" type="button" role="tab" aria-controls="panel-flowchart" aria-selected="false" tabindex="-1">3) Flowchart AI-bewust toetsen</button>
614    <button class="app-tab" id="tab-cards" type="button" role="tab" aria-controls="panel-cards" aria-selected="false" tabindex="-1">4) Gesprekskaarten 'AI, curriculum en toetsing'</button>
615  </nav>
616
617  <main class="app-panels">
618    <section class="app-panel" id="panel-toolkit" role="tabpanel" aria-labelledby="tab-toolkit" hidden>
619      <iframe class="embedded-page" title="Toolkit AI, curriculum en toetsing" src="https://maken.wikiwijs.nl/223515/Toolkit__AI__curriculum_en_toetsing" loading="eager"></iframe>
620    </section>
621
622    <section class="app-panel active" id="panel-scan" role="tabpanel" aria-labelledby="tab-scan">
623<!-- ===== Header ===== -->
624  <header>
625    <h1>Scan AI-bewust curriculum- en toetsprogramma</h1>
626    <div class="header-actions">
627      <button class="icon-btn" id="saveBtn" title="Opslaan">&#128190;</button>
628      <button class="icon-btn" id="loadBtn" title="Laden">&#128194;</button>
629      <button class="icon-btn" id="infoBtn" title="Instructie">i</button>
630      <button class="icon-btn" id="settingsBtn" title="Instellingen">&#9881;</button>
631
632      <div class="popover" id="settingsMenu">
633        <h3>Toon jaren</h3>
634        <label><input type="checkbox" data-year="2" checked> Jaar 2 (Vlak 2)</label>
635        <label><input type="checkbox" data-year="3" checked> Jaar 3 (Vlak 3)</label>
636        <label><input type="checkbox" data-year="4" checked> Jaar 4 (Vlak 4)</label>
637      </div>
638    </div>
639  </header>
640
641  <!-- ===== Invoerbalk ===== -->
642  <div class="toolbar">
643    <input type="text" id="courseInput" placeholder="Cursusnaam">
644    <button id="addBtn">Voer in</button>
645    <span class="hint">Sleep blokjes met de linkermuisknop ingedrukt &nbsp;|&nbsp; klik op een blokje voor het status-icoon &nbsp;|&nbsp; rechtsklik om te verwijderen</span>
646  </div>
647
648  <!-- ===== Whiteboard ===== -->
649  <div id="whiteboard">
650    <div class="board-grid" id="board">
651      <div class="grid-row titles">
652        <div class="cell title" data-year="1">Jaar 1</div>
653        <div class="cell title" data-year="2">Jaar 2</div>
654        <div class="cell title" data-year="3">
654Jaar 3</div>
655        <div class="cell title" data-year="4">Jaar 4</div>
656      </div>
657
658      <div class="level-label groen-label">De toetsing is AI-bewust. <button class="info-i" data-level="groen" title="Toon de inschattingsmatrix">i</button></div>
659      <div class="grid-row band-row">
660        <div class="cell band groen" data-year="1"></div>
661        <div class="cell band groen" data-year="2"></div>
662        <div class="cell band groen" data-year="3"></div>
663        <div class="cell band groen" data-year="4"></div>
664      </div>
665
666      <div class="level-label geel-label">Er zijn nog enkele AI-gerelateerde risico&rsquo;s bij deze toetsing. <button class="info-i" data-level="geel" title="Toon de inschattingsmatrix">i</button></div>
667      <div class="grid-row band-row">
668        <div class="cell band geel" data-year="1"></div>
669        <div class="cell band geel" data-year="2"></div>
670        <div class="cell band geel" data-year="3"></div>
671        <div class="cell band geel" data-year="4"></div>
672      </div>
673
674      <div class="level-label rood-label">Er zijn veel AI-gerelateerde risico&rsquo;s bij deze toetsing. <button class="info-i" data-level="rood" title="Toon de inschattingsmatrix">i</button></div>
675      <div class="grid-row band-row">
676        <div class="cell band rood" data-year="1"></div>
677        <div class="cell band rood" data-year="2"></div>
678        <div class="cell band rood" data-year="3"></div>
679        <div class="cell band rood" data-year="4"></div>
680      </div>
681    </div>
682    <!-- verplaatsbare blokjes worden hier toegevoegd -->
683  </div>
684
685  <!-- ===== Info / instructie modal ===== -->
686  <div class="modal-overlay" id="infoModal">
687    <div class="modal">
688      <div class="modal-header">
689        <h2>Uitleg &amp; instructie</h2>
690        <button class="close" id="closeInfo">&times;</button>
691      </div>
692      <div class="modal-body">
693        <h3>De verticale vlakken (jaren)</h3>
694        <p>De pagina is verdeeld in vier verticale vlakken, één per studiejaar:</p>
695        <ul>
696          <li><strong>Vlak 1</strong> &ndash; Jaar 1</li>
697          <li><strong>Vlak 2</strong> &ndash; Jaar 2</li>
698          <li><strong>Vlak 3</strong> &ndash; Jaar 3</li>
699          <li><strong>Vlak 4</strong> &ndash; Jaar 4</li>
700        </ul>
701
702        <h3>De horizontale vlakken (AI-bewustzijn van de toetsing)</h3>
703        <div class="legend"><span class="swatch" style="background:var(--groen)"></span> <span><strong>Groen:</strong> De toetsing is AI-bewust.</span></div>
704        <div class="legend"><span class="swatch" style="background:var(--geel)"></span> <span><strong>Geel:</strong> Er zijn nog enkele AI-gerelateerde risico&rsquo;s bij deze toetsing.</span></div>
705        <div class="legend"><span class="swatch" style="background:var(--rood)"></span> <span><strong>Rood:</strong> Er zijn veel AI-gerelateerde risico&rsquo;s bij deze toetsing.</span></div>
706
707        <h3>De status-iconen op een blokje</h3>
708        <p>Klik met de linkermuisknop op een cursusblokje of rechtstreeks op het statusicoon om het icoon te wisselen:</p>
709        <div class="legend"><span class="icon-legend icon-geel">?</span> <span>In deze cursus willen we verder uitdenken of en hoe we AI hier een rol in willen geven.</span></div>
710        <div class="legend"><span class="icon-legend icon-rood">!</span> <span>In deze cursus worden de kansen van AI nog niet benut / komt AI nog niet aan bod, terwijl dat wel wenselijk is.</span></div>
711        <div class="legend"><span class="icon-legend icon-groen">&#10003;</span> <span>In deze cursus zijn de kansen van AI benut / komt AI niet aan bod omdat dat niet wenselijk is.</span></div>
712
713        <h3>Cursus verwijderen</h3>
714        <p><strong>Klik met de rechtermuisknop op een cursusblokje om die cursus direct te wissen.</strong></p>
715
716      </div>
717    </div>
718  </div>
719
720  <!-- ===== Inschattingsmatrix modal ===== -->
721  <div class="modal-overlay" id="matrixModal">
722    <div class="modal modal-wide">
723      <div class="modal-header">
724        <h2>Inschattingsmatrix AI-bewust toetsen</h2>
725        <button class="close" id="closeMatrix">&times;</button>
726      </div>
727      <div class="modal-body">
728        <p>Deze niveaus van AI-bewustheid zijn geen exacte wetenschap. Elke toets en elk toetsprogramma is immer
728s anders. Elke beroepspraktijk wordt ook weer op andere manieren beïnvloed door generatieve AI. Gebruik onderstaande informatie daarom om een globaal idee te krijgen van waar je toetsen kunt plaatsen in het overzicht. Het gesprek dat daaruit volgt is belangrijker dan de exacte positie van de toetsen.</p>
729        <p><strong>Verificatiemaatregelen</strong> zijn (extra) manieren om te toetsen of studenten de kennis, vaardigheden en attitudes daadwerkelijk <u>zelf</u> bezitten. Voorbeelden hiervan zijn het toevoegen van een mondelinge component of een uitgebreidere verantwoording van brongebruik. Verificatiemaatregelen zijn ook manieren om te controleren of studenten daadwerkelijk bepaald werk hebben uitgevoerd en manieren waarop ze hun AI-gebruik transparant hebben verantwoord. Voorbeelden hiervan zijn het toevoegen van feedback, gesprekken en/of handtekeningen van begeleiders.</p>
730
731        <div class="matrix">
732          <div class="matrix-col col-groen" data-level="groen">
733            <div class="matrix-head">AI-bewustheid: Hoog<br>AI-Risico: Laag<br><br>Extra verificatiemaatregelen niet nodig</div>
734            <div class="matrix-cell">
735              <ul>
736                <li>Mondelinge toetsen zonder bijbehorend product</li>
737                <li>Presentaties zonder bijbehorend product (Live observaties / Performance assessments, waaronder o.a. observaties van beroepshandelingen, stagewerkzaamheden en/of practica)</li>
738                <li>Video-opnames van beroepshandelingen, stagewerkzaamheden en/of practica</li>
739                <li>Toetsen onder toezicht op locatie, waaronder o.a. toetsing met meerkeuzevragen, open vragen, casuïstiek, etc.</li>
740                <li>Beveiligde digitale toetsen via ANS (Met/zonder internet, Met/zonder aangeleverde bronnen, Met/zonder AI.)</li>
741              </ul>
742            </div>
743            <div class="matrix-foot">Hoe kan generatieve AI de toetsing en de voorbereiding erop versterken?</div>
744          </div>
745
746          <div class="matrix-col col-geel" data-level="geel">
747            <div class="matrix-head">AI-bewustheid: Gemiddeld<br>AI-Risico: Gemiddeld<br><br>Overweeg extra verificatiemaatregelen</div>
748            <div class="matrix-cell">
749              <ul>
750                <li>Mondelinge toetsen gebaseerd op een bijbehorend product.</li>
751                <li>Presentaties gebaseerd op een bijbehorend product.</li>
752                <li>Criteriumgerichte interviews gebaseerd op een bijbehorend product.</li>
753              </ul>
754              <p>Hierbij is het van belang om te kijken hoe het product tot stand komt en of daar onwenselijk gebruik van generatieve AI kan meespelen.</p>
755            </div>
756            <div class="matrix-foot">Hoe kan generatieve AI de toetsing en de voorbereiding erop versterken?</div>
757          </div>
758
759          <div class="matrix-col col-rood" data-level="rood">
760            <div class="matrix-head">AI-bewustheid: Laag<br>AI-Risico: Hoog<br><br>Extra verificatiemaatregelen nodig</div>
761            <div class="matrix-cell">
762              <ul>
763                <li>Alle soorten schriftelijke verslagen zonder verificatiemaatregelen</li>
764                <li>Opgenomen audiopresentaties zonder verificatiemaatregelen</li>
765                <li>Portfolio&rsquo;s zonder verificatiemaatregelen</li>
766                <li>Scripties zonder verificatiemaatregelen (met name scripties waarin theoretisch onderzoek centraal staat en een praktijkgerichte component ontbreekt of minimaal is)</li>
767              </ul>
768            </div>
769            <div class="matrix-foot">Hoe kan generatieve AI de toetsing en de voorbereiding erop versterken?</div>
770          </div>
771        </div>
772      </div>
773    </div>
774  </div>
775
776  <!-- verborgen bestand-invoer voor het laden van een opgeslagen bestand -->
777  <input type="file" id="fileInput" accept="application/json,.json" style="display:none">
778
779  <!-- toast melding -->
780  <div id="toast"></div>
781
782<script>
783/* ---------- Gedeelde opslag: alles wat de gebruiker doet blijft lokaal bewaard ---------- */
784window.toolkitState = (function(){
785  const KEY = 'toetsscan_ui';
786  function read(){
787    try{ return JSON.parse(localStorage.getItem(KEY) || '{}') || {}; }
788    catch(e){ return {}; }
789  }
790  function write(patch){
791    try{
792      const state = read();
793      Object.assign(state, patch);
794      localStorage.setItem(KEY, JSON.stringify(state));
795    }catch(e){}
796  }
797  return { read: read, write: write };
798})();
799</script>
799
800
801<script>
802(function(){
803  "use strict";
804
805  const whiteboard   = document.getElementById('whiteboard');
806  const board        = document.getElementById('board');
807  const courseInput  = document.getElementById('courseInput');
808  const addBtn       = document.getElementById('addBtn');
809  const settingsBtn  = document.getElementById('settingsBtn');
810  const settingsMenu = document.getElementById('settingsMenu');
811  const infoBtn      = document.getElementById('infoBtn');
812  const infoModal    = document.getElementById('infoModal');
813  const closeInfo    = document.getElementById('closeInfo');
814
815  // status-iconen die je doorklikt op een blokje (geel ? -> rood ! -> groen vinkje)
816  const ICONS = [
817    { sym:'?', cls:'icon-geel',  label:'In deze cursus willen we verder uitdenken of en hoe we AI hier een rol in willen geven.' },
818    { sym:'!', cls:'icon-rood',  label:'In deze cursus worden de kansen van AI nog niet benut / komt AI nog niet aan bod, terwijl dat wel wenselijk is.' },
819    { sym:'✓', cls:'icon-groen', label:'In deze cursus zijn de kansen van AI benut / komt AI niet aan bod omdat dat niet wenselijk is.' }
820  ];
821
822  const LEVELS = ['groen','geel','rood'];
823  let cascade = 0; // verdeelt nieuwe blokjes binnen het eerste vak
824
825  function clamp(value, min, max){
826    return Math.max(min, Math.min(value, max));
827  }
828
829  function getBandCell(year, level){
830    const cell = board.querySelector('.cell.band.'+level+'[data-year="'+year+'"]');
831    if(!cell) return null;
832    const rect = cell.getBoundingClientRect();
833    return (rect.width > 0 && rect.height > 0) ? cell : null;
834  }
835
836  function setNoteAnchor(note, year, level, xRatio, yRatio){
837    note.dataset.year = String(year);
838    note.dataset.level = LEVELS.indexOf(level) >= 0 ? level : 'groen';
839    note.dataset.xRatio = String(clamp(Number(xRatio) || 0.5, 0, 1));
840    note.dataset.yRatio = String(clamp(Number(yRatio) || 0.5, 0, 1));
841  }
842
843  function getNoteAnchor(note){
844    return {
845      year: note.dataset.year || '1',
846      level: LEVELS.indexOf(note.dataset.level) >= 0 ? note.dataset.level : 'groen',
847      xRatio: clamp(parseFloat(note.dataset.xRatio) || 0.5, 0, 1),
848      yRatio: clamp(parseFloat(note.dataset.yRatio) || 0.5, 0, 1)
849    };
850  }
851
852  function positionNoteFromAnchor(note){
853    if(note.dataset.dragging === 'true') return;
854    const anchor = getNoteAnchor(note);
855    const cell = getBandCell(anchor.year, anchor.level);
856    if(!cell){
857      note.style.display = 'none';
858      return;
859    }
860
861    note.style.display = '';
862    const cellRect = cell.getBoundingClientRect();
863    const boardRect = whiteboard.getBoundingClientRect();
864    const noteWidth = note.offsetWidth;
865    const noteHeight = note.offsetHeight;
866
867    const minX = cellRect.width > noteWidth ? (noteWidth / 2) / cellRect.width : 0.5;
868    const maxX = cellRect.width > noteWidth ? 1 - minX : 0.5;
869    const minY = cellRect.height > noteHeight ? (noteHeight / 2) / cellRect.height : 0.5;
870    const maxY = cellRect.height > noteHeight ? 1 - minY : 0.5;
871    const xRatio = clamp(anchor.xRatio, minX, maxX);
872    const yRatio = clamp(anchor.yRatio, minY, maxY);
873
874    note.style.left = (cellRect.left - boardRect.left + xRatio * cellRect.width - noteWidth / 2) + 'px';
875    note.style.top  = (cellRect.top - boardRect.top + yRatio * cellRect.height - noteHeight / 2) + 'px';
876  }
877
878  function nearestBandCell(centerX, centerY){
879    let nearest = null;
880    let nearestDistance = Infinity;
881    LEVELS.forEach(function(level){
882      board.querySelectorAll('.cell.band.'+level).forEach(function(cell){
883        const rect = cell.getBoundingClientRect();
884        if(rect.width <= 0 || rect.height <= 0) return;
885        const dx = centerX < rect.left ? rect.left - centerX : (centerX > rect.right ? centerX - rect.right : 0);
886        const dy = centerY < rect.top ? rect.top - centerY : (centerY > rect.bottom ? centerY - rect.bottom : 0);
887        const distance = dx * dx + dy * dy;
888        if(distance < nearestDistance){
889          nearestDistance = distance;
890          nearest = { cell:cell, level:level, rect:rect };
891        }
892      });
893    });
894    return nearest;
895  }
896
897  function anchorNoteToNearestCell(note){
898    const noteRect = note.getBoundingClientRect();
899    const centerX = noteRect.left + noteRect.width / 2;
900    const centerY = noteRect.top + noteRect.height / 2;
901    const target = nearestBandCell(centerX, centerY);
902    if(!target) return;
903
904    setNoteAnchor(
905      note,
906      target.cell.getAttribute('data-year') || '1',
907      target.level,
908      (centerX - target.rect.left) / target.rect.width,
909      (centerY - target.rect.top) / target.rect.height
910    );
911    positionNoteFromAnchor(note);
912  }
913
914  function layoutAllNotes(){
915    if(whiteboard.clientWidth < 1 || whiteboard.clientHeight < 1) return;
916    whiteboard.querySelectorAll('.note').forEach(positionNoteFromAnchor);
917  }
918
919  let layoutFrame = 0;
920  function scheduleLayout(){
921    cancelAnimationFrame(layoutFrame);
922    layoutFrame = requestAnimationFrame(layoutAllNotes);
923  }
924
925  /* ---------- Blokje toevoegen ---------- */
926  function addNote(text, opts){
927    opts = opts || {};
928    const note = document.createElement('div');
929    note.className = 'note';
930    note.dataset.text = text;
931
932    const icon = document.createElement('div');
933    icon.className = 'note-icon';
934
935    const body = document.createElement('div');
936    body.className = 'body';
937    body.textContent = text;
938    body.title = 'Sleep met de linkermuisknop ingedrukt · klik om het icoon te wisselen · rechtsklik om te verwijderen';
939
940    note.appendChild(icon);
941    note.appendChild(body);
942
943    whiteboard.appendChild(note);
944
945    // ----- Status-icoon -----
946    // bij toevoegen staat het eerste icoon (geel ?) meteen zichtbaar;
947    // links klikken loopt door: geel ? -> rood ! -> groen vinkje -> geel ? ...
948    let state = (typeof opts.state === 'number') ? (((opts.state % 3) + 3) % 3) : 0;
949
950    function renderIcon(){
951      const ic = ICONS[state];
952      icon.textContent = ic.sym;
953      icon.className = 'note-icon active ' + ic.cls;
954      icon.title = ic.label + ' Klik om het volgende statusicoon te tonen.';
955      note.dataset.state = state;   // staat onthouden voor opslaan
956    }
957
958    renderIcon();   // toon direct het eerste icoon bij toevoegen
959
960    // Nieuwe opslag gebruikt een vast vak (jaar + niveau) en een relatieve
961    // positie binnen dat vak. Oude pixelposities worden eenmalig gemigreerd.
962    const hasAnchor = opts.year && LEVELS.indexOf(opts.level) >= 0 &&
963      typeof opts.xRatio === 'number' && typeof opts.yRatio === 'number';
964    if(hasAnchor){
965      setNoteAnchor(note, opts.year, opts.level, opts.xRatio, opts.yRatio);
966      positionNoteFromAnchor(note);
967    }else if(typeof opts.left === 'number' && typeof opts.top === 'number'){
968      note.style.left = opts.left + 'px';
969      note.style.top  = opts.top + 'px';
970      anchorNoteToNearestCell(note);
971    }else{
972      const slot = cascade++;
973      const xSlots = [0.20, 0.50, 0.80];
974      const ySlots = [0.28, 0.72];
975      setNoteAnchor(note, '1', 'groen', xSlots[slot % 3], ySlots[Math.floor(slot / 3) % 2]);
976      positionNoteFromAnchor(note);
977    }
978
979    // ----- Verwijderen via de rechtermuisknop -----
980    note.addEventListener('contextmenu', function(e){
981      e.preventDefault();
982      note.remove();
983      autoSave();          // verwijdering direct opslaan
984    });
985
986    function cycleStatus(){
987      state = (state + 1) % 3;
988      renderIcon();
989      autoSave();          // icoonwijziging direct opslaan
990    }
991
992    // ----- Slepen met de linkermuisknop; een gewone klik wisselt het icoon -----
993    enableDrag(note, body, cycleStatus);
994    icon.addEventListener('click', function(e){
995      e.stopPropagation();
996      cycleStatus();       // klikken op het icoon werkt hetzelfde als klikken op het blokje
997    });
998
999    autoSave();            // toevoeging direct opslaan
1000    return note;
1001  }
1002
1003  /* ---------- Sleepfunctionaliteit ----------
1004     Het hele blokje is versleepbaar met de linkermuisknop ingedrukt.
1005     Indrukken en loslaten zonder beweging telt als klik (onTap). */
1006  function enableDrag(note, surface, onTap){
1007    let startX, startY, origLeft, origTop, dragging = false, moved = false;
1008
1009    surface.addEventListener('pointerdown', function(e){
1010      if(e.button !== 0) return;          // alleen de linkermuisknop sleept
1011      e.preventDefault();
1012      dragging = true;
1013      moved = false;
1014      startX = e.clientX;
1015      startY = e.clientY;
1016      origLeft = note.offsetLeft;
1017      origTop  = note.offsetTop;
1018      note.style.zIndex = 1000;
1019      note.dataset.dragging = 'true';
1020      surface.setPointerCapture(e.pointerId);
1021    });
1022
1023    surface.addEventListener('pointermove', function(e){
1024      if(!dragging) return;
1025      const dx = e.clientX - startX;
1026      const dy = e.clientY - startY;
1027      if(!moved && (Math.abs(dx) > 3 || Math.abs(dy) > 3)){ moved = true; }
1028      if(!moved) return;
1029
1030      let newLeft = origLeft + dx;
1031      let newTop  = origTop + dy;
1032
1033      // binnen het whiteboard houden
1034      const maxLeft = whiteboard.clientWidth  - note.offsetWidth;
1035      const maxTop  = whiteboard.clientHeight - note.offsetHeight;
1036      newLeft = Math.max(0, Math.min(newLeft, maxLeft));
1037      newTop  = Math.max(0, Math.min(newTop,  maxTop));
1038
1039      note.style.left = newLeft + 'px';
1040      note.style.top  = newTop + 'px';
1041    });
1042
1043    function endDrag(e){
1044      if(!dragging) return;
1045      dragging = false;
1046      note.style.zIndex = 10;
1047      try{ surface.releasePointerCapture(e.pointerId); }catch(_){}
1048      if(!moved){
1049        if(typeof onTap === 'function'){ onTap(); }   // gewone klik -> icoon wisselen
1050      }else{
1051        note.dataset.dragging = 'false';
1052        anchorNoteToNearestCell(note);                // vastzetten in één van de 12 vakken
1053        autoSave();                                   // verplaatsing direct opslaan
1054      }
1055      note.dataset.dragging = 'false';
1056    }
1057    surface.addEventListener('pointerup', endDrag);
1058    surface.addEventListener('pointercancel', endDrag);
1059  }
1060
1061  /* ---------- Invoer afhandelen ---------- */
1062  function handleAdd(){
1063    const text = courseInput.value.trim();
1064    if(!text) { courseInput.focus(); return; }
1065    addNote(text);
1066    courseInput.value = '';
1067    window.toolkitState.write({ courseInput: '' });
1068    courseInput.focus();
1069  }
1070  courseInput.addEventListener('input', function(){
1071    window.toolkitState.write({ courseInput: courseInput.value });
1072  });
1073
1074  addBtn.addEventListener('click', handleAdd);
1075  courseInput.addEventListener('keydown', function(e){
1076    if(e.key === 'Enter') handleAdd();
1077  });
1078
1079  /* ---------- Instellingen: jaren tonen/verbergen ---------- */
1080  settingsBtn.addEventListener('click', function(e){
1081    e.stopPropagation();
1082    settingsMenu.classList.toggle('open');
1083  });
1084  settingsMenu.addEventListener('click', function(e){ e.stopPropagation(); });
1085  document.addEventListener('click', function(){ settingsMenu.classList.remove('open'); });
1086
1087  const yearBoxes = Array.prototype.slice.call(settingsMenu.querySelectorAll('input[type=checkbox]'));
1088
1089  function applyYear(cb){
1090    const year = cb.getAttribute('data-year');
1091    board.querySelectorAll('[data-year="'+year+'"]').forEach(function(c){
1092      c.style.display = cb.checked ? '' : 'none';
1093    });
1094  }
1095
1096  function saveYears(){
1097    const years = {};
1098    yearBoxes.forEach(function(cb){ years[cb.getAttribute('data-year')] = cb.checked; });
1099    window.toolkitState.write({ years: years });
1100  }
1101
1102  function restoreYears(){
1103    const years = window.toolkitState.read().years;
1104    if(!years) return;
1105    yearBoxes.forEach(function(cb){
1106      const year = cb.getAttribute('data-year');
1107      if(typeof years[year] === 'boolean') cb.checked = years[year];
1108      applyYear(cb);
1109    });
1110  }
1111
1112  yearBoxes.forEach(function(cb){
1113    cb.addEventListener('change', function(){
1114      applyYear(cb);
1115      saveYears();
1116      scheduleLayout();
1117    });
1118  });
1119
1120  /* ---------- Opslaan & laden via een bestand op de harde schijf ---------- */
1121  const saveBtn   = document.getElementById('saveBtn');
1122  const loadBtn   = document.getElementById('loadBtn');
1123  const fileInput = document.getElementById('fileInput');
1124  const toast     = document.getElementById('toast');
1125  let toastTimer;
1126
1127  function showToast(msg){
1128    toast.textContent = msg;
1129    toast.classList.add('show');
1130    clearTimeout(toastTimer);
1131    toastTimer = setTimeout(function(){ toast.classList.remove('show'); }, 1900);
1132  }
1133
1134  function collectNotes(){
1135    return Array.prototype.map.call(
1136      whiteboard.querySelectorAll('.note'),
1137      function(n){
1138        return {
1139          text:  n.dataset.text || '',
1140          left:  parseInt(n.style.left, 10) || 0,
1141          top:   parseInt(n.style.top, 10) || 0,
1142          state: parseInt(n.dataset.state, 10) || 0,
1143          year: n.dataset.year || '1',
1144          level: n.dataset.level || 'groen',
1145          xRatio: parseFloat(n.dataset.xRatio) || 0.5,
1146          yRatio: parseFloat(n.dataset.yRatio) || 0.5
1147        };
1148      }
1149    );
1150  }
1151
1152  // ----- Automatisch opslaan (lokaal in de browser) bij elke wijziging -----
1153  const AUTOSAVE_KEY = 'toetsscan_autosave';
1154  let suppressSave = false;
1155
1156  function autoSave(){
1157    if(suppressSave) return;
1158    try{ localStorage.setItem(AUTOSAVE_KEY, JSON.stringify(collectNotes())); }catch(e){}
1159  }
1160
1161  function autoRestore(){
1162    let raw = null;
1163    try{ raw = localStorage.getItem(AUTOSAVE_KEY); }catch(e){}
1164    if(!raw) return;
1165    let data;
1166    try{ data = JSON.parse(raw); }catch(e){ return; }
1167    if(!Array.isArray(data)) return;
1168    suppressSave = true;
1169    data.forEach(function(d){
1170      addNote(d.text, {
1171        left:d.left,
1172        top:d.top,
1173        year:d.year,
1174        level:d.level,
1175        xRatio:d.xRatio,
1176        yRatio:d.yRatio,
1177        state:(typeof d.state==='number' ? d.state : d.count)
1178      });
1179    });
1180    suppressSave = false;
1181    autoSave(); // migreert oude pixelposities direct naar vakvaste posities
1182  }
1183
1184  function saveBoard(){
1185    const data = collectNotes();
1186    const payload = { app:'toetsscan', version:3, positioning:'year-level-relative', notes:data };
1187    const blob = new Blob([JSON.stringify(payload, null, 2)], { type:'application/json' });
1188    const url  = URL.createObjectURL(blob);
1189    const a    = document.createElement('a');
1190    a.href = url;
1191    a.download = 'toetsscan.json';
1192    document.body.appendChild(a);
1193    a.click();
1194    document.body.removeChild(a);
1195    setTimeout(function(){ URL.revokeObjectURL(url); }, 1000);
1196    showToast(data.length + ' blokje(s) opgeslagen naar bestand.');
1197  }
1198
1199  function loadBoard(){
1200    fileInput.value = '';   // zodat hetzelfde bestand opnieuw gekozen kan worden
1201    fileInput.click();
1202  }
1203
1204  fileInput.addEventListener('change', function(){
1205    const file = fileInput.files && fileInput.files[0];
1206    if(!file) return;
1207    const reader = new FileReader();
1208    reader.onload = function(){
1209      let parsed;
1210      try{ parsed = JSON.parse(reader.result); }
1211      catch(e){ showToast('Laden mislukt: geen geldig bestand.'); return; }
1212      const data = Array.isArray(parsed) ? parsed : ((parsed && parsed.notes) || []);
1213      whiteboard.querySelectorAll('.note').forEach(function(n){ n.remove(); });
1214      cascade = 0;
1215      suppressSave = true;
1216      data.forEach(function(d){
1217        addNote(d.text, {
1218          left:d.left,
1219          top:d.top,
1220          year:d.year,
1221          level:d.level,
1222          xRatio:d.xRatio,
1223          yRatio:d.yRatio,
1224          state:(typeof d.state==='number' ? d.state : d.count)
1225        });
1226      });
1227      suppressSave = false;
1228      autoSave();
1229      showToast(data.length + ' blokje(s) geladen.');
1230    };
1231    reader.readAsText(file);
1232  });
1233
1234  saveBtn.addEventListener('click', saveBoard);
1235  loadBtn.addEventListener('click', loadBoard);
1236
1237  /* ---------- Info-modal ---------- */
1238  infoBtn.addEventListener('click', function(){ infoModal.classList.add('open'); });
1239  closeInfo.addEventListener('click', function(){ infoModal.classList.remove('open'); });
1240  infoModal.addEventListener('click', function(e){
1241    if(e.target === infoModal) infoModal.classList.remove('open');
1242  });
1243
1244  /* ---------- Inschattingsmatrix-modal (via de 'i' achter de balken) ---------- */
1245  const matrixModal = document.getElementById('matrixModal');
1246  const closeMatrix = document.getElementById('closeMatrix');
1247
1248  document.querySelectorAll('.info-i').forEach(function(btn){
1249    btn.addEventListener('click', function(e){
1250      e.stopPropagation();
1251      const lvl = btn.getAttribute('data-level');
1252      document.querySelectorAll('.matrix-col').forEach(function(c){
1253        c.classList.toggle('highlight', c.getAttribute('data-level') === lvl);
1254      });
1255      matrixModal.classList.add('open');
1256    });
1257  });
1258  closeMatrix.addEventListener('click', function(){ matrixModal.classList.remove('open'); });
1259  matrixModal.addEventListener('click', function(e){
1260    if(e.target === matrixModal) matrixModal.classList.remove('open');
1261  });
1262
1263  document.addEventListener('keydown', function(e){
1264    if(e.key === 'Escape'){
1265      infoModal.classList.remove('open');
1266      matrixModal.classList.remove('open');
1267    }
1268  });
1269
1270  /* ---------- Responsief herpositioneren ----------
1271     Elk blokje blijft gekoppeld aan hetzelfde jaar en dezelfde kleurzone.
1272     Alleen de pixelpositie wordt opnieuw berekend wanneer het bord verandert. */
1273  window.addEventListener('resize', scheduleLayout);
1274  window.addEventListener('toetsscan:layout', scheduleLayout);
1275  if(typeof ResizeObserver !== 'undefined'){
1276    const boardResizeObserver = new ResizeObserver(scheduleLayout);
1277    boardResizeObserver.observe(whiteboard);
1278    boardResizeObserver.observe(board);
1279  }
1280
1281  /* ---------- Automatisch herstellen van de laatst opgeslagen staat ---------- */
1282  restoreYears();
1283  const savedCourseInput = window.toolkitState.read().courseInput;
1284  if(typeof savedCourseInput === 'string') courseInput.value = savedCourseInput;
1285  autoRestore();
1286  scheduleLayout();
1287
1288})();
1289</script>
1289
1290    </section>
1291
1292    <section class="app-panel" id="panel-flowchart" role="tabpanel" aria-labelledby="tab-flowchart" hidden>
1293      <iframe class="embedded-page" title="Flowchart AI, curriculum en toetsing" srcdoc="&lt;!DOCTYPE html&gt;
1294&lt;html lang=&quot;nl&quot;&gt;
1295&lt;head&gt;
1296&lt;meta charset=&quot;UTF-8&quot;&gt;
1297&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
1298&lt;title&gt;Toolkit 'AI, curriculum en toetsing' – Flowchart AI-bewust toetsen&lt;/title&gt;
1299&lt;style&gt;
1300  :root{
1301    --brand:#E2004B;
1302    --brand-dark:#C50040;
1303    --ink:#1a1a1a;
1304    --line:#d0d0d0;
1305    --triangle:#7a7a7a;
1306    --box-border:#f3b9cd;
1307    --bg:#ffffff;
1308    --warn:#f6b500;
1309  }
1310  *{box-sizing:border-box;}
1311  html{ -webkit-text-size-adjust:100%; }
1312  body{
1313    margin:0;
1314    font-family:&quot;Segoe UI&quot;,&quot;Nunito&quot;,Verdana,Arial,sans-serif;
1315    color:var(--ink);
1316    background:#eef0f2;
1317    line-height:1.4;
1318  }
1319  .sheet{
1320    max-width:1180px;
1321    margin:24px auto;
1322    background:var(--bg);
1323    padding:28px 32px 40px;
1324    box-shadow:0 2px 14px rgba(0,0,0,.12);
1325    border-radius:6px;
1326  }
1327
1328  /* ---------- Header ---------- */
1329  .top{
1330    display:flex;
1331    justify-content:space-between;
1332    align-items:flex-start;
1333    gap:24px;
1334  }
1335  h1{
1336    font-size:24px;
1337    margin:0 0 14px;
1338    font-weight:800;
1339    color:var(--brand);
1340  }
1341  h1 .black{ color:var(--ink); }
1342  .logo{
1343    flex:0 0 auto;
1344    width:66px;height:66px;
1345  }
1346  .logo svg{ width:100%; height:100%; display:block; }
1347  .logo .lg-bg{ fill:var(--brand); }
1348  .intro{ font-size:14.5px; margin:0 0 16px; max-width:960px; }
1349  .intro strong{ font-weight:800; }
1350
1351  .warn{
1352    display:flex; gap:10px; align-items:flex-start;
1353    font-size:12px; color:#444;
1354    border-left:4px solid var(--warn);
1355    background:#fffbe9;
1356    padding:10px 14px;
1357    border-radius:4px;
1358    margin-bottom:22px;
1359    max-width:960px;
1360  }
1361  .warn .ico{ font-size:18px; line-height:1; }
1362
1363  /* ---------- Rows ---------- */
1364  .grid{ border:1px solid var(--line); border-radius:6px; overflow:hidden; }
1365  .row{
1366    display:flex;
1367    align-items:stretch;
1368    gap:16px;
1369    padding:18px 16px;
1370    border-bottom:1px solid var(--line);
1371  }
1372  .row:last-child{ border-bottom:none; }
1373
1374  /* number + triangle column */
1375  .stepcol{ flex:0 0 190px; display:flex; gap:8px; align-items:flex-start; }
1376  .stepno{
1377    flex:0 0 auto;
1378    width:34px;height:34px;border-radius:50%;
1379    border:1px solid #bbb; background:#f3f3f3;
1380    display:flex;align-items:center;justify-content:center;
1381    font-weight:700; font-size:15px;
1382  }
1383  .triangle{ flex:1 1 auto; }
1384  .triangle svg{ width:100%; height:auto; display:block; }
1385
1386  /* the flow lane */
1387  .flow{
1388    flex:1 1 auto;
1389    display:flex;
1390    flex-wrap:wrap;
1391    align-items:center;
1392    gap:10px;
1393  }
1394  .box{
1395    flex:1 1 160px;
1396    min-width:150px;
1397    border:1.5px solid var(--box-border);
1398    border-radius:14px;
1399    padding:12px 14px;
1400    font-size:12.5px;
1401    background:#fff;
1402    text-align:center;
1403    align-self:center;
1404  }
1405  .box.tight{ flex:1 1 150px; }
1406  .box strong{ font-weight:800; }
1407  .box .brandtext{ color:var(--brand); font-weight:800; }
1408  .box ol{ margin:6px 0 0; padding-left:18px; text-align:left; }
1409  .box ol li{ margin:2px 0; }
1410
1411  /* vertical stacks &amp; branches */
1412  .stack, .branch{ display:flex; flex-direction:column; gap:8px; flex:1 1 220px; min-width:180px; align-self:center; }
1413  /* inside a column, reset the row-oriented flex so children size to content */
1414  .stack &gt; .box, .stack &gt; a.btn{ flex:0 0 auto; }
1415  .branch-row{ display:flex; align-items:stretch; gap:8px; }
1416  .branch-row .box, .branch-row a.btn{ flex:1 1 auto; }
1417
1418  /* buttons / links */
1419  a.btn{
1420    display:flex;
1421    align-items:center;
1422    justify-content:center;
1423    gap:8px;
1424    flex:1 1 170px;
1425    min-width:150px;
1426    text-decoration:none;
1427    background:var(--brand);
1428    color:#fff;
1429    font-weight:700;
1430    font-size:12.5px;
1431    text-align:center;
1432    border-radius:14px;
1433    padding:13px 14px;
1434    transition:background .15s ease, transform .05s ease;
1435    align-self:center;
1436  }
1437  a.btn{
1438    cursor:pointer;
1439    position:relative;
1440    box-shadow:0 3px 8px rgba(226,0,75,.16);
1441    transition:background .15s ease,transform .15s ease,box-shadow .15s ease,outline-color .15s ease;
1442  }
1443  a.btn:hover{
1444    background:var(--brand-dark);
1445    transform:translateY(-4px) scale(1.018);
1446    box-shadow:0 11px 24px rgba(197,0,64,.28);
1447    outline:3px solid rgba(226,0,75,.18);
1448    outline-offset:3px;
1449  }
1450  a.btn:focus-visible{
1451    outline:4px solid rgba(226,0,75,.28);
1452    outline-offset:3px;
1453  }
1454  a.btn .chev{
1455    display:inline-block;
1456    transition:transform .15s ease;
1457  }
1458  a.btn:hover .chev{transform:translateX(5px);}
1459  a.btn::before,
1460  a.box.toolkit-route::before{
1461    content:'KLIK';
1462    position:absolute;
1463    top:7px;
1464    right:9px;
1465    padding:3px 6px;
1466    border-radius:8px;
1467    font-size:9px;
1468    font-weight:900;
1469    letter-spacing:.5px;
1470    line-height:1;
1471    opacity:0;
1472    transform:translateY(-5px);
1473    transition:opacity .15s ease,transform .15s ease;
1474    pointer-events:none;
1475  }
1476  a.btn::before{
1477    background:#fff;
1478    color:var(--brand);
1479  }
1480  a.box.toolkit-route::before{
1481    background:var(--brand);
1482    color:#fff;
1483  }
1484  a.btn:hover::before,
1485  a.box.toolkit-route:hover::before{
1486    opacity:1;
1487    transform:translateY(0);
1488  }
1489  a.box.toolkit-route{
1490    color:var(--ink);
1491    text-decoration:none;
1492    cursor:pointer;
1493    position:relative;
1494    box-shadow:0 2px 6px rgba(0,0,0,.05);
1495    transition:border-color .15s ease,box-shadow .15s ease,background .15s ease,transform .15s ease;
1496  }
1497  a.box.toolkit-route:hover{
1498    border-color:var(--brand);
1499    background:#fff8fb;
1500    transform:translateY(-4px) scale(1.018);
1501    box-shadow:0 11px 24px rgba(197,0,64,.2);
1502    outline:3px solid rgba(226,0,75,.16);
1503    outline-offset:3px;
1504  }
1505  a.box.toolkit-route:focus-visible{
1506    outline:4px solid rgba(226,0,75,.28);
1507    outline-offset:3px;
1508  }
1509  a.btn:active{ transform:translateY(1px); }
1510  a.btn .chev{ font-weight:900; }
1511
1512  /* arrows */
1513  .arr{ flex:0 0 auto; display:flex; align-items:center; }
1514  .arr.r{ }
1515  .arr.r .stem{ width:14px;height:9px;background:var(--brand); }
1516  .arr.r .head{
1517    width:0;height:0;
1518    border-top:11px solid transparent;
1519    border-bottom:11px solid transparent;
1520    border-left:16px solid var(--brand);
1521  }
1522  .arr.d{ flex-direction:column; align-self:center; margin:0 auto; }
1523  .arr.d .stem{ width:9px;height:12px;background:var(--brand); }
1524  .arr.d .head{
1525    width:0;height:0;
1526    border-left:11px solid transparent;
1527    border-right:11px solid transparent;
1528    border-top:16px solid var(--brand);
1529  }
1530
1531  /* ---------- Verbeterde driehoekdiagrammen ---------- */
1532  .sheet{position:relative;}
1533  .intro{
1534    max-width:none;
1535    padding-right:0;
1536    min-height:0;
1537    padding-top:0;
1538  }
1539  .stepcol{
1540    flex:0 0 220px;
1541    position:relative;
1542    display:flex;
1543    align-items:center;
1544    justify-content:center;
1545    padding:0 6px 0 40px;
1546    min-height:170px;
1547  }
1548  .stepno{
1549    position:absolute;
1550    left:0;
1551    top:0;
1552  }
1553  .triangle{
1554    flex:0 0 174px;
1555    width:174px;
1556    max-width:174px;
1557  }
1558  .triangle svg{
1559    width:174px;
1560    height:auto;
1561    overflow:visible;
1562  }
1563  .diagram-label text{
1564    fill:#333;
1565    font-family:&quot;Segoe UI&quot;,&quot;Nunito&quot;,Verdana,Arial,sans-serif;
1566    font-size:16px;
1567    font-weight:600;
1568    text-anchor:middle;
1569  }
1570  .diagram-label rect{
1571    fill:#fff;
1572    stroke:transparent;
1573    stroke-width:3;
1574  }
1575  .diagram-label.selected rect{stroke:var(--brand);}
1576  .diagram-label.selected text{
1577    fill:#222;
1578    font-weight:800;
1579  }
1580
1581  /* ---------- Responsive ---------- */
1582  @media (max-width:860px){
1583    .sheet{ padding:20px 16px 28px; }
1584    .intro{padding-right:0;}
1585    .row{ flex-direction:column; }
1586    .stepcol{ flex-basis:auto; align-self:center; }
1587    .triangle{ max-width:220px; }
1588    .flow{ flex-direction:column; align-items:stretch; }
1589    .box, a.btn{ flex-basis:auto; }
1590    .branch, .stack{ flex-basis:auto; }
1591    .arr.r{ transform:rotate(90deg); align-self:center; }
1592  }
1593  @media print{
1594    body{ background:#fff; }
1595    .sheet{ box-shadow:none; margin:0; max-width:100%; }
1596    a.btn{ -webkit-print-color-adjust:exact; print-color-adjust:exact; }
1597  }
1598&lt;/style&gt;
1599&lt;/head&gt;
1600&lt;body&gt;
1601&lt;div class=&quot;sheet&quot;&gt;
1602
1603  
1604
1605  &lt;p class=&quot;intro&quot;&gt;
1606    Het doel van deze flowchart is om je curriculum en toetsing AI-bewuster te maken. Deze flowchart start vanuit het perspectief van een &lt;strong&gt;individuele cursus&lt;/strong&gt;.
1607    Bij het gebruik van de flowchart zul je echter ook naar de positionering van de cursus binnen een leerlijn of volledig curriculum moeten kijken.
1608  &lt;/p&gt;
1609
1610  &lt;div class=&quot;warn&quot;&gt;
1611    &lt;span class=&quot;ico&quot;&gt;⚠️&lt;/span&gt;
1612    &lt;span&gt;&lt;strong&gt;Let op:&lt;/strong&gt; Informatie die je in een generatieve AI-chatbot plaatst kan door training van nieuwe modellen openbaar gemaakt worden. Voer daarom nooit beschermde of geheime informatie, zoals tentamenvragen, in. Bekijk ook kritisch de Generatieve AI Do’s en Don’ts van Hogeschool Rotterdam (zie toolkit).&lt;/span&gt;
1613  &lt;/div&gt;
1614
1615  &lt;div class=&quot;grid&quot;&gt;
1616
1617    &lt;!-- ================= ROW 1 : Leerdoelen ================= --&gt;
1618    &lt;div class=&quot;row&quot;&gt;
1619      &lt;div class=&quot;stepcol&quot;&gt;
1620        &lt;div class=&quot;stepno&quot;&gt;1&lt;/div&gt;
1621        &lt;div class=&quot;triangle&quot;&gt;
1622          
1623          &lt;svg viewBox=&quot;0 0 260 205&quot; role=&quot;img&quot; aria-label=&quot;Driehoek met Leerdoelen omcirkeld&quot;&gt;
1624            &lt;polygon points=&quot;130,50 42,158 218,158&quot; fill=&quot;none&quot; stroke=&quot;var(--triangle)&quot; stroke-width=&quot;2.5&quot;/&gt;
1625            &lt;g class=&quot;diagram-label selected&quot;&gt;
1626              &lt;rect x=&quot;75&quot; y=&quot;6&quot; width=&quot;110&quot; height=&quot;32&quot; rx=&quot;16&quot;/&gt;
1627              &lt;text x=&quot;130&quot; y=&quot;27&quot;&gt;Leerdoelen&lt;/text&gt;
1628            &lt;/g&gt;
1629            &lt;g class=&quot;diagram-label&quot;&gt;
1630              &lt;text x=&quot;47&quot; y=&quot;190&quot;&gt;Leeractiviteiten&lt;/text&gt;
1631            &lt;/g&gt;
1632            &lt;g class=&quot;diagram-label&quot;&gt;
1633              &lt;text x=&quot;215&quot; y=&quot;190&quot;&gt;Toetsing&lt;/text&gt;
1634            &lt;/g&gt;
1635          &lt;/svg&gt;
1636        &lt;/div&gt;
1637      &lt;/div&gt;
1638
1639      &lt;div class=&quot;flow&quot;&gt;
1640        &lt;div class=&quot;box&quot;&gt;
1641          Noteer de leerdoelen van de cursus. Noteer ook de leerdoelen van vergelijkbare cursussen die &lt;strong&gt;voor&lt;/strong&gt; of &lt;strong&gt;na&lt;/strong&gt; deze cursus komen.
1642          Analyseer welke onderdelen concentrisch zijn (herhalend en verdiepend terugkomen).
1643        &lt;/div&gt;
1644
1645        &lt;div class=&quot;arr r&quot;&gt;&lt;span class=&quot;stem&quot;&gt;&lt;/span&gt;&lt;span class=&quot;head&quot;&gt;&lt;/span&gt;&lt;/div&gt;
1646
1647        &lt;div class=&quot;box&quot;&gt;
1648          Analyseer de leerdoelen van je cursus. Moeten er vanwege generatieve AI
1649          &lt;ol type=&quot;A&quot;&gt;
1650            &lt;li&gt;leerdoelen verdwijnen?&lt;/li&gt;
1651            &lt;li&gt;leerdoelen worden aangepast?&lt;/li&gt;
1652            &lt;li&gt;leerdoelen worden toegevoegd?&lt;/li&gt;
1653          &lt;/ol&gt;
1654        &lt;/div&gt;
1655
1656        &lt;div class=&quot;arr r&quot;&gt;&lt;span class=&quot;stem&quot;&gt;&lt;/span&gt;&lt;span class=&quot;head&quot;&gt;&lt;/span&gt;&lt;/div&gt;
1657
1658        &lt;div class=&quot;stack&quot;&gt;
1659          &lt;div class=&quot;box&quot;&gt;
1660            &lt;strong&gt;Let op:&lt;/strong&gt; Als je leerdoelen verwijdert, aanpast of toevoegt, heeft dit gevolgen voor de toetsing en leeractiviteiten én voor eerdere of latere cursussen.
1661          &lt;/div&gt;
1662          &lt;div class=&quot;arr d&quot;&gt;&lt;span class=&quot;stem&quot;&gt;&lt;/span&gt;&lt;span class=&quot;head&quot;&gt;&lt;/span&gt;&lt;/div&gt;
1663          &lt;a class=&quot;btn&quot; href=&quot;#&quot; data-open-card-category=&quot;0&quot;&gt;
1664            Ga met betrokken collega’s in gesprek. Open de gesprekskaarten: &lt;span class=&quot;chev&quot;&gt;›&lt;/span&gt;
1665          &lt;/a&gt;
1666        &lt;/div&gt;
1667      &lt;/div&gt;
1668    &lt;/div&gt;
1669
1670    &lt;!-- ================= ROW 2 : Toetsing ================= --&gt;
1671    &lt;div class=&quot;row&quot;&gt;
1672      &lt;div class=&quot;stepcol&quot;&gt;
1673        &lt;div class=&quot;stepno&quot;&gt;2&lt;/div&gt;
1674        &lt;div class=&quot;triangle&quot;&gt;
1675          
1676          &lt;svg viewBox=&quot;0 0 260 205&quot; role=&quot;img&quot; aria-label=&quot;Driehoek met Toetsing omcirkeld&quot;&gt;
1677            &lt;polygon points=&quot;130,50 42,158 218,158&quot; fill=&quot;none&quot; stroke=&quot;var(--triangle)&quot; stroke-width=&quot;2.5&quot;/&gt;
1678            &lt;g class=&quot;diagram-label&quot;&gt;
1679              &lt;text x=&quot;130&quot; y=&quot;27&quot;&gt;Leerdoelen&lt;/text&gt;
1680            &lt;/g&gt;
1681            &lt;g class=&quot;diagram-label&quot;&gt;
1682              &lt;text x=&quot;47&quot; y=&quot;190&quot;&gt;Leeractiviteiten&lt;/text&gt;
1683            &lt;/g&gt;
1684            &lt;g class=&quot;diagram-label selected&quot;&gt;
1685              &lt;rect x=&quot;174&quot; y=&quot;165&quot; width=&quot;82&quot; height=&quot;32&quot; rx=&quot;16&quot;/&gt;
1686              &lt;text x=&quot;215&quot; y=&quot;187&quot;&gt;Toetsing&lt;/text&gt;
1687            &lt;/g&gt;
1688          &lt;/svg&gt;
1689        &lt;/div&gt;
1690      &lt;/div&gt;
1691
1692      &lt;div class=&quot;flow&quot;&gt;
1693        &lt;div class=&quot;box tight&quot;&gt;
1694          Stap in de schoenen van je student die de toetsing van je cursus moet doorlopen. Probeer de toetsing zoveel mogelijk door generatieve AI te laten doen.
1695          &lt;div style=&quot;margin-top:8px;&quot;&gt;⚠️ &lt;strong&gt;Wat valt je op?&lt;/strong&gt;&lt;/div&gt;
1696        &lt;/div&gt;
1697
1698        &lt;div class=&quot;arr r&quot;&gt;&lt;span class=&quot;stem&quot;&gt;&lt;/span&gt;&lt;span class=&quot;head&quot;&gt;&lt;/span&gt;&lt;/div&gt;
1699
1700        &lt;div class=&quot;branch&quot;&gt;
1701          &lt;div class=&quot;branch-row&quot;&gt;
1702            &lt;div class=&quot;box&quot;&gt;
1703              Er zijn &lt;span class=&quot;brandtext&quot;&gt;onbenutte kansen&lt;/span&gt; om generatieve AI in te zetten bij deze toetsing.
1704            &lt;/div&gt;
1705            &lt;div class=&quot;arr r&quot;&gt;&lt;span class=&quot;stem&quot;&gt;&lt;/span&gt;&lt;span class=&quot;head&quot;&gt;&lt;/span&gt;&lt;/div&gt;
1706            &lt;a class=&quot;btn&quot; href=&quot;#&quot; data-open-card-category=&quot;1&quot;&gt;
1707            Ga met betrokken collega’s in gesprek. Open de gesprekskaarten: &lt;span class=&quot;chev&quot;&gt;›&lt;/span&gt;
1708          &lt;/a&gt;
1709          &lt;/div&gt;
1710
1711          &lt;div class=&quot;branch-row&quot;&gt;
1712            &lt;div class=&quot;box&quot;&gt;
1713              Er zijn &lt;span class=&quot;brandtext&quot;&gt;risico’s&lt;/span&gt; dat je student door onverantwoord gebruik van generatieve AI de kennis, vaardigheden en attitudes niet zelf heeft verworven.
1714            &lt;/div&gt;
1715            &lt;div class=&quot;arr r&quot;&gt;&lt;span class=&quot;stem&quot;&gt;&lt;/span&gt;&lt;span class=&quot;head&quot;&gt;&lt;/span&gt;&lt;/div&gt;
1716            &lt;a class=&quot;btn&quot; href=&quot;#&quot; data-open-card-category=&quot;2&quot;&gt;
1717            Ga met betrokken collega’s in gesprek. Open de gesprekskaarten: &lt;span class=&quot;chev&quot;&gt;›&lt;/span&gt;
1718          &lt;/a&gt;
1719          &lt;/div&gt;
1720        &lt;/div&gt;
1721      &lt;/div&gt;
1722    &lt;/div&gt;
1723
1724    &lt;!-- ================= ROW 3 : Leeractiviteiten ================= --&gt;
1725    &lt;div class=&quot;row&quot;&gt;
1726      &lt;div class=&quot;stepcol&quot;&gt;
1727        &lt;div class=&quot;stepno&quot;&gt;3&lt;/div&gt;
1728        &lt;div class=&quot;triangle&quot;&gt;
1729          
1730          &lt;svg viewBox=&quot;0 0 260 205&quot; role=&quot;img&quot; aria-label=&quot;Driehoek met Leeractiviteiten omcirkeld&quot;&gt;
1731            &lt;polygon points=&quot;130,50 42,158 218,158&quot; fill=&quot;none&quot; stroke=&quot;var(--triangle)&quot; stroke-width=&quot;2.5&quot;/&gt;
1732            &lt;g class=&quot;diagram-label&quot;&gt;
1733              &lt;text x=&quot;130&quot; y=&quot;27&quot;&gt;Leerdoelen&lt;/text&gt;
1734            &lt;/g&gt;
1735            &lt;g class=&quot;diagram-label selected&quot;&gt;
1736              &lt;rect x=&quot;2&quot; y=&quot;165&quot; width=&quot;116&quot; height=&quot;32&quot; rx=&quot;16&quot;/&gt;
1737              &lt;text x=&quot;60&quot; y=&quot;187&quot;&gt;Leeractiviteiten&lt;/text&gt;
1738            &lt;/g&gt;
1739            &lt;g class=&quot;diagram-label&quot;&gt;
1740              &lt;text x=&quot;215&quot; y=&quot;190&quot;&gt;Toetsing&lt;/text&gt;
1741            &lt;/g&gt;
1742          &lt;/svg&gt;
1743        &lt;/div&gt;
1744      &lt;/div&gt;
1745
1746      &lt;div class=&quot;flow&quot;&gt;
1747        &lt;div class=&quot;box&quot;&gt;
1748          Bedenk welke leeractiviteiten goed passen bij de kennis, vaardigheden en attitudes die je studenten moeten verwerven.
1749          Kijk of ze goed aansluiten bij de leerdoelen en toetsing van de cursus.
1750        &lt;/div&gt;
1751
1752        &lt;div class=&quot;arr r&quot;&gt;&lt;span class=&quot;stem&quot;&gt;&lt;/span&gt;&lt;span class=&quot;head&quot;&gt;&lt;/span&gt;&lt;/div&gt;
1753
1754        &lt;div class=&quot;box&quot;&gt;
1755          Bedenk op welke manier je generatieve AI kunt gebruiken in leeractiviteiten &lt;strong&gt;voor&lt;/strong&gt;, &lt;strong&gt;tijdens&lt;/strong&gt; en &lt;strong&gt;na&lt;/strong&gt; het lesmoment.
1756          Bespreek na de leeractiviteiten de (on)mogelijkheden en (on)wenselijkheden van generatieve AI.
1757        &lt;/div&gt;
1758
1759        &lt;div class=&quot;arr r&quot;&gt;&lt;span class=&quot;stem&quot;&gt;&lt;/span&gt;&lt;span class=&quot;head&quot;&gt;&lt;/span&gt;&lt;/div&gt;
1760
1761        &lt;div class=&quot;stack&quot;&gt;
1762          &lt;a class=&quot;box toolkit-route&quot; href=&quot;#&quot; data-open-toolkit-page=&quot;https://maken.wikiwijs.nl/223515/Toolkit__AI__curriculum_en_toetsing_#!page-8674017&quot;&gt;
1763            Je kunt een generatieve AI-chatbot vragen om inspirerende werkvormen met AI, óf:
1764          &lt;/a&gt;
1765          &lt;div class=&quot;arr d&quot;&gt;&lt;span class=&quot;stem&quot;&gt;&lt;/span&gt;&lt;span class=&quot;head&quot;&gt;&lt;/span&gt;&lt;/div&gt;
1766          &lt;a class=&quot;btn&quot; href=&quot;#&quot; data-open-toolkit-page=&quot;https://maken.wikiwijs.nl/223515/Toolkit__AI__curriculum_en_toetsing_#!page-8674019&quot;&gt;
1767            Bekijk ons boekje ‘60 laagdrempelige werkvormen met AI’ &lt;span class=&quot;chev&quot;&gt;›&lt;/span&gt;
1768          &lt;/a&gt;
1769        &lt;/div&gt;
1770      &lt;/div&gt;
1771    &lt;/div&gt;
1772
1773  &lt;/div&gt;&lt;!-- /grid --&gt;
1774&lt;/div&gt;&lt;!-- /sheet --&gt;
1775&lt;script&gt;
1776  document.querySelectorAll('[data-open-card-category]').forEach(function(link){
1777    link.addEventListener('click', function(event){
1778      event.preventDefault();
1779      parent.postMessage({
1780        source:'toetsscan-flowchart',
1781        action:'open-card-category',
1782        category:Number(link.getAttribute('data-open-card-category'))
1783      }, '*');
1784    });
1785  });
1786  document.querySelectorAll('[data-open-toolkit-page]').forEach(function(link){
1787    link.addEventListener('click', function(event){
1788      event.preventDefault();
1789      parent.postMessage({
1790        source:'toetsscan-flowchart',
1791        action:'open-toolkit-page',
1792        url:link.getAttribute('data-open-toolkit-page')
1793      }, '*');
1794    });
1795  });
1796&lt;/script&gt;
1797&lt;/body&gt;
1798&lt;/html&gt;
1799"></iframe>
1800    </section>
1801
1802    <section class="app-panel" id="panel-cards" role="tabpanel" aria-labelledby="tab-cards" hidden>
1803      <div class="cards-shell">
1804        <header class="cards-header">
1805          <h2>Gesprekskaarten</h2>
1806          <div class="card-categories" role="tablist" aria-label="Categorieën gesprekskaarten">
1807            <button class="card-category" type="button" role="tab" aria-selected="true">Leerdoelen herzien</button>
1808            <button class="card-category" type="button" role="tab" aria-selected="false" tabindex="-1">Kansen van generatieve AI benutten</button>
1809            <button class="card-category" type="button" role="tab" aria-selected="false" tabindex="-1">Toetsing herzien</button>
1810          </div>
1811        </header>
1812
1813        <div class="card-warning" id="cardWarning" role="note" hidden>
1814          Houd goed in de gaten dat onderwijs en toetsing haalbaar, uitvoerbaar, betaalbaar, organiseerbaar en studeerbaar moeten blijven.
1815        </div>
1816
1817        <article class="conversation-card" aria-live="polite" aria-atomic="true">
1818          <div class="card-content">
1819            <div class="card-kicker">GESPREKSKAART</div>
1820            <h3 id="cardQuestion"></h3>
1821            <p id="cardSubtext" hidden></p>
1822          </div>
1823          <div class="card-counter" id="cardCounter"></div>
1824        </article>
1825
1826        <nav class="card-navigation" aria-label="Navigatie door gesprekskaarten">
1827          <button id="previousCard" type="button"><span aria-hidden="true">←</span> Vorige</button>
1828          <button id="nextCard" type="button">Volgende <span aria-hidden="true">→</span></button>
1829        </nav>
1830      </div>
1831    </section>
1832  </main>
1833
1834
1835<script>
1836(function(){
1837  "use strict";
1838  const scanHeader = document.querySelector('#panel-scan > header');
1839  const scanToolbar = document.querySelector('#panel-scan > .toolbar');
1840  if(scanHeader && scanToolbar){
1841    const scanActions = scanHeader.querySelector('.header-actions');
1842    if(scanActions) scanToolbar.appendChild(scanActions);
1843    scanHeader.remove();
1844  }
1845
1846  const tabs = Array.prototype.slice.call(document.querySelectorAll('.app-tab'));
1847  const panels = Array.prototype.slice.call(document.querySelectorAll('.app-panel'));
1848  const conversationCards = [{"title":"Leerdoelen herzien","cards":[{"question":"Welke aspecten van de beroepspraktijk die deze cursus raken worden niet beïnvloed door (generatieve) AI?"},{"question":"Welke aspecten van deze cursus moeten AI-vrij blijven (en kun je dat onderbouwen op meer dan alleen intuïtie)?"},{"question":"Welke aspecten van de beroepspraktijk die deze cursus raken veranderen volledig door de mogelijkheden die (generatieve) AI biedt?"},{"question":"Welke aspecten van de beroepspraktijk die deze cursus raken veranderen deels door de mogelijkheden die (generatieve) AI biedt?"},{"question":"Hoe verhouden de nieuwe mogelijkheden van (generatieve) AI zich tot de leerdoelen van deze cursus en verwante eerdere en latere cursussen in je curriculum?"},{"question":"In welke mate moeten je studenten (generatieve) AI leren gebruiken als een hulpmiddel binnen hun vakgebied? Wat moeten ze dan kunnen met (generatieve) AI?"},{"question":"Welke ethische vraagstukken rondom het gebruik van (generatieve) AI zijn relevant voor de beroepspraktijk van je studenten? Hoe kun je daarop inspelen in je onderwijs?"},{"question":"Wat betekent de inzet van (generatieve) AI voor de creatieve en innovatieve vaardigheden van je studenten? Hoe stimuleren we hun eigen denkwerk ondanks AI-mogelijkheden?"},{"question":"Je onderwijs, curriculum en toetsing afstemmen op de hu
1848idige beroepspraktijk maakt je onderwijs toekomstbestendig. Hoe kun je als opleiding ook (deels) toekomstbepalend zijn? De toekomstige beroepspraktijk kijkt immers ook naar nieuwe generaties voor innovatie."}]},{"title":"Kansen van generatieve AI benutten","cards":[{"question":"Waar zie je een toegevoegde waarde van generatieve AI in de beroepspraktijk van je student? Hoe kun je jouw studenten daar in deze cursus (inclusief toetsing) al kritisch kennis mee laten maken? Wat is daarvoor nodig?"},{"question":"Welke kennis, vaardigheden en attitudes hebben je studenten nodig om de output en inzet van generatieve AI in hun beroep op waarde te kunnen schatten? Wat is daarvan relevant voor deze cursus?"},{"question":"Op welke manier kan generatieve AI je student helpen om de kennis, vaardigheden en attitudes van deze cursus te verwerven?"},{"question":"Met welke werkvormen kun je studenten laten werken aan de kennis, vaardigheden en attitudes van deze cursus?","subtext":"Tip: Boekje ‘60 laagdrempelige werkvormen met AI’"},{"question":"Hoe kun jij als docent het goede voorbeeld geven met generatieve AI?"},{"question":"Hoe kun je jouw studenten helpen om de risico's van de inzet van generatieve AI bij het onderwerp van deze cursus te managen?"},{"question":"Weet jij hoe je collega's studenten helpen om de kansen van generatieve AI te benutten?"}]},{"title":"Toetsing herzien","cards":[{"question":"Kunnen de kennis, vaardigheden en attitudes van je cursus via een ‘Performance assessment’ worden getoetst?","subtext":"Een performance assessment is een manier van toetsen waarin je student de kennis, vaardigheden en attitudes in een echte of gesimuleerde (beroeps)situatie aantoont."},{"question":"Is er een mogelijkheid om de leerdoelen te toetsen met een toets onder toezicht op locatie?","subtext":"Via digitale toetsplatformen ANS en Schoolyear is het mogelijk om uitgebreide casuïstiek aan te bieden waarin zowel internet als (generatieve) AI (deels) worden aangezet of uitgezet. Je kunt dan ook meerdere (PDF) bestanden aanleveren waar studenten veilig digitaal mee aan de slag moeten. Enkel toegang tot PubMed of Google Scholar is ook een optie."},{"question":"Zijn er mogelijkheden om de beoordeling meer te richten op het proces dan nu gebeurt?"},{"question":"Op welke formatieve manier kan er in deze toetsing verder gekeken worden naar het proces in plaats van naar het eindproduct?"},{"question":"Is het mogelijk en/of wenselijk om een criteriumgericht interview of een mondelinge component toe te voegen aan de toetsing?"},{"question":"Is het een mogelijkheid dat de beoordeling van deze toets (deels) door een extern iemand (werkplekbegeleider / stagebegeleider) wordt gedaan? Kan een werkplekbegeleider of stagebegeleider verifiëren dat bepaalde acties, beweringen en/of bewijsvoering waar zijn?","subtext":"Als een werkplekbegeleider een deel van de beoordeling uitvoert en daarmee een summatieve rol heeft, moet deze worden aangewezen als externe examinator. Wanneer de werkplekbegeleider uitsluitend een verificatierol heeft, wordt deze formatief ingezet en is er geen sprake van een beoordelaarsrol in de zin van examinator."},{"question":"Hoe kun je studenten verplichten om expliciete evaluaties te maken van gebruikte bronnen, waardoor kritische reflectie op AI-gegenereerde inhoud noodzakelijk wordt?"},{"question":"Op welke manier zou je gebruik kunnen maken van video-opnames in de toetsing van deze opdracht?"},{"question":"Hoe is deze toets gepositioneerd in een eventuele leerlijn of het gehele toetsprogramma?","subtext":"Is het mogelijk om (delen van) de inhoud van deze toets naar een toets die later in het curriculum zit te verplaatsen? De overgebleven onderdelen van deze toets kunnen dan mogelijk op een andere manier getoetst worden."},{"question":"Hoe maak je duidelijk / ga je duidelijk maken hoe studenten generatieve AI mogen gebruiken bij deze cursus?","subtext":"Weet jij wat je collega’s toestaan of verbieden rondom AI? Weten je studenten dat ook?"}]}];
1849  const categoryButtons = Array.prototype.slice.call(document.querySelectorAll('.card-category'));
1850  const cardQuestion = document.getElementById('cardQuestion');
1851  const cardSubtext = document.getElementById('cardSubtext');
1852  const cardCounter = document.getElementById('cardCounter');
1853  const cardWarning = document.getElementById('cardWarning');
1854  const previousCard = document.getElementById('previousCard');
1855  const nextCard = document.getElementById('nextCard');
1856  const toolkitFrame = document.querySelector('#panel-toolkit iframe');
1857  const flowchartFrame = document.querySelector('#panel-flowchart iframe');
1858  const savedUI = window.toolkitState.read();
1859  let activeCategory = 0;
1860  let activeCard = 0;
1861
1862  if(Number.isInteger(savedUI.cardCategory) && savedUI.cardCategory >= 0 && savedUI.cardCategory < conversationCards.length){
1863    activeCategory = savedUI.cardCategory;
1864  }
1865  if(Number.isInteger(savedUI.cardIndex) && savedUI.cardIndex >= 0 && savedUI.cardIndex < conversationCards[activeCategory].cards.length){
1866    activeCard = savedUI.cardIndex;
1867  }
1868
1869  function renderConversationCard(){
1870    const category = conversationCards[activeCategory];
1871    const card = category.cards[activeCard];
1872    categoryButtons.forEach(function(button, index){
1873      const selected = index === activeCategory;
1874      button.setAttribute('aria-selected', selected ? 'true' : 'false');
1875      button.tabIndex = selected ? 0 : -1;
1876    });
1877    cardQuestion.textContent = card.question;
1878    if(card.subtext){
1879      cardSubtext.textContent = card.subtext;
1880      cardSubtext.hidden = false;
1881    }else{
1882      cardSubtext.textContent = '';
1883      cardSubtext.hidden = true;
1884    }
1885    cardCounter.textContent = (activeCard + 1) + ' van ' + category.cards.length;
1886    cardWarning.hidden = activeCategory !== 2;
1887    window.toolkitState.write({ cardCategory: activeCategory, cardIndex: activeCard });
1888  }
1889
1890  categoryButtons.forEach(function(button, index){
1891    button.addEventListener('click', function(){
1892      activeCategory = index;
1893      activeCard = 0;
1894      renderConversationCard();
1895    });
1896    button.addEventListener('keydown', function(event){
1897      if(event.key !== 'ArrowLeft' && event.key !== 'ArrowRight' && event.key !== 'Home' && event.key !== 'End') return;
1898      event.preventDefault();
1899      let nextCategory = index;
1900      if(event.key === 'ArrowLeft') nextCategory = (index - 1 + categoryButtons.length) % categoryButtons.length;
1901      if(event.key === 'ArrowRight') nextCategory = (index + 1) % categoryButtons.length;
1902      if(event.key === 'Home') nextCategory = 0;
1903      if(event.key === 'End') nextCategory = categoryButtons.length - 1;
1904      activeCategory = nextCategory;
1905      activeCard = 0;
1906      renderConversationCard();
1907      categoryButtons[nextCategory].focus();
1908    });
1909  });
1910
1911  previousCard.addEventListener('click', function(){
1912    const total = conversationCards[activeCategory].cards.length;
1913    activeCard = (activeCard - 1 + total) % total;
1914    renderConversationCard();
1915  });
1916
1917  nextCard.addEventListener('click', function(){
1918    const total = conversationCards[activeCategory].cards.length;
1919    activeCard = (activeCard + 1) % total;
1920    renderConversationCard();
1921  });
1922
1923  function showPanel(panelId, focusTab){
1924    tabs.forEach(function(tab){
1925      const active = tab.getAttribute('aria-controls') === panelId;
1926      tab.setAttribute('aria-selected', active ? 'true' : 'false');
1927      tab.tabIndex = active ? 0 : -1;
1928      if(active && focusTab) tab.focus();
1929    });
1930    panels.forEach(function(panel){
1931      const active = panel.id === panelId;
1932      panel.classList.toggle('active', active);
1933      panel.hidden = !active;
1934    });
1935    if(panelId === 'panel-scan'){
1936      window.dispatchEvent(new CustomEvent('toetsscan:layout'));
1937    }
1938    if(panelId === 'panel-cards') renderConversationCard();
1939    window.toolkitState.write({ panel: panelId });
1940  }
1941
1942  tabs.forEach(function(tab, index){
1943    tab.addEventListener('click', function(){
1944      showPanel(tab.getAttribute('aria-controls'), false);
1945    });
1946    tab.addEventListener('keydown', function(event){
1947      if(event.key !== 'ArrowLeft' && event.key !== 'ArrowRight' && event.key !== 'Home' && event.key !== 'End') return;
1948      event.preventDefault();
1949      let next = index;
1950      if(event.key === 'ArrowLeft') next = (index - 1 + tabs.length) % tabs.length;
1951      if(event.key === 'ArrowRight') next = (index + 1) % tabs.length;
1952      if(event.key === 'Home') next = 0;
1953      if(event.key === 'End') next = tabs.length - 1;
1954      showPanel(tabs[next].getAttribute('aria-controls'), true);
1955    });
1956  });
1957
1958  window.addEventListener('message', function(event){
1959    if(!flowchartFrame || event.source !== flowchartFrame.contentWindow) return;
1960    const message = event.data;
1961    if(!message || message.source !== 'toetsscan-flowchart') return;
1962
1963    if(message.action === 'open-card-category'){
1964      const category = Number(message.category);
1965      if(!Number.isInteger(category) || category < 0 || category >= conversationCards.length) return;
1966      showPanel('panel-cards', false);
1967      activeCategory = category;
1968      activeCard = 0;
1969      renderConversationCard();
1970    }
1971
1972    if(message.action === 'open-toolkit-page'){
1973      const allowedPrefix = 'https://maken.wikiwijs.nl/223515/Toolkit__AI__curriculum_en_toetsing_';
1974      if(typeof message.url !== 'string' || message.url.indexOf(allowedPrefix) !== 0) return;
1975      toolkitFrame.src = message.url;
1976      window.toolkitState.write({ toolkitUrl: message.url });
1977      showPanel('panel-toolkit', false);
1978    }
1979  });
1980
1981  const allowedToolkitPrefix = 'https://maken.wikiwijs.nl/223515/Toolkit__AI__curriculum_en_toetsing';
1982  if(toolkitFrame && typeof savedUI.toolkitUrl === 'string' && savedUI.toolkitUrl.indexOf(allowedToolkitPrefix) === 0){
1983    toolkitFrame.src = savedUI.toolkitUrl;
1984  }
1985
1986  renderConversationCard();
1987
1988  const savedPanel = savedUI.panel;
1989  const knownPanel = panels.some(function(panel){ return panel.id === savedPanel; });
1990  showPanel(knownPanel ? savedPanel : 'panel-scan', false);
1991})();
1992</script>
1992
1993</body>
1994</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.