Changes for page Data Protection & Ethics
Last modified by Veronika Kocher on Friday, 18 Sep 2026 16:47
From version 5.12
edited by Veronika Kocher
on Thursday, 03 Sep 2026 14:15
on Thursday, 03 Sep 2026 14:15
Change comment:
There is no comment for this version
To version 5.10
edited by Veronika Kocher
on Thursday, 03 Sep 2026 10:09
on Thursday, 03 Sep 2026 10:09
Change comment:
There is no comment for this version
Summary
-
Page properties (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -44,7 +44,7 @@ 44 44 45 45 == Who is responsible? == 46 46 47 - 47 +{{html}}<!-- ARSN_TOPIC_ROUTING_V1 -->{{/html}} 48 48 {{info title="Service routing"}} 49 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 50 ... ... @@ -68,13 +68,12 @@ 68 68 <!-- ARSN_SEARCH_TERMS_END --> 69 69 {{/html}} 70 70 71 -{{html clean="false"}} 72 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START --> 71 +\n\n 72 +\n\n{{html clean="false"}} 73 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 73 73 74 -<style data-sn-service-navigator-master="1"> 75 -/* ========================================================= 76 - MASTER TYPOGRAPHY 77 - ========================================================= */ 75 +<style data-sn-horizontal-box-harmonizer="7"> 76 +/* ---------- Typography: never justify headings ---------- */ 78 78 #xwikicontent h1, 79 79 #xwikicontent h2, 80 80 #xwikicontent h3, ... ... @@ -96,105 +96,88 @@ 96 96 word-spacing:normal!important; 97 97 } 98 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{ 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"]{ 127 127 box-sizing:border-box!important; 128 - border-left:4px solid #21b6d7!important; 129 - border-radius:8px; 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; 130 130 text-align:left!important; 116 + text-justify:auto!important; 131 131 word-spacing:normal!important; 118 + box-shadow:none!important; 132 132 } 133 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, 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, 141 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; 141 + --sn-callout-accent:#e94b13; 142 + background:#fff1ec!important; 147 147 } 148 148 149 -[data-sn-master-equal-height], 150 -[data-sn-master-first-row]{ 151 - box-sizing:border-box; 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; 152 152 } 153 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; 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; 172 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; 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; 184 184 } 185 185 </style> 186 186 187 -<script data-sn- service-navigator-master="1">168 +<script data-sn-horizontal-box-harmonizer="7"> 188 188 (function(){ 189 189 "use strict"; 190 190 191 - var PAGE_KIND="detail"; 192 - var PLACEHOLDER=true; 193 - var PLACEHOLDER_LABEL="COMING SOON"; 194 - 195 195 var MOBILE_MAX=767; 196 196 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; 197 197 var RESIZE_DEBOUNCE=220; 179 + var MIN_WIDTH_CHANGE=2; 198 198 199 199 var root= 200 200 document.getElementById("xwikicontent")|| ... ... @@ -204,114 +204,142 @@ 204 204 205 205 if(!root)return; 206 206 207 - var managedHeight=new Set(); 208 - var managedMargin=new Set(); 209 - var originalHeight=new WeakMap(); 210 - var originalMargin=new WeakMap(); 189 + var heightManaged=new Set(); 190 + var sectionManaged=new Set(); 191 + var contentManaged=new Set(); 211 211 193 + var originalMinHeight=new WeakMap(); 194 + var originalMarginTop=new WeakMap(); 195 + 212 212 var resizeTimer=0; 213 - var running=false; 197 + var lastWidth=-1; 198 + var hasApplied=false; 199 + var applying=false; 214 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 - ] 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; 276 276 } 277 - ]; 278 278 279 - function num(value){ 280 - var n=parseFloat(value); 281 - return Number.isFinite(n)?n:0; 219 + var r=el.getBoundingClientRect(); 220 + 221 + return ( 222 + r.width>=(minW||1)&& 223 + r.height>=(minH||1) 224 + ); 282 282 } 283 283 284 - function norm (value){285 - return String( value||"")227 + function normalizeText(text){ 228 + return String(text||"") 286 286 .replace(/\s+/g," ") 287 287 .trim() 288 288 .toUpperCase(); 289 289 } 290 290 291 - function visible(el){ 292 - if(!el||el.nodeType!==1)return false; 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 + } 293 293 294 - var style=getComputedStyle(el); 295 - var rect=el.getBoundingClientRect(); 243 + /* ---------- Custom coloured callouts ---------- */ 296 296 245 + function nativeCallout(el){ 246 + var c= 247 + typeof el.className==="string" 248 + ? el.className.toLowerCase() 249 + : ""; 250 + 297 297 return ( 298 - style.display!=="none"&& 299 - style.visibility!=="hidden"&& 300 - rect.width>20&& 301 - rect.height>4 252 + /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c) 302 302 ); 303 303 } 304 304 305 - function saveStyle(el,map,property){ 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){ 306 306 if(map.has(el))return; 307 307 308 308 map.set(el,{ 309 - value:el.style.getPropertyValue(property), 310 - priority:el.style.getPropertyPriority(property) 313 + value: 314 + el.style.getPropertyValue( 315 + property 316 + ), 317 + priority: 318 + el.style.getPropertyPriority( 319 + property 320 + ) 311 311 }); 312 312 } 313 313 314 - function restore Style(el,map,property){324 + function restoreOriginal(el,map,property){ 315 315 var original=map.get(el); 316 316 317 317 if(original&&original.value){ ... ... @@ -321,1069 +321,770 @@ 321 321 original.priority||"" 322 322 ); 323 323 }else{ 324 - el.style.removeProperty(property); 334 + el.style.removeProperty( 335 + property 336 + ); 325 325 } 326 326 } 327 327 328 328 function resetRuntime(){ 329 - managedHeight.forEach(function(el){330 - restore Style(341 + heightManaged.forEach(function(el){ 342 + restoreOriginal( 331 331 el, 332 - originalHeight, 344 + originalMinHeight, 333 333 "min-height" 334 334 ); 347 + 335 335 el.removeAttribute( 336 - "data-sn- master-equal-height"349 + "data-sn-equal-height-managed" 337 337 ); 338 338 }); 339 339 340 - managedMargin.forEach(function(el){341 - restore Style(353 + sectionManaged.forEach(function(el){ 354 + restoreOriginal( 342 342 el, 343 - originalMargin, 356 + originalMarginTop, 344 344 "margin-top" 345 345 ); 359 + 346 346 el.removeAttribute( 347 - "data-sn- master-first-row"361 + "data-sn-first-section-aligned" 348 348 ); 349 349 }); 350 350 351 - managedHeight.clear(); 352 - managedMargin.clear(); 353 - } 365 + contentManaged.forEach(function(el){ 366 + restoreOriginal( 367 + el, 368 + originalMarginTop, 369 + "margin-top" 370 + ); 354 354 355 - function themeFor(text){ 356 - var value=norm(text); 372 + el.removeAttribute( 373 + "data-sn-first-content-aligned" 374 + ); 375 + }); 357 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; 377 + heightManaged.clear(); 378 + sectionManaged.clear(); 379 + contentManaged.clear(); 374 374 } 375 375 376 - /* ======================================================= 377 - BORDERLESS FILLED RED/ORANGE CTA BUTTONS 378 - ======================================================= */ 382 + /* ---------- Card detection ---------- */ 379 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 - ); 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); 386 386 } 387 387 388 - function makeFilledRedOrangeCTAsBorderless(){ 389 - var RED_ORANGE=[233,75,19]; 393 + function boxLike(el){ 394 + if( 395 + !visible(el,MIN_W,MIN_H)|| 396 + excluded(el) 397 + ){ 398 + return false; 399 + } 390 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; 401 + var s=getComputedStyle(el); 402 + var r=el.getBoundingClientRect(); 397 397 398 - var style=getComputedStyle(el); 399 - var rgb=parseRGB(style.backgroundColor); 404 + var border= 405 + num(s.borderTopWidth)+ 406 + num(s.borderRightWidth)+ 407 + num(s.borderBottomWidth)+ 408 + num(s.borderLeftWidth); 400 400 401 - if(!rgb)return; 410 + var radius=Math.max( 411 + num(s.borderTopLeftRadius), 412 + num(s.borderTopRightRadius), 413 + num(s.borderBottomLeftRadius), 414 + num(s.borderBottomRightRadius) 415 + ); 402 402 403 - if( 404 - colourDistance( 405 - rgb, 406 - RED_ORANGE 407 - )>55 408 - ){ 409 - return; 410 - } 417 + var bg= 418 + s.backgroundColor&& 419 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 420 + s.backgroundColor!=="transparent"; 411 411 412 - var rect=el.getBoundingClientRect(); 422 + var shadow= 423 + s.boxShadow&& 424 + s.boxShadow!=="none"; 413 413 414 - if( 415 - rect.width<80|| 416 - rect.height<24 417 - ){ 418 - return; 419 - } 426 + return ( 427 + namedLikeBox(el)|| 428 + border>=1|| 429 + (bg&&radius>=3)|| 430 + (shadow&&r.width>=180) 431 + ); 432 + } 420 420 421 - el.style.setProperty( 422 - "border", 423 - "none", 424 - "important" 425 - ); 434 + function pickTarget(child){ 435 + if(!visible(child,MIN_W,MIN_H))return null; 426 426 427 - el.style.setProperty( 428 - "border-left", 429 - "none", 430 - "important" 431 - ); 437 + if(boxLike(child))return child; 432 432 433 - el.style.setProperty( 434 - "border-top", 435 - "none", 436 - "important" 437 - ); 439 + var cr=child.getBoundingClientRect(); 440 + var q=[]; 438 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 - ); 442 + Array.from(child.children||[]).forEach(function(el){ 443 + q.push({el:el,depth:1}); 456 456 }); 457 - } 458 458 459 - /* ======================================================= 460 - FULL-WIDTH THREE-LINE AREA LABELS 461 - ======================================================= */ 446 + var best=null; 447 + var bestScore=-Infinity; 462 462 463 - function compactText(value){ 464 - return String(value||"") 465 - .replace(/\s+/g," ") 466 - .trim(); 467 - } 449 + while(q.length){ 450 + var item=q.shift(); 451 + var el=item.el; 468 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 - } 453 + if(!visible(el,MIN_W,MIN_H))continue; 482 482 483 - var number= 484 - label.querySelector( 485 - ":scope > .arsn-area-number" 486 - ); 455 + var r=el.getBoundingClientRect(); 487 487 488 - var action= 489 - label.querySelector( 490 - ":scope > .arsn-area-action" 491 - ); 492 - 493 493 if( 494 - !number||495 - !action458 + r.width>=cr.width*.68&& 459 + boxLike(el) 496 496 ){ 497 - return; 498 - } 461 + var widthFit= 462 + 1-Math.min( 463 + 1, 464 + Math.abs(cr.width-r.width)/ 465 + Math.max(1,cr.width) 466 + ); 499 499 500 - var clone= 501 - label.cloneNode(true); 468 + var topFit= 469 + 1-Math.min( 470 + 1, 471 + Math.abs(cr.top-r.top)/100 472 + ); 502 502 503 - var cloneNumber= 504 - clone.querySelector( 505 - ":scope > .arsn-area-number" 506 - ); 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; 507 507 508 - var cloneAction= 509 - clone.querySelector( 510 - ":scope > .arsn-area-action" 511 - ); 512 - 513 - if(cloneNumber){ 514 - cloneNumber.remove(); 480 + if(score>bestScore){ 481 + best=el; 482 + bestScore=score; 483 + } 515 515 } 516 516 517 - if(cloneAction){ 518 - cloneAction.remove(); 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 + }); 519 519 } 494 + } 520 520 521 - var titleText= 522 - compactText( 523 - clone.textContent 524 - ); 496 + return best; 497 + } 525 525 526 - if(!titleText){ 527 - return; 528 - } 499 + function groupRows(entries){ 500 + var groups=[]; 529 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" 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 539 539 ); 509 + }) 510 + .forEach(function(entry){ 511 + var group=null; 540 540 541 - titleNode.className= 542 - "sn-area-label-title"; 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 + } 543 543 544 - titleNode.textContent= 545 - titleText; 525 + if(!group){ 526 + group={ 527 + top:entry.rect.top, 528 + entries:[] 529 + }; 530 + groups.push(group); 531 + } 546 546 547 - while(label.firstChild){ 548 - label.removeChild( 549 - label.firstChild 550 - ); 551 - } 533 + group.entries.push(entry); 534 + }); 552 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 - }); 536 + return groups; 595 595 } 596 596 597 - /* ======================================================= 598 - PLACEHOLDER BADGE 599 - ======================================================= */ 539 + function validRow(group){ 540 + if(group.entries.length<2)return false; 600 600 601 - function applyPlaceholderBadge(){ 602 - if(!PLACEHOLDER)return; 542 + var lefts= 543 + group.entries 544 + .map(function(e){return e.rect.left;}) 545 + .sort(function(a,b){return a-b;}); 603 603 604 604 if( 605 - document.querySelector(606 - ".sn-coming-soon-badge"607 - )548 + lefts[lefts.length-1]- 549 + lefts[0]< 550 + 80 608 608 ){ 609 - return; 552 + return false; 610 610 } 611 611 612 - var title= 613 - document.querySelector( 614 - "#document-title" 615 - )|| 616 - document.querySelector( 617 - "h1" 618 - ); 555 + var widths= 556 + group.entries 557 + .map(function(e){return e.rect.width;}) 558 + .filter(function(w){return w>0;}); 619 619 620 - if( !title)return;560 + if(widths.length<2)return false; 621 621 622 - var badge= 623 - document.createElement( 624 - "span" 625 - ); 562 + var minW= 563 + Math.min.apply(Math,widths); 626 626 627 - badge.className=628 - "sn-coming-soon-badge";565 + var maxW= 566 + Math.max.apply(Math,widths); 629 629 630 - badge.textContent= 631 - PLACEHOLDER_LABEL; 632 - 633 - badge.setAttribute( 634 - "aria-label", 635 - PLACEHOLDER_LABEL 568 + return ( 569 + maxW/ 570 + Math.max(1,minW)<= 571 + 1.9 636 636 ); 573 + } 637 637 638 - title.appendChild( 639 - badge 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" 640 640 ); 641 641 } 642 642 643 - /*=======================================================644 - DETAIL PAGE OWN-ACCENT PROPAGATION645 - =======================================================*/595 + function findKnownBar(card){ 596 + var cardRect= 597 + card.getBoundingClientRect(); 646 646 647 - function parseRGB(value){ 648 - var match=String(value||"").match( 649 - /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i 650 - ); 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; 651 651 652 - if(!match)returnnull;609 + var r=el.getBoundingClientRect(); 653 653 654 - return [ 655 - Number(match[1]), 656 - Number(match[2]), 657 - Number(match[3]) 658 - ]; 659 - } 611 + var rel= 612 + r.top- 613 + cardRect.top; 660 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 - ); 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; 667 667 } 668 668 669 - function paletteMatch(cssColor){ 670 - var rgb=parseRGB(cssColor); 631 + function alignKnownBars(cards){ 632 + var rows= 633 + cards.map(function(card){ 634 + var bar= 635 + findKnownBar(card); 671 671 672 - if(! rgb)return null;637 + if(!bar)return null; 673 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 - ]; 639 + var cr= 640 + card.getBoundingClientRect(); 680 680 681 - var b est=null;682 - varbestDistance=Infinity;642 + var br= 643 + bar.getBoundingClientRect(); 683 683 684 - palette.forEach(function(item){ 685 - var d=distance(rgb,item.rgb); 645 + return { 646 + bar:bar, 647 + relativeTop: 648 + br.top- 649 + cr.top 650 + }; 651 + }); 686 686 687 - if(d<bestDistance){ 688 - best=item; 689 - bestDistance=d; 690 - } 691 - }); 653 + if( 654 + rows.some(function(row){ 655 + return !row; 656 + }) 657 + ){ 658 + return false; 659 + } 692 692 693 - return bestDistance<=30 694 - ?best 695 - :null; 696 - } 661 + var target= 662 + Math.max.apply( 663 + Math, 664 + rows.map(function(row){ 665 + return row.relativeTop; 666 + }) 667 + ); 697 697 698 - function propagateDetailAccents(){ 699 - if(PAGE_KIND!=="detail")return; 669 + rows.forEach(function(row){ 670 + var delta= 671 + target- 672 + row.relativeTop; 700 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; 674 + if(delta<=1)return; 708 708 709 - var style=getComputedStyle(el); 676 + saveOriginal( 677 + row.bar, 678 + originalMarginTop, 679 + "margin-top" 680 + ); 710 710 711 - if( 712 - num(style.borderTopWidth)>=2 713 - ){ 714 - var match= 715 - paletteMatch( 716 - style.borderTopColor 717 - ); 682 + var current= 683 + num( 684 + getComputedStyle( 685 + row.bar 686 + ).marginTop 687 + ); 718 718 719 - if(match){ 720 - el.style.setProperty( 721 - "border-left", 722 - "4px solid "+match.hex, 723 - "important" 724 - ); 725 - } 726 - } 727 - }); 689 + row.bar.style.setProperty( 690 + "margin-top", 691 + ( 692 + current+ 693 + delta 694 + )+"px" 695 + ); 728 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" 697 + row.bar.setAttribute( 698 + "data-sn-first-section-aligned", 699 + "7" 742 742 ); 743 - }); 744 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" 702 + sectionManaged.add( 703 + row.bar 757 757 ); 758 758 }); 706 + 707 + return true; 759 759 } 760 760 761 - /* ======================================================= 762 - OVERVIEW SEMANTIC THEME PALETTE 763 - ======================================================= */ 710 + /* ---------- Generic first content after heading ---------- */ 764 764 765 - function smallestThemeHeaders(){ 766 - return Array.from( 767 - root.querySelectorAll( 768 - "div,span,p,strong,h3,h4,h5,h6" 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 + ) 769 769 ) 770 - ).filter(function(el){ 771 - if(!visible(el))return false; 772 - if(!themeFor(el.textContent))return false; 722 + .filter(function(el){ 723 + if(!visible(el,20,8))return false; 773 773 774 - return !Array.from( 775 - el.children||[] 776 - ).some(function(child){ 777 - return !!themeFor( 778 - child.textContent 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 + ) 779 779 ); 739 + }) 740 + .sort(function(a,b){ 741 + return ( 742 + a.getBoundingClientRect().top- 743 + b.getBoundingClientRect().top 744 + ); 780 780 }); 781 - }); 746 + 747 + return rows[0]||null; 782 782 } 783 783 784 - function findOverviewCard(header){ 785 - var node=header.parentElement; 786 - var candidates=[]; 750 + function firstContent(card,h){ 751 + if(!h)return null; 787 787 788 - while(node&&node!==root){ 789 - var rect=node.getBoundingClientRect(); 790 - var style=getComputedStyle(node); 753 + var cr= 754 + card.getBoundingClientRect(); 791 791 792 - var border= 793 - num(style.borderTopWidth)+ 794 - num(style.borderRightWidth)+ 795 - num(style.borderBottomWidth)+ 796 - num(style.borderLeftWidth); 756 + var hr= 757 + h.getBoundingClientRect(); 797 797 798 - if( 799 - rect.width>=220&& 800 - rect.width<=800&& 801 - rect.height>=120&& 802 - border>=1 803 - ){ 804 - candidates.push(node); 805 - } 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 + } 806 806 807 - node=node.parentElement; 808 - } 774 + if(!visible(el,30,8))return false; 809 809 810 - if(!candidates.length)return null; 776 + var text= 777 + String(el.textContent||"") 778 + .replace(/\s+/g," ") 779 + .trim(); 811 811 812 - candidates.sort(function(a,b){ 813 - return ( 814 - b.getBoundingClientRect().height- 815 - a.getBoundingClientRect().height 816 - ); 817 - }); 781 + if(text.length<3)return false; 818 818 819 - return candidates[0]; 820 - } 783 + var r=el.getBoundingClientRect(); 821 821 822 - function rowCandidates(link,card){ 823 - var result=[]; 824 - var cardRect= 825 - card.getBoundingClientRect(); 785 + if( 786 + r.top< 787 + hr.bottom-1 788 + ){ 789 + return false; 790 + } 826 826 827 - var node=link; 792 + if( 793 + r.top-cr.top> 794 + Math.min( 795 + 280, 796 + cr.height*.65 797 + ) 798 + ){ 799 + return false; 800 + } 828 828 829 - while(node&&node!==card){ 830 - if(visible(node)){ 831 - var rect= 832 - node.getBoundingClientRect(); 833 - 834 834 if( 835 - rect.height<=105&& 836 - rect.width>= 837 - cardRect.width*.50&& 838 - rect.width<= 839 - cardRect.width*1.03 803 + r.height> 804 + cr.height*.58 840 840 ){ 841 - re sult.push(node);806 + return false; 842 842 } 843 - } 844 844 845 - node=node.parentElement; 846 - } 809 + return true; 810 + }) 811 + .sort(function(a,b){ 812 + var ar= 813 + a.getBoundingClientRect(); 847 847 848 - r eturnresult;849 - }815 + var br= 816 + b.getBoundingClientRect(); 850 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 861 return ( 862 - num( 863 - getComputedStyle(el) 864 - .borderLeftWidth 865 - )>=1 819 + ar.top-br.top|| 820 + ar.height-br.height 866 866 ); 867 867 }); 868 868 869 - var pool= 870 - bordered.length 871 - ?bordered 872 - :candidates; 824 + return rows[0]||null; 825 + } 873 873 874 - pool.sort(function(a,b){ 875 - var ar= 876 - a.getBoundingClientRect(); 827 + function alignGeneric(cards){ 828 + var rows= 829 + cards.map(function(card){ 830 + var h= 831 + heading(card); 877 877 878 - var br= 879 - b.getBoundingClientRect(); 833 + var c= 834 + firstContent( 835 + card, 836 + h 837 + ); 880 880 881 - return ( 882 - ar.left-br.left|| 883 - br.width-ar.width 884 - ); 885 - }); 839 + if(!h||!c)return null; 886 886 887 - r eturnpool[0]||link;888 - }841 + var cr= 842 + card.getBoundingClientRect(); 889 889 890 - function applyOverviewPalette(){ 891 - if(PAGE_KIND!=="overview"){ 892 - return []; 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; 893 893 } 894 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 - }; 862 + var target= 863 + Math.max.apply( 864 + Math, 865 + rows.map(function(row){ 866 + return row.relativeTop; 909 909 }) 910 - .filter(function(row){ 911 - return !!row.card; 912 - }); 868 + ); 913 913 914 - var unique=[]; 915 - var seenHeaders=new Set(); 870 + rows.forEach(function(row){ 871 + var delta= 872 + target- 873 + row.relativeTop; 916 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 - ); 875 + if(delta<=1)return; 932 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" 877 + saveOriginal( 878 + row.content, 879 + originalMarginTop, 880 + "margin-top" 948 948 ); 949 949 950 - row.el.style.setProperty( 951 - "color", 952 - row.theme.text, 953 - "important" 954 - ); 883 + var current= 884 + num( 885 + getComputedStyle( 886 + row.content 887 + ).marginTop 888 + ); 955 955 956 - row.el.style.setProperty( 957 - "text-align", 958 - "left", 959 - "important" 890 + row.content.style.setProperty( 891 + "margin-top", 892 + ( 893 + current+ 894 + delta 895 + )+"px" 960 960 ); 961 961 962 - row.el.style.setProperty( 963 - "word-spacing", 964 - "normal", 965 - "important" 898 + row.content.setAttribute( 899 + "data-sn-first-content-aligned", 900 + "7" 966 966 ); 967 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 - }); 903 + contentManaged.add( 904 + row.content 905 + ); 1047 1047 }); 1048 1048 1049 - return u nique;908 + return true; 1050 1050 } 1051 1051 1052 - /* ======================================================= 1053 - OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW 1054 - ======================================================= */ 911 + function applyRow(group){ 912 + if(!validRow(group))return false; 1055 1055 1056 - function alignOverviewCards(headers){ 1057 - if( 1058 - PAGE_KIND!=="overview"|| 1059 - window.innerWidth<=MOBILE_MAX 1060 - ){ 1061 - return; 1062 - } 1063 - 1064 1064 var cards=[]; 1065 1065 var seen=new Set(); 1066 1066 1067 - headers.forEach(function(row){1068 - if(!seen.has(r ow.card)){1069 - seen.add(r ow.card);1070 - cards.push(r ow.card);917 + group.entries.forEach(function(entry){ 918 + if(!seen.has(entry.target)){ 919 + seen.add(entry.target); 920 + cards.push(entry.target); 1071 1071 } 1072 1072 }); 1073 1073 1074 - if(cards.length<2){ 1075 - return; 924 + if(cards.length<2)return false; 925 + 926 + if( 927 + !alignKnownBars(cards) 928 + ){ 929 + alignGeneric(cards); 1076 1076 } 1077 1077 1078 - // Group cards by actual top position. 1079 - var groups=[]; 932 + var maxHeight=0; 1080 1080 1081 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); 935 + maxHeight= 936 + Math.max( 937 + maxHeight, 938 + card.getBoundingClientRect().height 939 + ); 1107 1107 }); 1108 1108 1109 - groups.forEach(function(group){1110 - if(group.cards.length<2){1111 - return;1112 - }942 + maxHeight= 943 + Math.ceil( 944 + maxHeight 945 + ); 1113 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 - }); 947 + if(maxHeight<MIN_H)return false; 1131 1131 1132 - return candidates.length 1133 - ?candidates[0] 1134 - :null; 1135 - }); 949 + cards.forEach(function(card){ 950 + saveOriginal( 951 + card, 952 + originalMinHeight, 953 + "min-height" 954 + ); 1136 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 - ); 956 + card.style.setProperty( 957 + "min-height", 958 + maxHeight+"px" 959 + ); 1156 1156 1157 - firstHeaders.forEach(function(row){ 1158 - var relativeTop= 1159 - row.el 1160 - .getBoundingClientRect() 1161 - .top- 1162 - row.card 1163 - .getBoundingClientRect() 1164 - .top; 961 + card.setAttribute( 962 + "data-sn-equal-height-managed", 963 + "7" 964 + ); 1165 1165 1166 - var delta=1167 - targetTop-relativeTop;966 + heightManaged.add(card); 967 + }); 1168 1168 1169 - if(delta>1){ 1170 - saveStyle( 1171 - row.el, 1172 - originalMargin, 1173 - "margin-top" 1174 - ); 969 + return true; 970 + } 1175 1175 1176 - var current= 1177 - num( 1178 - getComputedStyle( 1179 - row.el 1180 - ).marginTop 1181 - ); 972 + function calculate(force){ 973 + if(applying)return; 1182 1182 1183 - row.el.style.setProperty( 1184 - "margin-top", 1185 - ( 1186 - current+delta 1187 - )+"px" 1188 - ); 975 + var width= 976 + Math.round( 977 + window.innerWidth 978 + ); 1189 1189 1190 - row.el.setAttribute( 1191 - "data-sn-master-first-row", 1192 - "1" 1193 - ); 980 + var meaningful= 981 + lastWidth<0|| 982 + Math.abs( 983 + width- 984 + lastWidth 985 + )>= 986 + MIN_WIDTH_CHANGE; 1194 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 1246 if( 1247 - PAGE_KIND!=="detail"|| 1248 - window.innerWidth<=MOBILE_MAX 989 + hasApplied&& 990 + !force&& 991 + !meaningful 1249 1249 ){ 1250 1250 return; 1251 1251 } 1252 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 - ]; 996 + applying=true; 1261 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); 998 + try{ 999 + harmoniseCustomCallouts(); 1270 1270 1271 - if(children.length<2){ 1272 - return; 1001 + if(width<=MOBILE_MAX){ 1002 + if(hasApplied){ 1003 + resetRuntime(); 1273 1273 } 1274 1274 1275 - var groups=[]; 1006 + hasApplied=false; 1007 + lastWidth=width; 1008 + return; 1009 + } 1276 1276 1277 - children.forEach(function(child){ 1278 - var top= 1279 - child 1280 - .getBoundingClientRect() 1281 - .top; 1011 + if(hasApplied){ 1012 + resetRuntime(); 1013 + } 1282 1282 1283 - var group=null; 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 + }); 1284 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 - } 1033 + var touched= 1034 + new Set(); 1295 1295 1296 - if(!group){ 1297 - group={ 1298 - top:top, 1299 - items:[] 1300 - }; 1301 - groups.push(group); 1302 - } 1036 + parents.forEach(function(parent){ 1037 + var entries=[]; 1303 1303 1304 - group.items.push(child); 1305 - }); 1306 - 1307 - groups.forEach(function(group){ 1308 - if(group.items.length<2){ 1039 + Array.from( 1040 + parent.children 1041 + ).forEach(function(child){ 1042 + if( 1043 + !visible( 1044 + child, 1045 + MIN_W, 1046 + MIN_H 1047 + ) 1048 + ){ 1309 1309 return; 1310 1310 } 1311 1311 1312 - var maxHeight=0; 1052 + var target= 1053 + pickTarget(child); 1313 1313 1314 - group.items.forEach(function(item){ 1315 - maxHeight= 1316 - Math.max( 1317 - maxHeight, 1318 - item 1319 - .getBoundingClientRect() 1320 - .height 1321 - ); 1055 + if(!target)return; 1056 + 1057 + entries.push({ 1058 + target:target, 1059 + rect: 1060 + target.getBoundingClientRect() 1322 1322 }); 1062 + }); 1323 1323 1324 - maxHeight= 1325 - Math.ceil(maxHeight); 1064 + groupRows( 1065 + entries 1066 + ).forEach(function(group){ 1067 + if(!validRow(group))return; 1326 1326 1327 - group.items.forEach(function(item){ 1328 - saveStyle( 1329 - item, 1330 - originalHeight, 1331 - "min-height" 1332 - ); 1069 + var targets= 1070 + group.entries.map(function(entry){ 1071 + return entry.target; 1072 + }); 1333 1333 1334 - item.style.setProperty( 1335 - "min-height", 1336 - maxHeight+"px" 1337 - ); 1074 + if( 1075 + !targets.some(function(el){ 1076 + return !touched.has(el); 1077 + }) 1078 + ){ 1079 + return; 1080 + } 1338 1338 1339 - item.setAttribute( 1340 - "data-sn-master-equal-height", 1341 - "1" 1342 - ); 1343 - 1344 - managedHeight.add(item); 1345 - }); 1082 + if(applyRow(group)){ 1083 + targets.forEach(function(el){ 1084 + touched.add(el); 1085 + }); 1086 + } 1346 1346 }); 1347 1347 }); 1348 - }); 1349 - } 1350 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 - } 1090 + lastWidth=width; 1091 + hasApplied=true; 1381 1381 }finally{ 1382 - running=false;1093 + applying=false; 1383 1383 } 1384 1384 } 1385 1385 1386 - function onResize(){1097 + function resize(){ 1387 1387 if(resizeTimer){ 1388 1388 clearTimeout( 1389 1389 resizeTimer ... ... @@ -1394,40 +1394,19 @@ 1394 1394 setTimeout( 1395 1395 function(){ 1396 1396 resizeTimer=0; 1397 - run();1108 + calculate(false); 1398 1398 }, 1399 1399 RESIZE_DEBOUNCE 1400 1400 ); 1401 1401 } 1402 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 - 1114 + function waitImages(){ 1425 1425 var images= 1426 1426 Array.from( 1427 1427 root.querySelectorAll("img") 1428 1428 ); 1429 1429 1430 - await Promise.all(1120 + return Promise.all( 1431 1431 images.map(function(img){ 1432 1432 if(img.complete){ 1433 1433 return Promise.resolve(); ... ... @@ -1452,20 +1452,46 @@ 1452 1452 }); 1453 1453 }) 1454 1454 ); 1145 + } 1455 1455 1456 - run(); 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); 1457 1457 } 1458 1458 1459 - window.addEventListener(1176 + addEventListener( 1460 1460 "resize", 1461 - onResize,1178 + resize, 1462 1462 {passive:true} 1463 1463 ); 1464 1464 1465 - waitForReady();1182 + initial(); 1466 1466 })(); 1467 1467 </script> 1468 1468 1469 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END --> 1470 -{{/html}} 1471 - 1186 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 1187 +{{/html}}\n