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