Last modified by Veronika Kocher on Friday, 18 Sep 2026 16:47

From version 41.3
edited by Veronika Kocher
on Friday, 04 Sep 2026 14:23
Change comment: There is no comment for this version
To version 39.22
edited by Veronika Kocher
on Thursday, 03 Sep 2026 9:34
Change comment: There is no comment for this version

Summary

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 &amp; Research Services Navigator</h2>
... ... @@ -435,9 +435,9 @@
435 435  )))
436 436  )))
437 437  
438 -(% class="arsn-phase-cta-wrap" style="padding:0 16px 16px 16px;" %)
442 +(% style="padding:0 16px 16px 16px;" %)
439 439  (((
440 -[[Explore Enable>>https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/Enable/||class="btn btn-primary btn-block arsn-phase-cta"]]
444 +[[Explore Enable>>https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/Enable/||class="btn btn-primary btn-block"]]
441 441  )))
442 442  )))
443 443  )))
... ... @@ -501,9 +501,9 @@
501 501  )))
502 502  )))
503 503  
504 -(% class="arsn-phase-cta-wrap" style="padding:0 16px 16px 16px;" %)
508 +(% style="padding:0 16px 16px 16px;" %)
505 505  (((
506 -[[Explore Work & Manage>>https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/Work%20%26%20Manage/||class="btn btn-primary btn-block arsn-phase-cta"]]
510 +[[Explore Work & Manage>>https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/Work%20%26%20Manage/||class="btn btn-primary btn-block"]]
507 507  )))
508 508  )))
509 509  )))
... ... @@ -577,9 +577,9 @@
577 577  )))
578 578  )))
579 579  
580 -(% class="arsn-phase-cta-wrap" style="padding:0 16px 16px 16px;" %)
584 +(% style="padding:0 16px 16px 16px;" %)
581 581  (((
582 -[[Explore Publish & Share>>https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/Publish%20%26%20Share/||class="btn btn-primary btn-block arsn-phase-cta"]]
586 +[[Explore Publish & Share>>https://xwiki.uni-ak.ac.at/bin/view/Service%20Navigator/Art%20%26%20Research%20Services%20Navigator/Publish%20%26%20Share/||class="btn btn-primary btn-block"]]
583 583  )))
584 584  )))
585 585  )))
... ... @@ -588,11 +588,6 @@
588 588  
589 589  (% style="margin-top:30px;" %)
590 590  (((
591 -
592 -<!-- ARSN_TRAINING_WORKSHOPS_INCLUDE_V1_START -->
593 -{{include reference="Service Navigator.Art & Research Services Navigator.Code.TrainingWorkshopsBlock" author="target" /}}
594 -<!-- ARSN_TRAINING_WORKSHOPS_INCLUDE_V1_END -->
595 -
596 596  == Practical resources ==
597 597  
598 598  Use practical resources when you need a concise overview, a step-by-step procedure or a ready-to-use project aid.
... ... @@ -641,132 +641,23 @@
641 641  )))
642 642  
643 643  {{html clean="false"}}
644 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_START -->
645 -
646 -<style data-sn-service-navigator-master="1">
647 -/* =========================================================
648 - MASTER TYPOGRAPHY
649 - ========================================================= */
650 -#xwikicontent h1,
651 -#xwikicontent h2,
652 -#xwikicontent h3,
653 -#xwikicontent h4,
654 -#xwikicontent h5,
655 -#xwikicontent h6,
656 -#xwikicontent .box-title,
657 -#xwikicontent [role="heading"],
658 -#xwikicontent h1 a,
659 -#xwikicontent h2 a,
660 -#xwikicontent h3 a,
661 -#xwikicontent h4 a,
662 -#xwikicontent h5 a,
663 -#xwikicontent h6 a,
664 -#xwikicontent .box-title a,
665 -#xwikicontent [role="heading"] a{
666 - text-align:left!important;
667 - text-justify:auto!important;
668 - word-spacing:normal!important;
669 -}
670 -
671 -/* =========================================================
672 - COMING SOON / IN VORBEREITUNG
673 - ========================================================= */
674 -.sn-coming-soon-badge{
675 - display:inline-block;
676 - vertical-align:middle;
677 - margin-left:10px;
678 - padding:4px 8px;
679 - border-radius:14px;
680 - border:1px solid #efd9cc;
681 - background:#fff4ee;
682 - color:#8a4d36;
683 - font-size:11px;
684 - font-weight:700;
685 - letter-spacing:.055em;
686 - line-height:1.2;
687 - white-space:nowrap;
688 -}
689 -
690 -/* =========================================================
691 - NATIVE / DETAIL CALLOUT GEOMETRY
692 - Preserve existing backgrounds.
693 - ========================================================= */
694 -#xwikicontent .arsn-info,
695 -#xwikicontent .dmp-info,
696 -#xwikicontent .ido-info,
697 -#xwikicontent .pp-info,
698 -#xwikicontent .infomessage{
699 - box-sizing:border-box!important;
700 - border-left:4px solid #21b6d7!important;
701 - border-radius:8px;
702 - text-align:left!important;
703 - word-spacing:normal!important;
704 -}
705 -
706 -#xwikicontent .arsn-warn,
707 -#xwikicontent .dmp-warn,
708 -#xwikicontent .ido-warn,
709 -#xwikicontent .pp-warn,
710 -#xwikicontent .warn,
711 -#xwikicontent .warning,
712 -#xwikicontent .warningmessage,
713 -#xwikicontent .errormessage{
714 - box-sizing:border-box!important;
715 - border-left:4px solid #e94b13!important;
716 - border-radius:8px;
717 - text-align:left!important;
718 - word-spacing:normal!important;
719 -}
720 -
721 -[data-sn-master-equal-height],
722 -[data-sn-master-first-row]{
643 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_START -->
644 +<style data-sn-horizontal-box-harmonizer="4">
645 +[data-sn-equal-height-managed],
646 +[data-sn-first-section-aligned]{
723 723   box-sizing:border-box;
724 724  }
725 -
726 -/* =========================================================
727 - FULL-WIDTH THREE-LINE NUMBER / TITLE / SUBTITLE BLOCKS
728 - ========================================================= */
729 -#xwikicontent .arsn-area-label[data-sn-three-line="1"]{
730 - display:grid!important;
731 - grid-template-columns:minmax(0,1fr)!important;
732 - grid-auto-rows:auto!important;
733 - width:100%!important;
734 - max-width:none!important;
735 - box-sizing:border-box!important;
736 - justify-items:start!important;
737 - align-items:start!important;
738 - gap:2px!important;
739 - text-align:left!important;
740 - text-align-last:left!important;
741 - text-justify:auto!important;
742 - word-spacing:normal!important;
743 - white-space:normal!important;
744 -}
745 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .arsn-area-number,
746 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .sn-area-label-title,
747 -#xwikicontent .arsn-area-label[data-sn-three-line="1"] > .arsn-area-action{
748 - display:block!important;
749 - width:100%!important;
750 - margin:0!important;
751 - text-align:left!important;
752 - text-align-last:left!important;
753 - text-justify:auto!important;
754 - word-spacing:normal!important;
755 - white-space:normal!important;
756 -}
757 757  </style>
758 -
759 -<script data-sn-service-navigator-master="1">
650 +<script data-sn-horizontal-box-harmonizer="4">
760 760  (function(){
761 761   "use strict";
762 762  
763 - var PAGE_KIND="overview";
764 - var PLACEHOLDER=false;
765 - var PLACEHOLDER_LABEL="COMING SOON";
766 -
767 767   var MOBILE_MAX=767;
768 768   var ROW_TOLERANCE=6;
769 - var RESIZE_DEBOUNCE=220;
656 + var MIN_W=150;
657 + var MIN_H=36;
658 + var MAX_PARENT_CHILDREN=16;
659 + var SEARCH_DEPTH=5;
770 770  
771 771   var root=
772 772   document.getElementById("xwikicontent")||
... ... @@ -776,105 +776,93 @@
776 776  
777 777   if(!root)return;
778 778  
779 - var managedHeight=new Set();
780 - var managedMargin=new Set();
781 - var originalHeight=new WeakMap();
782 - var originalMargin=new WeakMap();
669 + var heightManaged=new Set();
670 + var sectionManaged=new Set();
671 + var originalMinHeight=new WeakMap();
672 + var originalMarginTop=new WeakMap();
673 + var raf=0;
783 783  
784 - var resizeTimer=0;
785 - var running=false;
675 + function num(v){
676 + var n=parseFloat(v);
677 + return Number.isFinite(n)?n:0;
678 + }
786 786  
787 - var THEMES=[
788 - {
789 - name:"BLUE",
790 - accent:"#21b6d7",
791 - bg:"#eaf7fb",
792 - text:"#315d68",
793 - labels:[
794 - "HIER STARTEN",
795 - "ENTSCHEIDEN",
796 - "ÜBERPRÜFEN & ANPASSEN",
797 - "START HERE",
798 - "DECIDE",
799 - "REVIEW & ADAPT"
800 - ]
801 - },
802 - {
803 - name:"RED",
804 - accent:"#e94b13",
805 - bg:"#fff1ec",
806 - text:"#8a4d36",
807 - labels:[
808 - "PLANEN & ORGANISIEREN",
809 - "ORGANISIEREN & DOKUMENTIEREN",
810 - "PUBLIZIEREN & PRÄSENTIEREN",
811 - "PLAN & ORGANISE",
812 - "PLAN & ORGANIZE",
813 - "ORGANISE & DOCUMENT",
814 - "ORGANIZE & DOCUMENT",
815 - "PUBLISH & PRESENT"
816 - ]
817 - },
818 - {
819 - name:"YELLOW",
820 - accent:"#f0aa00",
821 - bg:"#fff8e7",
822 - text:"#785b17",
823 - labels:[
824 - "SCHÜTZEN & KLÄREN",
825 - "STANDARDISIEREN & IDENTIFIZIEREN",
826 - "ÖFFNEN, NACHNUTZEN & AUFFINDBAR MACHEN",
827 - "PROTECT & CLARIFY",
828 - "STANDARDISE & IDENTIFY",
829 - "STANDARDIZE & IDENTIFY",
830 - "OPEN, REUSE & MAKE FINDABLE"
831 - ]
832 - },
833 - {
834 - name:"GREEN",
835 - accent:"#38b76a",
836 - bg:"#edf9f1",
837 - text:"#3f7451",
838 - labels:[
839 - "INFRASTRUKTUR EINRICHTEN",
840 - "INFRASTRUKTUR & ZUSAMMENARBEIT EINRICHTEN",
841 - "SPEICHERN & ZUGRIFF STEUERN",
842 - "REPOSITORIUM, ERHALTEN & ÜBERGEBEN",
843 - "SET UP INFRASTRUCTURE",
844 - "SET UP INFRASTRUCTURE & COLLABORATION",
845 - "STORE & CONTROL ACCESS",
846 - "REPOSITORY, PRESERVE & HAND OVER"
847 - ]
680 + function visible(el,minW,minH){
681 + if(!el||el.nodeType!==1)return false;
682 +
683 + var s=getComputedStyle(el);
684 +
685 + if(
686 + s.display==="none"||
687 + s.visibility==="hidden"||
688 + Number(s.opacity)===0
689 + ){
690 + return false;
848 848   }
849 - ];
850 850  
851 - function num(value){
852 - var n=parseFloat(value);
853 - return Number.isFinite(n)?n:0;
693 + var r=el.getBoundingClientRect();
694 +
695 + return (
696 + r.width>=(minW||1)&&
697 + r.height>=(minH||1)
698 + );
854 854   }
855 855  
856 - function norm(value){
857 - return String(value||"")
858 - .replace(/\s+/g," ")
859 - .trim()
860 - .toUpperCase();
701 + function excluded(el){
702 + return (
703 + !el.matches||
704 + el.matches(
705 + "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]"
706 + )
707 + );
861 861   }
862 862  
863 - function visible(el){
864 - if(!el||el.nodeType!==1)return false;
710 + function namedLikeBox(el){
711 + var c=
712 + typeof el.className==="string"
713 + ? el.className
714 + : "";
865 865  
866 - var style=getComputedStyle(el);
867 - var rect=el.getBoundingClientRect();
716 + return /(^|[s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([s_-]|$)/i.test(c);
717 + }
868 868  
719 + function boxLike(el){
720 + if(!visible(el,MIN_W,MIN_H)||excluded(el))return false;
721 +
722 + var s=getComputedStyle(el);
723 + var r=el.getBoundingClientRect();
724 +
725 + var border=
726 + num(s.borderTopWidth)+
727 + num(s.borderRightWidth)+
728 + num(s.borderBottomWidth)+
729 + num(s.borderLeftWidth);
730 +
731 + var radius=Math.max(
732 + num(s.borderTopLeftRadius),
733 + num(s.borderTopRightRadius),
734 + num(s.borderBottomLeftRadius),
735 + num(s.borderBottomRightRadius)
736 + );
737 +
738 + var bg=
739 + s.backgroundColor&&
740 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
741 + s.backgroundColor!=="transparent";
742 +
743 + var shadow=
744 + s.boxShadow&&
745 + s.boxShadow!=="none";
746 +
869 869   return (
870 - style.display!=="none"&&
871 - style.visibility!=="hidden"&&
872 - rect.width>20&&
873 - rect.height>4
748 + namedLikeBox(el)||
749 + border>=1||
750 + (bg&&radius>=3)||
751 + (shadow&&r.width>=180)
874 874   );
875 875   }
876 876  
877 - function saveStyle(el,map,property){
755 + function saveOriginal(el,map,property){
878 878   if(map.has(el))return;
879 879  
880 880   map.set(el,{
... ... @@ -883,7 +883,7 @@
883 883   });
884 884   }
885 885  
886 - function restoreStyle(el,map,property){
764 + function restoreOriginal(el,map,property){
887 887   var original=map.get(el);
888 888  
889 889   if(original&&original.value){
... ... @@ -897,470 +897,247 @@
897 897   }
898 898   }
899 899  
900 - function resetRuntime(){
901 - managedHeight.forEach(function(el){
902 - restoreStyle(
778 + function reset(){
779 + heightManaged.forEach(function(el){
780 + restoreOriginal(
903 903   el,
904 - originalHeight,
782 + originalMinHeight,
905 905   "min-height"
906 906   );
785 +
907 907   el.removeAttribute(
908 - "data-sn-master-equal-height"
787 + "data-sn-equal-height-managed"
909 909   );
910 910   });
911 911  
912 - managedMargin.forEach(function(el){
913 - restoreStyle(
791 + sectionManaged.forEach(function(el){
792 + restoreOriginal(
914 914   el,
915 - originalMargin,
794 + originalMarginTop,
916 916   "margin-top"
917 917   );
797 +
918 918   el.removeAttribute(
919 - "data-sn-master-first-row"
799 + "data-sn-first-section-aligned"
920 920   );
921 921   });
922 922  
923 - managedHeight.clear();
924 - managedMargin.clear();
803 + heightManaged.clear();
804 + sectionManaged.clear();
925 925   }
926 926  
927 - function themeFor(text){
928 - var value=norm(text);
807 + function pickTarget(child){
808 + if(!visible(child,MIN_W,MIN_H))return null;
929 929  
930 - for(var i=0;i<THEMES.length;i++){
931 - for(var j=0;j<THEMES[i].labels.length;j++){
932 - var label=THEMES[i].labels[j];
933 -
934 - if(
935 - value===label||
936 - value.indexOf(label+" ")===0||
937 - value.indexOf(label+" -")===0||
938 - value.indexOf(label+" ·")===0
939 - ){
940 - return THEMES[i];
941 - }
942 - }
810 + if(boxLike(child)){
811 + return child;
943 943   }
944 944  
945 - return null;
946 - }
814 + var cr=child.getBoundingClientRect();
815 + var q=[];
947 947  
948 - /* =======================================================
949 - BORDERLESS FILLED RED/ORANGE CTA BUTTONS
950 - ======================================================= */
951 -
952 - function colourDistance(a,b){
953 - return Math.sqrt(
954 - Math.pow(a[0]-b[0],2)+
955 - Math.pow(a[1]-b[1],2)+
956 - Math.pow(a[2]-b[2],2)
957 - );
958 - }
959 -
960 - function makeFilledRedOrangeCTAsBorderless(){
961 - var RED_ORANGE=[233,75,19];
962 -
963 - Array.from(
964 - root.querySelectorAll(
965 - 'a,button,[role="button"],input[type="submit"],input[type="button"]'
966 - )
967 - ).forEach(function(el){
968 - if(!visible(el))return;
969 -
970 - var style=getComputedStyle(el);
971 - var rgb=parseRGB(style.backgroundColor);
972 -
973 - if(!rgb)return;
974 -
975 - if(
976 - colourDistance(
977 - rgb,
978 - RED_ORANGE
979 - )>55
980 - ){
981 - return;
982 - }
983 -
984 - var rect=el.getBoundingClientRect();
985 -
986 - if(
987 - rect.width<80||
988 - rect.height<24
989 - ){
990 - return;
991 - }
992 -
993 - el.style.setProperty(
994 - "border",
995 - "none",
996 - "important"
997 - );
998 -
999 - el.style.setProperty(
1000 - "border-left",
1001 - "none",
1002 - "important"
1003 - );
1004 -
1005 - el.style.setProperty(
1006 - "border-top",
1007 - "none",
1008 - "important"
1009 - );
1010 -
1011 - el.style.setProperty(
1012 - "border-right",
1013 - "none",
1014 - "important"
1015 - );
1016 -
1017 - el.style.setProperty(
1018 - "border-bottom",
1019 - "none",
1020 - "important"
1021 - );
1022 -
1023 - el.style.setProperty(
1024 - "box-shadow",
1025 - "none",
1026 - "important"
1027 - );
817 + Array.from(child.children||[]).forEach(function(el){
818 + q.push({el:el,depth:1});
1028 1028   });
1029 - }
1030 1030  
1031 - /* =======================================================
1032 - FULL-WIDTH THREE-LINE AREA LABELS
1033 - ======================================================= */
821 + var best=null;
822 + var bestScore=-Infinity;
1034 1034  
1035 - function compactText(value){
1036 - return String(value||"")
1037 - .replace(/\s+/g," ")
1038 - .trim();
1039 - }
824 + while(q.length){
825 + var item=q.shift();
826 + var el=item.el;
1040 1040  
1041 - function makeThreeLineAreaLabels(){
1042 - Array.from(
1043 - root.querySelectorAll(
1044 - ".arsn-area-label"
1045 - )
1046 - ).forEach(function(label){
1047 - if(
1048 - label.getAttribute(
1049 - "data-sn-three-line"
1050 - )==="1"
1051 - ){
1052 - return;
1053 - }
828 + if(!visible(el,MIN_W,MIN_H))continue;
1054 1054  
1055 - var number=
1056 - label.querySelector(
1057 - ":scope > .arsn-area-number"
1058 - );
830 + var r=el.getBoundingClientRect();
1059 1059  
1060 - var action=
1061 - label.querySelector(
1062 - ":scope > .arsn-area-action"
1063 - );
1064 -
1065 1065   if(
1066 - !number||
1067 - !action
833 + r.width>=cr.width*.68&&
834 + boxLike(el)
1068 1068   ){
1069 - return;
1070 - }
836 + var widthFit=
837 + 1-Math.min(
838 + 1,
839 + Math.abs(cr.width-r.width)/
840 + Math.max(1,cr.width)
841 + );
1071 1071  
1072 - var clone=
1073 - label.cloneNode(true);
843 + var topFit=
844 + 1-Math.min(
845 + 1,
846 + Math.abs(cr.top-r.top)/100
847 + );
1074 1074  
1075 - var cloneNumber=
1076 - clone.querySelector(
1077 - ":scope > .arsn-area-number"
1078 - );
849 + var score=
850 + widthFit*6+
851 + topFit*3+
852 + Math.min(r.height,900)/450+
853 + Math.min(r.width*r.height,900000)/900000;
1079 1079  
1080 - var cloneAction=
1081 - clone.querySelector(
1082 - ":scope > .arsn-area-action"
1083 - );
1084 -
1085 - if(cloneNumber){
1086 - cloneNumber.remove();
855 + if(score>bestScore){
856 + best=el;
857 + bestScore=score;
858 + }
1087 1087   }
1088 1088  
1089 - if(cloneAction){
1090 - cloneAction.remove();
861 + if(item.depth<SEARCH_DEPTH){
862 + Array.from(el.children||[]).forEach(function(next){
863 + q.push({
864 + el:next,
865 + depth:item.depth+1
866 + });
867 + });
1091 1091   }
869 + }
1092 1092  
1093 - var titleText=
1094 - compactText(
1095 - clone.textContent
1096 - );
871 + return best;
872 + }
1097 1097  
1098 - if(!titleText){
1099 - return;
1100 - }
874 + function groupsByVisualRow(entries){
875 + var groups=[];
1101 1101  
1102 - var numberNode=
1103 - number.cloneNode(true);
1104 -
1105 - var actionNode=
1106 - action.cloneNode(true);
1107 -
1108 - var titleNode=
1109 - document.createElement(
1110 - "span"
877 + entries
878 + .slice()
879 + .sort(function(a,b){
880 + return (
881 + a.rect.top-b.rect.top||
882 + a.rect.left-b.rect.left
1111 1111   );
884 + })
885 + .forEach(function(entry){
886 + var group=null;
1112 1112  
1113 - titleNode.className=
1114 - "sn-area-label-title";
888 + for(var i=0;i<groups.length;i++){
889 + if(
890 + Math.abs(
891 + groups[i].top-
892 + entry.rect.top
893 + )<=ROW_TOLERANCE
894 + ){
895 + group=groups[i];
896 + break;
897 + }
898 + }
1115 1115  
1116 - titleNode.textContent=
1117 - titleText;
900 + if(!group){
901 + group={
902 + top:entry.rect.top,
903 + entries:[]
904 + };
905 + groups.push(group);
906 + }
1118 1118  
1119 - while(label.firstChild){
1120 - label.removeChild(
1121 - label.firstChild
1122 - );
1123 - }
908 + group.entries.push(entry);
909 + });
1124 1124  
1125 - label.appendChild(
1126 - numberNode
1127 - );
1128 -
1129 - label.appendChild(
1130 - titleNode
1131 - );
1132 -
1133 - label.appendChild(
1134 - actionNode
1135 - );
1136 -
1137 - label.setAttribute(
1138 - "data-sn-three-line",
1139 - "1"
1140 - );
1141 -
1142 - var head=
1143 - label.closest(
1144 - ".arsn-area-head"
1145 - );
1146 -
1147 - if(head){
1148 - head.style.setProperty(
1149 - "width",
1150 - "100%",
1151 - "important"
1152 - );
1153 -
1154 - head.style.setProperty(
1155 - "max-width",
1156 - "100%",
1157 - "important"
1158 - );
1159 -
1160 - head.style.setProperty(
1161 - "box-sizing",
1162 - "border-box",
1163 - "important"
1164 - );
1165 - }
1166 - });
911 + return groups;
1167 1167   }
1168 1168  
1169 - /* =======================================================
1170 - PLACEHOLDER BADGE
1171 - ======================================================= */
914 + function validHorizontalGroup(group){
915 + if(group.entries.length<2)return false;
1172 1172  
1173 - function applyPlaceholderBadge(){
1174 - if(!PLACEHOLDER)return;
917 + var lefts=
918 + group.entries
919 + .map(function(e){return e.rect.left;})
920 + .sort(function(a,b){return a-b;});
1175 1175  
1176 1176   if(
1177 - document.querySelector(
1178 - ".sn-coming-soon-badge"
1179 - )
923 + lefts[lefts.length-1]-
924 + lefts[0]<
925 + 80
1180 1180   ){
1181 - return;
927 + return false;
1182 1182   }
1183 1183  
1184 - var title=
1185 - document.querySelector(
1186 - "#document-title"
1187 - )||
1188 - document.querySelector(
1189 - "h1"
1190 - );
930 + var widths=
931 + group.entries
932 + .map(function(e){return e.rect.width;})
933 + .filter(function(w){return w>0;});
1191 1191  
1192 - if(!title)return;
935 + if(widths.length<2)return false;
1193 1193  
1194 - var badge=
1195 - document.createElement(
1196 - "span"
1197 - );
937 + var minWidth=Math.min.apply(Math,widths);
938 + var maxWidth=Math.max.apply(Math,widths);
1198 1198  
1199 - badge.className=
1200 - "sn-coming-soon-badge";
1201 -
1202 - badge.textContent=
1203 - PLACEHOLDER_LABEL;
1204 -
1205 - badge.setAttribute(
1206 - "aria-label",
1207 - PLACEHOLDER_LABEL
940 + return (
941 + maxWidth/
942 + Math.max(1,minWidth)<=
943 + 1.9
1208 1208   );
945 + }
1209 1209  
1210 - title.appendChild(
1211 - badge
1212 - );
947 + function normalizeText(text){
948 + return String(text||"")
949 + .replace(/s+/g," ")
950 + .trim()
951 + .toUpperCase();
1213 1213   }
1214 1214  
1215 - /* =======================================================
1216 - DETAIL PAGE OWN-ACCENT PROPAGATION
1217 - ======================================================= */
954 + function exactKnownFirstSection(el){
955 + var text=normalizeText(el.textContent);
1218 1218  
1219 - function parseRGB(value){
1220 - var match=String(value||"").match(
1221 - /rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)/i
957 + return (
958 + text==="HIER STARTEN"||
959 + text==="ORGANISIEREN & DOKUMENTIEREN"||
960 + text==="ENTSCHEIDEN"||
961 + text==="START HERE"||
962 + text==="GET STARTED"||
963 + text==="ORGANISE & DOCUMENT"||
964 + text==="ORGANIZE & DOCUMENT"||
965 + text==="DECIDE"
1222 1222   );
1223 -
1224 - if(!match)return null;
1225 -
1226 - return [
1227 - Number(match[1]),
1228 - Number(match[2]),
1229 - Number(match[3])
1230 - ];
1231 1231   }
1232 1232  
1233 - function distance(a,b){
1234 - return Math.sqrt(
1235 - Math.pow(a[0]-b[0],2)+
1236 - Math.pow(a[1]-b[1],2)+
1237 - Math.pow(a[2]-b[2],2)
1238 - );
1239 - }
969 + function visuallyFirstSectionBar(card){
970 + var cardRect=card.getBoundingClientRect();
971 + var candidates=[];
1240 1240  
1241 - function paletteMatch(cssColor){
1242 - var rgb=parseRGB(cssColor);
1243 -
1244 - if(!rgb)return null;
1245 -
1246 - var palette=[
1247 - {hex:"#21b6d7",rgb:[33,182,215]},
1248 - {hex:"#e94b13",rgb:[233,75,19]},
1249 - {hex:"#f0aa00",rgb:[240,170,0]},
1250 - {hex:"#38b76a",rgb:[56,183,106]}
1251 - ];
1252 -
1253 - var best=null;
1254 - var bestDistance=Infinity;
1255 -
1256 - palette.forEach(function(item){
1257 - var d=distance(rgb,item.rgb);
1258 -
1259 - if(d<bestDistance){
1260 - best=item;
1261 - bestDistance=d;
1262 - }
1263 - });
1264 -
1265 - return bestDistance<=30
1266 - ?best
1267 - :null;
1268 - }
1269 -
1270 - function propagateDetailAccents(){
1271 - if(PAGE_KIND!=="detail")return;
1272 -
1273 1273   Array.from(
1274 - root.querySelectorAll(
1275 - ".arsn-call,.dmp-call,.ido-call,.pp-call,"+
1276 - ".arsn-source,.dmp-source,.ido-source,.pp-source"
974 + card.querySelectorAll(
975 + "div,p,span,strong,h3,h4,h5,h6"
1277 1277   )
1278 1278   ).forEach(function(el){
1279 - if(!visible(el))return;
978 + if(!visible(el,20,6))return;
979 + if(excluded(el))return;
1280 1280  
1281 - var style=getComputedStyle(el);
981 + var r=el.getBoundingClientRect();
982 + var relativeTop=r.top-cardRect.top;
1282 1282  
1283 1283   if(
1284 - num(style.borderTopWidth)>=2
985 + relativeTop<45||
986 + relativeTop>cardRect.height*.72
1285 1285   ){
1286 - var match=
1287 - paletteMatch(
1288 - style.borderTopColor
1289 - );
1290 -
1291 - if(match){
1292 - el.style.setProperty(
1293 - "border-left",
1294 - "4px solid "+match.hex,
1295 - "important"
1296 - );
1297 - }
988 + return;
1298 1298   }
1299 - });
1300 1300  
1301 - // Warning families: explicit safety override.
1302 - Array.from(
1303 - root.querySelectorAll(
1304 - ".arsn-warn,.dmp-warn,.ido-warn,.pp-warn,"+
1305 - ".warn,.warning,.warningmessage,.errormessage"
1306 - )
1307 - ).forEach(function(el){
1308 - if(!visible(el))return;
991 + var widthRatio=
992 + r.width/
993 + Math.max(1,cardRect.width);
1309 1309  
1310 - el.style.setProperty(
1311 - "border-left",
1312 - "4px solid #e94b13",
1313 - "important"
1314 - );
1315 - });
995 + if(
996 + widthRatio<.55||
997 + widthRatio>1.05||
998 + r.height>54
999 + ){
1000 + return;
1001 + }
1316 1316  
1317 - // Info families: explicit orientation override.
1318 - Array.from(
1319 - root.querySelectorAll(
1320 - ".arsn-info,.dmp-info,.ido-info,.pp-info,.infomessage"
1321 - )
1322 - ).forEach(function(el){
1323 - if(!visible(el))return;
1003 + var text=normalizeText(el.textContent);
1324 1324  
1325 - el.style.setProperty(
1326 - "border-left",
1327 - "4px solid #21b6d7",
1328 - "important"
1329 - );
1330 - });
1331 - }
1005 + if(
1006 + text.length<2||
1007 + text.length>90
1008 + ){
1009 + return;
1010 + }
1332 1332  
1333 - /* =======================================================
1334 - OVERVIEW SEMANTIC THEME PALETTE
1335 - ======================================================= */
1012 + var style=getComputedStyle(el);
1336 1336  
1337 - function smallestThemeHeaders(){
1338 - return Array.from(
1339 - root.querySelectorAll(
1340 - "div,span,p,strong,h3,h4,h5,h6"
1341 - )
1342 - ).filter(function(el){
1343 - if(!visible(el))return false;
1344 - if(!themeFor(el.textContent))return false;
1014 + var bg=
1015 + style.backgroundColor&&
1016 + style.backgroundColor!=="rgba(0, 0, 0, 0)"&&
1017 + style.backgroundColor!=="transparent";
1345 1345  
1346 - return !Array.from(
1347 - el.children||[]
1348 - ).some(function(child){
1349 - return !!themeFor(
1350 - child.textContent
1351 - );
1352 - });
1353 - });
1354 - }
1355 -
1356 - function findOverviewCard(header){
1357 - var node=header.parentElement;
1358 - var candidates=[];
1359 -
1360 - while(node&&node!==root){
1361 - var rect=node.getBoundingClientRect();
1362 - var style=getComputedStyle(node);
1363 -
1364 1364   var border=
1365 1365   num(style.borderTopWidth)+
1366 1366   num(style.borderRightWidth)+
... ... @@ -1367,755 +1367,315 @@
1367 1367   num(style.borderBottomWidth)+
1368 1368   num(style.borderLeftWidth);
1369 1369  
1370 - if(
1371 - rect.width>=220&&
1372 - rect.width<=800&&
1373 - rect.height>=120&&
1374 - border>=1
1375 - ){
1376 - candidates.push(node);
1377 - }
1025 + var mostlyUpper=
1026 + text.length>=3&&
1027 + text===text.toUpperCase();
1378 1378  
1379 - node=node.parentElement;
1380 - }
1029 + var exact=exactKnownFirstSection(el);
1381 1381  
1382 - if(!candidates.length)return null;
1031 + var score=
1032 + (exact?20:0)+
1033 + (bg?6:0)+
1034 + (border>=1?2:0)+
1035 + (mostlyUpper?4:0)+
1036 + (num(style.fontWeight)>=600?1:0);
1383 1383  
1384 - candidates.sort(function(a,b){
1385 - return (
1386 - b.getBoundingClientRect().height-
1387 - a.getBoundingClientRect().height
1388 - );
1038 + if(score>=7){
1039 + candidates.push({
1040 + el:el,
1041 + relativeTop:relativeTop,
1042 + width:r.width,
1043 + score:score
1044 + });
1045 + }
1389 1389   });
1390 1390  
1391 - return candidates[0];
1392 - }
1048 + if(!candidates.length)return null;
1393 1393  
1394 - function rowCandidates(link,card){
1395 - var result=[];
1396 - var cardRect=
1397 - card.getBoundingClientRect();
1398 -
1399 - var node=link;
1400 -
1401 - while(node&&node!==card){
1402 - if(visible(node)){
1403 - var rect=
1404 - node.getBoundingClientRect();
1405 -
1406 - if(
1407 - rect.height<=105&&
1408 - rect.width>=
1409 - cardRect.width*.50&&
1410 - rect.width<=
1411 - cardRect.width*1.03
1412 - ){
1413 - result.push(node);
1414 - }
1050 + candidates.sort(function(a,b){
1051 + if(a.score!==b.score)return b.score-a.score;
1052 + if(Math.abs(a.relativeTop-b.relativeTop)>3){
1053 + return a.relativeTop-b.relativeTop;
1415 1415   }
1055 + return b.width-a.width;
1056 + });
1416 1416  
1417 - node=node.parentElement;
1418 - }
1058 + // For exact known labels always prefer the earliest exact match.
1059 + var exacts=candidates.filter(function(c){
1060 + return exactKnownFirstSection(c.el);
1061 + });
1419 1419  
1420 - return result;
1421 - }
1422 -
1423 - function chooseOuterRow(
1424 - candidates,
1425 - link
1426 - ){
1427 - if(!candidates.length){
1428 - return link;
1063 + if(exacts.length){
1064 + exacts.sort(function(a,b){
1065 + return a.relativeTop-b.relativeTop||b.width-a.width;
1066 + });
1067 + return exacts[0].el;
1429 1429   }
1430 1430  
1431 - var bordered=
1432 - candidates.filter(function(el){
1433 - return (
1434 - num(
1435 - getComputedStyle(el)
1436 - .borderLeftWidth
1437 - )>=1
1438 - );
1439 - });
1070 + // Generic fallback: earliest high-confidence bar.
1071 + candidates.sort(function(a,b){
1072 + return a.relativeTop-b.relativeTop||b.score-a.score||b.width-a.width;
1073 + });
1440 1440  
1441 - var pool=
1442 - bordered.length
1443 - ?bordered
1444 - :candidates;
1075 + return candidates[0].el;
1076 + }
1445 1445  
1446 - pool.sort(function(a,b){
1447 - var ar=
1448 - a.getBoundingClientRect();
1078 + function alignFirstSections(cards){
1079 + var rows=
1080 + cards.map(function(card){
1081 + var bar=
1082 + visuallyFirstSectionBar(card);
1449 1449  
1450 - var br=
1451 - b.getBoundingClientRect();
1084 + if(!bar)return null;
1452 1452  
1453 - return (
1454 - ar.left-br.left||
1455 - br.width-ar.width
1456 - );
1457 - });
1086 + var cardRect=
1087 + card.getBoundingClientRect();
1458 1458  
1459 - return pool[0]||link;
1460 - }
1089 + var barRect=
1090 + bar.getBoundingClientRect();
1461 1461  
1462 - function applyOverviewPalette(){
1463 - if(PAGE_KIND!=="overview"){
1464 - return [];
1092 + return {
1093 + card:card,
1094 + bar:bar,
1095 + relativeTop:
1096 + barRect.top-cardRect.top,
1097 + label:
1098 + normalizeText(bar.textContent)
1099 + };
1100 + });
1101 +
1102 + // Conservative: only align when every card in the horizontal row
1103 + // has a reliable first section bar.
1104 + if(
1105 + rows.some(function(row){
1106 + return !row;
1107 + })
1108 + ){
1109 + return null;
1465 1465   }
1466 1466  
1467 - var headers=
1468 - smallestThemeHeaders()
1469 - .map(function(el){
1470 - return {
1471 - el:el,
1472 - theme:
1473 - themeFor(
1474 - el.textContent
1475 - ),
1476 - card:
1477 - findOverviewCard(
1478 - el
1479 - )
1480 - };
1112 + var targetTop=
1113 + Math.max.apply(
1114 + Math,
1115 + rows.map(function(row){
1116 + return row.relativeTop;
1481 1481   })
1482 - .filter(function(row){
1483 - return !!row.card;
1484 - });
1118 + );
1485 1485  
1486 - var unique=[];
1487 - var seenHeaders=new Set();
1120 + rows.forEach(function(row){
1121 + var delta=
1122 + targetTop-
1123 + row.relativeTop;
1488 1488  
1489 - headers.forEach(function(row){
1490 - var key=
1491 - row.theme.name+
1492 - "|"+
1493 - Math.round(
1494 - row.card
1495 - .getBoundingClientRect()
1496 - .left
1497 - )+
1498 - "|"+
1499 - Math.round(
1500 - row.el
1501 - .getBoundingClientRect()
1502 - .top
1503 - );
1125 + if(delta<=1)return;
1504 1504  
1505 - if(!seenHeaders.has(key)){
1506 - seenHeaders.add(key);
1507 - unique.push(row);
1508 - }
1509 - });
1510 -
1511 - unique.forEach(function(row){
1512 - var headerRect=
1513 - row.el
1514 - .getBoundingClientRect();
1515 -
1516 - row.el.style.setProperty(
1517 - "background",
1518 - row.theme.bg,
1519 - "important"
1127 + saveOriginal(
1128 + row.bar,
1129 + originalMarginTop,
1130 + "margin-top"
1520 1520   );
1521 1521  
1522 - row.el.style.setProperty(
1523 - "color",
1524 - row.theme.text,
1525 - "important"
1526 - );
1133 + var currentMargin=
1134 + num(
1135 + getComputedStyle(
1136 + row.bar
1137 + ).marginTop
1138 + );
1527 1527  
1528 - row.el.style.setProperty(
1529 - "text-align",
1530 - "left",
1531 - "important"
1140 + row.bar.style.setProperty(
1141 + "margin-top",
1142 + (
1143 + currentMargin+
1144 + delta
1145 + )+"px"
1532 1532   );
1533 1533  
1534 - row.el.style.setProperty(
1535 - "word-spacing",
1536 - "normal",
1537 - "important"
1148 + row.bar.setAttribute(
1149 + "data-sn-first-section-aligned",
1150 + "4"
1538 1538   );
1539 1539  
1540 - var later=
1541 - unique
1542 - .filter(function(other){
1543 - return (
1544 - other.card===row.card&&
1545 - other.el
1546 - .getBoundingClientRect()
1547 - .top>
1548 - headerRect.top+2
1549 - );
1550 - })
1551 - .sort(function(a,b){
1552 - return (
1553 - a.el
1554 - .getBoundingClientRect()
1555 - .top-
1556 - b.el
1557 - .getBoundingClientRect()
1558 - .top
1559 - );
1560 - });
1561 -
1562 - var stopTop=
1563 - later.length
1564 - ?later[0].el
1565 - .getBoundingClientRect()
1566 - .top
1567 - :Infinity;
1568 -
1569 - Array.from(
1570 - row.card.querySelectorAll("a")
1571 - ).forEach(function(link){
1572 - if(
1573 - link.classList &&
1574 - link.classList.contains(
1575 - "arsn-phase-cta"
1576 - )
1577 - ){
1578 - return;
1579 - }
1580 -
1581 - if(!visible(link))return;
1582 -
1583 - var rect=
1584 - link.getBoundingClientRect();
1585 -
1586 - if(
1587 - rect.top<=
1588 - headerRect.bottom-2||
1589 - rect.top>=
1590 - stopTop-2
1591 - ){
1592 - return;
1593 - }
1594 -
1595 - var candidates=
1596 - rowCandidates(
1597 - link,
1598 - row.card
1599 - );
1600 -
1601 - var target=
1602 - chooseOuterRow(
1603 - candidates,
1604 - link
1605 - );
1606 -
1607 - candidates.forEach(function(el){
1608 - el.style.setProperty(
1609 - "border-left",
1610 - "0 solid transparent",
1611 - "important"
1612 - );
1613 - });
1614 -
1615 - target.style.setProperty(
1616 - "border-left",
1617 - "3px solid "+
1618 - row.theme.accent,
1619 - "important"
1620 - );
1621 -
1622 - target.style.setProperty(
1623 - "box-sizing",
1624 - "border-box",
1625 - "important"
1626 - );
1627 - });
1153 + sectionManaged.add(row.bar);
1628 1628   });
1629 1629  
1630 - return unique;
1156 + return {
1157 + labels:
1158 + rows.map(function(row){
1159 + return row.label;
1160 + }),
1161 + targetRelativeTop:
1162 + Math.round(targetTop)
1163 + };
1631 1631   }
1632 1632  
1633 - /* =======================================================
1634 - OVERVIEW CARD HEIGHT + FIRST THEMATIC ROW
1635 - ======================================================= */
1636 -
1637 - function alignOverviewCards(headers){
1638 - if(
1639 - PAGE_KIND!=="overview"||
1640 - window.innerWidth<=MOBILE_MAX
1641 - ){
1642 - return;
1166 + function applyGroup(group){
1167 + if(!validHorizontalGroup(group)){
1168 + return null;
1643 1643   }
1644 1644  
1645 1645   var cards=[];
1646 1646   var seen=new Set();
1647 1647  
1648 - headers.forEach(function(row){
1649 - if(!seen.has(row.card)){
1650 - seen.add(row.card);
1651 - cards.push(row.card);
1174 + group.entries.forEach(function(entry){
1175 + if(!seen.has(entry.target)){
1176 + seen.add(entry.target);
1177 + cards.push(entry.target);
1652 1652   }
1653 1653   });
1654 1654  
1655 - if(cards.length<2){
1656 - return;
1657 - }
1181 + if(cards.length<2)return null;
1658 1658  
1659 - // Group cards by actual top position.
1660 - var groups=[];
1183 + var firstSection=
1184 + alignFirstSections(cards);
1661 1661  
1662 - cards.forEach(function(card){
1663 - var top=
1664 - card.getBoundingClientRect().top;
1186 + // The section alignment can change natural card heights.
1187 + // Measure only afterwards.
1188 + var maxHeight=0;
1665 1665  
1666 - var group=null;
1667 -
1668 - for(var i=0;i<groups.length;i++){
1669 - if(
1670 - Math.abs(
1671 - groups[i].top-top
1672 - )<=ROW_TOLERANCE
1673 - ){
1674 - group=groups[i];
1675 - break;
1676 - }
1677 - }
1678 -
1679 - if(!group){
1680 - group={
1681 - top:top,
1682 - cards:[]
1683 - };
1684 - groups.push(group);
1685 - }
1686 -
1687 - group.cards.push(card);
1190 + cards.forEach(function(card){
1191 + maxHeight=Math.max(
1192 + maxHeight,
1193 + card.getBoundingClientRect().height
1194 + );
1688 1688   });
1689 1689  
1690 - groups.forEach(function(group){
1691 - if(group.cards.length<2){
1692 - return;
1693 - }
1197 + maxHeight=Math.ceil(maxHeight);
1694 1694  
1695 - var firstHeaders=
1696 - group.cards.map(function(card){
1697 - var candidates=
1698 - headers
1699 - .filter(function(row){
1700 - return row.card===card;
1701 - })
1702 - .sort(function(a,b){
1703 - return (
1704 - a.el
1705 - .getBoundingClientRect()
1706 - .top-
1707 - b.el
1708 - .getBoundingClientRect()
1709 - .top
1710 - );
1711 - });
1199 + if(maxHeight<MIN_H)return null;
1712 1712  
1713 - return candidates.length
1714 - ?candidates[0]
1715 - :null;
1716 - });
1201 + cards.forEach(function(card){
1202 + saveOriginal(
1203 + card,
1204 + originalMinHeight,
1205 + "min-height"
1206 + );
1717 1717  
1718 - if(
1719 - !firstHeaders.some(function(row){
1720 - return !row;
1721 - })
1722 - ){
1723 - var targetTop=
1724 - Math.max.apply(
1725 - Math,
1726 - firstHeaders.map(function(row){
1727 - return (
1728 - row.el
1729 - .getBoundingClientRect()
1730 - .top-
1731 - row.card
1732 - .getBoundingClientRect()
1733 - .top
1734 - );
1735 - })
1736 - );
1208 + card.style.setProperty(
1209 + "min-height",
1210 + maxHeight+"px"
1211 + );
1737 1737  
1738 - firstHeaders.forEach(function(row){
1739 - var relativeTop=
1740 - row.el
1741 - .getBoundingClientRect()
1742 - .top-
1743 - row.card
1744 - .getBoundingClientRect()
1745 - .top;
1213 + card.setAttribute(
1214 + "data-sn-equal-height-managed",
1215 + "4"
1216 + );
1746 1746  
1747 - var delta=
1748 - targetTop-relativeTop;
1749 -
1750 - if(delta>1){
1751 - saveStyle(
1752 - row.el,
1753 - originalMargin,
1754 - "margin-top"
1755 - );
1756 -
1757 - var current=
1758 - num(
1759 - getComputedStyle(
1760 - row.el
1761 - ).marginTop
1762 - );
1763 -
1764 - row.el.style.setProperty(
1765 - "margin-top",
1766 - (
1767 - current+delta
1768 - )+"px"
1769 - );
1770 -
1771 - row.el.setAttribute(
1772 - "data-sn-master-first-row",
1773 - "1"
1774 - );
1775 -
1776 - managedMargin.add(
1777 - row.el
1778 - );
1779 - }
1780 - });
1781 - }
1782 -
1783 - var maxHeight=0;
1784 -
1785 - group.cards.forEach(function(card){
1786 - maxHeight=
1787 - Math.max(
1788 - maxHeight,
1789 - card
1790 - .getBoundingClientRect()
1791 - .height
1792 - );
1793 - });
1794 -
1795 - maxHeight=
1796 - Math.ceil(maxHeight);
1797 -
1798 - group.cards.forEach(function(card){
1799 - saveStyle(
1800 - card,
1801 - originalHeight,
1802 - "min-height"
1803 - );
1804 -
1805 - card.style.setProperty(
1806 - "min-height",
1807 - maxHeight+"px"
1808 - );
1809 -
1810 - card.setAttribute(
1811 - "data-sn-master-equal-height",
1812 - "1"
1813 - );
1814 -
1815 - managedHeight.add(
1816 - card
1817 - );
1818 - });
1218 + heightManaged.add(card);
1819 1819   });
1220 +
1221 + return {
1222 + cards:cards.length,
1223 + height:maxHeight,
1224 + firstSection:firstSection
1225 + };
1820 1820   }
1821 1821  
1822 - /* =======================================================
1823 - DETAIL GRID EQUAL HEIGHT, DESKTOP ONLY
1824 - ======================================================= */
1228 + function run(){
1229 + reset();
1825 1825  
1826 - function equaliseDetailGrids(){
1827 1827   if(
1828 - PAGE_KIND!=="detail"||
1829 1829   window.innerWidth<=MOBILE_MAX
1830 1830   ){
1831 1831   return;
1832 1832   }
1833 1833  
1834 - var selectors=[
1835 - ".arsn-grid",
1836 - ".arsn-grid-2",
1837 - ".arsn-grid-3",
1838 - ".dmp-grid",
1839 - ".ido-grid",
1840 - ".pp-grid"
1841 - ];
1842 -
1843 - selectors.forEach(function(selector){
1237 + var parents=
1844 1844   Array.from(
1845 - root.querySelectorAll(selector)
1846 - ).forEach(function(grid){
1847 - var children=
1848 - Array.from(
1849 - grid.children||[]
1850 - ).filter(visible);
1239 + root.querySelectorAll("*")
1240 + ).filter(function(parent){
1241 + return (
1242 + visible(parent,MIN_W,MIN_H)&&
1243 + parent.children&&
1244 + parent.children.length>=2&&
1245 + parent.children.length<=MAX_PARENT_CHILDREN
1246 + );
1247 + });
1851 1851  
1852 - if(children.length<2){
1853 - return;
1854 - }
1249 + var touched=new Set();
1855 1855  
1856 - var groups=[];
1251 + parents.forEach(function(parent){
1252 + var entries=[];
1857 1857  
1858 - children.forEach(function(child){
1859 - var top=
1860 - child
1861 - .getBoundingClientRect()
1862 - .top;
1254 + Array.from(parent.children).forEach(function(child){
1255 + if(!visible(child,MIN_W,MIN_H))return;
1863 1863  
1864 - var group=null;
1257 + var target=pickTarget(child);
1258 + if(!target)return;
1865 1865  
1866 - for(var i=0;i<groups.length;i++){
1867 - if(
1868 - Math.abs(
1869 - groups[i].top-top
1870 - )<=ROW_TOLERANCE
1871 - ){
1872 - group=groups[i];
1873 - break;
1874 - }
1875 - }
1876 -
1877 - if(!group){
1878 - group={
1879 - top:top,
1880 - items:[]
1881 - };
1882 - groups.push(group);
1883 - }
1884 -
1885 - group.items.push(child);
1260 + entries.push({
1261 + target:target,
1262 + rect:target.getBoundingClientRect()
1886 1886   });
1264 + });
1887 1887  
1888 - groups.forEach(function(group){
1889 - if(group.items.length<2){
1890 - return;
1891 - }
1266 + if(entries.length<2)return;
1892 1892  
1893 - var maxHeight=0;
1268 + groupsByVisualRow(entries).forEach(function(group){
1269 + if(!validHorizontalGroup(group))return;
1894 1894  
1895 - group.items.forEach(function(item){
1896 - maxHeight=
1897 - Math.max(
1898 - maxHeight,
1899 - item
1900 - .getBoundingClientRect()
1901 - .height
1902 - );
1271 + var signature=
1272 + group.entries.map(function(entry){
1273 + return entry.target;
1903 1903   });
1904 1904  
1905 - maxHeight=
1906 - Math.ceil(maxHeight);
1276 + if(
1277 + !signature.some(function(el){
1278 + return !touched.has(el);
1279 + })
1280 + ){
1281 + return;
1282 + }
1907 1907  
1908 - group.items.forEach(function(item){
1909 - saveStyle(
1910 - item,
1911 - originalHeight,
1912 - "min-height"
1913 - );
1284 + var applied=
1285 + applyGroup(group);
1914 1914  
1915 - item.style.setProperty(
1916 - "min-height",
1917 - maxHeight+"px"
1918 - );
1919 -
1920 - item.setAttribute(
1921 - "data-sn-master-equal-height",
1922 - "1"
1923 - );
1924 -
1925 - managedHeight.add(item);
1287 + if(applied){
1288 + signature.forEach(function(el){
1289 + touched.add(el);
1926 1926   });
1927 - });
1291 + }
1928 1928   });
1929 1929   });
1930 1930   }
1931 1931  
1932 - /* =======================================================
1933 - RUN / RESPONSIVE SCHEDULING
1934 - ======================================================= */
1296 + function schedule(){
1297 + if(raf)cancelAnimationFrame(raf);
1935 1935  
1936 - function run(){
1937 - if(running)return;
1938 -
1939 - running=true;
1940 -
1941 - try{
1942 - resetRuntime();
1943 - applyPlaceholderBadge();
1944 - propagateDetailAccents();
1945 -
1946 - var headers=
1947 - applyOverviewPalette();
1948 -
1949 - makeThreeLineAreaLabels();
1950 - makeFilledRedOrangeCTAsBorderless();
1951 -
1952 - if(
1953 - window.innerWidth>
1954 - MOBILE_MAX
1955 - ){
1956 - alignOverviewCards(
1957 - headers
1958 - );
1959 -
1960 - equaliseDetailGrids();
1961 - }
1962 - }finally{
1963 - running=false;
1964 - }
1299 + raf=requestAnimationFrame(function(){
1300 + raf=requestAnimationFrame(function(){
1301 + raf=0;
1302 + run();
1303 + });
1304 + });
1965 1965   }
1966 1966  
1967 - function onResize(){
1968 - if(resizeTimer){
1969 - clearTimeout(
1970 - resizeTimer
1971 - );
1972 - }
1307 + addEventListener("resize",schedule,{passive:true});
1308 + addEventListener("load",schedule,{once:true});
1973 1973  
1974 - resizeTimer=
1975 - setTimeout(
1976 - function(){
1977 - resizeTimer=0;
1978 - run();
1979 - },
1980 - RESIZE_DEBOUNCE
1981 - );
1982 - }
1310 + root.addEventListener(
1311 + "click",
1312 + function(){
1313 + setTimeout(schedule,0);
1314 + },
1315 + true
1316 + );
1983 1983  
1984 - async function waitForReady(){
1985 - if(
1986 - document.readyState!=="complete"
1987 - ){
1988 - await new Promise(function(resolve){
1989 - window.addEventListener(
1990 - "load",
1991 - resolve,
1992 - {once:true}
1993 - );
1994 - });
1318 + Array.from(root.querySelectorAll("img")).forEach(function(img){
1319 + if(!img.complete){
1320 + img.addEventListener("load",schedule,{once:true});
1995 1995   }
1322 + });
1996 1996  
1997 - if(
1998 - document.fonts&&
1999 - document.fonts.ready
2000 - ){
2001 - try{
2002 - await document.fonts.ready;
2003 - }catch(error){}
2004 - }
2005 -
2006 - var images=
2007 - Array.from(
2008 - root.querySelectorAll("img")
2009 - );
2010 -
2011 - await Promise.all(
2012 - images.map(function(img){
2013 - if(img.complete){
2014 - return Promise.resolve();
2015 - }
2016 -
2017 - return new Promise(function(resolve){
2018 - var done=function(){
2019 - resolve();
2020 - };
2021 -
2022 - img.addEventListener(
2023 - "load",
2024 - done,
2025 - {once:true}
2026 - );
2027 -
2028 - img.addEventListener(
2029 - "error",
2030 - done,
2031 - {once:true}
2032 - );
2033 - });
2034 - })
2035 - );
2036 -
2037 - run();
1324 + if(document.fonts&&document.fonts.ready){
1325 + document.fonts.ready.then(schedule);
2038 2038   }
2039 2039  
2040 - window.addEventListener(
2041 - "resize",
2042 - onResize,
2043 - {passive:true}
2044 - );
2045 -
2046 - waitForReady();
1328 + schedule();
1329 + setTimeout(schedule,200);
1330 + setTimeout(schedule,650);
1331 + setTimeout(schedule,1400);
2047 2047  })();
2048 2048  </script>
2049 -
2050 -<!-- SN_SERVICE_NAVIGATOR_MASTER_STYLE_END -->
1334 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->
2051 2051  {{/html}}
2052 2052  
2053 -{{html clean="false"}}
2054 -<!-- ARSN_PHASE_CTA_MOBILE_EDGE_FIX_V3_START -->
2055 -<style data-arsn-phase-cta-mobile-edge-fix="3">
2056 -@media (max-width:767px){
2057 -
2058 - /* Remove the white side gutters around the three phase CTAs. */
2059 - #xwikicontent .arsn-phase-cta-wrap{
2060 - box-sizing:border-box!important;
2061 - width:calc(100% + 2px)!important;
2062 - max-width:none!important;
2063 - margin:14px -1px -1px -1px!important;
2064 - padding:0!important;
2065 - border:0!important;
2066 - border-left:0!important;
2067 - box-shadow:none!important;
2068 - background:transparent!important;
2069 - }
2070 -
2071 - /* Full-width orange CTA; no extra border/shadow. */
2072 - #xwikicontent a.arsn-phase-cta{
2073 - display:flex!important;
2074 - align-items:center!important;
2075 - justify-content:center!important;
2076 - gap:8px!important;
2077 -
2078 - box-sizing:border-box!important;
2079 - width:100%!important;
2080 - max-width:none!important;
2081 - min-width:0!important;
2082 -
2083 - margin:0!important;
2084 - padding:12px 14px!important;
2085 -
2086 - border:0!important;
2087 - border-left:0!important;
2088 - border-right:0!important;
2089 - border-top:0!important;
2090 - border-bottom:0!important;
2091 - box-shadow:none!important;
2092 -
2093 - border-radius:8px!important;
2094 -
2095 - text-align:center!important;
2096 - text-align-last:center!important;
2097 - text-justify:auto!important;
2098 - word-spacing:normal!important;
2099 - white-space:normal!important;
2100 - }
2101 -
2102 - /* Keep an XWiki external-link icon on the same line/flex row. */
2103 - #xwikicontent a.arsn-phase-cta::after{
2104 - flex:0 0 auto!important;
2105 - margin-left:2px!important;
2106 - }
2107 -
2108 - #xwikicontent a.arsn-phase-cta > .fa,
2109 - #xwikicontent a.arsn-phase-cta > .icon,
2110 - #xwikicontent a.arsn-phase-cta > .external-link-icon,
2111 - #xwikicontent a.arsn-phase-cta > [class*="external"]{
2112 - position:static!important;
2113 - display:inline-block!important;
2114 - flex:0 0 auto!important;
2115 - margin:0!important;
2116 - }
2117 -}
2118 -</style>
2119 -<!-- ARSN_PHASE_CTA_MOBILE_EDGE_FIX_V3_END -->
2120 -{{/html}}
2121 -