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