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