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

From version 5.9
edited by Veronika Kocher
on Thursday, 03 Sep 2026 9:34
Change comment: There is no comment for this version
To version 5.7
edited by Veronika Kocher
on Wednesday, 02 Sep 2026 13:13
Change comment: There is no comment for this version

Summary

Details

Page properties
Content
... ... @@ -261,698 +261,3 @@
261 261  </div>
262 262  {{/html}}
263 263  
264 -{{html clean="false"}}
265 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_START -->
266 -<style data-sn-horizontal-box-harmonizer="4">
267 -[data-sn-equal-height-managed],
268 -[data-sn-first-section-aligned]{
269 - box-sizing:border-box;
270 -}
271 -</style>
272 -<script data-sn-horizontal-box-harmonizer="4">
273 -(function(){
274 - "use strict";
275 -
276 - var MOBILE_MAX=767;
277 - var ROW_TOLERANCE=6;
278 - var MIN_W=150;
279 - var MIN_H=36;
280 - var MAX_PARENT_CHILDREN=16;
281 - var SEARCH_DEPTH=5;
282 -
283 - var root=
284 - document.getElementById("xwikicontent")||
285 - document.querySelector(".xwiki-rendering-content")||
286 - document.querySelector("main")||
287 - document.body;
288 -
289 - if(!root)return;
290 -
291 - var heightManaged=new Set();
292 - var sectionManaged=new Set();
293 - var originalMinHeight=new WeakMap();
294 - var originalMarginTop=new WeakMap();
295 - var raf=0;
296 -
297 - function num(v){
298 - var n=parseFloat(v);
299 - return Number.isFinite(n)?n:0;
300 - }
301 -
302 - function visible(el,minW,minH){
303 - if(!el||el.nodeType!==1)return false;
304 -
305 - var s=getComputedStyle(el);
306 -
307 - if(
308 - s.display==="none"||
309 - s.visibility==="hidden"||
310 - Number(s.opacity)===0
311 - ){
312 - return false;
313 - }
314 -
315 - var r=el.getBoundingClientRect();
316 -
317 - return (
318 - r.width>=(minW||1)&&
319 - r.height>=(minH||1)
320 - );
321 - }
322 -
323 - function excluded(el){
324 - return (
325 - !el.matches||
326 - el.matches(
327 - "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]"
328 - )
329 - );
330 - }
331 -
332 - function namedLikeBox(el){
333 - var c=
334 - typeof el.className==="string"
335 - ? el.className
336 - : "";
337 -
338 - return /(^|[s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([s_-]|$)/i.test(c);
339 - }
340 -
341 - function boxLike(el){
342 - if(!visible(el,MIN_W,MIN_H)||excluded(el))return false;
343 -
344 - var s=getComputedStyle(el);
345 - var r=el.getBoundingClientRect();
346 -
347 - var border=
348 - num(s.borderTopWidth)+
349 - num(s.borderRightWidth)+
350 - num(s.borderBottomWidth)+
351 - num(s.borderLeftWidth);
352 -
353 - var radius=Math.max(
354 - num(s.borderTopLeftRadius),
355 - num(s.borderTopRightRadius),
356 - num(s.borderBottomLeftRadius),
357 - num(s.borderBottomRightRadius)
358 - );
359 -
360 - var bg=
361 - s.backgroundColor&&
362 - s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
363 - s.backgroundColor!=="transparent";
364 -
365 - var shadow=
366 - s.boxShadow&&
367 - s.boxShadow!=="none";
368 -
369 - return (
370 - namedLikeBox(el)||
371 - border>=1||
372 - (bg&&radius>=3)||
373 - (shadow&&r.width>=180)
374 - );
375 - }
376 -
377 - function saveOriginal(el,map,property){
378 - if(map.has(el))return;
379 -
380 - map.set(el,{
381 - value:el.style.getPropertyValue(property),
382 - priority:el.style.getPropertyPriority(property)
383 - });
384 - }
385 -
386 - function restoreOriginal(el,map,property){
387 - var original=map.get(el);
388 -
389 - if(original&&original.value){
390 - el.style.setProperty(
391 - property,
392 - original.value,
393 - original.priority||""
394 - );
395 - }else{
396 - el.style.removeProperty(property);
397 - }
398 - }
399 -
400 - function reset(){
401 - heightManaged.forEach(function(el){
402 - restoreOriginal(
403 - el,
404 - originalMinHeight,
405 - "min-height"
406 - );
407 -
408 - el.removeAttribute(
409 - "data-sn-equal-height-managed"
410 - );
411 - });
412 -
413 - sectionManaged.forEach(function(el){
414 - restoreOriginal(
415 - el,
416 - originalMarginTop,
417 - "margin-top"
418 - );
419 -
420 - el.removeAttribute(
421 - "data-sn-first-section-aligned"
422 - );
423 - });
424 -
425 - heightManaged.clear();
426 - sectionManaged.clear();
427 - }
428 -
429 - function pickTarget(child){
430 - if(!visible(child,MIN_W,MIN_H))return null;
431 -
432 - if(boxLike(child)){
433 - return child;
434 - }
435 -
436 - var cr=child.getBoundingClientRect();
437 - var q=[];
438 -
439 - Array.from(child.children||[]).forEach(function(el){
440 - q.push({el:el,depth:1});
441 - });
442 -
443 - var best=null;
444 - var bestScore=-Infinity;
445 -
446 - while(q.length){
447 - var item=q.shift();
448 - var el=item.el;
449 -
450 - if(!visible(el,MIN_W,MIN_H))continue;
451 -
452 - var r=el.getBoundingClientRect();
453 -
454 - if(
455 - r.width>=cr.width*.68&&
456 - boxLike(el)
457 - ){
458 - var widthFit=
459 - 1-Math.min(
460 - 1,
461 - Math.abs(cr.width-r.width)/
462 - Math.max(1,cr.width)
463 - );
464 -
465 - var topFit=
466 - 1-Math.min(
467 - 1,
468 - Math.abs(cr.top-r.top)/100
469 - );
470 -
471 - var score=
472 - widthFit*6+
473 - topFit*3+
474 - Math.min(r.height,900)/450+
475 - Math.min(r.width*r.height,900000)/900000;
476 -
477 - if(score>bestScore){
478 - best=el;
479 - bestScore=score;
480 - }
481 - }
482 -
483 - if(item.depth<SEARCH_DEPTH){
484 - Array.from(el.children||[]).forEach(function(next){
485 - q.push({
486 - el:next,
487 - depth:item.depth+1
488 - });
489 - });
490 - }
491 - }
492 -
493 - return best;
494 - }
495 -
496 - function groupsByVisualRow(entries){
497 - var groups=[];
498 -
499 - entries
500 - .slice()
501 - .sort(function(a,b){
502 - return (
503 - a.rect.top-b.rect.top||
504 - a.rect.left-b.rect.left
505 - );
506 - })
507 - .forEach(function(entry){
508 - var group=null;
509 -
510 - for(var i=0;i<groups.length;i++){
511 - if(
512 - Math.abs(
513 - groups[i].top-
514 - entry.rect.top
515 - )<=ROW_TOLERANCE
516 - ){
517 - group=groups[i];
518 - break;
519 - }
520 - }
521 -
522 - if(!group){
523 - group={
524 - top:entry.rect.top,
525 - entries:[]
526 - };
527 - groups.push(group);
528 - }
529 -
530 - group.entries.push(entry);
531 - });
532 -
533 - return groups;
534 - }
535 -
536 - function validHorizontalGroup(group){
537 - if(group.entries.length<2)return false;
538 -
539 - var lefts=
540 - group.entries
541 - .map(function(e){return e.rect.left;})
542 - .sort(function(a,b){return a-b;});
543 -
544 - if(
545 - lefts[lefts.length-1]-
546 - lefts[0]<
547 - 80
548 - ){
549 - return false;
550 - }
551 -
552 - var widths=
553 - group.entries
554 - .map(function(e){return e.rect.width;})
555 - .filter(function(w){return w>0;});
556 -
557 - if(widths.length<2)return false;
558 -
559 - var minWidth=Math.min.apply(Math,widths);
560 - var maxWidth=Math.max.apply(Math,widths);
561 -
562 - return (
563 - maxWidth/
564 - Math.max(1,minWidth)<=
565 - 1.9
566 - );
567 - }
568 -
569 - function normalizeText(text){
570 - return String(text||"")
571 - .replace(/s+/g," ")
572 - .trim()
573 - .toUpperCase();
574 - }
575 -
576 - function exactKnownFirstSection(el){
577 - var text=normalizeText(el.textContent);
578 -
579 - return (
580 - text==="HIER STARTEN"||
581 - text==="ORGANISIEREN & DOKUMENTIEREN"||
582 - text==="ENTSCHEIDEN"||
583 - text==="START HERE"||
584 - text==="GET STARTED"||
585 - text==="ORGANISE & DOCUMENT"||
586 - text==="ORGANIZE & DOCUMENT"||
587 - text==="DECIDE"
588 - );
589 - }
590 -
591 - function visuallyFirstSectionBar(card){
592 - var cardRect=card.getBoundingClientRect();
593 - var candidates=[];
594 -
595 - Array.from(
596 - card.querySelectorAll(
597 - "div,p,span,strong,h3,h4,h5,h6"
598 - )
599 - ).forEach(function(el){
600 - if(!visible(el,20,6))return;
601 - if(excluded(el))return;
602 -
603 - var r=el.getBoundingClientRect();
604 - var relativeTop=r.top-cardRect.top;
605 -
606 - if(
607 - relativeTop<45||
608 - relativeTop>cardRect.height*.72
609 - ){
610 - return;
611 - }
612 -
613 - var widthRatio=
614 - r.width/
615 - Math.max(1,cardRect.width);
616 -
617 - if(
618 - widthRatio<.55||
619 - widthRatio>1.05||
620 - r.height>54
621 - ){
622 - return;
623 - }
624 -
625 - var text=normalizeText(el.textContent);
626 -
627 - if(
628 - text.length<2||
629 - text.length>90
630 - ){
631 - return;
632 - }
633 -
634 - var style=getComputedStyle(el);
635 -
636 - var bg=
637 - style.backgroundColor&&
638 - style.backgroundColor!=="rgba(0, 0, 0, 0)"&&
639 - style.backgroundColor!=="transparent";
640 -
641 - var border=
642 - num(style.borderTopWidth)+
643 - num(style.borderRightWidth)+
644 - num(style.borderBottomWidth)+
645 - num(style.borderLeftWidth);
646 -
647 - var mostlyUpper=
648 - text.length>=3&&
649 - text===text.toUpperCase();
650 -
651 - var exact=exactKnownFirstSection(el);
652 -
653 - var score=
654 - (exact?20:0)+
655 - (bg?6:0)+
656 - (border>=1?2:0)+
657 - (mostlyUpper?4:0)+
658 - (num(style.fontWeight)>=600?1:0);
659 -
660 - if(score>=7){
661 - candidates.push({
662 - el:el,
663 - relativeTop:relativeTop,
664 - width:r.width,
665 - score:score
666 - });
667 - }
668 - });
669 -
670 - if(!candidates.length)return null;
671 -
672 - candidates.sort(function(a,b){
673 - if(a.score!==b.score)return b.score-a.score;
674 - if(Math.abs(a.relativeTop-b.relativeTop)>3){
675 - return a.relativeTop-b.relativeTop;
676 - }
677 - return b.width-a.width;
678 - });
679 -
680 - // For exact known labels always prefer the earliest exact match.
681 - var exacts=candidates.filter(function(c){
682 - return exactKnownFirstSection(c.el);
683 - });
684 -
685 - if(exacts.length){
686 - exacts.sort(function(a,b){
687 - return a.relativeTop-b.relativeTop||b.width-a.width;
688 - });
689 - return exacts[0].el;
690 - }
691 -
692 - // Generic fallback: earliest high-confidence bar.
693 - candidates.sort(function(a,b){
694 - return a.relativeTop-b.relativeTop||b.score-a.score||b.width-a.width;
695 - });
696 -
697 - return candidates[0].el;
698 - }
699 -
700 - function alignFirstSections(cards){
701 - var rows=
702 - cards.map(function(card){
703 - var bar=
704 - visuallyFirstSectionBar(card);
705 -
706 - if(!bar)return null;
707 -
708 - var cardRect=
709 - card.getBoundingClientRect();
710 -
711 - var barRect=
712 - bar.getBoundingClientRect();
713 -
714 - return {
715 - card:card,
716 - bar:bar,
717 - relativeTop:
718 - barRect.top-cardRect.top,
719 - label:
720 - normalizeText(bar.textContent)
721 - };
722 - });
723 -
724 - // Conservative: only align when every card in the horizontal row
725 - // has a reliable first section bar.
726 - if(
727 - rows.some(function(row){
728 - return !row;
729 - })
730 - ){
731 - return null;
732 - }
733 -
734 - var targetTop=
735 - Math.max.apply(
736 - Math,
737 - rows.map(function(row){
738 - return row.relativeTop;
739 - })
740 - );
741 -
742 - rows.forEach(function(row){
743 - var delta=
744 - targetTop-
745 - row.relativeTop;
746 -
747 - if(delta<=1)return;
748 -
749 - saveOriginal(
750 - row.bar,
751 - originalMarginTop,
752 - "margin-top"
753 - );
754 -
755 - var currentMargin=
756 - num(
757 - getComputedStyle(
758 - row.bar
759 - ).marginTop
760 - );
761 -
762 - row.bar.style.setProperty(
763 - "margin-top",
764 - (
765 - currentMargin+
766 - delta
767 - )+"px"
768 - );
769 -
770 - row.bar.setAttribute(
771 - "data-sn-first-section-aligned",
772 - "4"
773 - );
774 -
775 - sectionManaged.add(row.bar);
776 - });
777 -
778 - return {
779 - labels:
780 - rows.map(function(row){
781 - return row.label;
782 - }),
783 - targetRelativeTop:
784 - Math.round(targetTop)
785 - };
786 - }
787 -
788 - function applyGroup(group){
789 - if(!validHorizontalGroup(group)){
790 - return null;
791 - }
792 -
793 - var cards=[];
794 - var seen=new Set();
795 -
796 - group.entries.forEach(function(entry){
797 - if(!seen.has(entry.target)){
798 - seen.add(entry.target);
799 - cards.push(entry.target);
800 - }
801 - });
802 -
803 - if(cards.length<2)return null;
804 -
805 - var firstSection=
806 - alignFirstSections(cards);
807 -
808 - // The section alignment can change natural card heights.
809 - // Measure only afterwards.
810 - var maxHeight=0;
811 -
812 - cards.forEach(function(card){
813 - maxHeight=Math.max(
814 - maxHeight,
815 - card.getBoundingClientRect().height
816 - );
817 - });
818 -
819 - maxHeight=Math.ceil(maxHeight);
820 -
821 - if(maxHeight<MIN_H)return null;
822 -
823 - cards.forEach(function(card){
824 - saveOriginal(
825 - card,
826 - originalMinHeight,
827 - "min-height"
828 - );
829 -
830 - card.style.setProperty(
831 - "min-height",
832 - maxHeight+"px"
833 - );
834 -
835 - card.setAttribute(
836 - "data-sn-equal-height-managed",
837 - "4"
838 - );
839 -
840 - heightManaged.add(card);
841 - });
842 -
843 - return {
844 - cards:cards.length,
845 - height:maxHeight,
846 - firstSection:firstSection
847 - };
848 - }
849 -
850 - function run(){
851 - reset();
852 -
853 - if(
854 - window.innerWidth<=MOBILE_MAX
855 - ){
856 - return;
857 - }
858 -
859 - var parents=
860 - Array.from(
861 - root.querySelectorAll("*")
862 - ).filter(function(parent){
863 - return (
864 - visible(parent,MIN_W,MIN_H)&&
865 - parent.children&&
866 - parent.children.length>=2&&
867 - parent.children.length<=MAX_PARENT_CHILDREN
868 - );
869 - });
870 -
871 - var touched=new Set();
872 -
873 - parents.forEach(function(parent){
874 - var entries=[];
875 -
876 - Array.from(parent.children).forEach(function(child){
877 - if(!visible(child,MIN_W,MIN_H))return;
878 -
879 - var target=pickTarget(child);
880 - if(!target)return;
881 -
882 - entries.push({
883 - target:target,
884 - rect:target.getBoundingClientRect()
885 - });
886 - });
887 -
888 - if(entries.length<2)return;
889 -
890 - groupsByVisualRow(entries).forEach(function(group){
891 - if(!validHorizontalGroup(group))return;
892 -
893 - var signature=
894 - group.entries.map(function(entry){
895 - return entry.target;
896 - });
897 -
898 - if(
899 - !signature.some(function(el){
900 - return !touched.has(el);
901 - })
902 - ){
903 - return;
904 - }
905 -
906 - var applied=
907 - applyGroup(group);
908 -
909 - if(applied){
910 - signature.forEach(function(el){
911 - touched.add(el);
912 - });
913 - }
914 - });
915 - });
916 - }
917 -
918 - function schedule(){
919 - if(raf)cancelAnimationFrame(raf);
920 -
921 - raf=requestAnimationFrame(function(){
922 - raf=requestAnimationFrame(function(){
923 - raf=0;
924 - run();
925 - });
926 - });
927 - }
928 -
929 - addEventListener("resize",schedule,{passive:true});
930 - addEventListener("load",schedule,{once:true});
931 -
932 - root.addEventListener(
933 - "click",
934 - function(){
935 - setTimeout(schedule,0);
936 - },
937 - true
938 - );
939 -
940 - Array.from(root.querySelectorAll("img")).forEach(function(img){
941 - if(!img.complete){
942 - img.addEventListener("load",schedule,{once:true});
943 - }
944 - });
945 -
946 - if(document.fonts&&document.fonts.ready){
947 - document.fonts.ready.then(schedule);
948 - }
949 -
950 - schedule();
951 - setTimeout(schedule,200);
952 - setTimeout(schedule,650);
953 - setTimeout(schedule,1400);
954 -})();
955 -</script>
956 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->
957 -{{/html}}
958 -