Wiki source code of Data Protection & Ethics

Version 5.13 by Veronika Kocher on Thursday, 03 Sep 2026 14:58

Show last authors
1 Assess personal data, confidentiality, consent, sensitive materials and ethical considerations early in the project.
2
3 == Overview ==
4
5 Add a concise explanation of this topic and why it matters for Art & Research projects.
6
7 == What you need to know ==
8
9 * Key concepts
10 * Relevant requirements
11 * Important distinctions
12
13 == What you need to do ==
14
15 1. Identify what applies to your project.
16 2. Document the relevant decisions.
17 3. Use appropriate institutional services and support where needed.
18
19 == Key questions ==
20
21 * What needs to be decided?
22 * Who is responsible?
23 * What needs to be documented?
24 * Are there legal, ethical or technical constraints?
25 * What needs to happen before the next project phase?
26
27 == Services & Tools ==
28
29 Add links to relevant institutional services, infrastructure and tools.
30
31 == Info Sheets & Checklists ==
32
33 Add links to related Info Sheets, checklists and templates.
34
35 == Tutorials ==
36
37
38 {{html}}<span data-arsn-coming-soon="true" style="display:inline-block;margin:6px 0 8px 0;padding:4px 9px;border-radius:14px;background:#fff4ee;border:1px solid #efd9cc;color:#8a4d36;font-size:11px;font-weight:700;letter-spacing:.065em;line-height:1.2;">COMING SOON</span>{{/html}}
39 Add links to step-by-step tutorials for this topic.
40
41 == Related Topics ==
42
43 Add links to related pages in Enable, Work & Manage, and Publish & Share.
44
45 == Who is responsible? ==
46
47
48 {{info title="Service routing"}}
49 **Primary specialist service(s):** Data Protection Officer for personal-data questions; project/host unit and the applicable ethics or funder route for ethical review.
50
51 **Role of Support Kunst und Forschung (SKF):** Coordinates project and funder requirements and helps route specialist review; it is not the data-protection authority.
52 {{/info}}
53
54 If you are unsure which route applies, start with the service named above. For funded or project-based research where several units are involved, SKF can coordinate the project route.
55
56 {{html}}
57 <!-- ARSN_SEARCH_TERMS_START -->
58 <details class="arsn-search-terms" style="margin-top:28px;padding-top:10px;border-top:1px solid #eee;">
59 <summary style="cursor:pointer;color:#666;font-size:13px;">Search terms &amp; related topics</summary>
60 <div style="margin-top:9px;color:#555;font-size:13px;">
61 <p style="margin:0 0 8px 0;">
62 This topic can also be found through related terms, synonyms and common search queries.
63 Select a term to search the Art &amp; Research Services Navigator.
64 </p>
65 <p style="margin:0;"><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=art%20and%20research#arsn-search-input" class="arsn-search-term" data-search-term="art and research" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">art and research</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=enable#arsn-search-input" class="arsn-search-term" data-search-term="enable" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">enable</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=data%20protection#arsn-search-input" class="arsn-search-term" data-search-term="data protection" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">data protection</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=personal%20data#arsn-search-input" class="arsn-search-term" data-search-term="personal data" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">personal data</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=gdpr#arsn-search-input" class="arsn-search-term" data-search-term="gdpr" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">gdpr</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=ethics#arsn-search-input" class="arsn-search-term" data-search-term="ethics" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">ethics</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=consent#arsn-search-input" class="arsn-search-term" data-search-term="consent" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">consent</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=sensitive%20data#arsn-search-input" class="arsn-search-term" data-search-term="sensitive data" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">sensitive data</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=confidentiality#arsn-search-input" class="arsn-search-term" data-search-term="confidentiality" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">confidentiality</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=data%20privacy#arsn-search-input" class="arsn-search-term" data-search-term="data privacy" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">data privacy</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=dsgvo#arsn-search-input" class="arsn-search-term" data-search-term="dsgvo" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">dsgvo</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=anonymisation#arsn-search-input" class="arsn-search-term" data-search-term="anonymisation" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">anonymisation</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=anonymization#arsn-search-input" class="arsn-search-term" data-search-term="anonymization" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">anonymization</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=pseudonymisation#arsn-search-input" class="arsn-search-term" data-search-term="pseudonymisation" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">pseudonymisation</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=pseudonymization#arsn-search-input" class="arsn-search-term" data-search-term="pseudonymization" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">pseudonymization</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=datenschutz#arsn-search-input" class="arsn-search-term" data-search-term="datenschutz" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">datenschutz</a><a href="https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/?q=einwilligung#arsn-search-input" class="arsn-search-term" data-search-term="einwilligung" style="display:inline-block;margin:3px 5px 3px 0;padding:3px 8px;border:1px solid #d7d7d7;border-radius:14px;background:#fff;color:#333;text-decoration:none;font-size:12px;">einwilligung</a></p>
66 </div>
67 </details>
68 <!-- ARSN_SEARCH_TERMS_END -->
69 {{/html}}
70
71 {{html clean="false"}}
72 <!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START -->
73
74 <style data-sn-service-navigator-master="1">
75 /* =========================================================
76 MASTER TYPOGRAPHY
77 ========================================================= */
78 #xwikicontent h1,
79 #xwikicontent h2,
80 #xwikicontent h3,
81 #xwikicontent h4,
82 #xwikicontent h5,
83 #xwikicontent h6,
84 #xwikicontent .box-title,
85 #xwikicontent [role="heading"],
86 #xwikicontent h1 a,
87 #xwikicontent h2 a,
88 #xwikicontent h3 a,
89 #xwikicontent h4 a,
90 #xwikicontent h5 a,
91 #xwikicontent h6 a,
92 #xwikicontent .box-title a,
93 #xwikicontent [role="heading"] a{
94 text-align:left!important;
95 text-justify:auto!important;
96 word-spacing:normal!important;
97 }
98
99 /* =========================================================
100 COMING SOON / IN VORBEREITUNG
101 ========================================================= */
102 .sn-coming-soon-badge{
103 display:inline-block;
104 vertical-align:middle;
105 margin-left:10px;
106 padding:4px 8px;
107 border-radius:14px;
108 border:1px solid #efd9cc;
109 background:#fff4ee;
110 color:#8a4d36;
111 font-size:11px;
112 font-weight:700;
113 letter-spacing:.055em;
114 line-height:1.2;
115 white-space:nowrap;
116 }
117
118 /* =========================================================
119 NATIVE / DETAIL CALLOUT GEOMETRY
120 Preserve existing backgrounds.
121 ========================================================= */
122 #xwikicontent .arsn-info,
123 #xwikicontent .dmp-info,
124 #xwikicontent .ido-info,
125 #xwikicontent .pp-info,
126 #xwikicontent .infomessage{
127 box-sizing:border-box!important;
128 border-left:4px solid #21b6d7!important;
129 border-radius:8px;
130 text-align:left!important;
131 word-spacing:normal!important;
132 }
133
134 #xwikicontent .arsn-warn,
135 #xwikicontent .dmp-warn,
136 #xwikicontent .ido-warn,
137 #xwikicontent .pp-warn,
138 #xwikicontent .warn,
139 #xwikicontent .warning,
140 #xwikicontent .warningmessage,
141 #xwikicontent .errormessage{
142 box-sizing:border-box!important;
143 border-left:4px solid #e94b13!important;
144 border-radius:8px;
145 text-align:left!important;
146 word-spacing:normal!important;
147 }
148
149 [data-sn-master-equal-height],
150 [data-sn-master-first-row]{
151 box-sizing:border-box;
152 }
153
154 /* =========================================================
155 FULL-WIDTH THREE-LINE NUMBER / TITLE / SUBTITLE BLOCKS
156 ========================================================= */
157 #xwikicontent .arsn-area-label[data-sn-three-line="1"]{
158 display:grid!important;
159 grid-template-columns:minmax(0,1fr)!important;
160 grid-auto-rows:auto!important;
161 width:100%!important;
162 max-width:none!important;
163 box-sizing:border-box!important;
164 justify-items:start!important;
165 align-items:start!important;
166 gap:2px!important;
167 text-align:left!important;
168 text-align-last:left!important;
169 text-justify:auto!important;
170 word-spacing:normal!important;
171 white-space:normal!important;
172 }
173 #xwikicontent .arsn-area-label[data-sn-three-line="1"] > .arsn-area-number,
174 #xwikicontent .arsn-area-label[data-sn-three-line="1"] > .sn-area-label-title,
175 #xwikicontent .arsn-area-label[data-sn-three-line="1"] > .arsn-area-action{
176 display:block!important;
177 width:100%!important;
178 margin:0!important;
179 text-align:left!important;
180 text-align-last:left!important;
181 text-justify:auto!important;
182 word-spacing:normal!important;
183 white-space:normal!important;
184 }
185 </style>
186
187 <script data-sn-service-navigator-master="1">
188 (function(){
189 "use strict";
190
191 var PAGE_KIND="detail";
192 var PLACEHOLDER=true;
193 var PLACEHOLDER_LABEL="COMING SOON";
194
195 var MOBILE_MAX=767;
196 var ROW_TOLERANCE=6;
197 var RESIZE_DEBOUNCE=220;
198
199 var root=
200 document.getElementById("xwikicontent")||
201 document.querySelector(".xwiki-rendering-content")||
202 document.querySelector("main")||
203 document.body;
204
205 if(!root)return;
206
207 var managedHeight=new Set();
208 var managedMargin=new Set();
209 var originalHeight=new WeakMap();
210 var originalMargin=new WeakMap();
211
212 var resizeTimer=0;
213 var running=false;
214
215 var THEMES=[
216 {
217 name:"BLUE",
218 accent:"#21b6d7",
219 bg:"#eaf7fb",
220 text:"#315d68",
221 labels:[
222 "HIER STARTEN",
223 "ENTSCHEIDEN",
224 "ÜBERPRÜFEN & ANPASSEN",
225 "START HERE",
226 "DECIDE",
227 "REVIEW & ADAPT"
228 ]
229 },
230 {
231 name:"RED",
232 accent:"#e94b13",
233 bg:"#fff1ec",
234 text:"#8a4d36",
235 labels:[
236 "PLANEN & ORGANISIEREN",
237 "ORGANISIEREN & DOKUMENTIEREN",
238 "PUBLIZIEREN & PRÄSENTIEREN",
239 "PLAN & ORGANISE",
240 "PLAN & ORGANIZE",
241 "ORGANISE & DOCUMENT",
242 "ORGANIZE & DOCUMENT",
243 "PUBLISH & PRESENT"
244 ]
245 },
246 {
247 name:"YELLOW",
248 accent:"#f0aa00",
249 bg:"#fff8e7",
250 text:"#785b17",
251 labels:[
252 "SCHÜTZEN & KLÄREN",
253 "STANDARDISIEREN & IDENTIFIZIEREN",
254 "ÖFFNEN, NACHNUTZEN & AUFFINDBAR MACHEN",
255 "PROTECT & CLARIFY",
256 "STANDARDISE & IDENTIFY",
257 "STANDARDIZE & IDENTIFY",
258 "OPEN, REUSE & MAKE FINDABLE"
259 ]
260 },
261 {
262 name:"GREEN",
263 accent:"#38b76a",
264 bg:"#edf9f1",
265 text:"#3f7451",
266 labels:[
267 "INFRASTRUKTUR EINRICHTEN",
268 "INFRASTRUKTUR & ZUSAMMENARBEIT EINRICHTEN",
269 "SPEICHERN & ZUGRIFF STEUERN",
270 "REPOSITORIUM, ERHALTEN & ÜBERGEBEN",
271 "SET UP INFRASTRUCTURE",
272 "SET UP INFRASTRUCTURE & COLLABORATION",
273 "STORE & CONTROL ACCESS",
274 "REPOSITORY, PRESERVE & HAND OVER"
275 ]
276 }
277 ];
278
279 function num(value){
280 var n=parseFloat(value);
281 return Number.isFinite(n)?n:0;
282 }
283
284 function norm(value){
285 return String(value||"")
286 .replace(/\s+/g," ")
287 .trim()
288 .toUpperCase();
289 }
290
291 function visible(el){
292 if(!el||el.nodeType!==1)return false;
293
294 var style=getComputedStyle(el);
295 var rect=el.getBoundingClientRect();
296
297 return (
298 style.display!=="none"&&
299 style.visibility!=="hidden"&&
300 rect.width>20&&
301 rect.height>4
302 );
303 }
304
305 function saveStyle(el,map,property){
306 if(map.has(el))return;
307
308 map.set(el,{
309 value:el.style.getPropertyValue(property),
310 priority:el.style.getPropertyPriority(property)
311 });
312 }
313
314 function restoreStyle(el,map,property){
315 var original=map.get(el);
316
317 if(original&&original.value){
318 el.style.setProperty(
319 property,
320 original.value,
321 original.priority||""
322 );
323 }else{
324 el.style.removeProperty(property);
325 }
326 }
327
328 function resetRuntime(){
329 managedHeight.forEach(function(el){
330 restoreStyle(
331 el,
332 originalHeight,
333 "min-height"
334 );
335 el.removeAttribute(
336 "data-sn-master-equal-height"
337 );
338 });
339
340 managedMargin.forEach(function(el){
341 restoreStyle(
342 el,
343 originalMargin,
344 "margin-top"
345 );
346 el.removeAttribute(
347 "data-sn-master-first-row"
348 );
349 });
350
351 managedHeight.clear();
352 managedMargin.clear();
353 }
354
355 function themeFor(text){
356 var value=norm(text);
357
358 for(var i=0;i<THEMES.length;i++){
359 for(var j=0;j<THEMES[i].labels.length;j++){
360 var label=THEMES[i].labels[j];
361
362 if(
363 value===label||
364 value.indexOf(label+" ")===0||
365 value.indexOf(label+" -")===0||
366 value.indexOf(label+" ·")===0
367 ){
368 return THEMES[i];
369 }
370 }
371 }
372
373 return null;
374 }
375
376 /* =======================================================
377 BORDERLESS FILLED RED/ORANGE CTA BUTTONS
378 ======================================================= */
379
380 function colourDistance(a,b){
381 return Math.sqrt(
382 Math.pow(a[0]-b[0],2)+
383 Math.pow(a[1]-b[1],2)+
384 Math.pow(a[2]-b[2],2)
385 );
386 }
387
388 function makeFilledRedOrangeCTAsBorderless(){
389 var RED_ORANGE=[233,75,19];
390
391 Array.from(
392 root.querySelectorAll(
393 'a,button,[role="button"],input[type="submit"],input[type="button"]'
394 )
395 ).forEach(function(el){
396 if(!visible(el))return;
397
398 var style=getComputedStyle(el);
399 var rgb=parseRGB(style.backgroundColor);
400
401 if(!rgb)return;
402
403 if(
404 colourDistance(
405 rgb,
406 RED_ORANGE
407 )>55
408 ){
409 return;
410 }
411
412 var rect=el.getBoundingClientRect();
413
414 if(
415 rect.width<80||
416 rect.height<24
417 ){
418 return;
419 }
420
421 el.style.setProperty(
422 "border",
423 "none",
424 "important"
425 );
426
427 el.style.setProperty(
428 "border-left",
429 "none",
430 "important"
431 );
432
433 el.style.setProperty(
434 "border-top",
435 "none",
436 "important"
437 );
438
439 el.style.setProperty(
440 "border-right",
441 "none",
442 "important"
443 );
444
445 el.style.setProperty(
446 "border-bottom",
447 "none",
448 "important"
449 );
450
451 el.style.setProperty(
452 "box-shadow",
453 "none",
454 "important"
455 );
456 });
457 }
458
459 /* =======================================================
460 FULL-WIDTH THREE-LINE AREA LABELS
461 ======================================================= */
462
463 function compactText(value){
464 return String(value||"")
465 .replace(/\s+/g," ")
466 .trim();
467 }
468
469 function makeThreeLineAreaLabels(){
470 Array.from(
471 root.querySelectorAll(
472 ".arsn-area-label"
473 )
474 ).forEach(function(label){
475 if(
476 label.getAttribute(
477 "data-sn-three-line"
478 )==="1"
479 ){
480 return;
481 }
482
483 var number=
484 label.querySelector(
485 ":scope > .arsn-area-number"
486 );
487
488 var action=
489 label.querySelector(
490 ":scope > .arsn-area-action"
491 );
492
493 if(
494 !number||
495 !action
496 ){
497 return;
498 }
499
500 var clone=
501 label.cloneNode(true);
502
503 var cloneNumber=
504 clone.querySelector(
505 ":scope > .arsn-area-number"
506 );
507
508 var cloneAction=
509 clone.querySelector(
510 ":scope > .arsn-area-action"
511 );
512
513 if(cloneNumber){
514 cloneNumber.remove();
515 }
516
517 if(cloneAction){
518 cloneAction.remove();
519 }
520
521 var titleText=
522 compactText(
523 clone.textContent
524 );
525
526 if(!titleText){
527 return;
528 }
529
530 var numberNode=
531 number.cloneNode(true);
532
533 var actionNode=
534 action.cloneNode(true);
535
536 var titleNode=
537 document.createElement(
538 "span"
539 );
540
541 titleNode.className=
542 "sn-area-label-title";
543
544 titleNode.textContent=
545 titleText;
546
547 while(label.firstChild){
548 label.removeChild(
549 label.firstChild
550 );
551 }
552
553 label.appendChild(
554 numberNode
555 );
556
557 label.appendChild(
558 titleNode
559 );
560
561 label.appendChild(
562 actionNode
563 );
564
565 label.setAttribute(
566 "data-sn-three-line",
567 "1"
568 );
569
570 var head=
571 label.closest(
572 ".arsn-area-head"
573 );
574
575 if(head){
576 head.style.setProperty(
577 "width",
578 "100%",
579 "important"
580 );
581
582 head.style.setProperty(
583 "max-width",
584 "100%",
585 "important"
586 );
587
588 head.style.setProperty(
589 "box-sizing",
590 "border-box",
591 "important"
592 );
593 }
594 });
595 }
596
597 /* =======================================================
598 PLACEHOLDER BADGE
599 ======================================================= */
600
601 function applyPlaceholderBadge(){
602 if(!PLACEHOLDER)return;
603
604 if(
605 document.querySelector(
606 ".sn-coming-soon-badge"
607 )
608 ){
609 return;
610 }
611
612 var title=
613 document.querySelector(
614 "#document-title"
615 )||
616 document.querySelector(
617 "h1"
618 );
619
620 if(!title)return;
621
622 var badge=
623 document.createElement(
624 "span"
625 );
626
627 badge.className=
628 "sn-coming-soon-badge";
629
630 badge.textContent=
631 PLACEHOLDER_LABEL;
632
633 badge.setAttribute(
634 "aria-label",
635 PLACEHOLDER_LABEL
636 );
637
638 title.appendChild(
639 badge
640 );
641 }
642
643 /* =======================================================
644 DETAIL PAGE OWN-ACCENT PROPAGATION
645 ======================================================= */
646
647 function parseRGB(value){
648 var match=String(value||"").match(
649 /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i
650 );
651
652 if(!match)return null;
653
654 return [
655 Number(match[1]),
656 Number(match[2]),
657 Number(match[3])
658 ];
659 }
660
661 function distance(a,b){
662 return Math.sqrt(
663 Math.pow(a[0]-b[0],2)+
664 Math.pow(a[1]-b[1],2)+
665 Math.pow(a[2]-b[2],2)
666 );
667 }
668
669 function paletteMatch(cssColor){
670 var rgb=parseRGB(cssColor);
671
672 if(!rgb)return null;
673
674 var palette=[
675 {hex:"#21b6d7",rgb:[33,182,215]},
676 {hex:"#e94b13",rgb:[233,75,19]},
677 {hex:"#f0aa00",rgb:[240,170,0]},
678 {hex:"#38b76a",rgb:[56,183,106]}
679 ];
680
681 var best=null;
682 var bestDistance=Infinity;
683
684 palette.forEach(function(item){
685 var d=distance(rgb,item.rgb);
686
687 if(d<bestDistance){
688 best=item;
689 bestDistance=d;
690 }
691 });
692
693 return bestDistance<=30
694 ?best
695 :null;
696 }
697
698 function propagateDetailAccents(){
699 if(PAGE_KIND!=="detail")return;
700
701 Array.from(
702 root.querySelectorAll(
703 ".arsn-call,.dmp-call,.ido-call,.pp-call,"+
704 ".arsn-source,.dmp-source,.ido-source,.pp-source"
705 )
706 ).forEach(function(el){
707 if(!visible(el))return;
708
709 var style=getComputedStyle(el);
710
711 if(
712 num(style.borderTopWidth)>=2
713 ){
714 var match=
715 paletteMatch(
716 style.borderTopColor
717 );
718
719 if(match){
720 el.style.setProperty(
721 "border-left",
722 "4px solid "+match.hex,
723 "important"
724 );
725 }
726 }
727 });
728
729 // Warning families: explicit safety override.
730 Array.from(
731 root.querySelectorAll(
732 ".arsn-warn,.dmp-warn,.ido-warn,.pp-warn,"+
733 ".warn,.warning,.warningmessage,.errormessage"
734 )
735 ).forEach(function(el){
736 if(!visible(el))return;
737
738 el.style.setProperty(
739 "border-left",
740 "4px solid #e94b13",
741 "important"
742 );
743 });
744
745 // Info families: explicit orientation override.
746 Array.from(
747 root.querySelectorAll(
748 ".arsn-info,.dmp-info,.ido-info,.pp-info,.infomessage"
749 )
750 ).forEach(function(el){
751 if(!visible(el))return;
752
753 el.style.setProperty(
754 "border-left",
755 "4px solid #21b6d7",
756 "important"
757 );
758 });
759 }
760
761 /* =======================================================
762 OVERVIEW SEMANTIC THEME PALETTE
763 ======================================================= */
764
765 function smallestThemeHeaders(){
766 return Array.from(
767 root.querySelectorAll(
768 "div,span,p,strong,h3,h4,h5,h6"
769 )
770 ).filter(function(el){
771 if(!visible(el))return false;
772 if(!themeFor(el.textContent))return false;
773
774 return !Array.from(
775 el.children||[]
776 ).some(function(child){
777 return !!themeFor(
778 child.textContent
779 );
780 });
781 });
782 }
783
784 function findOverviewCard(header){
785 var node=header.parentElement;
786 var candidates=[];
787
788 while(node&&node!==root){
789 var rect=node.getBoundingClientRect();
790 var style=getComputedStyle(node);
791
792 var border=
793 num(style.borderTopWidth)+
794 num(style.borderRightWidth)+
795 num(style.borderBottomWidth)+
796 num(style.borderLeftWidth);
797
798 if(
799 rect.width>=220&&
800 rect.width<=800&&
801 rect.height>=120&&
802 border>=1
803 ){
804 candidates.push(node);
805 }
806
807 node=node.parentElement;
808 }
809
810 if(!candidates.length)return null;
811
812 candidates.sort(function(a,b){
813 return (
814 b.getBoundingClientRect().height-
815 a.getBoundingClientRect().height
816 );
817 });
818
819 return candidates[0];
820 }
821
822 function rowCandidates(link,card){
823 var result=[];
824 var cardRect=
825 card.getBoundingClientRect();
826
827 var node=link;
828
829 while(node&&node!==card){
830 if(visible(node)){
831 var rect=
832 node.getBoundingClientRect();
833
834 if(
835 rect.height<=105&&
836 rect.width>=
837 cardRect.width*.50&&
838 rect.width<=
839 cardRect.width*1.03
840 ){
841 result.push(node);
842 }
843 }
844
845 node=node.parentElement;
846 }
847
848 return result;
849 }
850
851 function chooseOuterRow(
852 candidates,
853 link
854 ){
855 if(!candidates.length){
856 return link;
857 }
858
859 var bordered=
860 candidates.filter(function(el){
861 return (
862 num(
863 getComputedStyle(el)
864 .borderLeftWidth
865 )>=1
866 );
867 });
868
869 var pool=
870 bordered.length
871 ?bordered
872 :candidates;
873
874 pool.sort(function(a,b){
875 var ar=
876 a.getBoundingClientRect();
877
878 var br=
879 b.getBoundingClientRect();
880
881 return (
882 ar.left-br.left||
883 br.width-ar.width
884 );
885 });
886
887 return pool[0]||link;
888 }
889
890 function applyOverviewPalette(){
891 if(PAGE_KIND!=="overview"){
892 return [];
893 }
894
895 var headers=
896 smallestThemeHeaders()
897 .map(function(el){
898 return {
899 el:el,
900 theme:
901 themeFor(
902 el.textContent
903 ),
904 card:
905 findOverviewCard(
906 el
907 )
908 };
909 })
910 .filter(function(row){
911 return !!row.card;
912 });
913
914 var unique=[];
915 var seenHeaders=new Set();
916
917 headers.forEach(function(row){
918 var key=
919 row.theme.name+
920 "|"+
921 Math.round(
922 row.card
923 .getBoundingClientRect()
924 .left
925 )+
926 "|"+
927 Math.round(
928 row.el
929 .getBoundingClientRect()
930 .top
931 );
932
933 if(!seenHeaders.has(key)){
934 seenHeaders.add(key);
935 unique.push(row);
936 }
937 });
938
939 unique.forEach(function(row){
940 var headerRect=
941 row.el
942 .getBoundingClientRect();
943
944 row.el.style.setProperty(
945 "background",
946 row.theme.bg,
947 "important"
948 );
949
950 row.el.style.setProperty(
951 "color",
952 row.theme.text,
953 "important"
954 );
955
956 row.el.style.setProperty(
957 "text-align",
958 "left",
959 "important"
960 );
961
962 row.el.style.setProperty(
963 "word-spacing",
964 "normal",
965 "important"
966 );
967
968 var later=
969 unique
970 .filter(function(other){
971 return (
972 other.card===row.card&&
973 other.el
974 .getBoundingClientRect()
975 .top>
976 headerRect.top+2
977 );
978 })
979 .sort(function(a,b){
980 return (
981 a.el
982 .getBoundingClientRect()
983 .top-
984 b.el
985 .getBoundingClientRect()
986 .top
987 );
988 });
989
990 var stopTop=
991 later.length
992 ?later[0].el
993 .getBoundingClientRect()
994 .top
995 :Infinity;
996
997 Array.from(
998 row.card.querySelectorAll("a")
999 ).forEach(function(link){
1000 if(!visible(link))return;
1001
1002 var rect=
1003 link.getBoundingClientRect();
1004
1005 if(
1006 rect.top<=
1007 headerRect.bottom-2||
1008 rect.top>=
1009 stopTop-2
1010 ){
1011 return;
1012 }
1013
1014 var candidates=
1015 rowCandidates(
1016 link,
1017 row.card
1018 );
1019
1020 var target=
1021 chooseOuterRow(
1022 candidates,
1023 link
1024 );
1025
1026 candidates.forEach(function(el){
1027 el.style.setProperty(
1028 "border-left",
1029 "0 solid transparent",
1030 "important"
1031 );
1032 });
1033
1034 target.style.setProperty(
1035 "border-left",
1036 "3px solid "+
1037 row.theme.accent,
1038 "important"
1039 );
1040
1041 target.style.setProperty(
1042 "box-sizing",
1043 "border-box",
1044 "important"
1045 );
1046 });
1047 });
1048
1049 return unique;
1050 }
1051
1052 /* =======================================================
1053 OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW
1054 ======================================================= */
1055
1056 function alignOverviewCards(headers){
1057 if(
1058 PAGE_KIND!=="overview"||
1059 window.innerWidth<=MOBILE_MAX
1060 ){
1061 return;
1062 }
1063
1064 var cards=[];
1065 var seen=new Set();
1066
1067 headers.forEach(function(row){
1068 if(!seen.has(row.card)){
1069 seen.add(row.card);
1070 cards.push(row.card);
1071 }
1072 });
1073
1074 if(cards.length<2){
1075 return;
1076 }
1077
1078 // Group cards by actual top position.
1079 var groups=[];
1080
1081 cards.forEach(function(card){
1082 var top=
1083 card.getBoundingClientRect().top;
1084
1085 var group=null;
1086
1087 for(var i=0;i<groups.length;i++){
1088 if(
1089 Math.abs(
1090 groups[i].top-top
1091 )<=ROW_TOLERANCE
1092 ){
1093 group=groups[i];
1094 break;
1095 }
1096 }
1097
1098 if(!group){
1099 group={
1100 top:top,
1101 cards:[]
1102 };
1103 groups.push(group);
1104 }
1105
1106 group.cards.push(card);
1107 });
1108
1109 groups.forEach(function(group){
1110 if(group.cards.length<2){
1111 return;
1112 }
1113
1114 var firstHeaders=
1115 group.cards.map(function(card){
1116 var candidates=
1117 headers
1118 .filter(function(row){
1119 return row.card===card;
1120 })
1121 .sort(function(a,b){
1122 return (
1123 a.el
1124 .getBoundingClientRect()
1125 .top-
1126 b.el
1127 .getBoundingClientRect()
1128 .top
1129 );
1130 });
1131
1132 return candidates.length
1133 ?candidates[0]
1134 :null;
1135 });
1136
1137 if(
1138 !firstHeaders.some(function(row){
1139 return !row;
1140 })
1141 ){
1142 var targetTop=
1143 Math.max.apply(
1144 Math,
1145 firstHeaders.map(function(row){
1146 return (
1147 row.el
1148 .getBoundingClientRect()
1149 .top-
1150 row.card
1151 .getBoundingClientRect()
1152 .top
1153 );
1154 })
1155 );
1156
1157 firstHeaders.forEach(function(row){
1158 var relativeTop=
1159 row.el
1160 .getBoundingClientRect()
1161 .top-
1162 row.card
1163 .getBoundingClientRect()
1164 .top;
1165
1166 var delta=
1167 targetTop-relativeTop;
1168
1169 if(delta>1){
1170 saveStyle(
1171 row.el,
1172 originalMargin,
1173 "margin-top"
1174 );
1175
1176 var current=
1177 num(
1178 getComputedStyle(
1179 row.el
1180 ).marginTop
1181 );
1182
1183 row.el.style.setProperty(
1184 "margin-top",
1185 (
1186 current+delta
1187 )+"px"
1188 );
1189
1190 row.el.setAttribute(
1191 "data-sn-master-first-row",
1192 "1"
1193 );
1194
1195 managedMargin.add(
1196 row.el
1197 );
1198 }
1199 });
1200 }
1201
1202 var maxHeight=0;
1203
1204 group.cards.forEach(function(card){
1205 maxHeight=
1206 Math.max(
1207 maxHeight,
1208 card
1209 .getBoundingClientRect()
1210 .height
1211 );
1212 });
1213
1214 maxHeight=
1215 Math.ceil(maxHeight);
1216
1217 group.cards.forEach(function(card){
1218 saveStyle(
1219 card,
1220 originalHeight,
1221 "min-height"
1222 );
1223
1224 card.style.setProperty(
1225 "min-height",
1226 maxHeight+"px"
1227 );
1228
1229 card.setAttribute(
1230 "data-sn-master-equal-height",
1231 "1"
1232 );
1233
1234 managedHeight.add(
1235 card
1236 );
1237 });
1238 });
1239 }
1240
1241 /* =======================================================
1242 DETAIL GRID EQUAL HEIGHT, DESKTOP ONLY
1243 ======================================================= */
1244
1245 function equaliseDetailGrids(){
1246 if(
1247 PAGE_KIND!=="detail"||
1248 window.innerWidth<=MOBILE_MAX
1249 ){
1250 return;
1251 }
1252
1253 var selectors=[
1254 ".arsn-grid",
1255 ".arsn-grid-2",
1256 ".arsn-grid-3",
1257 ".dmp-grid",
1258 ".ido-grid",
1259 ".pp-grid"
1260 ];
1261
1262 selectors.forEach(function(selector){
1263 Array.from(
1264 root.querySelectorAll(selector)
1265 ).forEach(function(grid){
1266 var children=
1267 Array.from(
1268 grid.children||[]
1269 ).filter(visible);
1270
1271 if(children.length<2){
1272 return;
1273 }
1274
1275 var groups=[];
1276
1277 children.forEach(function(child){
1278 var top=
1279 child
1280 .getBoundingClientRect()
1281 .top;
1282
1283 var group=null;
1284
1285 for(var i=0;i<groups.length;i++){
1286 if(
1287 Math.abs(
1288 groups[i].top-top
1289 )<=ROW_TOLERANCE
1290 ){
1291 group=groups[i];
1292 break;
1293 }
1294 }
1295
1296 if(!group){
1297 group={
1298 top:top,
1299 items:[]
1300 };
1301 groups.push(group);
1302 }
1303
1304 group.items.push(child);
1305 });
1306
1307 groups.forEach(function(group){
1308 if(group.items.length<2){
1309 return;
1310 }
1311
1312 var maxHeight=0;
1313
1314 group.items.forEach(function(item){
1315 maxHeight=
1316 Math.max(
1317 maxHeight,
1318 item
1319 .getBoundingClientRect()
1320 .height
1321 );
1322 });
1323
1324 maxHeight=
1325 Math.ceil(maxHeight);
1326
1327 group.items.forEach(function(item){
1328 saveStyle(
1329 item,
1330 originalHeight,
1331 "min-height"
1332 );
1333
1334 item.style.setProperty(
1335 "min-height",
1336 maxHeight+"px"
1337 );
1338
1339 item.setAttribute(
1340 "data-sn-master-equal-height",
1341 "1"
1342 );
1343
1344 managedHeight.add(item);
1345 });
1346 });
1347 });
1348 });
1349 }
1350
1351 /* =======================================================
1352 RUN / RESPONSIVE SCHEDULING
1353 ======================================================= */
1354
1355 function run(){
1356 if(running)return;
1357
1358 running=true;
1359
1360 try{
1361 resetRuntime();
1362 applyPlaceholderBadge();
1363 propagateDetailAccents();
1364
1365 var headers=
1366 applyOverviewPalette();
1367
1368 makeThreeLineAreaLabels();
1369 makeFilledRedOrangeCTAsBorderless();
1370
1371 if(
1372 window.innerWidth>
1373 MOBILE_MAX
1374 ){
1375 alignOverviewCards(
1376 headers
1377 );
1378
1379 equaliseDetailGrids();
1380 }
1381 }finally{
1382 running=false;
1383 }
1384 }
1385
1386 function onResize(){
1387 if(resizeTimer){
1388 clearTimeout(
1389 resizeTimer
1390 );
1391 }
1392
1393 resizeTimer=
1394 setTimeout(
1395 function(){
1396 resizeTimer=0;
1397 run();
1398 },
1399 RESIZE_DEBOUNCE
1400 );
1401 }
1402
1403 async function waitForReady(){
1404 if(
1405 document.readyState!=="complete"
1406 ){
1407 await new Promise(function(resolve){
1408 window.addEventListener(
1409 "load",
1410 resolve,
1411 {once:true}
1412 );
1413 });
1414 }
1415
1416 if(
1417 document.fonts&&
1418 document.fonts.ready
1419 ){
1420 try{
1421 await document.fonts.ready;
1422 }catch(error){}
1423 }
1424
1425 var images=
1426 Array.from(
1427 root.querySelectorAll("img")
1428 );
1429
1430 await Promise.all(
1431 images.map(function(img){
1432 if(img.complete){
1433 return Promise.resolve();
1434 }
1435
1436 return new Promise(function(resolve){
1437 var done=function(){
1438 resolve();
1439 };
1440
1441 img.addEventListener(
1442 "load",
1443 done,
1444 {once:true}
1445 );
1446
1447 img.addEventListener(
1448 "error",
1449 done,
1450 {once:true}
1451 );
1452 });
1453 })
1454 );
1455
1456 run();
1457 }
1458
1459 window.addEventListener(
1460 "resize",
1461 onResize,
1462 {passive:true}
1463 );
1464
1465 waitForReady();
1466 })();
1467 </script>
1468
1469 <!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END -->
1470 {{/html}}