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

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