Changes for page Art & Research Services Navigator
Last modified by Veronika Kocher on Friday, 18 Sep 2026 16:47
From version 40.1
edited by Veronika Kocher
on Thursday, 03 Sep 2026 15:57
on Thursday, 03 Sep 2026 15:57
Change comment:
There is no comment for this version
To version 39.23
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
-
... ... @@ -2,12 +2,14 @@ 2 2 3 3 The **Art & Research Services Navigator** helps you find the right guidance, services and resources for each stage of your project. 4 4 5 -{{info title="Support for Your Project:"}} 5 +{{info title="How responsibilities work"}} 6 +The navigator brings services together around the project lifecycle and the researcher's task. It is a navigation layer across university services, not a separate organisational unit. 6 6 7 - 8 - **Support Kunst und Forschung (SKF)** provides guidance for projects and grant applications and collaborates with the appropriate university services as needed. 8 +**Support Kunst und Forschung (SKF)** supports project and funding activities — especially project development, funding and calls, proposals, and coordination of funded projects — and, where useful, connects them with the University's relevant services. 9 9 10 - The Navigator guides you through the project phases to the resources and points of contact relevant to your project. 10 +Depending on the question, these may include the **University Library / Research Data Management & Repository**, **IT**, **Legal and Data Protection**, **Finance and Personnel**, **Publications and Communication**, **Event Management**, the **International Office** and other services. 11 + 12 +The **institute, department or other host unit** remains the artistic or academic home of the project. The navigator brings these offers together along the project stages so you can start from your need rather than from the organisational chart. 11 11 {{/info}} 12 12 13 13 ... ... @@ -637,13 +637,12 @@ 637 637 {{/info}} 638 638 ))) 639 639 640 -{{html clean="false"}} 641 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START --> 642 +\n\n 643 +\n\n{{html clean="false"}} 644 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_START --> 642 642 643 -<style data-sn-service-navigator-master="1"> 644 -/* ========================================================= 645 - MASTER TYPOGRAPHY 646 - ========================================================= */ 646 +<style data-sn-horizontal-box-harmonizer="7"> 647 +/* ---------- Typography: never justify headings ---------- */ 647 647 #xwikicontent h1, 648 648 #xwikicontent h2, 649 649 #xwikicontent h3, ... ... @@ -665,105 +665,88 @@ 665 665 word-spacing:normal!important; 666 666 } 667 667 668 -/* ========================================================= 669 - COMING SOON / IN VORBEREITUNG 670 - ========================================================= */ 671 -.sn-coming-soon-badge{ 672 - display:inline-block; 673 - vertical-align:middle; 674 - margin-left:10px; 675 - padding:4px 8px; 676 - border-radius:14px; 677 - border:1px solid #efd9cc; 678 - background:#fff4ee; 679 - color:#8a4d36; 680 - font-size:11px; 681 - font-weight:700; 682 - letter-spacing:.055em; 683 - line-height:1.2; 684 - white-space:nowrap; 685 -} 686 - 687 -/* ========================================================= 688 - NATIVE / DETAIL CALLOUT GEOMETRY 689 - Preserve existing backgrounds. 690 - ========================================================= */ 691 -#xwikicontent .arsn-info, 692 -#xwikicontent .dmp-info, 693 -#xwikicontent .ido-info, 694 -#xwikicontent .pp-info, 695 -#xwikicontent .infomessage{ 669 +/* ---------- Native XWiki semantic callouts ---------- */ 670 +#xwikicontent .box.infomessage, 671 +#xwikicontent .infomessage, 672 +#xwikicontent .box.warningmessage, 673 +#xwikicontent .warningmessage, 674 +#xwikicontent .box.successmessage, 675 +#xwikicontent .successmessage, 676 +#xwikicontent .box.errormessage, 677 +#xwikicontent .errormessage, 678 +#xwikicontent [data-sn-callout-harmonized="1"]{ 696 696 box-sizing:border-box!important; 697 - border-left:4px solid #21b6d7!important; 698 - border-radius:8px; 680 + border-radius:8px!important; 681 + border-top:1px solid rgba(0,0,0,.08)!important; 682 + border-right:1px solid rgba(0,0,0,.08)!important; 683 + border-bottom:1px solid rgba(0,0,0,.08)!important; 684 + border-left:4px solid var(--sn-callout-accent,#21b6d7)!important; 685 + padding:14px 16px!important; 699 699 text-align:left!important; 687 + text-justify:auto!important; 700 700 word-spacing:normal!important; 689 + box-shadow:none!important; 701 701 } 702 702 703 -#xwikicontent .arsn-warn, 704 -#xwikicontent .dmp-warn, 705 -#xwikicontent .ido-warn, 706 -#xwikicontent .pp-warn, 707 -#xwikicontent .warn, 708 -#xwikicontent .warning, 709 -#xwikicontent .warningmessage, 692 +#xwikicontent .box.infomessage, 693 +#xwikicontent .infomessage{ 694 + --sn-callout-accent:#21b6d7; 695 + background:#eaf7fb!important; 696 +} 697 + 698 +#xwikicontent .box.warningmessage, 699 +#xwikicontent .warningmessage{ 700 + --sn-callout-accent:#f0aa00; 701 + background:#fff8e7!important; 702 +} 703 + 704 +#xwikicontent .box.successmessage, 705 +#xwikicontent .successmessage{ 706 + --sn-callout-accent:#38b76a; 707 + background:#edf9f1!important; 708 +} 709 + 710 +#xwikicontent .box.errormessage, 710 710 #xwikicontent .errormessage{ 711 - box-sizing:border-box!important; 712 - border-left:4px solid #e94b13!important; 713 - border-radius:8px; 714 - text-align:left!important; 715 - word-spacing:normal!important; 712 + --sn-callout-accent:#e94b13; 713 + background:#fff1ec!important; 716 716 } 717 717 718 -[data-sn-master-equal-height], 719 -[data-sn-master-first-row]{ 720 - box-sizing:border-box; 716 +#xwikicontent [data-sn-callout-harmonized="1"] > :first-child, 717 +#xwikicontent .infomessage > :first-child, 718 +#xwikicontent .warningmessage > :first-child, 719 +#xwikicontent .successmessage > :first-child, 720 +#xwikicontent .errormessage > :first-child{ 721 + margin-top:0!important; 721 721 } 722 722 723 -/* ========================================================= 724 - FULL-WIDTH THREE-LINE NUMBER / TITLE / SUBTITLE BLOCKS 725 - ========================================================= */ 726 -#xwikicontent .arsn-area-label[data-sn-three-line="1"]{ 727 - display:grid!important; 728 - grid-template-columns:minmax(0,1fr)!important; 729 - grid-auto-rows:auto!important; 730 - width:100%!important; 731 - max-width:none!important; 732 - box-sizing:border-box!important; 733 - justify-items:start!important; 734 - align-items:start!important; 735 - gap:2px!important; 736 - text-align:left!important; 737 - text-align-last:left!important; 738 - text-justify:auto!important; 739 - word-spacing:normal!important; 740 - white-space:normal!important; 724 +#xwikicontent [data-sn-callout-harmonized="1"] > :last-child, 725 +#xwikicontent .infomessage > :last-child, 726 +#xwikicontent .warningmessage > :last-child, 727 +#xwikicontent .successmessage > :last-child, 728 +#xwikicontent .errormessage > :last-child{ 729 + margin-bottom:0!important; 741 741 } 742 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .arsn-area-number, 743 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .sn-area-label-title, 744 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .arsn-area-action{ 745 - display:block!important; 746 - width:100%!important; 747 - margin:0!important; 748 - text-align:left!important; 749 - text-align-last:left!important; 750 - text-justify:auto!important; 751 - word-spacing:normal!important; 752 - white-space:normal!important; 731 + 732 +#xwikicontent [data-sn-equal-height-managed], 733 +#xwikicontent [data-sn-first-section-aligned], 734 +#xwikicontent [data-sn-first-content-aligned]{ 735 + box-sizing:border-box; 753 753 } 754 754 </style> 755 755 756 -<script data-sn- service-navigator-master="1">739 +<script data-sn-horizontal-box-harmonizer="7"> 757 757 (function(){ 758 758 "use strict"; 759 759 760 - var PAGE_KIND="overview"; 761 - var PLACEHOLDER=false; 762 - var PLACEHOLDER_LABEL="COMING SOON"; 763 - 764 764 var MOBILE_MAX=767; 765 765 var ROW_TOLERANCE=6; 745 + var MIN_W=150; 746 + var MIN_H=36; 747 + var MAX_PARENT_CHILDREN=18; 748 + var SEARCH_DEPTH=5; 766 766 var RESIZE_DEBOUNCE=220; 750 + var MIN_WIDTH_CHANGE=2; 767 767 768 768 var root= 769 769 document.getElementById("xwikicontent")|| ... ... @@ -773,114 +773,142 @@ 773 773 774 774 if(!root)return; 775 775 776 - var managedHeight=new Set(); 777 - var managedMargin=new Set(); 778 - var originalHeight=new WeakMap(); 779 - var originalMargin=new WeakMap(); 760 + var heightManaged=new Set(); 761 + var sectionManaged=new Set(); 762 + var contentManaged=new Set(); 780 780 764 + var originalMinHeight=new WeakMap(); 765 + var originalMarginTop=new WeakMap(); 766 + 781 781 var resizeTimer=0; 782 - var running=false; 768 + var lastWidth=-1; 769 + var hasApplied=false; 770 + var applying=false; 783 783 784 - var THEMES=[ 785 - { 786 - name:"BLUE", 787 - accent:"#21b6d7", 788 - bg:"#eaf7fb", 789 - text:"#315d68", 790 - labels:[ 791 - "HIER STARTEN", 792 - "ENTSCHEIDEN", 793 - "ÜBERPRÜFEN & ANPASSEN", 794 - "START HERE", 795 - "DECIDE", 796 - "REVIEW & ADAPT" 797 - ] 798 - }, 799 - { 800 - name:"RED", 801 - accent:"#e94b13", 802 - bg:"#fff1ec", 803 - text:"#8a4d36", 804 - labels:[ 805 - "PLANEN & ORGANISIEREN", 806 - "ORGANISIEREN & DOKUMENTIEREN", 807 - "PUBLIZIEREN & PRÄSENTIEREN", 808 - "PLAN & ORGANISE", 809 - "PLAN & ORGANIZE", 810 - "ORGANISE & DOCUMENT", 811 - "ORGANIZE & DOCUMENT", 812 - "PUBLISH & PRESENT" 813 - ] 814 - }, 815 - { 816 - name:"YELLOW", 817 - accent:"#f0aa00", 818 - bg:"#fff8e7", 819 - text:"#785b17", 820 - labels:[ 821 - "SCHÜTZEN & KLÄREN", 822 - "STANDARDISIEREN & IDENTIFIZIEREN", 823 - "ÖFFNEN, NACHNUTZEN & AUFFINDBAR MACHEN", 824 - "PROTECT & CLARIFY", 825 - "STANDARDISE & IDENTIFY", 826 - "STANDARDIZE & IDENTIFY", 827 - "OPEN, REUSE & MAKE FINDABLE" 828 - ] 829 - }, 830 - { 831 - name:"GREEN", 832 - accent:"#38b76a", 833 - bg:"#edf9f1", 834 - text:"#3f7451", 835 - labels:[ 836 - "INFRASTRUKTUR EINRICHTEN", 837 - "INFRASTRUKTUR & ZUSAMMENARBEIT EINRICHTEN", 838 - "SPEICHERN & ZUGRIFF STEUERN", 839 - "REPOSITORIUM, ERHALTEN & ÜBERGEBEN", 840 - "SET UP INFRASTRUCTURE", 841 - "SET UP INFRASTRUCTURE & COLLABORATION", 842 - "STORE & CONTROL ACCESS", 843 - "REPOSITORY, PRESERVE & HAND OVER" 844 - ] 772 + function num(v){ 773 + var n=parseFloat(v); 774 + return Number.isFinite(n)?n:0; 775 + } 776 + 777 + function visible(el,minW,minH){ 778 + if(!el||el.nodeType!==1)return false; 779 + 780 + var s=getComputedStyle(el); 781 + 782 + if( 783 + s.display==="none"|| 784 + s.visibility==="hidden"|| 785 + Number(s.opacity)===0 786 + ){ 787 + return false; 845 845 } 846 - ]; 847 847 848 - function num(value){ 849 - var n=parseFloat(value); 850 - return Number.isFinite(n)?n:0; 790 + var r=el.getBoundingClientRect(); 791 + 792 + return ( 793 + r.width>=(minW||1)&& 794 + r.height>=(minH||1) 795 + ); 851 851 } 852 852 853 - function norm (value){854 - return String( value||"")798 + function normalizeText(text){ 799 + return String(text||"") 855 855 .replace(/\s+/g," ") 856 856 .trim() 857 857 .toUpperCase(); 858 858 } 859 859 860 - function visible(el){ 861 - if(!el||el.nodeType!==1)return false; 805 + function excluded(el){ 806 + return ( 807 + !el.matches|| 808 + el.matches( 809 + "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]" 810 + ) 811 + ); 812 + } 862 862 863 - var style=getComputedStyle(el); 864 - var rect=el.getBoundingClientRect(); 814 + /* ---------- Custom coloured callouts ---------- */ 865 865 816 + function nativeCallout(el){ 817 + var c= 818 + typeof el.className==="string" 819 + ? el.className.toLowerCase() 820 + : ""; 821 + 866 866 return ( 867 - style.display!=="none"&& 868 - style.visibility!=="hidden"&& 869 - rect.width>20&& 870 - rect.height>4 823 + /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c) 871 871 ); 872 872 } 873 873 874 - function saveStyle(el,map,property){ 827 + function customCallout(el){ 828 + if(!visible(el,220,42)||excluded(el))return false; 829 + 830 + var r=el.getBoundingClientRect(); 831 + 832 + if(r.height>520)return false; 833 + 834 + var s=getComputedStyle(el); 835 + 836 + var bg= 837 + s.backgroundColor&& 838 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 839 + s.backgroundColor!=="transparent"&& 840 + s.backgroundColor!=="rgb(255, 255, 255)"; 841 + 842 + var left= 843 + num(s.borderLeftWidth); 844 + 845 + return ( 846 + bg&& 847 + left>=2 848 + ); 849 + } 850 + 851 + function harmoniseCustomCallouts(){ 852 + Array.from( 853 + root.querySelectorAll( 854 + "div,aside,section" 855 + ) 856 + ).forEach(function(el){ 857 + if(nativeCallout(el))return; 858 + if(!customCallout(el))return; 859 + 860 + var s=getComputedStyle(el); 861 + 862 + el.setAttribute( 863 + "data-sn-callout-harmonized", 864 + "1" 865 + ); 866 + 867 + if( 868 + s.borderLeftColor 869 + ){ 870 + el.style.setProperty( 871 + "--sn-callout-accent", 872 + s.borderLeftColor 873 + ); 874 + } 875 + }); 876 + } 877 + 878 + /* ---------- Restore only values V7 itself changed ---------- */ 879 + 880 + function saveOriginal(el,map,property){ 875 875 if(map.has(el))return; 876 876 877 877 map.set(el,{ 878 - value:el.style.getPropertyValue(property), 879 - priority:el.style.getPropertyPriority(property) 884 + value: 885 + el.style.getPropertyValue( 886 + property 887 + ), 888 + priority: 889 + el.style.getPropertyPriority( 890 + property 891 + ) 880 880 }); 881 881 } 882 882 883 - function restore Style(el,map,property){895 + function restoreOriginal(el,map,property){ 884 884 var original=map.get(el); 885 885 886 886 if(original&&original.value){ ... ... @@ -890,1069 +890,770 @@ 890 890 original.priority||"" 891 891 ); 892 892 }else{ 893 - el.style.removeProperty(property); 905 + el.style.removeProperty( 906 + property 907 + ); 894 894 } 895 895 } 896 896 897 897 function resetRuntime(){ 898 - managedHeight.forEach(function(el){899 - restore Style(912 + heightManaged.forEach(function(el){ 913 + restoreOriginal( 900 900 el, 901 - originalHeight, 915 + originalMinHeight, 902 902 "min-height" 903 903 ); 918 + 904 904 el.removeAttribute( 905 - "data-sn- master-equal-height"920 + "data-sn-equal-height-managed" 906 906 ); 907 907 }); 908 908 909 - managedMargin.forEach(function(el){910 - restore Style(924 + sectionManaged.forEach(function(el){ 925 + restoreOriginal( 911 911 el, 912 - originalMargin, 927 + originalMarginTop, 913 913 "margin-top" 914 914 ); 930 + 915 915 el.removeAttribute( 916 - "data-sn- master-first-row"932 + "data-sn-first-section-aligned" 917 917 ); 918 918 }); 919 919 920 - managedHeight.clear(); 921 - managedMargin.clear(); 922 - } 936 + contentManaged.forEach(function(el){ 937 + restoreOriginal( 938 + el, 939 + originalMarginTop, 940 + "margin-top" 941 + ); 923 923 924 - function themeFor(text){ 925 - var value=norm(text); 943 + el.removeAttribute( 944 + "data-sn-first-content-aligned" 945 + ); 946 + }); 926 926 927 - for(var i=0;i<THEMES.length;i++){ 928 - for(var j=0;j<THEMES[i].labels.length;j++){ 929 - var label=THEMES[i].labels[j]; 930 - 931 - if( 932 - value===label|| 933 - value.indexOf(label+" ")===0|| 934 - value.indexOf(label+" -")===0|| 935 - value.indexOf(label+" ·")===0 936 - ){ 937 - return THEMES[i]; 938 - } 939 - } 940 - } 941 - 942 - return null; 948 + heightManaged.clear(); 949 + sectionManaged.clear(); 950 + contentManaged.clear(); 943 943 } 944 944 945 - /* ======================================================= 946 - BORDERLESS FILLED RED/ORANGE CTA BUTTONS 947 - ======================================================= */ 953 + /* ---------- Card detection ---------- */ 948 948 949 - function colourDistance(a,b){ 950 - return Math.sqrt( 951 - Math.pow(a[0]-b[0],2)+ 952 - Math.pow(a[1]-b[1],2)+ 953 - Math.pow(a[2]-b[2],2) 954 - ); 955 + function namedLikeBox(el){ 956 + var c= 957 + typeof el.className==="string" 958 + ? el.className 959 + : ""; 960 + 961 + return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c); 955 955 } 956 956 957 - function makeFilledRedOrangeCTAsBorderless(){ 958 - var RED_ORANGE=[233,75,19]; 964 + function boxLike(el){ 965 + if( 966 + !visible(el,MIN_W,MIN_H)|| 967 + excluded(el) 968 + ){ 969 + return false; 970 + } 959 959 960 - Array.from( 961 - root.querySelectorAll( 962 - 'a,button,[role="button"],input[type="submit"],input[type="button"]' 963 - ) 964 - ).forEach(function(el){ 965 - if(!visible(el))return; 972 + var s=getComputedStyle(el); 973 + var r=el.getBoundingClientRect(); 966 966 967 - var style=getComputedStyle(el); 968 - var rgb=parseRGB(style.backgroundColor); 975 + var border= 976 + num(s.borderTopWidth)+ 977 + num(s.borderRightWidth)+ 978 + num(s.borderBottomWidth)+ 979 + num(s.borderLeftWidth); 969 969 970 - if(!rgb)return; 981 + var radius=Math.max( 982 + num(s.borderTopLeftRadius), 983 + num(s.borderTopRightRadius), 984 + num(s.borderBottomLeftRadius), 985 + num(s.borderBottomRightRadius) 986 + ); 971 971 972 - if( 973 - colourDistance( 974 - rgb, 975 - RED_ORANGE 976 - )>55 977 - ){ 978 - return; 979 - } 988 + var bg= 989 + s.backgroundColor&& 990 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&& 991 + s.backgroundColor!=="transparent"; 980 980 981 - var rect=el.getBoundingClientRect(); 993 + var shadow= 994 + s.boxShadow&& 995 + s.boxShadow!=="none"; 982 982 983 - if( 984 - rect.width<80|| 985 - rect.height<24 986 - ){ 987 - return; 988 - } 997 + return ( 998 + namedLikeBox(el)|| 999 + border>=1|| 1000 + (bg&&radius>=3)|| 1001 + (shadow&&r.width>=180) 1002 + ); 1003 + } 989 989 990 - el.style.setProperty( 991 - "border", 992 - "none", 993 - "important" 994 - ); 1005 + function pickTarget(child){ 1006 + if(!visible(child,MIN_W,MIN_H))return null; 995 995 996 - el.style.setProperty( 997 - "border-left", 998 - "none", 999 - "important" 1000 - ); 1008 + if(boxLike(child))return child; 1001 1001 1002 - el.style.setProperty( 1003 - "border-top", 1004 - "none", 1005 - "important" 1006 - ); 1010 + var cr=child.getBoundingClientRect(); 1011 + var q=[]; 1007 1007 1008 - el.style.setProperty( 1009 - "border-right", 1010 - "none", 1011 - "important" 1012 - ); 1013 - 1014 - el.style.setProperty( 1015 - "border-bottom", 1016 - "none", 1017 - "important" 1018 - ); 1019 - 1020 - el.style.setProperty( 1021 - "box-shadow", 1022 - "none", 1023 - "important" 1024 - ); 1013 + Array.from(child.children||[]).forEach(function(el){ 1014 + q.push({el:el,depth:1}); 1025 1025 }); 1026 - } 1027 1027 1028 - /* ======================================================= 1029 - FULL-WIDTH THREE-LINE AREA LABELS 1030 - ======================================================= */ 1017 + var best=null; 1018 + var bestScore=-Infinity; 1031 1031 1032 - function compactText(value){ 1033 - return String(value||"") 1034 - .replace(/\s+/g," ") 1035 - .trim(); 1036 - } 1020 + while(q.length){ 1021 + var item=q.shift(); 1022 + var el=item.el; 1037 1037 1038 - function makeThreeLineAreaLabels(){ 1039 - Array.from( 1040 - root.querySelectorAll( 1041 - ".arsn-area-label" 1042 - ) 1043 - ).forEach(function(label){ 1044 - if( 1045 - label.getAttribute( 1046 - "data-sn-three-line" 1047 - )==="1" 1048 - ){ 1049 - return; 1050 - } 1024 + if(!visible(el,MIN_W,MIN_H))continue; 1051 1051 1052 - var number= 1053 - label.querySelector( 1054 - ":scope > .arsn-area-number" 1055 - ); 1026 + var r=el.getBoundingClientRect(); 1056 1056 1057 - var action= 1058 - label.querySelector( 1059 - ":scope > .arsn-area-action" 1060 - ); 1061 - 1062 1062 if( 1063 - !number||1064 - !action1029 + r.width>=cr.width*.68&& 1030 + boxLike(el) 1065 1065 ){ 1066 - return; 1067 - } 1032 + var widthFit= 1033 + 1-Math.min( 1034 + 1, 1035 + Math.abs(cr.width-r.width)/ 1036 + Math.max(1,cr.width) 1037 + ); 1068 1068 1069 - var clone= 1070 - label.cloneNode(true); 1039 + var topFit= 1040 + 1-Math.min( 1041 + 1, 1042 + Math.abs(cr.top-r.top)/100 1043 + ); 1071 1071 1072 - var cloneNumber= 1073 - clone.querySelector( 1074 - ":scope > .arsn-area-number" 1075 - ); 1045 + var score= 1046 + widthFit*6+ 1047 + topFit*3+ 1048 + Math.min(r.height,900)/450+ 1049 + Math.min(r.width*r.height,900000)/900000; 1076 1076 1077 - var cloneAction= 1078 - clone.querySelector( 1079 - ":scope > .arsn-area-action" 1080 - ); 1081 - 1082 - if(cloneNumber){ 1083 - cloneNumber.remove(); 1051 + if(score>bestScore){ 1052 + best=el; 1053 + bestScore=score; 1054 + } 1084 1084 } 1085 1085 1086 - if(cloneAction){ 1087 - cloneAction.remove(); 1057 + if(item.depth<SEARCH_DEPTH){ 1058 + Array.from(el.children||[]).forEach(function(next){ 1059 + q.push({ 1060 + el:next, 1061 + depth:item.depth+1 1062 + }); 1063 + }); 1088 1088 } 1065 + } 1089 1089 1090 - var titleText= 1091 - compactText( 1092 - clone.textContent 1093 - ); 1067 + return best; 1068 + } 1094 1094 1095 - if(!titleText){ 1096 - return; 1097 - } 1070 + function groupRows(entries){ 1071 + var groups=[]; 1098 1098 1099 - var numberNode= 1100 - number.cloneNode(true); 1101 - 1102 - var actionNode= 1103 - action.cloneNode(true); 1104 - 1105 - var titleNode= 1106 - document.createElement( 1107 - "span" 1073 + entries 1074 + .slice() 1075 + .sort(function(a,b){ 1076 + return ( 1077 + a.rect.top-b.rect.top|| 1078 + a.rect.left-b.rect.left 1108 1108 ); 1080 + }) 1081 + .forEach(function(entry){ 1082 + var group=null; 1109 1109 1110 - titleNode.className= 1111 - "sn-area-label-title"; 1084 + for(var i=0;i<groups.length;i++){ 1085 + if( 1086 + Math.abs( 1087 + groups[i].top- 1088 + entry.rect.top 1089 + )<=ROW_TOLERANCE 1090 + ){ 1091 + group=groups[i]; 1092 + break; 1093 + } 1094 + } 1112 1112 1113 - titleNode.textContent= 1114 - titleText; 1096 + if(!group){ 1097 + group={ 1098 + top:entry.rect.top, 1099 + entries:[] 1100 + }; 1101 + groups.push(group); 1102 + } 1115 1115 1116 - while(label.firstChild){ 1117 - label.removeChild( 1118 - label.firstChild 1119 - ); 1120 - } 1104 + group.entries.push(entry); 1105 + }); 1121 1121 1122 - label.appendChild( 1123 - numberNode 1124 - ); 1125 - 1126 - label.appendChild( 1127 - titleNode 1128 - ); 1129 - 1130 - label.appendChild( 1131 - actionNode 1132 - ); 1133 - 1134 - label.setAttribute( 1135 - "data-sn-three-line", 1136 - "1" 1137 - ); 1138 - 1139 - var head= 1140 - label.closest( 1141 - ".arsn-area-head" 1142 - ); 1143 - 1144 - if(head){ 1145 - head.style.setProperty( 1146 - "width", 1147 - "100%", 1148 - "important" 1149 - ); 1150 - 1151 - head.style.setProperty( 1152 - "max-width", 1153 - "100%", 1154 - "important" 1155 - ); 1156 - 1157 - head.style.setProperty( 1158 - "box-sizing", 1159 - "border-box", 1160 - "important" 1161 - ); 1162 - } 1163 - }); 1107 + return groups; 1164 1164 } 1165 1165 1166 - /* ======================================================= 1167 - PLACEHOLDER BADGE 1168 - ======================================================= */ 1110 + function validRow(group){ 1111 + if(group.entries.length<2)return false; 1169 1169 1170 - function applyPlaceholderBadge(){ 1171 - if(!PLACEHOLDER)return; 1113 + var lefts= 1114 + group.entries 1115 + .map(function(e){return e.rect.left;}) 1116 + .sort(function(a,b){return a-b;}); 1172 1172 1173 1173 if( 1174 - document.querySelector(1175 - ".sn-coming-soon-badge"1176 - )1119 + lefts[lefts.length-1]- 1120 + lefts[0]< 1121 + 80 1177 1177 ){ 1178 - return; 1123 + return false; 1179 1179 } 1180 1180 1181 - var title= 1182 - document.querySelector( 1183 - "#document-title" 1184 - )|| 1185 - document.querySelector( 1186 - "h1" 1187 - ); 1126 + var widths= 1127 + group.entries 1128 + .map(function(e){return e.rect.width;}) 1129 + .filter(function(w){return w>0;}); 1188 1188 1189 - if( !title)return;1131 + if(widths.length<2)return false; 1190 1190 1191 - var badge= 1192 - document.createElement( 1193 - "span" 1194 - ); 1133 + var minW= 1134 + Math.min.apply(Math,widths); 1195 1195 1196 - badge.className=1197 - "sn-coming-soon-badge";1136 + var maxW= 1137 + Math.max.apply(Math,widths); 1198 1198 1199 - badge.textContent= 1200 - PLACEHOLDER_LABEL; 1201 - 1202 - badge.setAttribute( 1203 - "aria-label", 1204 - PLACEHOLDER_LABEL 1139 + return ( 1140 + maxW/ 1141 + Math.max(1,minW)<= 1142 + 1.9 1205 1205 ); 1144 + } 1206 1206 1207 - title.appendChild( 1208 - badge 1146 + /* ---------- Known ARSN first section bars ---------- */ 1147 + 1148 + function knownBar(el){ 1149 + var text= 1150 + normalizeText( 1151 + el.textContent 1152 + ); 1153 + 1154 + return ( 1155 + text==="HIER STARTEN"|| 1156 + text==="ORGANISIEREN & DOKUMENTIEREN"|| 1157 + text==="ENTSCHEIDEN"|| 1158 + text==="START HERE"|| 1159 + text==="GET STARTED"|| 1160 + text==="ORGANISE & DOCUMENT"|| 1161 + text==="ORGANIZE & DOCUMENT"|| 1162 + text==="DECIDE" 1209 1209 ); 1210 1210 } 1211 1211 1212 - /*=======================================================1213 - DETAIL PAGE OWN-ACCENT PROPAGATION1214 - =======================================================*/1166 + function findKnownBar(card){ 1167 + var cardRect= 1168 + card.getBoundingClientRect(); 1215 1215 1216 - function parseRGB(value){ 1217 - var match=String(value||"").match( 1218 - /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i 1219 - ); 1170 + var rows= 1171 + Array.from( 1172 + card.querySelectorAll( 1173 + "div,p,span,strong,h3,h4,h5,h6" 1174 + ) 1175 + ) 1176 + .filter(function(el){ 1177 + if(!visible(el,20,6))return false; 1178 + if(!knownBar(el))return false; 1220 1220 1221 - if(!match)returnnull;1180 + var r=el.getBoundingClientRect(); 1222 1222 1223 - return [ 1224 - Number(match[1]), 1225 - Number(match[2]), 1226 - Number(match[3]) 1227 - ]; 1228 - } 1182 + var rel= 1183 + r.top- 1184 + cardRect.top; 1229 1229 1230 - function distance(a,b){ 1231 - return Math.sqrt( 1232 - Math.pow(a[0]-b[0],2)+ 1233 - Math.pow(a[1]-b[1],2)+ 1234 - Math.pow(a[2]-b[2],2) 1235 - ); 1186 + return ( 1187 + rel>=35&& 1188 + rel<= 1189 + cardRect.height*.75 1190 + ); 1191 + }) 1192 + .sort(function(a,b){ 1193 + return ( 1194 + a.getBoundingClientRect().top- 1195 + b.getBoundingClientRect().top 1196 + ); 1197 + }); 1198 + 1199 + return rows[0]||null; 1236 1236 } 1237 1237 1238 - function paletteMatch(cssColor){ 1239 - var rgb=parseRGB(cssColor); 1202 + function alignKnownBars(cards){ 1203 + var rows= 1204 + cards.map(function(card){ 1205 + var bar= 1206 + findKnownBar(card); 1240 1240 1241 - if(! rgb)return null;1208 + if(!bar)return null; 1242 1242 1243 - var palette=[ 1244 - {hex:"#21b6d7",rgb:[33,182,215]}, 1245 - {hex:"#e94b13",rgb:[233,75,19]}, 1246 - {hex:"#f0aa00",rgb:[240,170,0]}, 1247 - {hex:"#38b76a",rgb:[56,183,106]} 1248 - ]; 1210 + var cr= 1211 + card.getBoundingClientRect(); 1249 1249 1250 - var b est=null;1251 - varbestDistance=Infinity;1213 + var br= 1214 + bar.getBoundingClientRect(); 1252 1252 1253 - palette.forEach(function(item){ 1254 - var d=distance(rgb,item.rgb); 1216 + return { 1217 + bar:bar, 1218 + relativeTop: 1219 + br.top- 1220 + cr.top 1221 + }; 1222 + }); 1255 1255 1256 - if(d<bestDistance){ 1257 - best=item; 1258 - bestDistance=d; 1259 - } 1260 - }); 1224 + if( 1225 + rows.some(function(row){ 1226 + return !row; 1227 + }) 1228 + ){ 1229 + return false; 1230 + } 1261 1261 1262 - return bestDistance<=30 1263 - ?best 1264 - :null; 1265 - } 1232 + var target= 1233 + Math.max.apply( 1234 + Math, 1235 + rows.map(function(row){ 1236 + return row.relativeTop; 1237 + }) 1238 + ); 1266 1266 1267 - function propagateDetailAccents(){ 1268 - if(PAGE_KIND!=="detail")return; 1240 + rows.forEach(function(row){ 1241 + var delta= 1242 + target- 1243 + row.relativeTop; 1269 1269 1270 - Array.from( 1271 - root.querySelectorAll( 1272 - ".arsn-call,.dmp-call,.ido-call,.pp-call,"+ 1273 - ".arsn-source,.dmp-source,.ido-source,.pp-source" 1274 - ) 1275 - ).forEach(function(el){ 1276 - if(!visible(el))return; 1245 + if(delta<=1)return; 1277 1277 1278 - var style=getComputedStyle(el); 1247 + saveOriginal( 1248 + row.bar, 1249 + originalMarginTop, 1250 + "margin-top" 1251 + ); 1279 1279 1280 - if( 1281 - num(style.borderTopWidth)>=2 1282 - ){ 1283 - var match= 1284 - paletteMatch( 1285 - style.borderTopColor 1286 - ); 1253 + var current= 1254 + num( 1255 + getComputedStyle( 1256 + row.bar 1257 + ).marginTop 1258 + ); 1287 1287 1288 - if(match){ 1289 - el.style.setProperty( 1290 - "border-left", 1291 - "4px solid "+match.hex, 1292 - "important" 1293 - ); 1294 - } 1295 - } 1296 - }); 1260 + row.bar.style.setProperty( 1261 + "margin-top", 1262 + ( 1263 + current+ 1264 + delta 1265 + )+"px" 1266 + ); 1297 1297 1298 - // Warning families: explicit safety override. 1299 - Array.from( 1300 - root.querySelectorAll( 1301 - ".arsn-warn,.dmp-warn,.ido-warn,.pp-warn,"+ 1302 - ".warn,.warning,.warningmessage,.errormessage" 1303 - ) 1304 - ).forEach(function(el){ 1305 - if(!visible(el))return; 1306 - 1307 - el.style.setProperty( 1308 - "border-left", 1309 - "4px solid #e94b13", 1310 - "important" 1268 + row.bar.setAttribute( 1269 + "data-sn-first-section-aligned", 1270 + "7" 1311 1311 ); 1312 - }); 1313 1313 1314 - // Info families: explicit orientation override. 1315 - Array.from( 1316 - root.querySelectorAll( 1317 - ".arsn-info,.dmp-info,.ido-info,.pp-info,.infomessage" 1318 - ) 1319 - ).forEach(function(el){ 1320 - if(!visible(el))return; 1321 - 1322 - el.style.setProperty( 1323 - "border-left", 1324 - "4px solid #21b6d7", 1325 - "important" 1273 + sectionManaged.add( 1274 + row.bar 1326 1326 ); 1327 1327 }); 1277 + 1278 + return true; 1328 1328 } 1329 1329 1330 - /* ======================================================= 1331 - OVERVIEW SEMANTIC THEME PALETTE 1332 - ======================================================= */ 1281 + /* ---------- Generic first content after heading ---------- */ 1333 1333 1334 - function smallestThemeHeaders(){ 1335 - return Array.from( 1336 - root.querySelectorAll( 1337 - "div,span,p,strong,h3,h4,h5,h6" 1283 + function heading(card){ 1284 + var cr= 1285 + card.getBoundingClientRect(); 1286 + 1287 + var rows= 1288 + Array.from( 1289 + card.querySelectorAll( 1290 + "h1,h2,h3,h4,h5,h6,.box-title,[role=heading]" 1291 + ) 1338 1338 ) 1339 - ).filter(function(el){ 1340 - if(!visible(el))return false; 1341 - if(!themeFor(el.textContent))return false; 1293 + .filter(function(el){ 1294 + if(!visible(el,20,8))return false; 1342 1342 1343 - return !Array.from( 1344 - el.children||[] 1345 - ).some(function(child){ 1346 - return !!themeFor( 1347 - child.textContent 1296 + var r=el.getBoundingClientRect(); 1297 + 1298 + var rel= 1299 + r.top- 1300 + cr.top; 1301 + 1302 + return ( 1303 + rel>=0&& 1304 + rel<= 1305 + Math.min( 1306 + 160, 1307 + cr.height*.45 1308 + ) 1348 1348 ); 1310 + }) 1311 + .sort(function(a,b){ 1312 + return ( 1313 + a.getBoundingClientRect().top- 1314 + b.getBoundingClientRect().top 1315 + ); 1349 1349 }); 1350 - }); 1317 + 1318 + return rows[0]||null; 1351 1351 } 1352 1352 1353 - function findOverviewCard(header){ 1354 - var node=header.parentElement; 1355 - var candidates=[]; 1321 + function firstContent(card,h){ 1322 + if(!h)return null; 1356 1356 1357 - while(node&&node!==root){ 1358 - var rect=node.getBoundingClientRect(); 1359 - var style=getComputedStyle(node); 1324 + var cr= 1325 + card.getBoundingClientRect(); 1360 1360 1361 - var border= 1362 - num(style.borderTopWidth)+ 1363 - num(style.borderRightWidth)+ 1364 - num(style.borderBottomWidth)+ 1365 - num(style.borderLeftWidth); 1327 + var hr= 1328 + h.getBoundingClientRect(); 1366 1366 1367 - if( 1368 - rect.width>=220&& 1369 - rect.width<=800&& 1370 - rect.height>=120&& 1371 - border>=1 1372 - ){ 1373 - candidates.push(node); 1374 - } 1330 + var rows= 1331 + Array.from( 1332 + card.querySelectorAll( 1333 + "p,div,ul,ol,dl,blockquote" 1334 + ) 1335 + ) 1336 + .filter(function(el){ 1337 + if( 1338 + el===h|| 1339 + h.contains(el)|| 1340 + el.contains(h) 1341 + ){ 1342 + return false; 1343 + } 1375 1375 1376 - node=node.parentElement; 1377 - } 1345 + if(!visible(el,30,8))return false; 1378 1378 1379 - if(!candidates.length)return null; 1347 + var text= 1348 + String(el.textContent||"") 1349 + .replace(/\s+/g," ") 1350 + .trim(); 1380 1380 1381 - candidates.sort(function(a,b){ 1382 - return ( 1383 - b.getBoundingClientRect().height- 1384 - a.getBoundingClientRect().height 1385 - ); 1386 - }); 1352 + if(text.length<3)return false; 1387 1387 1388 - return candidates[0]; 1389 - } 1354 + var r=el.getBoundingClientRect(); 1390 1390 1391 - function rowCandidates(link,card){ 1392 - var result=[]; 1393 - var cardRect= 1394 - card.getBoundingClientRect(); 1356 + if( 1357 + r.top< 1358 + hr.bottom-1 1359 + ){ 1360 + return false; 1361 + } 1395 1395 1396 - var node=link; 1363 + if( 1364 + r.top-cr.top> 1365 + Math.min( 1366 + 280, 1367 + cr.height*.65 1368 + ) 1369 + ){ 1370 + return false; 1371 + } 1397 1397 1398 - while(node&&node!==card){ 1399 - if(visible(node)){ 1400 - var rect= 1401 - node.getBoundingClientRect(); 1402 - 1403 1403 if( 1404 - rect.height<=105&& 1405 - rect.width>= 1406 - cardRect.width*.50&& 1407 - rect.width<= 1408 - cardRect.width*1.03 1374 + r.height> 1375 + cr.height*.58 1409 1409 ){ 1410 - re sult.push(node);1377 + return false; 1411 1411 } 1412 - } 1413 1413 1414 - node=node.parentElement; 1415 - } 1380 + return true; 1381 + }) 1382 + .sort(function(a,b){ 1383 + var ar= 1384 + a.getBoundingClientRect(); 1416 1416 1417 - r eturnresult;1418 - }1386 + var br= 1387 + b.getBoundingClientRect(); 1419 1419 1420 - function chooseOuterRow( 1421 - candidates, 1422 - link 1423 - ){ 1424 - if(!candidates.length){ 1425 - return link; 1426 - } 1427 - 1428 - var bordered= 1429 - candidates.filter(function(el){ 1430 1430 return ( 1431 - num( 1432 - getComputedStyle(el) 1433 - .borderLeftWidth 1434 - )>=1 1390 + ar.top-br.top|| 1391 + ar.height-br.height 1435 1435 ); 1436 1436 }); 1437 1437 1438 - var pool= 1439 - bordered.length 1440 - ?bordered 1441 - :candidates; 1395 + return rows[0]||null; 1396 + } 1442 1442 1443 - pool.sort(function(a,b){ 1444 - var ar= 1445 - a.getBoundingClientRect(); 1398 + function alignGeneric(cards){ 1399 + var rows= 1400 + cards.map(function(card){ 1401 + var h= 1402 + heading(card); 1446 1446 1447 - var br= 1448 - b.getBoundingClientRect(); 1404 + var c= 1405 + firstContent( 1406 + card, 1407 + h 1408 + ); 1449 1449 1450 - return ( 1451 - ar.left-br.left|| 1452 - br.width-ar.width 1453 - ); 1454 - }); 1410 + if(!h||!c)return null; 1455 1455 1456 - r eturnpool[0]||link;1457 - }1412 + var cr= 1413 + card.getBoundingClientRect(); 1458 1458 1459 - function applyOverviewPalette(){ 1460 - if(PAGE_KIND!=="overview"){ 1461 - return []; 1415 + var rr= 1416 + c.getBoundingClientRect(); 1417 + 1418 + return { 1419 + content:c, 1420 + relativeTop: 1421 + rr.top-cr.top 1422 + }; 1423 + }); 1424 + 1425 + if( 1426 + rows.some(function(row){ 1427 + return !row; 1428 + }) 1429 + ){ 1430 + return false; 1462 1462 } 1463 1463 1464 - var headers= 1465 - smallestThemeHeaders() 1466 - .map(function(el){ 1467 - return { 1468 - el:el, 1469 - theme: 1470 - themeFor( 1471 - el.textContent 1472 - ), 1473 - card: 1474 - findOverviewCard( 1475 - el 1476 - ) 1477 - }; 1433 + var target= 1434 + Math.max.apply( 1435 + Math, 1436 + rows.map(function(row){ 1437 + return row.relativeTop; 1478 1478 }) 1479 - .filter(function(row){ 1480 - return !!row.card; 1481 - }); 1439 + ); 1482 1482 1483 - var unique=[]; 1484 - var seenHeaders=new Set(); 1441 + rows.forEach(function(row){ 1442 + var delta= 1443 + target- 1444 + row.relativeTop; 1485 1485 1486 - headers.forEach(function(row){ 1487 - var key= 1488 - row.theme.name+ 1489 - "|"+ 1490 - Math.round( 1491 - row.card 1492 - .getBoundingClientRect() 1493 - .left 1494 - )+ 1495 - "|"+ 1496 - Math.round( 1497 - row.el 1498 - .getBoundingClientRect() 1499 - .top 1500 - ); 1446 + if(delta<=1)return; 1501 1501 1502 - if(!seenHeaders.has(key)){ 1503 - seenHeaders.add(key); 1504 - unique.push(row); 1505 - } 1506 - }); 1507 - 1508 - unique.forEach(function(row){ 1509 - var headerRect= 1510 - row.el 1511 - .getBoundingClientRect(); 1512 - 1513 - row.el.style.setProperty( 1514 - "background", 1515 - row.theme.bg, 1516 - "important" 1448 + saveOriginal( 1449 + row.content, 1450 + originalMarginTop, 1451 + "margin-top" 1517 1517 ); 1518 1518 1519 - row.el.style.setProperty( 1520 - "color", 1521 - row.theme.text, 1522 - "important" 1523 - ); 1454 + var current= 1455 + num( 1456 + getComputedStyle( 1457 + row.content 1458 + ).marginTop 1459 + ); 1524 1524 1525 - row.el.style.setProperty( 1526 - "text-align", 1527 - "left", 1528 - "important" 1461 + row.content.style.setProperty( 1462 + "margin-top", 1463 + ( 1464 + current+ 1465 + delta 1466 + )+"px" 1529 1529 ); 1530 1530 1531 - row.el.style.setProperty( 1532 - "word-spacing", 1533 - "normal", 1534 - "important" 1469 + row.content.setAttribute( 1470 + "data-sn-first-content-aligned", 1471 + "7" 1535 1535 ); 1536 1536 1537 - var later= 1538 - unique 1539 - .filter(function(other){ 1540 - return ( 1541 - other.card===row.card&& 1542 - other.el 1543 - .getBoundingClientRect() 1544 - .top> 1545 - headerRect.top+2 1546 - ); 1547 - }) 1548 - .sort(function(a,b){ 1549 - return ( 1550 - a.el 1551 - .getBoundingClientRect() 1552 - .top- 1553 - b.el 1554 - .getBoundingClientRect() 1555 - .top 1556 - ); 1557 - }); 1558 - 1559 - var stopTop= 1560 - later.length 1561 - ?later[0].el 1562 - .getBoundingClientRect() 1563 - .top 1564 - :Infinity; 1565 - 1566 - Array.from( 1567 - row.card.querySelectorAll("a") 1568 - ).forEach(function(link){ 1569 - if(!visible(link))return; 1570 - 1571 - var rect= 1572 - link.getBoundingClientRect(); 1573 - 1574 - if( 1575 - rect.top<= 1576 - headerRect.bottom-2|| 1577 - rect.top>= 1578 - stopTop-2 1579 - ){ 1580 - return; 1581 - } 1582 - 1583 - var candidates= 1584 - rowCandidates( 1585 - link, 1586 - row.card 1587 - ); 1588 - 1589 - var target= 1590 - chooseOuterRow( 1591 - candidates, 1592 - link 1593 - ); 1594 - 1595 - candidates.forEach(function(el){ 1596 - el.style.setProperty( 1597 - "border-left", 1598 - "0 solid transparent", 1599 - "important" 1600 - ); 1601 - }); 1602 - 1603 - target.style.setProperty( 1604 - "border-left", 1605 - "3px solid "+ 1606 - row.theme.accent, 1607 - "important" 1608 - ); 1609 - 1610 - target.style.setProperty( 1611 - "box-sizing", 1612 - "border-box", 1613 - "important" 1614 - ); 1615 - }); 1474 + contentManaged.add( 1475 + row.content 1476 + ); 1616 1616 }); 1617 1617 1618 - return u nique;1479 + return true; 1619 1619 } 1620 1620 1621 - /* ======================================================= 1622 - OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW 1623 - ======================================================= */ 1482 + function applyRow(group){ 1483 + if(!validRow(group))return false; 1624 1624 1625 - function alignOverviewCards(headers){ 1626 - if( 1627 - PAGE_KIND!=="overview"|| 1628 - window.innerWidth<=MOBILE_MAX 1629 - ){ 1630 - return; 1631 - } 1632 - 1633 1633 var cards=[]; 1634 1634 var seen=new Set(); 1635 1635 1636 - headers.forEach(function(row){1637 - if(!seen.has(r ow.card)){1638 - seen.add(r ow.card);1639 - cards.push(r ow.card);1488 + group.entries.forEach(function(entry){ 1489 + if(!seen.has(entry.target)){ 1490 + seen.add(entry.target); 1491 + cards.push(entry.target); 1640 1640 } 1641 1641 }); 1642 1642 1643 - if(cards.length<2){ 1644 - return; 1495 + if(cards.length<2)return false; 1496 + 1497 + if( 1498 + !alignKnownBars(cards) 1499 + ){ 1500 + alignGeneric(cards); 1645 1645 } 1646 1646 1647 - // Group cards by actual top position. 1648 - var groups=[]; 1503 + var maxHeight=0; 1649 1649 1650 1650 cards.forEach(function(card){ 1651 - var top= 1652 - card.getBoundingClientRect().top; 1653 - 1654 - var group=null; 1655 - 1656 - for(var i=0;i<groups.length;i++){ 1657 - if( 1658 - Math.abs( 1659 - groups[i].top-top 1660 - )<=ROW_TOLERANCE 1661 - ){ 1662 - group=groups[i]; 1663 - break; 1664 - } 1665 - } 1666 - 1667 - if(!group){ 1668 - group={ 1669 - top:top, 1670 - cards:[] 1671 - }; 1672 - groups.push(group); 1673 - } 1674 - 1675 - group.cards.push(card); 1506 + maxHeight= 1507 + Math.max( 1508 + maxHeight, 1509 + card.getBoundingClientRect().height 1510 + ); 1676 1676 }); 1677 1677 1678 - groups.forEach(function(group){1679 - if(group.cards.length<2){1680 - return;1681 - }1513 + maxHeight= 1514 + Math.ceil( 1515 + maxHeight 1516 + ); 1682 1682 1683 - var firstHeaders= 1684 - group.cards.map(function(card){ 1685 - var candidates= 1686 - headers 1687 - .filter(function(row){ 1688 - return row.card===card; 1689 - }) 1690 - .sort(function(a,b){ 1691 - return ( 1692 - a.el 1693 - .getBoundingClientRect() 1694 - .top- 1695 - b.el 1696 - .getBoundingClientRect() 1697 - .top 1698 - ); 1699 - }); 1518 + if(maxHeight<MIN_H)return false; 1700 1700 1701 - return candidates.length 1702 - ?candidates[0] 1703 - :null; 1704 - }); 1520 + cards.forEach(function(card){ 1521 + saveOriginal( 1522 + card, 1523 + originalMinHeight, 1524 + "min-height" 1525 + ); 1705 1705 1706 - if( 1707 - !firstHeaders.some(function(row){ 1708 - return !row; 1709 - }) 1710 - ){ 1711 - var targetTop= 1712 - Math.max.apply( 1713 - Math, 1714 - firstHeaders.map(function(row){ 1715 - return ( 1716 - row.el 1717 - .getBoundingClientRect() 1718 - .top- 1719 - row.card 1720 - .getBoundingClientRect() 1721 - .top 1722 - ); 1723 - }) 1724 - ); 1527 + card.style.setProperty( 1528 + "min-height", 1529 + maxHeight+"px" 1530 + ); 1725 1725 1726 - firstHeaders.forEach(function(row){ 1727 - var relativeTop= 1728 - row.el 1729 - .getBoundingClientRect() 1730 - .top- 1731 - row.card 1732 - .getBoundingClientRect() 1733 - .top; 1532 + card.setAttribute( 1533 + "data-sn-equal-height-managed", 1534 + "7" 1535 + ); 1734 1734 1735 - var delta=1736 - targetTop-relativeTop;1537 + heightManaged.add(card); 1538 + }); 1737 1737 1738 - if(delta>1){ 1739 - saveStyle( 1740 - row.el, 1741 - originalMargin, 1742 - "margin-top" 1743 - ); 1540 + return true; 1541 + } 1744 1744 1745 - var current= 1746 - num( 1747 - getComputedStyle( 1748 - row.el 1749 - ).marginTop 1750 - ); 1543 + function calculate(force){ 1544 + if(applying)return; 1751 1751 1752 - row.el.style.setProperty( 1753 - "margin-top", 1754 - ( 1755 - current+delta 1756 - )+"px" 1757 - ); 1546 + var width= 1547 + Math.round( 1548 + window.innerWidth 1549 + ); 1758 1758 1759 - row.el.setAttribute( 1760 - "data-sn-master-first-row", 1761 - "1" 1762 - ); 1551 + var meaningful= 1552 + lastWidth<0|| 1553 + Math.abs( 1554 + width- 1555 + lastWidth 1556 + )>= 1557 + MIN_WIDTH_CHANGE; 1763 1763 1764 - managedMargin.add( 1765 - row.el 1766 - ); 1767 - } 1768 - }); 1769 - } 1770 - 1771 - var maxHeight=0; 1772 - 1773 - group.cards.forEach(function(card){ 1774 - maxHeight= 1775 - Math.max( 1776 - maxHeight, 1777 - card 1778 - .getBoundingClientRect() 1779 - .height 1780 - ); 1781 - }); 1782 - 1783 - maxHeight= 1784 - Math.ceil(maxHeight); 1785 - 1786 - group.cards.forEach(function(card){ 1787 - saveStyle( 1788 - card, 1789 - originalHeight, 1790 - "min-height" 1791 - ); 1792 - 1793 - card.style.setProperty( 1794 - "min-height", 1795 - maxHeight+"px" 1796 - ); 1797 - 1798 - card.setAttribute( 1799 - "data-sn-master-equal-height", 1800 - "1" 1801 - ); 1802 - 1803 - managedHeight.add( 1804 - card 1805 - ); 1806 - }); 1807 - }); 1808 - } 1809 - 1810 - /* ======================================================= 1811 - DETAIL GRID EQUAL HEIGHT, DESKTOP ONLY 1812 - ======================================================= */ 1813 - 1814 - function equaliseDetailGrids(){ 1815 1815 if( 1816 - PAGE_KIND!=="detail"|| 1817 - window.innerWidth<=MOBILE_MAX 1560 + hasApplied&& 1561 + !force&& 1562 + !meaningful 1818 1818 ){ 1819 1819 return; 1820 1820 } 1821 1821 1822 - var selectors=[ 1823 - ".arsn-grid", 1824 - ".arsn-grid-2", 1825 - ".arsn-grid-3", 1826 - ".dmp-grid", 1827 - ".ido-grid", 1828 - ".pp-grid" 1829 - ]; 1567 + applying=true; 1830 1830 1831 - selectors.forEach(function(selector){ 1832 - Array.from( 1833 - root.querySelectorAll(selector) 1834 - ).forEach(function(grid){ 1835 - var children= 1836 - Array.from( 1837 - grid.children||[] 1838 - ).filter(visible); 1569 + try{ 1570 + harmoniseCustomCallouts(); 1839 1839 1840 - if(children.length<2){ 1841 - return; 1572 + if(width<=MOBILE_MAX){ 1573 + if(hasApplied){ 1574 + resetRuntime(); 1842 1842 } 1843 1843 1844 - var groups=[]; 1577 + hasApplied=false; 1578 + lastWidth=width; 1579 + return; 1580 + } 1845 1845 1846 - children.forEach(function(child){ 1847 - var top= 1848 - child 1849 - .getBoundingClientRect() 1850 - .top; 1582 + if(hasApplied){ 1583 + resetRuntime(); 1584 + } 1851 1851 1852 - var group=null; 1586 + var parents= 1587 + Array.from( 1588 + root.querySelectorAll("*") 1589 + ) 1590 + .filter(function(parent){ 1591 + return ( 1592 + visible( 1593 + parent, 1594 + MIN_W, 1595 + MIN_H 1596 + )&& 1597 + parent.children&& 1598 + parent.children.length>=2&& 1599 + parent.children.length<= 1600 + MAX_PARENT_CHILDREN 1601 + ); 1602 + }); 1853 1853 1854 - for(var i=0;i<groups.length;i++){ 1855 - if( 1856 - Math.abs( 1857 - groups[i].top-top 1858 - )<=ROW_TOLERANCE 1859 - ){ 1860 - group=groups[i]; 1861 - break; 1862 - } 1863 - } 1604 + var touched= 1605 + new Set(); 1864 1864 1865 - if(!group){ 1866 - group={ 1867 - top:top, 1868 - items:[] 1869 - }; 1870 - groups.push(group); 1871 - } 1607 + parents.forEach(function(parent){ 1608 + var entries=[]; 1872 1872 1873 - group.items.push(child); 1874 - }); 1875 - 1876 - groups.forEach(function(group){ 1877 - if(group.items.length<2){ 1610 + Array.from( 1611 + parent.children 1612 + ).forEach(function(child){ 1613 + if( 1614 + !visible( 1615 + child, 1616 + MIN_W, 1617 + MIN_H 1618 + ) 1619 + ){ 1878 1878 return; 1879 1879 } 1880 1880 1881 - var maxHeight=0; 1623 + var target= 1624 + pickTarget(child); 1882 1882 1883 - group.items.forEach(function(item){ 1884 - maxHeight= 1885 - Math.max( 1886 - maxHeight, 1887 - item 1888 - .getBoundingClientRect() 1889 - .height 1890 - ); 1626 + if(!target)return; 1627 + 1628 + entries.push({ 1629 + target:target, 1630 + rect: 1631 + target.getBoundingClientRect() 1891 1891 }); 1633 + }); 1892 1892 1893 - maxHeight= 1894 - Math.ceil(maxHeight); 1635 + groupRows( 1636 + entries 1637 + ).forEach(function(group){ 1638 + if(!validRow(group))return; 1895 1895 1896 - group.items.forEach(function(item){ 1897 - saveStyle( 1898 - item, 1899 - originalHeight, 1900 - "min-height" 1901 - ); 1640 + var targets= 1641 + group.entries.map(function(entry){ 1642 + return entry.target; 1643 + }); 1902 1902 1903 - item.style.setProperty( 1904 - "min-height", 1905 - maxHeight+"px" 1906 - ); 1645 + if( 1646 + !targets.some(function(el){ 1647 + return !touched.has(el); 1648 + }) 1649 + ){ 1650 + return; 1651 + } 1907 1907 1908 - item.setAttribute( 1909 - "data-sn-master-equal-height", 1910 - "1" 1911 - ); 1912 - 1913 - managedHeight.add(item); 1914 - }); 1653 + if(applyRow(group)){ 1654 + targets.forEach(function(el){ 1655 + touched.add(el); 1656 + }); 1657 + } 1915 1915 }); 1916 1916 }); 1917 - }); 1918 - } 1919 1919 1920 - /* ======================================================= 1921 - RUN / RESPONSIVE SCHEDULING 1922 - ======================================================= */ 1923 - 1924 - function run(){ 1925 - if(running)return; 1926 - 1927 - running=true; 1928 - 1929 - try{ 1930 - resetRuntime(); 1931 - applyPlaceholderBadge(); 1932 - propagateDetailAccents(); 1933 - 1934 - var headers= 1935 - applyOverviewPalette(); 1936 - 1937 - makeThreeLineAreaLabels(); 1938 - makeFilledRedOrangeCTAsBorderless(); 1939 - 1940 - if( 1941 - window.innerWidth> 1942 - MOBILE_MAX 1943 - ){ 1944 - alignOverviewCards( 1945 - headers 1946 - ); 1947 - 1948 - equaliseDetailGrids(); 1949 - } 1661 + lastWidth=width; 1662 + hasApplied=true; 1950 1950 }finally{ 1951 - running=false;1664 + applying=false; 1952 1952 } 1953 1953 } 1954 1954 1955 - function onResize(){1668 + function resize(){ 1956 1956 if(resizeTimer){ 1957 1957 clearTimeout( 1958 1958 resizeTimer ... ... @@ -1963,40 +1963,19 @@ 1963 1963 setTimeout( 1964 1964 function(){ 1965 1965 resizeTimer=0; 1966 - run();1679 + calculate(false); 1967 1967 }, 1968 1968 RESIZE_DEBOUNCE 1969 1969 ); 1970 1970 } 1971 1971 1972 - async function waitForReady(){ 1973 - if( 1974 - document.readyState!=="complete" 1975 - ){ 1976 - await new Promise(function(resolve){ 1977 - window.addEventListener( 1978 - "load", 1979 - resolve, 1980 - {once:true} 1981 - ); 1982 - }); 1983 - } 1984 - 1985 - if( 1986 - document.fonts&& 1987 - document.fonts.ready 1988 - ){ 1989 - try{ 1990 - await document.fonts.ready; 1991 - }catch(error){} 1992 - } 1993 - 1685 + function waitImages(){ 1994 1994 var images= 1995 1995 Array.from( 1996 1996 root.querySelectorAll("img") 1997 1997 ); 1998 1998 1999 - await Promise.all(1691 + return Promise.all( 2000 2000 images.map(function(img){ 2001 2001 if(img.complete){ 2002 2002 return Promise.resolve(); ... ... @@ -2021,20 +2021,46 @@ 2021 2021 }); 2022 2022 }) 2023 2023 ); 1716 + } 2024 2024 2025 - run(); 1718 + async function initial(){ 1719 + if( 1720 + document.readyState!== 1721 + "complete" 1722 + ){ 1723 + await new Promise(function(resolve){ 1724 + addEventListener( 1725 + "load", 1726 + resolve, 1727 + {once:true} 1728 + ); 1729 + }); 1730 + } 1731 + 1732 + if( 1733 + document.fonts&& 1734 + document.fonts.ready 1735 + ){ 1736 + try{ 1737 + await document.fonts.ready; 1738 + }catch(error){} 1739 + } 1740 + 1741 + await waitImages(); 1742 + 1743 + // Exactly one initial layout calculation. 1744 + calculate(true); 2026 2026 } 2027 2027 2028 - window.addEventListener(1747 + addEventListener( 2029 2029 "resize", 2030 - onResize,1749 + resize, 2031 2031 {passive:true} 2032 2032 ); 2033 2033 2034 - waitForReady();1753 + initial(); 2035 2035 })(); 2036 2036 </script> 2037 2037 2038 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END --> 2039 -{{/html}} 2040 - 1757 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_END --> 1758 +{{/html}}\n