Changes for page Service Navigator
Last modified by Veronika Kocher on Thursday, 03 Sep 2026 14:15
From version 22.15
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
To version 22.16
edited by Veronika Kocher
on Thursday, 03 Sep 2026 13:04
on Thursday, 03 Sep 2026 13:04
Change comment:
There is no comment for this version
Summary
-
Page properties (1 modified, 0 added, 0 removed)
Details
- Page properties
-
- Content
-
... ... @@ -285,12 +285,13 @@ 285 285 </div> 286 286 {{/html}} 287 287 288 -\n\n 289 -\n\n{{html clean="false"}} 290 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 288 +{{html clean="false"}} 289 +<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START --> 291 291 292 -<style data-sn-horizontal-box-harmonizer="7"> 293 -/* ---------- Typography: never justify headings ---------- */ 291 +<style data-sn-service-navigator-master="1"> 292 +/* ========================================================= 293 + MASTER TYPOGRAPHY 294 + ========================================================= */ 294 294 #xwikicontent h1, 295 295 #xwikicontent h2, 296 296 #xwikicontent h3, ... ... @@ -312,88 +312,73 @@ 312 312 word-spacing:normal!important; 313 313 } 314 314 315 -/* ---------- Native XWiki semantic callouts ---------- */ 316 -#xwikicontent .box.infomessage, 317 -#xwikicontent .infomessage, 318 -#xwikicontent .box.warningmessage, 319 -#xwikicontent .warningmessage, 320 -#xwikicontent .box.successmessage, 321 -#xwikicontent .successmessage, 322 -#xwikicontent .box.errormessage, 323 -#xwikicontent .errormessage, 324 -#xwikicontent [data-sn-callout-harmonized="1"]{ 316 +/* ========================================================= 317 + COMING SOON / IN VORBEREITUNG 318 + ========================================================= */ 319 +.sn-coming-soon-badge{ 320 + display:inline-block; 321 + vertical-align:middle; 322 + margin-left:10px; 323 + padding:4px 8px; 324 + border-radius:14px; 325 + border:1px solid #efd9cc; 326 + background:#fff4ee; 327 + color:#8a4d36; 328 + font-size:11px; 329 + font-weight:700; 330 + letter-spacing:.055em; 331 + line-height:1.2; 332 + white-space:nowrap; 333 +} 334 + 335 +/* ========================================================= 336 + NATIVE / DETAIL CALLOUT GEOMETRY 337 + Preserve existing backgrounds. 338 + ========================================================= */ 339 +#xwikicontent .arsn-info, 340 +#xwikicontent .dmp-info, 341 +#xwikicontent .ido-info, 342 +#xwikicontent .pp-info, 343 +#xwikicontent .infomessage{ 325 325 box-sizing:border-box!important; 326 - border-radius:8px!important; 327 - border-top:1px solid rgba(0,0,0,.08)!important; 328 - border-right:1px solid rgba(0,0,0,.08)!important; 329 - border-bottom:1px solid rgba(0,0,0,.08)!important; 330 - border-left:4px solid var(--sn-callout-accent,#21b6d7)!important; 331 - padding:14px 16px!important; 345 + border-left:4px solid #21b6d7!important; 346 + border-radius:8px; 332 332 text-align:left!important; 333 - text-justify:auto!important; 334 334 word-spacing:normal!important; 335 - box-shadow:none!important; 336 336 } 337 337 338 -#xwikicontent .box.infomessage, 339 -#xwikicontent .infomessage{ 340 - --sn-callout-accent:#21b6d7; 341 - background:#eaf7fb!important; 342 -} 343 - 344 -#xwikicontent .box.warningmessage, 345 -#xwikicontent .warningmessage{ 346 - --sn-callout-accent:#f0aa00; 347 - background:#fff8e7!important; 348 -} 349 - 350 -#xwikicontent .box.successmessage, 351 -#xwikicontent .successmessage{ 352 - --sn-callout-accent:#38b76a; 353 - background:#edf9f1!important; 354 -} 355 - 356 -#xwikicontent .box.errormessage, 351 +#xwikicontent .arsn-warn, 352 +#xwikicontent .dmp-warn, 353 +#xwikicontent .ido-warn, 354 +#xwikicontent .pp-warn, 355 +#xwikicontent .warn, 356 +#xwikicontent .warning, 357 +#xwikicontent .warningmessage, 357 357 #xwikicontent .errormessage{ 358 - --sn-callout-accent:#e94b13; 359 - background:#fff1ec!important; 359 + box-sizing:border-box!important; 360 + border-left:4px solid #e94b13!important; 361 + border-radius:8px; 362 + text-align:left!important; 363 + word-spacing:normal!important; 360 360 } 361 361 362 -#xwikicontent [data-sn-callout-harmonized="1"] > :first-child, 363 -#xwikicontent .infomessage > :first-child, 364 -#xwikicontent .warningmessage > :first-child, 365 -#xwikicontent .successmessage > :first-child, 366 -#xwikicontent .errormessage > :first-child{ 367 - margin-top:0!important; 368 -} 369 - 370 -#xwikicontent [data-sn-callout-harmonized="1"] > :last-child, 371 -#xwikicontent .infomessage > :last-child, 372 -#xwikicontent .warningmessage > :last-child, 373 -#xwikicontent .successmessage > :last-child, 374 -#xwikicontent .errormessage > :last-child{ 375 - margin-bottom:0!important; 376 -} 377 - 378 -#xwikicontent [data-sn-equal-height-managed], 379 -#xwikicontent [data-sn-first-section-aligned], 380 -#xwikicontent [data-sn-first-content-aligned]{ 366 +[data-sn-master-equal-height], 367 +[data-sn-master-first-row]{ 381 381 box-sizing:border-box; 382 382 } 383 383 </style> 384 384 385 -<script data-sn- horizontal-box-harmonizer="7">372 +<script data-sn-service-navigator-master="1"> 386 386 (function(){ 387 387 "use strict"; 388 388 376 + var PAGE_KIND="overview"; 377 + var PLACEHOLDER=false; 378 + var PLACEHOLDER_LABEL="COMING SOON"; 379 + 389 389 var MOBILE_MAX=767; 390 390 var ROW_TOLERANCE=6; 391 - var MIN_W=150; 392 - var MIN_H=36; 393 - var MAX_PARENT_CHILDREN=18; 394 - var SEARCH_DEPTH=5; 395 395 var RESIZE_DEBOUNCE=220; 396 - var MIN_WIDTH_CHANGE=2; 397 397 398 398 var root= 399 399 document.getElementById("xwikicontent")|| ... ... @@ -403,142 +403,114 @@ 403 403 404 404 if(!root)return; 405 405 406 - var heightManaged=new Set(); 407 - var sectionManaged=new Set(); 408 - var contentManaged=new Set(); 392 + var managedHeight=new Set(); 393 + var managedMargin=new Set(); 394 + var originalHeight=new WeakMap(); 395 + var originalMargin=new WeakMap(); 409 409 410 - var originalMinHeight=new WeakMap(); 411 - var originalMarginTop=new WeakMap(); 412 - 413 413 var resizeTimer=0; 414 - var lastWidth=-1; 415 - var hasApplied=false; 416 - var applying=false; 398 + var running=false; 417 417 418 - function num(v){ 419 - var n=parseFloat(v); 420 - return Number.isFinite(n)?n:0; 421 - } 422 - 423 - function visible(el,minW,minH){ 424 - if(!el||el.nodeType!==1)return false; 425 - 426 - var s=getComputedStyle(el); 427 - 428 - if( 429 - s.display==="none"|| 430 - s.visibility==="hidden"|| 431 - Number(s.opacity)===0 432 - ){ 433 - return false; 400 + var THEMES=[ 401 + { 402 + name:"BLUE", 403 + accent:"#21b6d7", 404 + bg:"#eaf7fb", 405 + text:"#315d68", 406 + labels:[ 407 + "HIER STARTEN", 408 + "ENTSCHEIDEN", 409 + "ÜBERPRÜFEN & ANPASSEN", 410 + "START HERE", 411 + "DECIDE", 412 + "REVIEW & ADAPT" 413 + ] 414 + }, 415 + { 416 + name:"RED", 417 + accent:"#e94b13", 418 + bg:"#fff1ec", 419 + text:"#8a4d36", 420 + labels:[ 421 + "PLANEN & ORGANISIEREN", 422 + "ORGANISIEREN & DOKUMENTIEREN", 423 + "PUBLIZIEREN & PRÄSENTIEREN", 424 + "PLAN & ORGANISE", 425 + "PLAN & ORGANIZE", 426 + "ORGANISE & DOCUMENT", 427 + "ORGANIZE & DOCUMENT", 428 + "PUBLISH & PRESENT" 429 + ] 430 + }, 431 + { 432 + name:"YELLOW", 433 + accent:"#f0aa00", 434 + bg:"#fff8e7", 435 + text:"#785b17", 436 + labels:[ 437 + "SCHÜTZEN & KLÄREN", 438 + "STANDARDISIEREN & IDENTIFIZIEREN", 439 + "ÖFFNEN, NACHNUTZEN & AUFFINDBAR MACHEN", 440 + "PROTECT & CLARIFY", 441 + "STANDARDISE & IDENTIFY", 442 + "STANDARDIZE & IDENTIFY", 443 + "OPEN, REUSE & MAKE FINDABLE" 444 + ] 445 + }, 446 + { 447 + name:"GREEN", 448 + accent:"#38b76a", 449 + bg:"#edf9f1", 450 + text:"#3f7451", 451 + labels:[ 452 + "INFRASTRUKTUR EINRICHTEN", 453 + "INFRASTRUKTUR & ZUSAMMENARBEIT EINRICHTEN", 454 + "SPEICHERN & ZUGRIFF STEUERN", 455 + "REPOSITORIUM, ERHALTEN & ÜBERGEBEN", 456 + "SET UP INFRASTRUCTURE", 457 + "SET UP INFRASTRUCTURE & COLLABORATION", 458 + "STORE & CONTROL ACCESS", 459 + "REPOSITORY, PRESERVE & HAND OVER" 460 + ] 434 434 } 462 + ]; 435 435 436 - var r=el.getBoundingClientRect(); 437 - 438 - return ( 439 - r.width>=(minW||1)&& 440 - r.height>=(minH||1) 441 - ); 464 + function num(value){ 465 + var n=parseFloat(value); 466 + return Number.isFinite(n)?n:0; 442 442 } 443 443 444 - function normal izeText(text){445 - return String( text||"")469 + function norm(value){ 470 + return String(value||"") 446 446 .replace(/\s+/g," ") 447 447 .trim() 448 448 .toUpperCase(); 449 449 } 450 450 451 - function excluded(el){ 452 - return ( 453 - !el.matches|| 454 - el.matches( 455 - "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]" 456 - ) 457 - ); 458 - } 476 + function visible(el){ 477 + if(!el||el.nodeType!==1)return false; 459 459 460 - /* ---------- Custom coloured callouts ---------- */ 479 + var style=getComputedStyle(el); 480 + var rect=el.getBoundingClientRect(); 461 461 462 - function nativeCallout(el){ 463 - var c= 464 - typeof el.className==="string" 465 - ? el.className.toLowerCase() 466 - : ""; 467 - 468 468 return ( 469 - /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c) 483 + style.display!=="none"&& 484 + style.visibility!=="hidden"&& 485 + rect.width>20&& 486 + rect.height>4 470 470 ); 471 471 } 472 472 473 - function customCallout(el){ 474 - if(!visible(el,220,42)||excluded(el))return false; 475 - 476 - var r=el.getBoundingClientRect(); 477 - 478 - if(r.height>520)return false; 479 - 480 - var s=getComputedStyle(el); 481 - 482 - var bg= 483 - s.backgroundColor&& 484 - s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 485 - s.backgroundColor!=="transparent"&& 486 - s.backgroundColor!=="rgb(255, 255, 255)"; 487 - 488 - var left= 489 - num(s.borderLeftWidth); 490 - 491 - return ( 492 - bg&& 493 - left>=2 494 - ); 495 - } 496 - 497 - function harmoniseCustomCallouts(){ 498 - Array.from( 499 - root.querySelectorAll( 500 - "div,aside,section" 501 - ) 502 - ).forEach(function(el){ 503 - if(nativeCallout(el))return; 504 - if(!customCallout(el))return; 505 - 506 - var s=getComputedStyle(el); 507 - 508 - el.setAttribute( 509 - "data-sn-callout-harmonized", 510 - "1" 511 - ); 512 - 513 - if( 514 - s.borderLeftColor 515 - ){ 516 - el.style.setProperty( 517 - "--sn-callout-accent", 518 - s.borderLeftColor 519 - ); 520 - } 521 - }); 522 - } 523 - 524 - /* ---------- Restore only values V7 itself changed ---------- */ 525 - 526 - function saveOriginal(el,map,property){ 490 + function saveStyle(el,map,property){ 527 527 if(map.has(el))return; 528 528 529 529 map.set(el,{ 530 - value: 531 - el.style.getPropertyValue( 532 - property 533 - ), 534 - priority: 535 - el.style.getPropertyPriority( 536 - property 537 - ) 494 + value:el.style.getPropertyValue(property), 495 + priority:el.style.getPropertyPriority(property) 538 538 }); 539 539 } 540 540 541 - function restore Original(el,map,property){499 + function restoreStyle(el,map,property){ 542 542 var original=map.get(el); 543 543 544 544 if(original&&original.value){ ... ... @@ -548,770 +548,845 @@ 548 548 original.priority||"" 549 549 ); 550 550 }else{ 551 - el.style.removeProperty( 552 - property 553 - ); 509 + el.style.removeProperty(property); 554 554 } 555 555 } 556 556 557 557 function resetRuntime(){ 558 - heightManaged.forEach(function(el){559 - restore Original(514 + managedHeight.forEach(function(el){ 515 + restoreStyle( 560 560 el, 561 - original MinHeight,517 + originalHeight, 562 562 "min-height" 563 563 ); 564 - 565 565 el.removeAttribute( 566 - "data-sn-equal-height -managed"521 + "data-sn-master-equal-height" 567 567 ); 568 568 }); 569 569 570 - sectionManaged.forEach(function(el){571 - restore Original(525 + managedMargin.forEach(function(el){ 526 + restoreStyle( 572 572 el, 573 - originalMargin Top,528 + originalMargin, 574 574 "margin-top" 575 575 ); 576 - 577 577 el.removeAttribute( 578 - "data-sn-first- section-aligned"532 + "data-sn-master-first-row" 579 579 ); 580 580 }); 581 581 582 - contentManaged.forEach(function(el){ 583 - restoreOriginal( 584 - el, 585 - originalMarginTop, 586 - "margin-top" 587 - ); 588 - 589 - el.removeAttribute( 590 - "data-sn-first-content-aligned" 591 - ); 592 - }); 593 - 594 - heightManaged.clear(); 595 - sectionManaged.clear(); 596 - contentManaged.clear(); 536 + managedHeight.clear(); 537 + managedMargin.clear(); 597 597 } 598 598 599 - /* ---------- Card detection ---------- */ 540 + function themeFor(text){ 541 + var value=norm(text); 600 600 601 - function namedLikeBox(el){ 602 - var c= 603 - typeof el.className==="string" 604 - ? el.className 605 - : ""; 543 + for(var i=0;i<THEMES.length;i++){ 544 + for(var j=0;j<THEMES[i].labels.length;j++){ 545 + var label=THEMES[i].labels[j]; 606 606 607 - return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c); 547 + if( 548 + value===label|| 549 + value.indexOf(label+" ")===0|| 550 + value.indexOf(label+" -")===0|| 551 + value.indexOf(label+" ·")===0 552 + ){ 553 + return THEMES[i]; 554 + } 555 + } 556 + } 557 + 558 + return null; 608 608 } 609 609 610 - function boxLike(el){ 561 + /* ======================================================= 562 + PLACEHOLDER BADGE 563 + ======================================================= */ 564 + 565 + function applyPlaceholderBadge(){ 566 + if(!PLACEHOLDER)return; 567 + 611 611 if( 612 - !visible(el,MIN_W,MIN_H)|| 613 - excluded(el) 569 + document.querySelector( 570 + ".sn-coming-soon-badge" 571 + ) 614 614 ){ 615 - return false;573 + return; 616 616 } 617 617 618 - var s=getComputedStyle(el); 619 - var r=el.getBoundingClientRect(); 576 + var title= 577 + document.querySelector( 578 + "#document-title" 579 + )|| 580 + document.querySelector( 581 + "h1" 582 + ); 620 620 621 - var border= 622 - num(s.borderTopWidth)+ 623 - num(s.borderRightWidth)+ 624 - num(s.borderBottomWidth)+ 625 - num(s.borderLeftWidth); 584 + if(!title)return; 626 626 627 - var radius=Math.max( 628 - num(s.borderTopLeftRadius), 629 - num(s.borderTopRightRadius), 630 - num(s.borderBottomLeftRadius), 631 - num(s.borderBottomRightRadius) 586 + var badge= 587 + document.createElement( 588 + "span" 589 + ); 590 + 591 + badge.className= 592 + "sn-coming-soon-badge"; 593 + 594 + badge.textContent= 595 + PLACEHOLDER_LABEL; 596 + 597 + badge.setAttribute( 598 + "aria-label", 599 + PLACEHOLDER_LABEL 632 632 ); 633 633 634 - var bg=635 - s.backgroundColor&&636 - s.backgroundColor!=="rgba(0, 0, 0, 0)"&&637 - s.backgroundColor!=="transparent";602 + title.appendChild( 603 + badge 604 + ); 605 + } 638 638 639 - var shadow=640 - s.boxShadow&&641 - s.boxShadow!=="none";607 + /* ======================================================= 608 + DETAIL PAGE OWN-ACCENT PROPAGATION 609 + ======================================================= */ 642 642 643 - return ( 644 - namedLikeBox(el)|| 645 - border>=1|| 646 - (bg&&radius>=3)|| 647 - (shadow&&r.width>=180) 611 + function parseRGB(value){ 612 + var match=String(value||"").match( 613 + /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i 648 648 ); 615 + 616 + if(!match)return null; 617 + 618 + return [ 619 + Number(match[1]), 620 + Number(match[2]), 621 + Number(match[3]) 622 + ]; 649 649 } 650 650 651 - function pickTarget(child){ 652 - if(!visible(child,MIN_W,MIN_H))return null; 625 + function distance(a,b){ 626 + return Math.sqrt( 627 + Math.pow(a[0]-b[0],2)+ 628 + Math.pow(a[1]-b[1],2)+ 629 + Math.pow(a[2]-b[2],2) 630 + ); 631 + } 653 653 654 - if(boxLike(child))return child; 633 + function paletteMatch(cssColor){ 634 + var rgb=parseRGB(cssColor); 655 655 656 - var cr=child.getBoundingClientRect(); 657 - var q=[]; 636 + if(!rgb)return null; 658 658 659 - Array.from(child.children||[]).forEach(function(el){ 660 - q.push({el:el,depth:1}); 661 - }); 638 + var palette=[ 639 + {hex:"#21b6d7",rgb:[33,182,215]}, 640 + {hex:"#e94b13",rgb:[233,75,19]}, 641 + {hex:"#f0aa00",rgb:[240,170,0]}, 642 + {hex:"#38b76a",rgb:[56,183,106]} 643 + ]; 662 662 663 663 var best=null; 664 - var best Score=-Infinity;646 + var bestDistance=Infinity; 665 665 666 - while(q.length){ 667 - var item=q.shift(); 668 - var el=item.el; 648 + palette.forEach(function(item){ 649 + var d=distance(rgb,item.rgb); 669 669 670 - if(!visible(el,MIN_W,MIN_H))continue; 651 + if(d<bestDistance){ 652 + best=item; 653 + bestDistance=d; 654 + } 655 + }); 671 671 672 - var r=el.getBoundingClientRect(); 657 + return bestDistance<=30 658 + ?best 659 + :null; 660 + } 673 673 662 + function propagateDetailAccents(){ 663 + if(PAGE_KIND!=="detail")return; 664 + 665 + Array.from( 666 + root.querySelectorAll( 667 + ".arsn-call,.dmp-call,.ido-call,.pp-call,"+ 668 + ".arsn-source,.dmp-source,.ido-source,.pp-source" 669 + ) 670 + ).forEach(function(el){ 671 + if(!visible(el))return; 672 + 673 + var style=getComputedStyle(el); 674 + 674 674 if( 675 - r.width>=cr.width*.68&& 676 - boxLike(el) 676 + num(style.borderTopWidth)>=2 677 677 ){ 678 - var widthFit= 679 - 1-Math.min( 680 - 1, 681 - Math.abs(cr.width-r.width)/ 682 - Math.max(1,cr.width) 678 + var match= 679 + paletteMatch( 680 + style.borderTopColor 683 683 ); 684 684 685 - var topFit= 686 - 1-Math.min( 687 - 1, 688 - Math.abs(cr.top-r.top)/100 683 + if(match){ 684 + el.style.setProperty( 685 + "border-left", 686 + "4px solid "+match.hex, 687 + "important" 689 689 ); 690 - 691 - var score= 692 - widthFit*6+ 693 - topFit*3+ 694 - Math.min(r.height,900)/450+ 695 - Math.min(r.width*r.height,900000)/900000; 696 - 697 - if(score>bestScore){ 698 - best=el; 699 - bestScore=score; 700 700 } 701 701 } 691 + }); 702 702 703 - if(item.depth<SEARCH_DEPTH){ 704 - Array.from(el.children||[]).forEach(function(next){ 705 - q.push({ 706 - el:next, 707 - depth:item.depth+1 708 - }); 709 - }); 710 - } 711 - } 693 + // Warning families: explicit safety override. 694 + Array.from( 695 + root.querySelectorAll( 696 + ".arsn-warn,.dmp-warn,.ido-warn,.pp-warn,"+ 697 + ".warn,.warning,.warningmessage,.errormessage" 698 + ) 699 + ).forEach(function(el){ 700 + if(!visible(el))return; 712 712 713 - return best; 714 - } 702 + el.style.setProperty( 703 + "border-left", 704 + "4px solid #e94b13", 705 + "important" 706 + ); 707 + }); 715 715 716 - function groupRows(entries){ 717 - var groups=[]; 709 + // Info families: explicit orientation override. 710 + Array.from( 711 + root.querySelectorAll( 712 + ".arsn-info,.dmp-info,.ido-info,.pp-info,.infomessage" 713 + ) 714 + ).forEach(function(el){ 715 + if(!visible(el))return; 718 718 719 - entries 720 - .slice() 721 - .sort(function(a,b){ 722 - return ( 723 - a.rect.top-b.rect.top|| 724 - a.rect.left-b.rect.left 725 - ); 726 - }) 727 - .forEach(function(entry){ 728 - var group=null; 717 + el.style.setProperty( 718 + "border-left", 719 + "4px solid #21b6d7", 720 + "important" 721 + ); 722 + }); 723 + } 729 729 730 - for(var i=0;i<groups.length;i++){ 731 - if( 732 - Math.abs( 733 - groups[i].top- 734 - entry.rect.top 735 - )<=ROW_TOLERANCE 736 - ){ 737 - group=groups[i]; 738 - break; 739 - } 740 - } 725 + /* ======================================================= 726 + OVERVIEW SEMANTIC THEME PALETTE 727 + ======================================================= */ 741 741 742 - if(!group){ 743 - group={ 744 - top:entry.rect.top, 745 - entries:[] 746 - }; 747 - groups.push(group); 748 - } 729 + function smallestThemeHeaders(){ 730 + return Array.from( 731 + root.querySelectorAll( 732 + "div,span,p,strong,h3,h4,h5,h6" 733 + ) 734 + ).filter(function(el){ 735 + if(!visible(el))return false; 736 + if(!themeFor(el.textContent))return false; 749 749 750 - group.entries.push(entry); 738 + return !Array.from( 739 + el.children||[] 740 + ).some(function(child){ 741 + return !!themeFor( 742 + child.textContent 743 + ); 751 751 }); 752 - 753 - return groups; 745 + }); 754 754 } 755 755 756 - function validRow(group){ 757 - if(group.entries.length<2)return false; 748 + function findOverviewCard(header){ 749 + var node=header.parentElement; 750 + var candidates=[]; 758 758 759 - var lefts= 760 - group.entries 761 - .map(function(e){return e.rect.left;}) 762 - .sort(function(a,b){return a-b;}); 752 + while(node&&node!==root){ 753 + var rect=node.getBoundingClientRect(); 754 + var style=getComputedStyle(node); 763 763 764 - if( 765 - lefts[lefts.length-1]- 766 - lefts[0]< 767 - 80 768 - ){ 769 - return false; 770 - } 756 + var border= 757 + num(style.borderTopWidth)+ 758 + num(style.borderRightWidth)+ 759 + num(style.borderBottomWidth)+ 760 + num(style.borderLeftWidth); 771 771 772 - var widths= 773 - group.entries 774 - .map(function(e){return e.rect.width;}) 775 - .filter(function(w){return w>0;}); 762 + if( 763 + rect.width>=220&& 764 + rect.width<=800&& 765 + rect.height>=120&& 766 + border>=1 767 + ){ 768 + candidates.push(node); 769 + } 776 776 777 - if(widths.length<2)return false; 771 + node=node.parentElement; 772 + } 778 778 779 - var minW= 780 - Math.min.apply(Math,widths); 774 + if(!candidates.length)return null; 781 781 782 - var maxW= 783 - Math.max.apply(Math,widths); 784 - 785 - return ( 786 - maxW/ 787 - Math.max(1,minW)<= 788 - 1.9 789 - ); 790 - } 791 - 792 - /* ---------- Known ARSN first section bars ---------- */ 793 - 794 - function knownBar(el){ 795 - var text= 796 - normalizeText( 797 - el.textContent 776 + candidates.sort(function(a,b){ 777 + return ( 778 + b.getBoundingClientRect().height- 779 + a.getBoundingClientRect().height 798 798 ); 781 + }); 799 799 800 - return ( 801 - text==="HIER STARTEN"|| 802 - text==="ORGANISIEREN & DOKUMENTIEREN"|| 803 - text==="ENTSCHEIDEN"|| 804 - text==="START HERE"|| 805 - text==="GET STARTED"|| 806 - text==="ORGANISE & DOCUMENT"|| 807 - text==="ORGANIZE & DOCUMENT"|| 808 - text==="DECIDE" 809 - ); 783 + return candidates[0]; 810 810 } 811 811 812 - function findKnownBar(card){ 786 + function rowCandidates(link,card){ 787 + var result=[]; 813 813 var cardRect= 814 814 card.getBoundingClientRect(); 815 815 816 - var rows= 817 - Array.from( 818 - card.querySelectorAll( 819 - "div,p,span,strong,h3,h4,h5,h6" 820 - ) 821 - ) 822 - .filter(function(el){ 823 - if(!visible(el,20,6))return false; 824 - if(!knownBar(el))return false; 791 + var node=link; 825 825 826 - var r=el.getBoundingClientRect(); 793 + while(node&&node!==card){ 794 + if(visible(node)){ 795 + var rect= 796 + node.getBoundingClientRect(); 827 827 828 - var rel= 829 - r.top- 830 - cardRect.top; 798 + if( 799 + rect.height<=105&& 800 + rect.width>= 801 + cardRect.width*.50&& 802 + rect.width<= 803 + cardRect.width*1.03 804 + ){ 805 + result.push(node); 806 + } 807 + } 831 831 809 + node=node.parentElement; 810 + } 811 + 812 + return result; 813 + } 814 + 815 + function chooseOuterRow( 816 + candidates, 817 + link 818 + ){ 819 + if(!candidates.length){ 820 + return link; 821 + } 822 + 823 + var bordered= 824 + candidates.filter(function(el){ 832 832 return ( 833 - rel>=35&& 834 - rel<= 835 - cardRect.height*.75 826 + num( 827 + getComputedStyle(el) 828 + .borderLeftWidth 829 + )>=1 836 836 ); 837 - }) 838 - .sort(function(a,b){ 839 - return ( 840 - a.getBoundingClientRect().top- 841 - b.getBoundingClientRect().top 842 - ); 843 843 }); 844 844 845 - return rows[0]||null; 846 - } 833 + var pool= 834 + bordered.length 835 + ?bordered 836 + :candidates; 847 847 848 - function alignKnownBars(cards){ 849 - var rows= 850 - cards.map(function(card){ 851 - var bar= 852 - findKnownBar(card); 838 + pool.sort(function(a,b){ 839 + var ar= 840 + a.getBoundingClientRect(); 853 853 854 - if(!bar)return null; 842 + var br= 843 + b.getBoundingClientRect(); 855 855 856 - var cr= 857 - card.getBoundingClientRect(); 845 + return ( 846 + ar.left-br.left|| 847 + br.width-ar.width 848 + ); 849 + }); 858 858 859 - varbr=860 - bar.getBoundingClientRect();851 + return pool[0]||link; 852 + } 861 861 862 - return { 863 - bar:bar, 864 - relativeTop: 865 - br.top- 866 - cr.top 867 - }; 868 - }); 869 - 870 - if( 871 - rows.some(function(row){ 872 - return !row; 873 - }) 874 - ){ 875 - return false; 854 + function applyOverviewPalette(){ 855 + if(PAGE_KIND!=="overview"){ 856 + return []; 876 876 } 877 877 878 - var target= 879 - Math.max.apply( 880 - Math, 881 - rows.map(function(row){ 882 - return row.relativeTop; 859 + var headers= 860 + smallestThemeHeaders() 861 + .map(function(el){ 862 + return { 863 + el:el, 864 + theme: 865 + themeFor( 866 + el.textContent 867 + ), 868 + card: 869 + findOverviewCard( 870 + el 871 + ) 872 + }; 883 883 }) 884 - ); 874 + .filter(function(row){ 875 + return !!row.card; 876 + }); 885 885 886 - rows.forEach(function(row){ 887 - var delta= 888 - target- 889 - row.relativeTop; 878 + var unique=[]; 879 + var seenHeaders=new Set(); 890 890 891 - if(delta<=1)return; 881 + headers.forEach(function(row){ 882 + var key= 883 + row.theme.name+ 884 + "|"+ 885 + Math.round( 886 + row.card 887 + .getBoundingClientRect() 888 + .left 889 + )+ 890 + "|"+ 891 + Math.round( 892 + row.el 893 + .getBoundingClientRect() 894 + .top 895 + ); 892 892 893 - sa veOriginal(894 - r ow.bar,895 - originalMarginTop,896 - "margin-top"897 - );897 + if(!seenHeaders.has(key)){ 898 + seenHeaders.add(key); 899 + unique.push(row); 900 + } 901 + }); 898 898 899 - var current= 900 - num( 901 - getComputedStyle( 902 - row.bar 903 - ).marginTop 904 - ); 903 + unique.forEach(function(row){ 904 + var headerRect= 905 + row.el 906 + .getBoundingClientRect(); 905 905 906 - row.bar.style.setProperty( 907 - "margin-top", 908 - ( 909 - current+ 910 - delta 911 - )+"px" 908 + row.el.style.setProperty( 909 + "background", 910 + row.theme.bg, 911 + "important" 912 912 ); 913 913 914 - row.bar.setAttribute( 915 - "data-sn-first-section-aligned", 916 - "7" 914 + row.el.style.setProperty( 915 + "color", 916 + row.theme.text, 917 + "important" 917 917 ); 918 918 919 - sectionManaged.add( 920 - row.bar 920 + row.el.style.setProperty( 921 + "text-align", 922 + "left", 923 + "important" 921 921 ); 922 - }); 923 923 924 - return true; 925 - } 926 + row.el.style.setProperty( 927 + "word-spacing", 928 + "normal", 929 + "important" 930 + ); 926 926 927 - /* ---------- Generic first content after heading ---------- */ 932 + var later= 933 + unique 934 + .filter(function(other){ 935 + return ( 936 + other.card===row.card&& 937 + other.el 938 + .getBoundingClientRect() 939 + .top> 940 + headerRect.top+2 941 + ); 942 + }) 943 + .sort(function(a,b){ 944 + return ( 945 + a.el 946 + .getBoundingClientRect() 947 + .top- 948 + b.el 949 + .getBoundingClientRect() 950 + .top 951 + ); 952 + }); 928 928 929 - function heading(card){ 930 - var cr= 931 - card.getBoundingClientRect(); 954 + var stopTop= 955 + later.length 956 + ?later[0].el 957 + .getBoundingClientRect() 958 + .top 959 + :Infinity; 932 932 933 - var rows= 934 934 Array.from( 935 - card.querySelectorAll( 936 - "h1,h2,h3,h4,h5,h6,.box-title,[role=heading]" 937 - ) 938 - ) 939 - .filter(function(el){ 940 - if(!visible(el,20,8))return false; 962 + row.card.querySelectorAll("a") 963 + ).forEach(function(link){ 964 + if(!visible(link))return; 941 941 942 - var r=el.getBoundingClientRect(); 966 + var rect= 967 + link.getBoundingClientRect(); 943 943 944 - var rel= 945 - r.top- 946 - cr.top; 947 - 948 - return ( 949 - rel>=0&& 950 - rel<= 951 - Math.min( 952 - 160, 953 - cr.height*.45 954 - ) 955 - ); 956 - }) 957 - .sort(function(a,b){ 958 - return ( 959 - a.getBoundingClientRect().top- 960 - b.getBoundingClientRect().top 961 - ); 962 - }); 963 - 964 - return rows[0]||null; 965 - } 966 - 967 - function firstContent(card,h){ 968 - if(!h)return null; 969 - 970 - var cr= 971 - card.getBoundingClientRect(); 972 - 973 - var hr= 974 - h.getBoundingClientRect(); 975 - 976 - var rows= 977 - Array.from( 978 - card.querySelectorAll( 979 - "p,div,ul,ol,dl,blockquote" 980 - ) 981 - ) 982 - .filter(function(el){ 983 983 if( 984 - el===h|| 985 - h.contains(el)|| 986 - el.contains(h) 970 + rect.top<= 971 + headerRect.bottom-2|| 972 + rect.top>= 973 + stopTop-2 987 987 ){ 988 - return false;975 + return; 989 989 } 990 990 991 - if(!visible(el,30,8))return false; 978 + var candidates= 979 + rowCandidates( 980 + link, 981 + row.card 982 + ); 992 992 993 - var text= 994 - String(el.textContent||"") 995 - .replace(/\s+/g," ") 996 - .trim(); 984 + var target= 985 + chooseOuterRow( 986 + candidates, 987 + link 988 + ); 997 997 998 - if(text.length<3)return false; 990 + candidates.forEach(function(el){ 991 + el.style.setProperty( 992 + "border-left", 993 + "0 solid transparent", 994 + "important" 995 + ); 996 + }); 999 999 1000 - var r=el.getBoundingClientRect(); 998 + target.style.setProperty( 999 + "border-left", 1000 + "3px solid "+ 1001 + row.theme.accent, 1002 + "important" 1003 + ); 1001 1001 1002 - if( 1003 - r.top< 1004 - hr.bottom-1 1005 - ){ 1006 - return false; 1007 - } 1008 - 1009 - if( 1010 - r.top-cr.top> 1011 - Math.min( 1012 - 280, 1013 - cr.height*.65 1014 - ) 1015 - ){ 1016 - return false; 1017 - } 1018 - 1019 - if( 1020 - r.height> 1021 - cr.height*.58 1022 - ){ 1023 - return false; 1024 - } 1025 - 1026 - return true; 1027 - }) 1028 - .sort(function(a,b){ 1029 - var ar= 1030 - a.getBoundingClientRect(); 1031 - 1032 - var br= 1033 - b.getBoundingClientRect(); 1034 - 1035 - return ( 1036 - ar.top-br.top|| 1037 - ar.height-br.height 1005 + target.style.setProperty( 1006 + "box-sizing", 1007 + "border-box", 1008 + "important" 1038 1038 ); 1039 1039 }); 1011 + }); 1040 1040 1041 - return rows[0]||null;1013 + return unique; 1042 1042 } 1043 1043 1044 - function alignGeneric(cards){ 1045 - var rows= 1046 - cards.map(function(card){ 1047 - var h= 1048 - heading(card); 1016 + /* ======================================================= 1017 + OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW 1018 + ======================================================= */ 1049 1049 1050 - var c= 1051 - firstContent( 1052 - card, 1053 - h 1054 - ); 1055 - 1056 - if(!h||!c)return null; 1057 - 1058 - var cr= 1059 - card.getBoundingClientRect(); 1060 - 1061 - var rr= 1062 - c.getBoundingClientRect(); 1063 - 1064 - return { 1065 - content:c, 1066 - relativeTop: 1067 - rr.top-cr.top 1068 - }; 1069 - }); 1070 - 1020 + function alignOverviewCards(headers){ 1071 1071 if( 1072 - rows.some(function(row){ 1073 - return !row; 1074 - }) 1022 + PAGE_KIND!=="overview"|| 1023 + window.innerWidth<=MOBILE_MAX 1075 1075 ){ 1076 - return false;1025 + return; 1077 1077 } 1078 1078 1079 - var target= 1080 - Math.max.apply( 1081 - Math, 1082 - rows.map(function(row){ 1083 - return row.relativeTop; 1084 - }) 1085 - ); 1028 + var cards=[]; 1029 + var seen=new Set(); 1086 1086 1087 - rows.forEach(function(row){ 1088 - var delta= 1089 - target- 1090 - row.relativeTop; 1031 + headers.forEach(function(row){ 1032 + if(!seen.has(row.card)){ 1033 + seen.add(row.card); 1034 + cards.push(row.card); 1035 + } 1036 + }); 1091 1091 1092 - if(delta<=1)return; 1038 + if(cards.length<2){ 1039 + return; 1040 + } 1093 1093 1094 - saveOriginal( 1095 - row.content, 1096 - originalMarginTop, 1097 - "margin-top" 1098 - ); 1042 + // Group cards by actual top position. 1043 + var groups=[]; 1099 1099 1100 - var current= 1101 - num( 1102 - getComputedStyle( 1103 - row.content 1104 - ).marginTop 1105 - ); 1045 + cards.forEach(function(card){ 1046 + var top= 1047 + card.getBoundingClientRect().top; 1106 1106 1107 - row.content.style.setProperty( 1108 - "margin-top", 1109 - ( 1110 - current+ 1111 - delta 1112 - )+"px" 1113 - ); 1049 + var group=null; 1114 1114 1115 - row.content.setAttribute( 1116 - "data-sn-first-content-aligned", 1117 - "7" 1118 - ); 1051 + for(var i=0;i<groups.length;i++){ 1052 + if( 1053 + Math.abs( 1054 + groups[i].top-top 1055 + )<=ROW_TOLERANCE 1056 + ){ 1057 + group=groups[i]; 1058 + break; 1059 + } 1060 + } 1119 1119 1120 - contentManaged.add( 1121 - row.content 1122 - ); 1062 + if(!group){ 1063 + group={ 1064 + top:top, 1065 + cards:[] 1066 + }; 1067 + groups.push(group); 1068 + } 1069 + 1070 + group.cards.push(card); 1123 1123 }); 1124 1124 1125 - return true; 1126 - } 1073 + groups.forEach(function(group){ 1074 + if(group.cards.length<2){ 1075 + return; 1076 + } 1127 1127 1128 - function applyRow(group){ 1129 - if(!validRow(group))return false; 1078 + var firstHeaders= 1079 + group.cards.map(function(card){ 1080 + var candidates= 1081 + headers 1082 + .filter(function(row){ 1083 + return row.card===card; 1084 + }) 1085 + .sort(function(a,b){ 1086 + return ( 1087 + a.el 1088 + .getBoundingClientRect() 1089 + .top- 1090 + b.el 1091 + .getBoundingClientRect() 1092 + .top 1093 + ); 1094 + }); 1130 1130 1131 - var cards=[]; 1132 - var seen=new Set(); 1096 + return candidates.length 1097 + ?candidates[0] 1098 + :null; 1099 + }); 1133 1133 1134 - group.entries.forEach(function(entry){ 1135 - if(!seen.has(entry.target)){ 1136 - seen.add(entry.target); 1137 - cards.push(entry.target); 1138 - } 1139 - }); 1101 + if( 1102 + !firstHeaders.some(function(row){ 1103 + return !row; 1104 + }) 1105 + ){ 1106 + var targetTop= 1107 + Math.max.apply( 1108 + Math, 1109 + firstHeaders.map(function(row){ 1110 + return ( 1111 + row.el 1112 + .getBoundingClientRect() 1113 + .top- 1114 + row.card 1115 + .getBoundingClientRect() 1116 + .top 1117 + ); 1118 + }) 1119 + ); 1140 1140 1141 - if(cards.length<2)return false; 1121 + firstHeaders.forEach(function(row){ 1122 + var relativeTop= 1123 + row.el 1124 + .getBoundingClientRect() 1125 + .top- 1126 + row.card 1127 + .getBoundingClientRect() 1128 + .top; 1142 1142 1143 - if( 1144 - !alignKnownBars(cards) 1145 - ){ 1146 - alignGeneric(cards); 1147 - } 1130 + var delta= 1131 + targetTop-relativeTop; 1148 1148 1149 - var maxHeight=0; 1133 + if(delta>1){ 1134 + saveStyle( 1135 + row.el, 1136 + originalMargin, 1137 + "margin-top" 1138 + ); 1150 1150 1151 - cards.forEach(function(card){ 1152 - maxHeight= 1153 - Math.max( 1154 - maxHeight, 1155 - card.getBoundingClientRect().height 1156 - ); 1157 - }); 1140 + var current= 1141 + num( 1142 + getComputedStyle( 1143 + row.el 1144 + ).marginTop 1145 + ); 1158 1158 1159 - maxHeight= 1160 - Math.ceil( 1161 - maxHeight 1162 - ); 1147 + row.el.style.setProperty( 1148 + "margin-top", 1149 + ( 1150 + current+delta 1151 + )+"px" 1152 + ); 1163 1163 1164 - if(maxHeight<MIN_H)return false; 1154 + row.el.setAttribute( 1155 + "data-sn-master-first-row", 1156 + "1" 1157 + ); 1165 1165 1166 - cards.forEach(function(card){1167 - saveOriginal(1168 - card,1169 - originalMinHeight,1170 - "min-height"1171 - );1159 + managedMargin.add( 1160 + row.el 1161 + ); 1162 + } 1163 + }); 1164 + } 1172 1172 1173 - card.style.setProperty( 1174 - "min-height", 1175 - maxHeight+"px" 1176 - ); 1166 + var maxHeight=0; 1177 1177 1178 - card.setAttribute( 1179 - "data-sn-equal-height-managed", 1180 - "7" 1181 - ); 1168 + group.cards.forEach(function(card){ 1169 + maxHeight= 1170 + Math.max( 1171 + maxHeight, 1172 + card 1173 + .getBoundingClientRect() 1174 + .height 1175 + ); 1176 + }); 1182 1182 1183 - heightManaged.add(card);1184 - });1178 + maxHeight= 1179 + Math.ceil(maxHeight); 1185 1185 1186 - return true; 1187 - } 1181 + group.cards.forEach(function(card){ 1182 + saveStyle( 1183 + card, 1184 + originalHeight, 1185 + "min-height" 1186 + ); 1188 1188 1189 - function calculate(force){ 1190 - if(applying)return; 1188 + card.style.setProperty( 1189 + "min-height", 1190 + maxHeight+"px" 1191 + ); 1191 1191 1192 - varwidth=1193 - Math.round(1194 - window.innerWidth1195 - ); 1193 + card.setAttribute( 1194 + "data-sn-master-equal-height", 1195 + "1" 1196 + ); 1196 1196 1197 - var meaningful= 1198 - lastWidth<0|| 1199 - Math.abs( 1200 - width- 1201 - lastWidth 1202 - )>= 1203 - MIN_WIDTH_CHANGE; 1198 + managedHeight.add( 1199 + card 1200 + ); 1201 + }); 1202 + }); 1203 + } 1204 1204 1205 + /* ======================================================= 1206 + DETAIL GRID EQUAL HEIGHT, DESKTOP ONLY 1207 + ======================================================= */ 1208 + 1209 + function equaliseDetailGrids(){ 1205 1205 if( 1206 - hasApplied&& 1207 - !force&& 1208 - !meaningful 1211 + PAGE_KIND!=="detail"|| 1212 + window.innerWidth<=MOBILE_MAX 1209 1209 ){ 1210 1210 return; 1211 1211 } 1212 1212 1213 - applying=true; 1217 + var selectors=[ 1218 + ".arsn-grid", 1219 + ".arsn-grid-2", 1220 + ".arsn-grid-3", 1221 + ".dmp-grid", 1222 + ".ido-grid", 1223 + ".pp-grid" 1224 + ]; 1214 1214 1215 - try{ 1216 - harmoniseCustomCallouts(); 1226 + selectors.forEach(function(selector){ 1227 + Array.from( 1228 + root.querySelectorAll(selector) 1229 + ).forEach(function(grid){ 1230 + var children= 1231 + Array.from( 1232 + grid.children||[] 1233 + ).filter(visible); 1217 1217 1218 - if(width<=MOBILE_MAX){ 1219 - if(hasApplied){ 1220 - resetRuntime(); 1235 + if(children.length<2){ 1236 + return; 1221 1221 } 1222 1222 1223 - hasApplied=false; 1224 - lastWidth=width; 1225 - return; 1226 - } 1239 + var groups=[]; 1227 1227 1228 - if(hasApplied){ 1229 - resetRuntime(); 1230 - } 1241 + children.forEach(function(child){ 1242 + var top= 1243 + child 1244 + .getBoundingClientRect() 1245 + .top; 1231 1231 1232 - var parents= 1233 - Array.from( 1234 - root.querySelectorAll("*") 1235 - ) 1236 - .filter(function(parent){ 1237 - return ( 1238 - visible( 1239 - parent, 1240 - MIN_W, 1241 - MIN_H 1242 - )&& 1243 - parent.children&& 1244 - parent.children.length>=2&& 1245 - parent.children.length<= 1246 - MAX_PARENT_CHILDREN 1247 - ); 1248 - }); 1247 + var group=null; 1249 1249 1250 - var touched= 1251 - new Set(); 1249 + for(var i=0;i<groups.length;i++){ 1250 + if( 1251 + Math.abs( 1252 + groups[i].top-top 1253 + )<=ROW_TOLERANCE 1254 + ){ 1255 + group=groups[i]; 1256 + break; 1257 + } 1258 + } 1252 1252 1253 - parents.forEach(function(parent){ 1254 - var entries=[]; 1260 + if(!group){ 1261 + group={ 1262 + top:top, 1263 + items:[] 1264 + }; 1265 + groups.push(group); 1266 + } 1255 1255 1256 - Array.from( 1257 - parent.children 1258 - ).forEach(function(child){ 1259 - if( 1260 - !visible( 1261 - child, 1262 - MIN_W, 1263 - MIN_H 1264 - ) 1265 - ){ 1268 + group.items.push(child); 1269 + }); 1270 + 1271 + groups.forEach(function(group){ 1272 + if(group.items.length<2){ 1266 1266 return; 1267 1267 } 1268 1268 1269 - var target= 1270 - pickTarget(child); 1276 + var maxHeight=0; 1271 1271 1272 - if(!target)return; 1273 - 1274 - entries.push({ 1275 - target:target, 1276 - rect: 1277 - target.getBoundingClientRect() 1278 + group.items.forEach(function(item){ 1279 + maxHeight= 1280 + Math.max( 1281 + maxHeight, 1282 + item 1283 + .getBoundingClientRect() 1284 + .height 1285 + ); 1278 1278 }); 1279 - }); 1280 1280 1281 - groupRows( 1282 - entries 1283 - ).forEach(function(group){ 1284 - if(!validRow(group))return; 1288 + maxHeight= 1289 + Math.ceil(maxHeight); 1285 1285 1286 - var targets= 1287 - group.entries.map(function(entry){ 1288 - return entry.target; 1289 - }); 1291 + group.items.forEach(function(item){ 1292 + saveStyle( 1293 + item, 1294 + originalHeight, 1295 + "min-height" 1296 + ); 1290 1290 1291 - if( 1292 - !targets.some(function(el){ 1293 - return !touched.has(el); 1294 - }) 1295 - ){ 1296 - return; 1297 - } 1298 + item.style.setProperty( 1299 + "min-height", 1300 + maxHeight+"px" 1301 + ); 1298 1298 1299 - if(applyRow(group)){ 1300 - targets.forEach(function(el){ 1301 - touched.add(el); 1302 - }); 1303 - } 1303 + item.setAttribute( 1304 + "data-sn-master-equal-height", 1305 + "1" 1306 + ); 1307 + 1308 + managedHeight.add(item); 1309 + }); 1304 1304 }); 1305 1305 }); 1312 + }); 1313 + } 1306 1306 1307 - lastWidth=width; 1308 - hasApplied=true; 1315 + /* ======================================================= 1316 + RUN / RESPONSIVE SCHEDULING 1317 + ======================================================= */ 1318 + 1319 + function run(){ 1320 + if(running)return; 1321 + 1322 + running=true; 1323 + 1324 + try{ 1325 + resetRuntime(); 1326 + applyPlaceholderBadge(); 1327 + propagateDetailAccents(); 1328 + 1329 + var headers= 1330 + applyOverviewPalette(); 1331 + 1332 + if( 1333 + window.innerWidth> 1334 + MOBILE_MAX 1335 + ){ 1336 + alignOverviewCards( 1337 + headers 1338 + ); 1339 + 1340 + equaliseDetailGrids(); 1341 + } 1309 1309 }finally{ 1310 - applying=false;1343 + running=false; 1311 1311 } 1312 1312 } 1313 1313 1314 - function resize(){1347 + function onResize(){ 1315 1315 if(resizeTimer){ 1316 1316 clearTimeout( 1317 1317 resizeTimer ... ... @@ -1322,19 +1322,40 @@ 1322 1322 setTimeout( 1323 1323 function(){ 1324 1324 resizeTimer=0; 1325 - calculate(false);1358 + run(); 1326 1326 }, 1327 1327 RESIZE_DEBOUNCE 1328 1328 ); 1329 1329 } 1330 1330 1331 - function waitImages(){ 1364 + async function waitForReady(){ 1365 + if( 1366 + document.readyState!=="complete" 1367 + ){ 1368 + await new Promise(function(resolve){ 1369 + window.addEventListener( 1370 + "load", 1371 + resolve, 1372 + {once:true} 1373 + ); 1374 + }); 1375 + } 1376 + 1377 + if( 1378 + document.fonts&& 1379 + document.fonts.ready 1380 + ){ 1381 + try{ 1382 + await document.fonts.ready; 1383 + }catch(error){} 1384 + } 1385 + 1332 1332 var images= 1333 1333 Array.from( 1334 1334 root.querySelectorAll("img") 1335 1335 ); 1336 1336 1337 - returnPromise.all(1391 + await Promise.all( 1338 1338 images.map(function(img){ 1339 1339 if(img.complete){ 1340 1340 return Promise.resolve(); ... ... @@ -1359,46 +1359,20 @@ 1359 1359 }); 1360 1360 }) 1361 1361 ); 1362 - } 1363 1363 1364 - async function initial(){ 1365 - if( 1366 - document.readyState!== 1367 - "complete" 1368 - ){ 1369 - await new Promise(function(resolve){ 1370 - addEventListener( 1371 - "load", 1372 - resolve, 1373 - {once:true} 1374 - ); 1375 - }); 1376 - } 1377 - 1378 - if( 1379 - document.fonts&& 1380 - document.fonts.ready 1381 - ){ 1382 - try{ 1383 - await document.fonts.ready; 1384 - }catch(error){} 1385 - } 1386 - 1387 - await waitImages(); 1388 - 1389 - // Exactly one initial layout calculation. 1390 - calculate(true); 1417 + run(); 1391 1391 } 1392 1392 1393 - addEventListener( 1420 + window.addEventListener( 1394 1394 "resize", 1395 - resize,1422 + onResize, 1396 1396 {passive:true} 1397 1397 ); 1398 1398 1399 - i nitial();1426 + waitForReady(); 1400 1400 })(); 1401 1401 </script> 1402 1402 1403 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 1404 -{{/html}}\n 1430 +<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END --> 1431 +{{/html}} 1432 +