Wiki source code of Data Protection & Ethics

Version 5.10 by Veronika Kocher on Thursday, 03 Sep 2026 10:09

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 {{html}}<!-- ARSN_TOPIC_ROUTING_V1 -->{{/html}}
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 \n\n
72 \n\n{{html clean="false"}}
73 <!-- SN_HORIZONTAL_BOX_HARMONIZER_START -->
74
75 <style data-sn-horizontal-box-harmonizer="7">
76 /* ---------- Typography: never justify headings ---------- */
77 #xwikicontent h1,
78 #xwikicontent h2,
79 #xwikicontent h3,
80 #xwikicontent h4,
81 #xwikicontent h5,
82 #xwikicontent h6,
83 #xwikicontent .box-title,
84 #xwikicontent [role="heading"],
85 #xwikicontent h1 a,
86 #xwikicontent h2 a,
87 #xwikicontent h3 a,
88 #xwikicontent h4 a,
89 #xwikicontent h5 a,
90 #xwikicontent h6 a,
91 #xwikicontent .box-title a,
92 #xwikicontent [role="heading"] a{
93 text-align:left!important;
94 text-justify:auto!important;
95 word-spacing:normal!important;
96 }
97
98 /* ---------- Native XWiki semantic callouts ---------- */
99 #xwikicontent .box.infomessage,
100 #xwikicontent .infomessage,
101 #xwikicontent .box.warningmessage,
102 #xwikicontent .warningmessage,
103 #xwikicontent .box.successmessage,
104 #xwikicontent .successmessage,
105 #xwikicontent .box.errormessage,
106 #xwikicontent .errormessage,
107 #xwikicontent [data-sn-callout-harmonized="1"]{
108 box-sizing:border-box!important;
109 border-radius:8px!important;
110 border-top:1px solid rgba(0,0,0,.08)!important;
111 border-right:1px solid rgba(0,0,0,.08)!important;
112 border-bottom:1px solid rgba(0,0,0,.08)!important;
113 border-left:4px solid var(--sn-callout-accent,#21b6d7)!important;
114 padding:14px 16px!important;
115 text-align:left!important;
116 text-justify:auto!important;
117 word-spacing:normal!important;
118 box-shadow:none!important;
119 }
120
121 #xwikicontent .box.infomessage,
122 #xwikicontent .infomessage{
123 --sn-callout-accent:#21b6d7;
124 background:#eaf7fb!important;
125 }
126
127 #xwikicontent .box.warningmessage,
128 #xwikicontent .warningmessage{
129 --sn-callout-accent:#f0aa00;
130 background:#fff8e7!important;
131 }
132
133 #xwikicontent .box.successmessage,
134 #xwikicontent .successmessage{
135 --sn-callout-accent:#38b76a;
136 background:#edf9f1!important;
137 }
138
139 #xwikicontent .box.errormessage,
140 #xwikicontent .errormessage{
141 --sn-callout-accent:#e94b13;
142 background:#fff1ec!important;
143 }
144
145 #xwikicontent [data-sn-callout-harmonized="1"] > :first-child,
146 #xwikicontent .infomessage > :first-child,
147 #xwikicontent .warningmessage > :first-child,
148 #xwikicontent .successmessage > :first-child,
149 #xwikicontent .errormessage > :first-child{
150 margin-top:0!important;
151 }
152
153 #xwikicontent [data-sn-callout-harmonized="1"] > :last-child,
154 #xwikicontent .infomessage > :last-child,
155 #xwikicontent .warningmessage > :last-child,
156 #xwikicontent .successmessage > :last-child,
157 #xwikicontent .errormessage > :last-child{
158 margin-bottom:0!important;
159 }
160
161 #xwikicontent [data-sn-equal-height-managed],
162 #xwikicontent [data-sn-first-section-aligned],
163 #xwikicontent [data-sn-first-content-aligned]{
164 box-sizing:border-box;
165 }
166 </style>
167
168 <script data-sn-horizontal-box-harmonizer="7">
169 (function(){
170 "use strict";
171
172 var MOBILE_MAX=767;
173 var ROW_TOLERANCE=6;
174 var MIN_W=150;
175 var MIN_H=36;
176 var MAX_PARENT_CHILDREN=18;
177 var SEARCH_DEPTH=5;
178 var RESIZE_DEBOUNCE=220;
179 var MIN_WIDTH_CHANGE=2;
180
181 var root=
182 document.getElementById("xwikicontent")||
183 document.querySelector(".xwiki-rendering-content")||
184 document.querySelector("main")||
185 document.body;
186
187 if(!root)return;
188
189 var heightManaged=new Set();
190 var sectionManaged=new Set();
191 var contentManaged=new Set();
192
193 var originalMinHeight=new WeakMap();
194 var originalMarginTop=new WeakMap();
195
196 var resizeTimer=0;
197 var lastWidth=-1;
198 var hasApplied=false;
199 var applying=false;
200
201 function num(v){
202 var n=parseFloat(v);
203 return Number.isFinite(n)?n:0;
204 }
205
206 function visible(el,minW,minH){
207 if(!el||el.nodeType!==1)return false;
208
209 var s=getComputedStyle(el);
210
211 if(
212 s.display==="none"||
213 s.visibility==="hidden"||
214 Number(s.opacity)===0
215 ){
216 return false;
217 }
218
219 var r=el.getBoundingClientRect();
220
221 return (
222 r.width>=(minW||1)&&
223 r.height>=(minH||1)
224 );
225 }
226
227 function normalizeText(text){
228 return String(text||"")
229 .replace(/\s+/g," ")
230 .trim()
231 .toUpperCase();
232 }
233
234 function excluded(el){
235 return (
236 !el.matches||
237 el.matches(
238 "button,input,select,textarea,option,label,img,svg,canvas,table,thead,tbody,tfoot,tr,td,th,summary,script,style,noscript,template,.btn,.chip,[role=button]"
239 )
240 );
241 }
242
243 /* ---------- Custom coloured callouts ---------- */
244
245 function nativeCallout(el){
246 var c=
247 typeof el.className==="string"
248 ? el.className.toLowerCase()
249 : "";
250
251 return (
252 /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c)
253 );
254 }
255
256 function customCallout(el){
257 if(!visible(el,220,42)||excluded(el))return false;
258
259 var r=el.getBoundingClientRect();
260
261 if(r.height>520)return false;
262
263 var s=getComputedStyle(el);
264
265 var bg=
266 s.backgroundColor&&
267 s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
268 s.backgroundColor!=="transparent"&&
269 s.backgroundColor!=="rgb(255, 255, 255)";
270
271 var left=
272 num(s.borderLeftWidth);
273
274 return (
275 bg&&
276 left>=2
277 );
278 }
279
280 function harmoniseCustomCallouts(){
281 Array.from(
282 root.querySelectorAll(
283 "div,aside,section"
284 )
285 ).forEach(function(el){
286 if(nativeCallout(el))return;
287 if(!customCallout(el))return;
288
289 var s=getComputedStyle(el);
290
291 el.setAttribute(
292 "data-sn-callout-harmonized",
293 "1"
294 );
295
296 if(
297 s.borderLeftColor
298 ){
299 el.style.setProperty(
300 "--sn-callout-accent",
301 s.borderLeftColor
302 );
303 }
304 });
305 }
306
307 /* ---------- Restore only values V7 itself changed ---------- */
308
309 function saveOriginal(el,map,property){
310 if(map.has(el))return;
311
312 map.set(el,{
313 value:
314 el.style.getPropertyValue(
315 property
316 ),
317 priority:
318 el.style.getPropertyPriority(
319 property
320 )
321 });
322 }
323
324 function restoreOriginal(el,map,property){
325 var original=map.get(el);
326
327 if(original&&original.value){
328 el.style.setProperty(
329 property,
330 original.value,
331 original.priority||""
332 );
333 }else{
334 el.style.removeProperty(
335 property
336 );
337 }
338 }
339
340 function resetRuntime(){
341 heightManaged.forEach(function(el){
342 restoreOriginal(
343 el,
344 originalMinHeight,
345 "min-height"
346 );
347
348 el.removeAttribute(
349 "data-sn-equal-height-managed"
350 );
351 });
352
353 sectionManaged.forEach(function(el){
354 restoreOriginal(
355 el,
356 originalMarginTop,
357 "margin-top"
358 );
359
360 el.removeAttribute(
361 "data-sn-first-section-aligned"
362 );
363 });
364
365 contentManaged.forEach(function(el){
366 restoreOriginal(
367 el,
368 originalMarginTop,
369 "margin-top"
370 );
371
372 el.removeAttribute(
373 "data-sn-first-content-aligned"
374 );
375 });
376
377 heightManaged.clear();
378 sectionManaged.clear();
379 contentManaged.clear();
380 }
381
382 /* ---------- Card detection ---------- */
383
384 function namedLikeBox(el){
385 var c=
386 typeof el.className==="string"
387 ? el.className
388 : "";
389
390 return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c);
391 }
392
393 function boxLike(el){
394 if(
395 !visible(el,MIN_W,MIN_H)||
396 excluded(el)
397 ){
398 return false;
399 }
400
401 var s=getComputedStyle(el);
402 var r=el.getBoundingClientRect();
403
404 var border=
405 num(s.borderTopWidth)+
406 num(s.borderRightWidth)+
407 num(s.borderBottomWidth)+
408 num(s.borderLeftWidth);
409
410 var radius=Math.max(
411 num(s.borderTopLeftRadius),
412 num(s.borderTopRightRadius),
413 num(s.borderBottomLeftRadius),
414 num(s.borderBottomRightRadius)
415 );
416
417 var bg=
418 s.backgroundColor&&
419 s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
420 s.backgroundColor!=="transparent";
421
422 var shadow=
423 s.boxShadow&&
424 s.boxShadow!=="none";
425
426 return (
427 namedLikeBox(el)||
428 border>=1||
429 (bg&&radius>=3)||
430 (shadow&&r.width>=180)
431 );
432 }
433
434 function pickTarget(child){
435 if(!visible(child,MIN_W,MIN_H))return null;
436
437 if(boxLike(child))return child;
438
439 var cr=child.getBoundingClientRect();
440 var q=[];
441
442 Array.from(child.children||[]).forEach(function(el){
443 q.push({el:el,depth:1});
444 });
445
446 var best=null;
447 var bestScore=-Infinity;
448
449 while(q.length){
450 var item=q.shift();
451 var el=item.el;
452
453 if(!visible(el,MIN_W,MIN_H))continue;
454
455 var r=el.getBoundingClientRect();
456
457 if(
458 r.width>=cr.width*.68&&
459 boxLike(el)
460 ){
461 var widthFit=
462 1-Math.min(
463 1,
464 Math.abs(cr.width-r.width)/
465 Math.max(1,cr.width)
466 );
467
468 var topFit=
469 1-Math.min(
470 1,
471 Math.abs(cr.top-r.top)/100
472 );
473
474 var score=
475 widthFit*6+
476 topFit*3+
477 Math.min(r.height,900)/450+
478 Math.min(r.width*r.height,900000)/900000;
479
480 if(score>bestScore){
481 best=el;
482 bestScore=score;
483 }
484 }
485
486 if(item.depth<SEARCH_DEPTH){
487 Array.from(el.children||[]).forEach(function(next){
488 q.push({
489 el:next,
490 depth:item.depth+1
491 });
492 });
493 }
494 }
495
496 return best;
497 }
498
499 function groupRows(entries){
500 var groups=[];
501
502 entries
503 .slice()
504 .sort(function(a,b){
505 return (
506 a.rect.top-b.rect.top||
507 a.rect.left-b.rect.left
508 );
509 })
510 .forEach(function(entry){
511 var group=null;
512
513 for(var i=0;i<groups.length;i++){
514 if(
515 Math.abs(
516 groups[i].top-
517 entry.rect.top
518 )<=ROW_TOLERANCE
519 ){
520 group=groups[i];
521 break;
522 }
523 }
524
525 if(!group){
526 group={
527 top:entry.rect.top,
528 entries:[]
529 };
530 groups.push(group);
531 }
532
533 group.entries.push(entry);
534 });
535
536 return groups;
537 }
538
539 function validRow(group){
540 if(group.entries.length<2)return false;
541
542 var lefts=
543 group.entries
544 .map(function(e){return e.rect.left;})
545 .sort(function(a,b){return a-b;});
546
547 if(
548 lefts[lefts.length-1]-
549 lefts[0]<
550 80
551 ){
552 return false;
553 }
554
555 var widths=
556 group.entries
557 .map(function(e){return e.rect.width;})
558 .filter(function(w){return w>0;});
559
560 if(widths.length<2)return false;
561
562 var minW=
563 Math.min.apply(Math,widths);
564
565 var maxW=
566 Math.max.apply(Math,widths);
567
568 return (
569 maxW/
570 Math.max(1,minW)<=
571 1.9
572 );
573 }
574
575 /* ---------- Known ARSN first section bars ---------- */
576
577 function knownBar(el){
578 var text=
579 normalizeText(
580 el.textContent
581 );
582
583 return (
584 text==="HIER STARTEN"||
585 text==="ORGANISIEREN & DOKUMENTIEREN"||
586 text==="ENTSCHEIDEN"||
587 text==="START HERE"||
588 text==="GET STARTED"||
589 text==="ORGANISE & DOCUMENT"||
590 text==="ORGANIZE & DOCUMENT"||
591 text==="DECIDE"
592 );
593 }
594
595 function findKnownBar(card){
596 var cardRect=
597 card.getBoundingClientRect();
598
599 var rows=
600 Array.from(
601 card.querySelectorAll(
602 "div,p,span,strong,h3,h4,h5,h6"
603 )
604 )
605 .filter(function(el){
606 if(!visible(el,20,6))return false;
607 if(!knownBar(el))return false;
608
609 var r=el.getBoundingClientRect();
610
611 var rel=
612 r.top-
613 cardRect.top;
614
615 return (
616 rel>=35&&
617 rel<=
618 cardRect.height*.75
619 );
620 })
621 .sort(function(a,b){
622 return (
623 a.getBoundingClientRect().top-
624 b.getBoundingClientRect().top
625 );
626 });
627
628 return rows[0]||null;
629 }
630
631 function alignKnownBars(cards){
632 var rows=
633 cards.map(function(card){
634 var bar=
635 findKnownBar(card);
636
637 if(!bar)return null;
638
639 var cr=
640 card.getBoundingClientRect();
641
642 var br=
643 bar.getBoundingClientRect();
644
645 return {
646 bar:bar,
647 relativeTop:
648 br.top-
649 cr.top
650 };
651 });
652
653 if(
654 rows.some(function(row){
655 return !row;
656 })
657 ){
658 return false;
659 }
660
661 var target=
662 Math.max.apply(
663 Math,
664 rows.map(function(row){
665 return row.relativeTop;
666 })
667 );
668
669 rows.forEach(function(row){
670 var delta=
671 target-
672 row.relativeTop;
673
674 if(delta<=1)return;
675
676 saveOriginal(
677 row.bar,
678 originalMarginTop,
679 "margin-top"
680 );
681
682 var current=
683 num(
684 getComputedStyle(
685 row.bar
686 ).marginTop
687 );
688
689 row.bar.style.setProperty(
690 "margin-top",
691 (
692 current+
693 delta
694 )+"px"
695 );
696
697 row.bar.setAttribute(
698 "data-sn-first-section-aligned",
699 "7"
700 );
701
702 sectionManaged.add(
703 row.bar
704 );
705 });
706
707 return true;
708 }
709
710 /* ---------- Generic first content after heading ---------- */
711
712 function heading(card){
713 var cr=
714 card.getBoundingClientRect();
715
716 var rows=
717 Array.from(
718 card.querySelectorAll(
719 "h1,h2,h3,h4,h5,h6,.box-title,[role=heading]"
720 )
721 )
722 .filter(function(el){
723 if(!visible(el,20,8))return false;
724
725 var r=el.getBoundingClientRect();
726
727 var rel=
728 r.top-
729 cr.top;
730
731 return (
732 rel>=0&&
733 rel<=
734 Math.min(
735 160,
736 cr.height*.45
737 )
738 );
739 })
740 .sort(function(a,b){
741 return (
742 a.getBoundingClientRect().top-
743 b.getBoundingClientRect().top
744 );
745 });
746
747 return rows[0]||null;
748 }
749
750 function firstContent(card,h){
751 if(!h)return null;
752
753 var cr=
754 card.getBoundingClientRect();
755
756 var hr=
757 h.getBoundingClientRect();
758
759 var rows=
760 Array.from(
761 card.querySelectorAll(
762 "p,div,ul,ol,dl,blockquote"
763 )
764 )
765 .filter(function(el){
766 if(
767 el===h||
768 h.contains(el)||
769 el.contains(h)
770 ){
771 return false;
772 }
773
774 if(!visible(el,30,8))return false;
775
776 var text=
777 String(el.textContent||"")
778 .replace(/\s+/g," ")
779 .trim();
780
781 if(text.length<3)return false;
782
783 var r=el.getBoundingClientRect();
784
785 if(
786 r.top<
787 hr.bottom-1
788 ){
789 return false;
790 }
791
792 if(
793 r.top-cr.top>
794 Math.min(
795 280,
796 cr.height*.65
797 )
798 ){
799 return false;
800 }
801
802 if(
803 r.height>
804 cr.height*.58
805 ){
806 return false;
807 }
808
809 return true;
810 })
811 .sort(function(a,b){
812 var ar=
813 a.getBoundingClientRect();
814
815 var br=
816 b.getBoundingClientRect();
817
818 return (
819 ar.top-br.top||
820 ar.height-br.height
821 );
822 });
823
824 return rows[0]||null;
825 }
826
827 function alignGeneric(cards){
828 var rows=
829 cards.map(function(card){
830 var h=
831 heading(card);
832
833 var c=
834 firstContent(
835 card,
836 h
837 );
838
839 if(!h||!c)return null;
840
841 var cr=
842 card.getBoundingClientRect();
843
844 var rr=
845 c.getBoundingClientRect();
846
847 return {
848 content:c,
849 relativeTop:
850 rr.top-cr.top
851 };
852 });
853
854 if(
855 rows.some(function(row){
856 return !row;
857 })
858 ){
859 return false;
860 }
861
862 var target=
863 Math.max.apply(
864 Math,
865 rows.map(function(row){
866 return row.relativeTop;
867 })
868 );
869
870 rows.forEach(function(row){
871 var delta=
872 target-
873 row.relativeTop;
874
875 if(delta<=1)return;
876
877 saveOriginal(
878 row.content,
879 originalMarginTop,
880 "margin-top"
881 );
882
883 var current=
884 num(
885 getComputedStyle(
886 row.content
887 ).marginTop
888 );
889
890 row.content.style.setProperty(
891 "margin-top",
892 (
893 current+
894 delta
895 )+"px"
896 );
897
898 row.content.setAttribute(
899 "data-sn-first-content-aligned",
900 "7"
901 );
902
903 contentManaged.add(
904 row.content
905 );
906 });
907
908 return true;
909 }
910
911 function applyRow(group){
912 if(!validRow(group))return false;
913
914 var cards=[];
915 var seen=new Set();
916
917 group.entries.forEach(function(entry){
918 if(!seen.has(entry.target)){
919 seen.add(entry.target);
920 cards.push(entry.target);
921 }
922 });
923
924 if(cards.length<2)return false;
925
926 if(
927 !alignKnownBars(cards)
928 ){
929 alignGeneric(cards);
930 }
931
932 var maxHeight=0;
933
934 cards.forEach(function(card){
935 maxHeight=
936 Math.max(
937 maxHeight,
938 card.getBoundingClientRect().height
939 );
940 });
941
942 maxHeight=
943 Math.ceil(
944 maxHeight
945 );
946
947 if(maxHeight<MIN_H)return false;
948
949 cards.forEach(function(card){
950 saveOriginal(
951 card,
952 originalMinHeight,
953 "min-height"
954 );
955
956 card.style.setProperty(
957 "min-height",
958 maxHeight+"px"
959 );
960
961 card.setAttribute(
962 "data-sn-equal-height-managed",
963 "7"
964 );
965
966 heightManaged.add(card);
967 });
968
969 return true;
970 }
971
972 function calculate(force){
973 if(applying)return;
974
975 var width=
976 Math.round(
977 window.innerWidth
978 );
979
980 var meaningful=
981 lastWidth<0||
982 Math.abs(
983 width-
984 lastWidth
985 )>=
986 MIN_WIDTH_CHANGE;
987
988 if(
989 hasApplied&&
990 !force&&
991 !meaningful
992 ){
993 return;
994 }
995
996 applying=true;
997
998 try{
999 harmoniseCustomCallouts();
1000
1001 if(width<=MOBILE_MAX){
1002 if(hasApplied){
1003 resetRuntime();
1004 }
1005
1006 hasApplied=false;
1007 lastWidth=width;
1008 return;
1009 }
1010
1011 if(hasApplied){
1012 resetRuntime();
1013 }
1014
1015 var parents=
1016 Array.from(
1017 root.querySelectorAll("*")
1018 )
1019 .filter(function(parent){
1020 return (
1021 visible(
1022 parent,
1023 MIN_W,
1024 MIN_H
1025 )&&
1026 parent.children&&
1027 parent.children.length>=2&&
1028 parent.children.length<=
1029 MAX_PARENT_CHILDREN
1030 );
1031 });
1032
1033 var touched=
1034 new Set();
1035
1036 parents.forEach(function(parent){
1037 var entries=[];
1038
1039 Array.from(
1040 parent.children
1041 ).forEach(function(child){
1042 if(
1043 !visible(
1044 child,
1045 MIN_W,
1046 MIN_H
1047 )
1048 ){
1049 return;
1050 }
1051
1052 var target=
1053 pickTarget(child);
1054
1055 if(!target)return;
1056
1057 entries.push({
1058 target:target,
1059 rect:
1060 target.getBoundingClientRect()
1061 });
1062 });
1063
1064 groupRows(
1065 entries
1066 ).forEach(function(group){
1067 if(!validRow(group))return;
1068
1069 var targets=
1070 group.entries.map(function(entry){
1071 return entry.target;
1072 });
1073
1074 if(
1075 !targets.some(function(el){
1076 return !touched.has(el);
1077 })
1078 ){
1079 return;
1080 }
1081
1082 if(applyRow(group)){
1083 targets.forEach(function(el){
1084 touched.add(el);
1085 });
1086 }
1087 });
1088 });
1089
1090 lastWidth=width;
1091 hasApplied=true;
1092 }finally{
1093 applying=false;
1094 }
1095 }
1096
1097 function resize(){
1098 if(resizeTimer){
1099 clearTimeout(
1100 resizeTimer
1101 );
1102 }
1103
1104 resizeTimer=
1105 setTimeout(
1106 function(){
1107 resizeTimer=0;
1108 calculate(false);
1109 },
1110 RESIZE_DEBOUNCE
1111 );
1112 }
1113
1114 function waitImages(){
1115 var images=
1116 Array.from(
1117 root.querySelectorAll("img")
1118 );
1119
1120 return Promise.all(
1121 images.map(function(img){
1122 if(img.complete){
1123 return Promise.resolve();
1124 }
1125
1126 return new Promise(function(resolve){
1127 var done=function(){
1128 resolve();
1129 };
1130
1131 img.addEventListener(
1132 "load",
1133 done,
1134 {once:true}
1135 );
1136
1137 img.addEventListener(
1138 "error",
1139 done,
1140 {once:true}
1141 );
1142 });
1143 })
1144 );
1145 }
1146
1147 async function initial(){
1148 if(
1149 document.readyState!==
1150 "complete"
1151 ){
1152 await new Promise(function(resolve){
1153 addEventListener(
1154 "load",
1155 resolve,
1156 {once:true}
1157 );
1158 });
1159 }
1160
1161 if(
1162 document.fonts&&
1163 document.fonts.ready
1164 ){
1165 try{
1166 await document.fonts.ready;
1167 }catch(error){}
1168 }
1169
1170 await waitImages();
1171
1172 // Exactly one initial layout calculation.
1173 calculate(true);
1174 }
1175
1176 addEventListener(
1177 "resize",
1178 resize,
1179 {passive:true}
1180 );
1181
1182 initial();
1183 })();
1184 </script>
1185
1186 <!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->
1187 {{/html}}\n