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