Last modified by Veronika Kocher on Friday, 04 Sep 2026 14:45

From version 9.1
edited by Veronika Kocher
on Tuesday, 01 Sep 2026 10:25
Change comment: There is no comment for this version
To version 9.4
edited by Veronika Kocher
on Thursday, 03 Sep 2026 9:34
Change comment: There is no comment for this version

Summary

Details

Page properties
Default language
... ... @@ -1,0 +1,1 @@
1 +en
Content
... ... @@ -425,3 +425,698 @@
425 425  </div>
426 426  {{/html}}
427 427  
428 +{{html clean="false"}}
429 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_START -->
430 +<style data-sn-horizontal-box-harmonizer="4">
431 +[data-sn-equal-height-managed],
432 +[data-sn-first-section-aligned]{
433 + box-sizing:border-box;
434 +}
435 +</style>
436 +<script data-sn-horizontal-box-harmonizer="4">
437 +(function(){
438 + "use strict";
439 +
440 + var MOBILE_MAX=767;
441 + var ROW_TOLERANCE=6;
442 + var MIN_W=150;
443 + var MIN_H=36;
444 + var MAX_PARENT_CHILDREN=16;
445 + var SEARCH_DEPTH=5;
446 +
447 + var root=
448 + document.getElementById("xwikicontent")||
449 + document.querySelector(".xwiki-rendering-content")||
450 + document.querySelector("main")||
451 + document.body;
452 +
453 + if(!root)return;
454 +
455 + var heightManaged=new Set();
456 + var sectionManaged=new Set();
457 + var originalMinHeight=new WeakMap();
458 + var originalMarginTop=new WeakMap();
459 + var raf=0;
460 +
461 + function num(v){
462 + var n=parseFloat(v);
463 + return Number.isFinite(n)?n:0;
464 + }
465 +
466 + function visible(el,minW,minH){
467 + if(!el||el.nodeType!==1)return false;
468 +
469 + var s=getComputedStyle(el);
470 +
471 + if(
472 + s.display==="none"||
473 + s.visibility==="hidden"||
474 + Number(s.opacity)===0
475 + ){
476 + return false;
477 + }
478 +
479 + var r=el.getBoundingClientRect();
480 +
481 + return (
482 + r.width>=(minW||1)&&
483 + r.height>=(minH||1)
484 + );
485 + }
486 +
487 + function excluded(el){
488 + return (
489 + !el.matches||
490 + el.matches(
491 + "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]"
492 + )
493 + );
494 + }
495 +
496 + function namedLikeBox(el){
497 + var c=
498 + typeof el.className==="string"
499 + ? el.className
500 + : "";
501 +
502 + return /(^|[s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([s_-]|$)/i.test(c);
503 + }
504 +
505 + function boxLike(el){
506 + if(!visible(el,MIN_W,MIN_H)||excluded(el))return false;
507 +
508 + var s=getComputedStyle(el);
509 + var r=el.getBoundingClientRect();
510 +
511 + var border=
512 + num(s.borderTopWidth)+
513 + num(s.borderRightWidth)+
514 + num(s.borderBottomWidth)+
515 + num(s.borderLeftWidth);
516 +
517 + var radius=Math.max(
518 + num(s.borderTopLeftRadius),
519 + num(s.borderTopRightRadius),
520 + num(s.borderBottomLeftRadius),
521 + num(s.borderBottomRightRadius)
522 + );
523 +
524 + var bg=
525 + s.backgroundColor&&
526 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
527 + s.backgroundColor!=="transparent";
528 +
529 + var shadow=
530 + s.boxShadow&&
531 + s.boxShadow!=="none";
532 +
533 + return (
534 + namedLikeBox(el)||
535 + border>=1||
536 + (bg&&radius>=3)||
537 + (shadow&&r.width>=180)
538 + );
539 + }
540 +
541 + function saveOriginal(el,map,property){
542 + if(map.has(el))return;
543 +
544 + map.set(el,{
545 + value:el.style.getPropertyValue(property),
546 + priority:el.style.getPropertyPriority(property)
547 + });
548 + }
549 +
550 + function restoreOriginal(el,map,property){
551 + var original=map.get(el);
552 +
553 + if(original&&original.value){
554 + el.style.setProperty(
555 + property,
556 + original.value,
557 + original.priority||""
558 + );
559 + }else{
560 + el.style.removeProperty(property);
561 + }
562 + }
563 +
564 + function reset(){
565 + heightManaged.forEach(function(el){
566 + restoreOriginal(
567 + el,
568 + originalMinHeight,
569 + "min-height"
570 + );
571 +
572 + el.removeAttribute(
573 + "data-sn-equal-height-managed"
574 + );
575 + });
576 +
577 + sectionManaged.forEach(function(el){
578 + restoreOriginal(
579 + el,
580 + originalMarginTop,
581 + "margin-top"
582 + );
583 +
584 + el.removeAttribute(
585 + "data-sn-first-section-aligned"
586 + );
587 + });
588 +
589 + heightManaged.clear();
590 + sectionManaged.clear();
591 + }
592 +
593 + function pickTarget(child){
594 + if(!visible(child,MIN_W,MIN_H))return null;
595 +
596 + if(boxLike(child)){
597 + return child;
598 + }
599 +
600 + var cr=child.getBoundingClientRect();
601 + var q=[];
602 +
603 + Array.from(child.children||[]).forEach(function(el){
604 + q.push({el:el,depth:1});
605 + });
606 +
607 + var best=null;
608 + var bestScore=-Infinity;
609 +
610 + while(q.length){
611 + var item=q.shift();
612 + var el=item.el;
613 +
614 + if(!visible(el,MIN_W,MIN_H))continue;
615 +
616 + var r=el.getBoundingClientRect();
617 +
618 + if(
619 + r.width>=cr.width*.68&&
620 + boxLike(el)
621 + ){
622 + var widthFit=
623 + 1-Math.min(
624 + 1,
625 + Math.abs(cr.width-r.width)/
626 + Math.max(1,cr.width)
627 + );
628 +
629 + var topFit=
630 + 1-Math.min(
631 + 1,
632 + Math.abs(cr.top-r.top)/100
633 + );
634 +
635 + var score=
636 + widthFit*6+
637 + topFit*3+
638 + Math.min(r.height,900)/450+
639 + Math.min(r.width*r.height,900000)/900000;
640 +
641 + if(score>bestScore){
642 + best=el;
643 + bestScore=score;
644 + }
645 + }
646 +
647 + if(item.depth<SEARCH_DEPTH){
648 + Array.from(el.children||[]).forEach(function(next){
649 + q.push({
650 + el:next,
651 + depth:item.depth+1
652 + });
653 + });
654 + }
655 + }
656 +
657 + return best;
658 + }
659 +
660 + function groupsByVisualRow(entries){
661 + var groups=[];
662 +
663 + entries
664 + .slice()
665 + .sort(function(a,b){
666 + return (
667 + a.rect.top-b.rect.top||
668 + a.rect.left-b.rect.left
669 + );
670 + })
671 + .forEach(function(entry){
672 + var group=null;
673 +
674 + for(var i=0;i<groups.length;i++){
675 + if(
676 + Math.abs(
677 + groups[i].top-
678 + entry.rect.top
679 + )<=ROW_TOLERANCE
680 + ){
681 + group=groups[i];
682 + break;
683 + }
684 + }
685 +
686 + if(!group){
687 + group={
688 + top:entry.rect.top,
689 + entries:[]
690 + };
691 + groups.push(group);
692 + }
693 +
694 + group.entries.push(entry);
695 + });
696 +
697 + return groups;
698 + }
699 +
700 + function validHorizontalGroup(group){
701 + if(group.entries.length<2)return false;
702 +
703 + var lefts=
704 + group.entries
705 + .map(function(e){return e.rect.left;})
706 + .sort(function(a,b){return a-b;});
707 +
708 + if(
709 + lefts[lefts.length-1]-
710 + lefts[0]<
711 + 80
712 + ){
713 + return false;
714 + }
715 +
716 + var widths=
717 + group.entries
718 + .map(function(e){return e.rect.width;})
719 + .filter(function(w){return w>0;});
720 +
721 + if(widths.length<2)return false;
722 +
723 + var minWidth=Math.min.apply(Math,widths);
724 + var maxWidth=Math.max.apply(Math,widths);
725 +
726 + return (
727 + maxWidth/
728 + Math.max(1,minWidth)<=
729 + 1.9
730 + );
731 + }
732 +
733 + function normalizeText(text){
734 + return String(text||"")
735 + .replace(/s+/g," ")
736 + .trim()
737 + .toUpperCase();
738 + }
739 +
740 + function exactKnownFirstSection(el){
741 + var text=normalizeText(el.textContent);
742 +
743 + return (
744 + text==="HIER STARTEN"||
745 + text==="ORGANISIEREN & DOKUMENTIEREN"||
746 + text==="ENTSCHEIDEN"||
747 + text==="START HERE"||
748 + text==="GET STARTED"||
749 + text==="ORGANISE & DOCUMENT"||
750 + text==="ORGANIZE & DOCUMENT"||
751 + text==="DECIDE"
752 + );
753 + }
754 +
755 + function visuallyFirstSectionBar(card){
756 + var cardRect=card.getBoundingClientRect();
757 + var candidates=[];
758 +
759 + Array.from(
760 + card.querySelectorAll(
761 + "div,p,span,strong,h3,h4,h5,h6"
762 + )
763 + ).forEach(function(el){
764 + if(!visible(el,20,6))return;
765 + if(excluded(el))return;
766 +
767 + var r=el.getBoundingClientRect();
768 + var relativeTop=r.top-cardRect.top;
769 +
770 + if(
771 + relativeTop<45||
772 + relativeTop>cardRect.height*.72
773 + ){
774 + return;
775 + }
776 +
777 + var widthRatio=
778 + r.width/
779 + Math.max(1,cardRect.width);
780 +
781 + if(
782 + widthRatio<.55||
783 + widthRatio>1.05||
784 + r.height>54
785 + ){
786 + return;
787 + }
788 +
789 + var text=normalizeText(el.textContent);
790 +
791 + if(
792 + text.length<2||
793 + text.length>90
794 + ){
795 + return;
796 + }
797 +
798 + var style=getComputedStyle(el);
799 +
800 + var bg=
801 + style.backgroundColor&&
802 + style.backgroundColor!=="rgba(0, 0, 0, 0)"&&
803 + style.backgroundColor!=="transparent";
804 +
805 + var border=
806 + num(style.borderTopWidth)+
807 + num(style.borderRightWidth)+
808 + num(style.borderBottomWidth)+
809 + num(style.borderLeftWidth);
810 +
811 + var mostlyUpper=
812 + text.length>=3&&
813 + text===text.toUpperCase();
814 +
815 + var exact=exactKnownFirstSection(el);
816 +
817 + var score=
818 + (exact?20:0)+
819 + (bg?6:0)+
820 + (border>=1?2:0)+
821 + (mostlyUpper?4:0)+
822 + (num(style.fontWeight)>=600?1:0);
823 +
824 + if(score>=7){
825 + candidates.push({
826 + el:el,
827 + relativeTop:relativeTop,
828 + width:r.width,
829 + score:score
830 + });
831 + }
832 + });
833 +
834 + if(!candidates.length)return null;
835 +
836 + candidates.sort(function(a,b){
837 + if(a.score!==b.score)return b.score-a.score;
838 + if(Math.abs(a.relativeTop-b.relativeTop)>3){
839 + return a.relativeTop-b.relativeTop;
840 + }
841 + return b.width-a.width;
842 + });
843 +
844 + // For exact known labels always prefer the earliest exact match.
845 + var exacts=candidates.filter(function(c){
846 + return exactKnownFirstSection(c.el);
847 + });
848 +
849 + if(exacts.length){
850 + exacts.sort(function(a,b){
851 + return a.relativeTop-b.relativeTop||b.width-a.width;
852 + });
853 + return exacts[0].el;
854 + }
855 +
856 + // Generic fallback: earliest high-confidence bar.
857 + candidates.sort(function(a,b){
858 + return a.relativeTop-b.relativeTop||b.score-a.score||b.width-a.width;
859 + });
860 +
861 + return candidates[0].el;
862 + }
863 +
864 + function alignFirstSections(cards){
865 + var rows=
866 + cards.map(function(card){
867 + var bar=
868 + visuallyFirstSectionBar(card);
869 +
870 + if(!bar)return null;
871 +
872 + var cardRect=
873 + card.getBoundingClientRect();
874 +
875 + var barRect=
876 + bar.getBoundingClientRect();
877 +
878 + return {
879 + card:card,
880 + bar:bar,
881 + relativeTop:
882 + barRect.top-cardRect.top,
883 + label:
884 + normalizeText(bar.textContent)
885 + };
886 + });
887 +
888 + // Conservative: only align when every card in the horizontal row
889 + // has a reliable first section bar.
890 + if(
891 + rows.some(function(row){
892 + return !row;
893 + })
894 + ){
895 + return null;
896 + }
897 +
898 + var targetTop=
899 + Math.max.apply(
900 + Math,
901 + rows.map(function(row){
902 + return row.relativeTop;
903 + })
904 + );
905 +
906 + rows.forEach(function(row){
907 + var delta=
908 + targetTop-
909 + row.relativeTop;
910 +
911 + if(delta<=1)return;
912 +
913 + saveOriginal(
914 + row.bar,
915 + originalMarginTop,
916 + "margin-top"
917 + );
918 +
919 + var currentMargin=
920 + num(
921 + getComputedStyle(
922 + row.bar
923 + ).marginTop
924 + );
925 +
926 + row.bar.style.setProperty(
927 + "margin-top",
928 + (
929 + currentMargin+
930 + delta
931 + )+"px"
932 + );
933 +
934 + row.bar.setAttribute(
935 + "data-sn-first-section-aligned",
936 + "4"
937 + );
938 +
939 + sectionManaged.add(row.bar);
940 + });
941 +
942 + return {
943 + labels:
944 + rows.map(function(row){
945 + return row.label;
946 + }),
947 + targetRelativeTop:
948 + Math.round(targetTop)
949 + };
950 + }
951 +
952 + function applyGroup(group){
953 + if(!validHorizontalGroup(group)){
954 + return null;
955 + }
956 +
957 + var cards=[];
958 + var seen=new Set();
959 +
960 + group.entries.forEach(function(entry){
961 + if(!seen.has(entry.target)){
962 + seen.add(entry.target);
963 + cards.push(entry.target);
964 + }
965 + });
966 +
967 + if(cards.length<2)return null;
968 +
969 + var firstSection=
970 + alignFirstSections(cards);
971 +
972 + // The section alignment can change natural card heights.
973 + // Measure only afterwards.
974 + var maxHeight=0;
975 +
976 + cards.forEach(function(card){
977 + maxHeight=Math.max(
978 + maxHeight,
979 + card.getBoundingClientRect().height
980 + );
981 + });
982 +
983 + maxHeight=Math.ceil(maxHeight);
984 +
985 + if(maxHeight<MIN_H)return null;
986 +
987 + cards.forEach(function(card){
988 + saveOriginal(
989 + card,
990 + originalMinHeight,
991 + "min-height"
992 + );
993 +
994 + card.style.setProperty(
995 + "min-height",
996 + maxHeight+"px"
997 + );
998 +
999 + card.setAttribute(
1000 + "data-sn-equal-height-managed",
1001 + "4"
1002 + );
1003 +
1004 + heightManaged.add(card);
1005 + });
1006 +
1007 + return {
1008 + cards:cards.length,
1009 + height:maxHeight,
1010 + firstSection:firstSection
1011 + };
1012 + }
1013 +
1014 + function run(){
1015 + reset();
1016 +
1017 + if(
1018 + window.innerWidth<=MOBILE_MAX
1019 + ){
1020 + return;
1021 + }
1022 +
1023 + var parents=
1024 + Array.from(
1025 + root.querySelectorAll("*")
1026 + ).filter(function(parent){
1027 + return (
1028 + visible(parent,MIN_W,MIN_H)&&
1029 + parent.children&&
1030 + parent.children.length>=2&&
1031 + parent.children.length<=MAX_PARENT_CHILDREN
1032 + );
1033 + });
1034 +
1035 + var touched=new Set();
1036 +
1037 + parents.forEach(function(parent){
1038 + var entries=[];
1039 +
1040 + Array.from(parent.children).forEach(function(child){
1041 + if(!visible(child,MIN_W,MIN_H))return;
1042 +
1043 + var target=pickTarget(child);
1044 + if(!target)return;
1045 +
1046 + entries.push({
1047 + target:target,
1048 + rect:target.getBoundingClientRect()
1049 + });
1050 + });
1051 +
1052 + if(entries.length<2)return;
1053 +
1054 + groupsByVisualRow(entries).forEach(function(group){
1055 + if(!validHorizontalGroup(group))return;
1056 +
1057 + var signature=
1058 + group.entries.map(function(entry){
1059 + return entry.target;
1060 + });
1061 +
1062 + if(
1063 + !signature.some(function(el){
1064 + return !touched.has(el);
1065 + })
1066 + ){
1067 + return;
1068 + }
1069 +
1070 + var applied=
1071 + applyGroup(group);
1072 +
1073 + if(applied){
1074 + signature.forEach(function(el){
1075 + touched.add(el);
1076 + });
1077 + }
1078 + });
1079 + });
1080 + }
1081 +
1082 + function schedule(){
1083 + if(raf)cancelAnimationFrame(raf);
1084 +
1085 + raf=requestAnimationFrame(function(){
1086 + raf=requestAnimationFrame(function(){
1087 + raf=0;
1088 + run();
1089 + });
1090 + });
1091 + }
1092 +
1093 + addEventListener("resize",schedule,{passive:true});
1094 + addEventListener("load",schedule,{once:true});
1095 +
1096 + root.addEventListener(
1097 + "click",
1098 + function(){
1099 + setTimeout(schedule,0);
1100 + },
1101 + true
1102 + );
1103 +
1104 + Array.from(root.querySelectorAll("img")).forEach(function(img){
1105 + if(!img.complete){
1106 + img.addEventListener("load",schedule,{once:true});
1107 + }
1108 + });
1109 +
1110 + if(document.fonts&&document.fonts.ready){
1111 + document.fonts.ready.then(schedule);
1112 + }
1113 +
1114 + schedule();
1115 + setTimeout(schedule,200);
1116 + setTimeout(schedule,650);
1117 + setTimeout(schedule,1400);
1118 +})();
1119 +</script>
1120 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->
1121 +{{/html}}
1122 +