Changes for page Plan Your Data Management

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

From version 4.8
edited by Veronika Kocher
on Thursday, 03 Sep 2026 9:18
Change comment: There is no comment for this version
To version 4.10
edited by Veronika Kocher
on Thursday, 03 Sep 2026 10:09
Change comment: There is no comment for this version

Summary

Details

Page properties
Content
... ... @@ -257,22 +257,115 @@
257 257  </div>
258 258  {{/html}}
259 259  
260 -{{html clean="false"}}
260 +\n\n
261 +\n\n{{html clean="false"}}
261 261  <!-- SN_HORIZONTAL_BOX_HARMONIZER_START -->
262 -<style data-sn-horizontal-box-harmonizer="1">
263 -[data-sn-equal-height-managed="1"]{box-sizing:border-box}
264 -@media(max-width:767px){
265 - [data-sn-equal-height-managed="1"]{min-height:0!important}
263 +
264 +<style data-sn-horizontal-box-harmonizer="7">
265 +/* ---------- Typography: never justify headings ---------- */
266 +#xwikicontent h1,
267 +#xwikicontent h2,
268 +#xwikicontent h3,
269 +#xwikicontent h4,
270 +#xwikicontent h5,
271 +#xwikicontent h6,
272 +#xwikicontent .box-title,
273 +#xwikicontent [role="heading"],
274 +#xwikicontent h1 a,
275 +#xwikicontent h2 a,
276 +#xwikicontent h3 a,
277 +#xwikicontent h4 a,
278 +#xwikicontent h5 a,
279 +#xwikicontent h6 a,
280 +#xwikicontent .box-title a,
281 +#xwikicontent [role="heading"] a{
282 + text-align:left!important;
283 + text-justify:auto!important;
284 + word-spacing:normal!important;
266 266  }
286 +
287 +/* ---------- Native XWiki semantic callouts ---------- */
288 +#xwikicontent .box.infomessage,
289 +#xwikicontent .infomessage,
290 +#xwikicontent .box.warningmessage,
291 +#xwikicontent .warningmessage,
292 +#xwikicontent .box.successmessage,
293 +#xwikicontent .successmessage,
294 +#xwikicontent .box.errormessage,
295 +#xwikicontent .errormessage,
296 +#xwikicontent [data-sn-callout-harmonized="1"]{
297 + box-sizing:border-box!important;
298 + border-radius:8px!important;
299 + border-top:1px solid rgba(0,0,0,.08)!important;
300 + border-right:1px solid rgba(0,0,0,.08)!important;
301 + border-bottom:1px solid rgba(0,0,0,.08)!important;
302 + border-left:4px solid var(--sn-callout-accent,#21b6d7)!important;
303 + padding:14px 16px!important;
304 + text-align:left!important;
305 + text-justify:auto!important;
306 + word-spacing:normal!important;
307 + box-shadow:none!important;
308 +}
309 +
310 +#xwikicontent .box.infomessage,
311 +#xwikicontent .infomessage{
312 + --sn-callout-accent:#21b6d7;
313 + background:#eaf7fb!important;
314 +}
315 +
316 +#xwikicontent .box.warningmessage,
317 +#xwikicontent .warningmessage{
318 + --sn-callout-accent:#f0aa00;
319 + background:#fff8e7!important;
320 +}
321 +
322 +#xwikicontent .box.successmessage,
323 +#xwikicontent .successmessage{
324 + --sn-callout-accent:#38b76a;
325 + background:#edf9f1!important;
326 +}
327 +
328 +#xwikicontent .box.errormessage,
329 +#xwikicontent .errormessage{
330 + --sn-callout-accent:#e94b13;
331 + background:#fff1ec!important;
332 +}
333 +
334 +#xwikicontent [data-sn-callout-harmonized="1"] > :first-child,
335 +#xwikicontent .infomessage > :first-child,
336 +#xwikicontent .warningmessage > :first-child,
337 +#xwikicontent .successmessage > :first-child,
338 +#xwikicontent .errormessage > :first-child{
339 + margin-top:0!important;
340 +}
341 +
342 +#xwikicontent [data-sn-callout-harmonized="1"] > :last-child,
343 +#xwikicontent .infomessage > :last-child,
344 +#xwikicontent .warningmessage > :last-child,
345 +#xwikicontent .successmessage > :last-child,
346 +#xwikicontent .errormessage > :last-child{
347 + margin-bottom:0!important;
348 +}
349 +
350 +#xwikicontent [data-sn-equal-height-managed],
351 +#xwikicontent [data-sn-first-section-aligned],
352 +#xwikicontent [data-sn-first-content-aligned]{
353 + box-sizing:border-box;
354 +}
267 267  </style>
268 -<script data-sn-horizontal-box-harmonizer="1">
356 +
357 +<script data-sn-horizontal-box-harmonizer="7">
269 269  (function(){
270 270   "use strict";
271 271  
272 272   var MOBILE_MAX=767;
273 - var ROW_TOLERANCE=4;
362 + var ROW_TOLERANCE=6;
274 274   var MIN_W=150;
275 275   var MIN_H=36;
365 + var MAX_PARENT_CHILDREN=18;
366 + var SEARCH_DEPTH=5;
367 + var RESIZE_DEBOUNCE=220;
368 + var MIN_WIDTH_CHANGE=2;
276 276  
277 277   var root=
278 278   document.getElementById("xwikicontent")||
... ... @@ -282,72 +282,297 @@
282 282  
283 283   if(!root)return;
284 284  
285 - var managed=new Set();
286 - var raf=0;
378 + var heightManaged=new Set();
379 + var sectionManaged=new Set();
380 + var contentManaged=new Set();
287 287  
382 + var originalMinHeight=new WeakMap();
383 + var originalMarginTop=new WeakMap();
384 +
385 + var resizeTimer=0;
386 + var lastWidth=-1;
387 + var hasApplied=false;
388 + var applying=false;
389 +
288 288   function num(v){
289 289   var n=parseFloat(v);
290 290   return Number.isFinite(n)?n:0;
291 291   }
292 292  
293 - function visible(el){
395 + function visible(el,minW,minH){
294 294   if(!el||el.nodeType!==1)return false;
397 +
295 295   var s=getComputedStyle(el);
296 - if(s.display==="none"||s.visibility==="hidden"||Number(s.opacity)===0)return false;
399 +
400 + if(
401 + s.display==="none"||
402 + s.visibility==="hidden"||
403 + Number(s.opacity)===0
404 + ){
405 + return false;
406 + }
407 +
297 297   var r=el.getBoundingClientRect();
298 - return r.width>=MIN_W&&r.height>=MIN_H;
409 +
410 + return (
411 + r.width>=(minW||1)&&
412 + r.height>=(minH||1)
413 + );
299 299   }
300 300  
416 + function normalizeText(text){
417 + return String(text||"")
418 + .replace(/\s+/g," ")
419 + .trim()
420 + .toUpperCase();
421 + }
422 +
301 301   function excluded(el){
302 - return !el.matches||el.matches(
303 - "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]"
424 + return (
425 + !el.matches||
426 + el.matches(
427 + "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]"
428 + )
304 304   );
305 305   }
306 306  
432 + /* ---------- Custom coloured callouts ---------- */
433 +
434 + function nativeCallout(el){
435 + var c=
436 + typeof el.className==="string"
437 + ? el.className.toLowerCase()
438 + : "";
439 +
440 + return (
441 + /(^|\s)(infomessage|warningmessage|successmessage|errormessage)(\s|$)/.test(c)
442 + );
443 + }
444 +
445 + function customCallout(el){
446 + if(!visible(el,220,42)||excluded(el))return false;
447 +
448 + var r=el.getBoundingClientRect();
449 +
450 + if(r.height>520)return false;
451 +
452 + var s=getComputedStyle(el);
453 +
454 + var bg=
455 + s.backgroundColor&&
456 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
457 + s.backgroundColor!=="transparent"&&
458 + s.backgroundColor!=="rgb(255, 255, 255)";
459 +
460 + var left=
461 + num(s.borderLeftWidth);
462 +
463 + return (
464 + bg&&
465 + left>=2
466 + );
467 + }
468 +
469 + function harmoniseCustomCallouts(){
470 + Array.from(
471 + root.querySelectorAll(
472 + "div,aside,section"
473 + )
474 + ).forEach(function(el){
475 + if(nativeCallout(el))return;
476 + if(!customCallout(el))return;
477 +
478 + var s=getComputedStyle(el);
479 +
480 + el.setAttribute(
481 + "data-sn-callout-harmonized",
482 + "1"
483 + );
484 +
485 + if(
486 + s.borderLeftColor
487 + ){
488 + el.style.setProperty(
489 + "--sn-callout-accent",
490 + s.borderLeftColor
491 + );
492 + }
493 + });
494 + }
495 +
496 + /* ---------- Restore only values V7 itself changed ---------- */
497 +
498 + function saveOriginal(el,map,property){
499 + if(map.has(el))return;
500 +
501 + map.set(el,{
502 + value:
503 + el.style.getPropertyValue(
504 + property
505 + ),
506 + priority:
507 + el.style.getPropertyPriority(
508 + property
509 + )
510 + });
511 + }
512 +
513 + function restoreOriginal(el,map,property){
514 + var original=map.get(el);
515 +
516 + if(original&&original.value){
517 + el.style.setProperty(
518 + property,
519 + original.value,
520 + original.priority||""
521 + );
522 + }else{
523 + el.style.removeProperty(
524 + property
525 + );
526 + }
527 + }
528 +
529 + function resetRuntime(){
530 + heightManaged.forEach(function(el){
531 + restoreOriginal(
532 + el,
533 + originalMinHeight,
534 + "min-height"
535 + );
536 +
537 + el.removeAttribute(
538 + "data-sn-equal-height-managed"
539 + );
540 + });
541 +
542 + sectionManaged.forEach(function(el){
543 + restoreOriginal(
544 + el,
545 + originalMarginTop,
546 + "margin-top"
547 + );
548 +
549 + el.removeAttribute(
550 + "data-sn-first-section-aligned"
551 + );
552 + });
553 +
554 + contentManaged.forEach(function(el){
555 + restoreOriginal(
556 + el,
557 + originalMarginTop,
558 + "margin-top"
559 + );
560 +
561 + el.removeAttribute(
562 + "data-sn-first-content-aligned"
563 + );
564 + });
565 +
566 + heightManaged.clear();
567 + sectionManaged.clear();
568 + contentManaged.clear();
569 + }
570 +
571 + /* ---------- Card detection ---------- */
572 +
307 307   function namedLikeBox(el){
308 - var c=typeof el.className==="string"?el.className:"";
574 + var c=
575 + typeof el.className==="string"
576 + ? el.className
577 + : "";
578 +
309 309   return /(^|[\s_-])(box|card|tile|panel|role|check|service|source|call|area|detail|resource|topic|warn|info)([\s_-]|$)/i.test(c);
310 310   }
311 311  
312 312   function boxLike(el){
313 - if(!visible(el)||excluded(el))return false;
583 + if(
584 + !visible(el,MIN_W,MIN_H)||
585 + excluded(el)
586 + ){
587 + return false;
588 + }
589 +
314 314   var s=getComputedStyle(el);
315 315   var r=el.getBoundingClientRect();
592 +
316 316   var border=
317 - num(s.borderTopWidth)+num(s.borderRightWidth)+
318 - num(s.borderBottomWidth)+num(s.borderLeftWidth);
594 + num(s.borderTopWidth)+
595 + num(s.borderRightWidth)+
596 + num(s.borderBottomWidth)+
597 + num(s.borderLeftWidth);
598 +
319 319   var radius=Math.max(
320 - num(s.borderTopLeftRadius),num(s.borderTopRightRadius),
321 - num(s.borderBottomLeftRadius),num(s.borderBottomRightRadius)
600 + num(s.borderTopLeftRadius),
601 + num(s.borderTopRightRadius),
602 + num(s.borderBottomLeftRadius),
603 + num(s.borderBottomRightRadius)
322 322   );
323 - var bg=s.backgroundColor&&s.backgroundColor!=="rgba(0, 0, 0, 0)"&&s.backgroundColor!=="transparent";
324 - var shadow=s.boxShadow&&s.boxShadow!=="none";
325 - return namedLikeBox(el)||border>=1||(bg&&radius>=3)||(shadow&&r.width>=180);
605 +
606 + var bg=
607 + s.backgroundColor&&
608 + s.backgroundColor!=="rgba(0, 0, 0, 0)"&&
609 + s.backgroundColor!=="transparent";
610 +
611 + var shadow=
612 + s.boxShadow&&
613 + s.boxShadow!=="none";
614 +
615 + return (
616 + namedLikeBox(el)||
617 + border>=1||
618 + (bg&&radius>=3)||
619 + (shadow&&r.width>=180)
620 + );
326 326   }
327 327  
328 328   function pickTarget(child){
329 - if(!visible(child))return null;
624 + if(!visible(child,MIN_W,MIN_H))return null;
625 +
330 330   if(boxLike(child))return child;
331 331  
332 332   var cr=child.getBoundingClientRect();
333 333   var q=[];
630 +
334 334   Array.from(child.children||[]).forEach(function(el){
335 335   q.push({el:el,depth:1});
336 336   });
337 337  
338 - var best=null,bestScore=-1;
635 + var best=null;
636 + var bestScore=-Infinity;
339 339  
340 340   while(q.length){
341 341   var item=q.shift();
342 342   var el=item.el;
343 - if(!visible(el))continue;
344 344  
642 + if(!visible(el,MIN_W,MIN_H))continue;
643 +
345 345   var r=el.getBoundingClientRect();
346 346  
347 - if(r.width>=cr.width*.72&&boxLike(el)){
348 - var widthFit=1-Math.min(1,Math.abs(cr.width-r.width)/Math.max(1,cr.width));
349 - var topFit=1-Math.min(1,Math.abs(cr.top-r.top)/80);
350 - var score=widthFit*5+topFit*2+Math.min(r.height,600)/600;
646 + if(
647 + r.width>=cr.width*.68&&
648 + boxLike(el)
649 + ){
650 + var widthFit=
651 + 1-Math.min(
652 + 1,
653 + Math.abs(cr.width-r.width)/
654 + Math.max(1,cr.width)
655 + );
656 +
657 + var topFit=
658 + 1-Math.min(
659 + 1,
660 + Math.abs(cr.top-r.top)/100
661 + );
662 +
663 + var score=
664 + widthFit*6+
665 + topFit*3+
666 + Math.min(r.height,900)/450+
667 + Math.min(r.width*r.height,900000)/900000;
668 +
351 351   if(score>bestScore){
352 352   best=el;
353 353   bestScore=score;
... ... @@ -354,9 +354,12 @@
354 354   }
355 355   }
356 356  
357 - if(item.depth<3){
675 + if(item.depth<SEARCH_DEPTH){
358 358   Array.from(el.children||[]).forEach(function(next){
359 - q.push({el:next,depth:item.depth+1});
677 + q.push({
678 + el:next,
679 + depth:item.depth+1
680 + });
360 360   });
361 361   }
362 362   }
... ... @@ -364,130 +364,692 @@
364 364   return best;
365 365   }
366 366  
367 - function reset(){
368 - managed.forEach(function(el){
369 - el.style.removeProperty("min-height");
370 - el.removeAttribute("data-sn-equal-height-managed");
371 - });
372 - managed.clear();
688 + function groupRows(entries){
689 + var groups=[];
690 +
691 + entries
692 + .slice()
693 + .sort(function(a,b){
694 + return (
695 + a.rect.top-b.rect.top||
696 + a.rect.left-b.rect.left
697 + );
698 + })
699 + .forEach(function(entry){
700 + var group=null;
701 +
702 + for(var i=0;i<groups.length;i++){
703 + if(
704 + Math.abs(
705 + groups[i].top-
706 + entry.rect.top
707 + )<=ROW_TOLERANCE
708 + ){
709 + group=groups[i];
710 + break;
711 + }
712 + }
713 +
714 + if(!group){
715 + group={
716 + top:entry.rect.top,
717 + entries:[]
718 + };
719 + groups.push(group);
720 + }
721 +
722 + group.entries.push(entry);
723 + });
724 +
725 + return groups;
373 373   }
374 374  
375 - function horizontalLayout(parent){
376 - if(!visible(parent))return false;
377 - var s=getComputedStyle(parent);
378 - if(s.display==="grid"||s.display==="inline-grid")return true;
379 - if(s.display==="flex"||s.display==="inline-flex"){
380 - return s.flexDirection==="row"||s.flexDirection==="row-reverse";
728 + function validRow(group){
729 + if(group.entries.length<2)return false;
730 +
731 + var lefts=
732 + group.entries
733 + .map(function(e){return e.rect.left;})
734 + .sort(function(a,b){return a-b;});
735 +
736 + if(
737 + lefts[lefts.length-1]-
738 + lefts[0]<
739 + 80
740 + ){
741 + return false;
381 381   }
382 - return false;
743 +
744 + var widths=
745 + group.entries
746 + .map(function(e){return e.rect.width;})
747 + .filter(function(w){return w>0;});
748 +
749 + if(widths.length<2)return false;
750 +
751 + var minW=
752 + Math.min.apply(Math,widths);
753 +
754 + var maxW=
755 + Math.max.apply(Math,widths);
756 +
757 + return (
758 + maxW/
759 + Math.max(1,minW)<=
760 + 1.9
761 + );
383 383   }
384 384  
385 - function rowGroups(entries){
386 - var groups=[];
387 - entries.slice().sort(function(a,b){
388 - return a.rect.top-b.rect.top||a.rect.left-b.rect.left;
389 - }).forEach(function(entry){
390 - var group=null;
391 - for(var i=0;i<groups.length;i++){
392 - if(Math.abs(groups[i].top-entry.rect.top)<=ROW_TOLERANCE){
393 - group=groups[i];
394 - break;
764 + /* ---------- Known ARSN first section bars ---------- */
765 +
766 + function knownBar(el){
767 + var text=
768 + normalizeText(
769 + el.textContent
770 + );
771 +
772 + return (
773 + text==="HIER STARTEN"||
774 + text==="ORGANISIEREN & DOKUMENTIEREN"||
775 + text==="ENTSCHEIDEN"||
776 + text==="START HERE"||
777 + text==="GET STARTED"||
778 + text==="ORGANISE & DOCUMENT"||
779 + text==="ORGANIZE & DOCUMENT"||
780 + text==="DECIDE"
781 + );
782 + }
783 +
784 + function findKnownBar(card){
785 + var cardRect=
786 + card.getBoundingClientRect();
787 +
788 + var rows=
789 + Array.from(
790 + card.querySelectorAll(
791 + "div,p,span,strong,h3,h4,h5,h6"
792 + )
793 + )
794 + .filter(function(el){
795 + if(!visible(el,20,6))return false;
796 + if(!knownBar(el))return false;
797 +
798 + var r=el.getBoundingClientRect();
799 +
800 + var rel=
801 + r.top-
802 + cardRect.top;
803 +
804 + return (
805 + rel>=35&&
806 + rel<=
807 + cardRect.height*.75
808 + );
809 + })
810 + .sort(function(a,b){
811 + return (
812 + a.getBoundingClientRect().top-
813 + b.getBoundingClientRect().top
814 + );
815 + });
816 +
817 + return rows[0]||null;
818 + }
819 +
820 + function alignKnownBars(cards){
821 + var rows=
822 + cards.map(function(card){
823 + var bar=
824 + findKnownBar(card);
825 +
826 + if(!bar)return null;
827 +
828 + var cr=
829 + card.getBoundingClientRect();
830 +
831 + var br=
832 + bar.getBoundingClientRect();
833 +
834 + return {
835 + bar:bar,
836 + relativeTop:
837 + br.top-
838 + cr.top
839 + };
840 + });
841 +
842 + if(
843 + rows.some(function(row){
844 + return !row;
845 + })
846 + ){
847 + return false;
848 + }
849 +
850 + var target=
851 + Math.max.apply(
852 + Math,
853 + rows.map(function(row){
854 + return row.relativeTop;
855 + })
856 + );
857 +
858 + rows.forEach(function(row){
859 + var delta=
860 + target-
861 + row.relativeTop;
862 +
863 + if(delta<=1)return;
864 +
865 + saveOriginal(
866 + row.bar,
867 + originalMarginTop,
868 + "margin-top"
869 + );
870 +
871 + var current=
872 + num(
873 + getComputedStyle(
874 + row.bar
875 + ).marginTop
876 + );
877 +
878 + row.bar.style.setProperty(
879 + "margin-top",
880 + (
881 + current+
882 + delta
883 + )+"px"
884 + );
885 +
886 + row.bar.setAttribute(
887 + "data-sn-first-section-aligned",
888 + "7"
889 + );
890 +
891 + sectionManaged.add(
892 + row.bar
893 + );
894 + });
895 +
896 + return true;
897 + }
898 +
899 + /* ---------- Generic first content after heading ---------- */
900 +
901 + function heading(card){
902 + var cr=
903 + card.getBoundingClientRect();
904 +
905 + var rows=
906 + Array.from(
907 + card.querySelectorAll(
908 + "h1,h2,h3,h4,h5,h6,.box-title,[role=heading]"
909 + )
910 + )
911 + .filter(function(el){
912 + if(!visible(el,20,8))return false;
913 +
914 + var r=el.getBoundingClientRect();
915 +
916 + var rel=
917 + r.top-
918 + cr.top;
919 +
920 + return (
921 + rel>=0&&
922 + rel<=
923 + Math.min(
924 + 160,
925 + cr.height*.45
926 + )
927 + );
928 + })
929 + .sort(function(a,b){
930 + return (
931 + a.getBoundingClientRect().top-
932 + b.getBoundingClientRect().top
933 + );
934 + });
935 +
936 + return rows[0]||null;
937 + }
938 +
939 + function firstContent(card,h){
940 + if(!h)return null;
941 +
942 + var cr=
943 + card.getBoundingClientRect();
944 +
945 + var hr=
946 + h.getBoundingClientRect();
947 +
948 + var rows=
949 + Array.from(
950 + card.querySelectorAll(
951 + "p,div,ul,ol,dl,blockquote"
952 + )
953 + )
954 + .filter(function(el){
955 + if(
956 + el===h||
957 + h.contains(el)||
958 + el.contains(h)
959 + ){
960 + return false;
395 395   }
396 - }
397 - if(!group){
398 - group={top:entry.rect.top,entries:[]};
399 - groups.push(group);
400 - }
401 - group.entries.push(entry);
962 +
963 + if(!visible(el,30,8))return false;
964 +
965 + var text=
966 + String(el.textContent||"")
967 + .replace(/\s+/g," ")
968 + .trim();
969 +
970 + if(text.length<3)return false;
971 +
972 + var r=el.getBoundingClientRect();
973 +
974 + if(
975 + r.top<
976 + hr.bottom-1
977 + ){
978 + return false;
979 + }
980 +
981 + if(
982 + r.top-cr.top>
983 + Math.min(
984 + 280,
985 + cr.height*.65
986 + )
987 + ){
988 + return false;
989 + }
990 +
991 + if(
992 + r.height>
993 + cr.height*.58
994 + ){
995 + return false;
996 + }
997 +
998 + return true;
999 + })
1000 + .sort(function(a,b){
1001 + var ar=
1002 + a.getBoundingClientRect();
1003 +
1004 + var br=
1005 + b.getBoundingClientRect();
1006 +
1007 + return (
1008 + ar.top-br.top||
1009 + ar.height-br.height
1010 + );
1011 + });
1012 +
1013 + return rows[0]||null;
1014 + }
1015 +
1016 + function alignGeneric(cards){
1017 + var rows=
1018 + cards.map(function(card){
1019 + var h=
1020 + heading(card);
1021 +
1022 + var c=
1023 + firstContent(
1024 + card,
1025 + h
1026 + );
1027 +
1028 + if(!h||!c)return null;
1029 +
1030 + var cr=
1031 + card.getBoundingClientRect();
1032 +
1033 + var rr=
1034 + c.getBoundingClientRect();
1035 +
1036 + return {
1037 + content:c,
1038 + relativeTop:
1039 + rr.top-cr.top
1040 + };
1041 + });
1042 +
1043 + if(
1044 + rows.some(function(row){
1045 + return !row;
1046 + })
1047 + ){
1048 + return false;
1049 + }
1050 +
1051 + var target=
1052 + Math.max.apply(
1053 + Math,
1054 + rows.map(function(row){
1055 + return row.relativeTop;
1056 + })
1057 + );
1058 +
1059 + rows.forEach(function(row){
1060 + var delta=
1061 + target-
1062 + row.relativeTop;
1063 +
1064 + if(delta<=1)return;
1065 +
1066 + saveOriginal(
1067 + row.content,
1068 + originalMarginTop,
1069 + "margin-top"
1070 + );
1071 +
1072 + var current=
1073 + num(
1074 + getComputedStyle(
1075 + row.content
1076 + ).marginTop
1077 + );
1078 +
1079 + row.content.style.setProperty(
1080 + "margin-top",
1081 + (
1082 + current+
1083 + delta
1084 + )+"px"
1085 + );
1086 +
1087 + row.content.setAttribute(
1088 + "data-sn-first-content-aligned",
1089 + "7"
1090 + );
1091 +
1092 + contentManaged.add(
1093 + row.content
1094 + );
402 402   });
403 - return groups;
1096 +
1097 + return true;
404 404   }
405 405  
406 - function run(){
407 - reset();
1100 + function applyRow(group){
1101 + if(!validRow(group))return false;
408 408  
409 - if(window.innerWidth<=MOBILE_MAX)return;
1103 + var cards=[];
1104 + var seen=new Set();
410 410  
411 - var parents=Array.from(root.querySelectorAll("*")).filter(function(el){
412 - return el.children&&el.children.length>=2&&horizontalLayout(el);
1106 + group.entries.forEach(function(entry){
1107 + if(!seen.has(entry.target)){
1108 + seen.add(entry.target);
1109 + cards.push(entry.target);
1110 + }
413 413   });
414 414  
415 - parents.forEach(function(parent){
416 - var entries=[];
1113 + if(cards.length<2)return false;
417 417  
418 - Array.from(parent.children).forEach(function(child){
419 - if(!visible(child))return;
420 - var target=pickTarget(child);
421 - if(!target)return;
422 - entries.push({
423 - target:target,
424 - rect:target.getBoundingClientRect()
425 - });
426 - });
1115 + if(
1116 + !alignKnownBars(cards)
1117 + ){
1118 + alignGeneric(cards);
1119 + }
427 427  
428 - if(entries.length<2)return;
1121 + var maxHeight=0;
429 429  
430 - rowGroups(entries).forEach(function(group){
431 - if(group.entries.length<2)return;
1123 + cards.forEach(function(card){
1124 + maxHeight=
1125 + Math.max(
1126 + maxHeight,
1127 + card.getBoundingClientRect().height
1128 + );
1129 + });
432 432  
433 - var lefts=group.entries.map(function(e){return e.rect.left;}).sort(function(a,b){return a-b;});
434 - if(lefts[lefts.length-1]-lefts[0]<80)return;
1131 + maxHeight=
1132 + Math.ceil(
1133 + maxHeight
1134 + );
435 435  
436 - var targets=[];
437 - var seen=new Set();
1136 + if(maxHeight<MIN_H)return false;
438 438  
439 - group.entries.forEach(function(e){
440 - if(!seen.has(e.target)){
441 - seen.add(e.target);
442 - targets.push(e.target);
443 - }
1138 + cards.forEach(function(card){
1139 + saveOriginal(
1140 + card,
1141 + originalMinHeight,
1142 + "min-height"
1143 + );
1144 +
1145 + card.style.setProperty(
1146 + "min-height",
1147 + maxHeight+"px"
1148 + );
1149 +
1150 + card.setAttribute(
1151 + "data-sn-equal-height-managed",
1152 + "7"
1153 + );
1154 +
1155 + heightManaged.add(card);
1156 + });
1157 +
1158 + return true;
1159 + }
1160 +
1161 + function calculate(force){
1162 + if(applying)return;
1163 +
1164 + var width=
1165 + Math.round(
1166 + window.innerWidth
1167 + );
1168 +
1169 + var meaningful=
1170 + lastWidth<0||
1171 + Math.abs(
1172 + width-
1173 + lastWidth
1174 + )>=
1175 + MIN_WIDTH_CHANGE;
1176 +
1177 + if(
1178 + hasApplied&&
1179 + !force&&
1180 + !meaningful
1181 + ){
1182 + return;
1183 + }
1184 +
1185 + applying=true;
1186 +
1187 + try{
1188 + harmoniseCustomCallouts();
1189 +
1190 + if(width<=MOBILE_MAX){
1191 + if(hasApplied){
1192 + resetRuntime();
1193 + }
1194 +
1195 + hasApplied=false;
1196 + lastWidth=width;
1197 + return;
1198 + }
1199 +
1200 + if(hasApplied){
1201 + resetRuntime();
1202 + }
1203 +
1204 + var parents=
1205 + Array.from(
1206 + root.querySelectorAll("*")
1207 + )
1208 + .filter(function(parent){
1209 + return (
1210 + visible(
1211 + parent,
1212 + MIN_W,
1213 + MIN_H
1214 + )&&
1215 + parent.children&&
1216 + parent.children.length>=2&&
1217 + parent.children.length<=
1218 + MAX_PARENT_CHILDREN
1219 + );
444 444   });
445 445  
446 - if(targets.length<2)return;
1222 + var touched=
1223 + new Set();
447 447  
448 - var max=0;
449 - targets.forEach(function(el){
450 - max=Math.max(max,el.getBoundingClientRect().height);
1225 + parents.forEach(function(parent){
1226 + var entries=[];
1227 +
1228 + Array.from(
1229 + parent.children
1230 + ).forEach(function(child){
1231 + if(
1232 + !visible(
1233 + child,
1234 + MIN_W,
1235 + MIN_H
1236 + )
1237 + ){
1238 + return;
1239 + }
1240 +
1241 + var target=
1242 + pickTarget(child);
1243 +
1244 + if(!target)return;
1245 +
1246 + entries.push({
1247 + target:target,
1248 + rect:
1249 + target.getBoundingClientRect()
1250 + });
451 451   });
452 452  
453 - max=Math.ceil(max);
454 - if(max<MIN_H)return;
1253 + groupRows(
1254 + entries
1255 + ).forEach(function(group){
1256 + if(!validRow(group))return;
455 455  
456 - targets.forEach(function(el){
457 - el.style.setProperty("min-height",max+"px");
458 - el.setAttribute("data-sn-equal-height-managed","1");
459 - managed.add(el);
1258 + var targets=
1259 + group.entries.map(function(entry){
1260 + return entry.target;
1261 + });
1262 +
1263 + if(
1264 + !targets.some(function(el){
1265 + return !touched.has(el);
1266 + })
1267 + ){
1268 + return;
1269 + }
1270 +
1271 + if(applyRow(group)){
1272 + targets.forEach(function(el){
1273 + touched.add(el);
1274 + });
1275 + }
460 460   });
461 461   });
462 - });
1278 +
1279 + lastWidth=width;
1280 + hasApplied=true;
1281 + }finally{
1282 + applying=false;
1283 + }
463 463   }
464 464  
465 - function schedule(){
466 - if(raf)cancelAnimationFrame(raf);
467 - raf=requestAnimationFrame(function(){
468 - raf=requestAnimationFrame(function(){
469 - raf=0;
470 - run();
471 - });
472 - });
1286 + function resize(){
1287 + if(resizeTimer){
1288 + clearTimeout(
1289 + resizeTimer
1290 + );
1291 + }
1292 +
1293 + resizeTimer=
1294 + setTimeout(
1295 + function(){
1296 + resizeTimer=0;
1297 + calculate(false);
1298 + },
1299 + RESIZE_DEBOUNCE
1300 + );
473 473   }
474 474  
475 - addEventListener("resize",schedule,{passive:true});
476 - addEventListener("load",schedule,{once:true});
1303 + function waitImages(){
1304 + var images=
1305 + Array.from(
1306 + root.querySelectorAll("img")
1307 + );
477 477  
478 - root.addEventListener("click",function(){
479 - setTimeout(schedule,0);
480 - },true);
1309 + return Promise.all(
1310 + images.map(function(img){
1311 + if(img.complete){
1312 + return Promise.resolve();
1313 + }
481 481  
482 - if(document.fonts&&document.fonts.ready){
483 - document.fonts.ready.then(schedule);
1315 + return new Promise(function(resolve){
1316 + var done=function(){
1317 + resolve();
1318 + };
1319 +
1320 + img.addEventListener(
1321 + "load",
1322 + done,
1323 + {once:true}
1324 + );
1325 +
1326 + img.addEventListener(
1327 + "error",
1328 + done,
1329 + {once:true}
1330 + );
1331 + });
1332 + })
1333 + );
484 484   }
485 485  
486 - schedule();
487 - setTimeout(schedule,250);
488 - setTimeout(schedule,900);
1336 + async function initial(){
1337 + if(
1338 + document.readyState!==
1339 + "complete"
1340 + ){
1341 + await new Promise(function(resolve){
1342 + addEventListener(
1343 + "load",
1344 + resolve,
1345 + {once:true}
1346 + );
1347 + });
1348 + }
1349 +
1350 + if(
1351 + document.fonts&&
1352 + document.fonts.ready
1353 + ){
1354 + try{
1355 + await document.fonts.ready;
1356 + }catch(error){}
1357 + }
1358 +
1359 + await waitImages();
1360 +
1361 + // Exactly one initial layout calculation.
1362 + calculate(true);
1363 + }
1364 +
1365 + addEventListener(
1366 + "resize",
1367 + resize,
1368 + {passive:true}
1369 + );
1370 +
1371 + initial();
489 489  })();
490 490  </script>
491 -<!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->
492 -{{/html}}
493 493  
1375 +<!-- SN_HORIZONTAL_BOX_HARMONIZER_END -->
1376 +{{/html}}\n